Skip to content

Commit 1524d69

Browse files
authored
Additional TES generation tooling udpates (#593)
* Additional TES generation tooling udpates * Added coverage tests for TESPackageGenerator * Addressed reviewer feedback * Changes to address review feedback
1 parent fcf4c91 commit 1524d69

8 files changed

Lines changed: 303769 additions & 269936 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
package org.opencds.cqf.tooling.casereporting.tes;
22

3-
import org.opencds.cqf.tooling.utilities.IOUtils;
4-
53
import java.util.Set;
4+
import org.opencds.cqf.tooling.utilities.IOUtils;
65

76
public class TESPackageGenerateParameters {
87
public String version; // -version (-v)
98
public String releaseLabel; // -releaselabel (-rl)
109
public String outputPath; // -outputpath (-op)
1110
public String outputFileName; // -outputfilename (-ofn)
1211
public String pathToInputBundle; // -pathtoinputbundle (-ptib)
13-
public String pathToConditionGrouperWorkbook; // -pathToConditionGrouperWorkbook (-ptcgw)
12+
public String pathToGroupersWorkbook; // -pathToGroupersWorkbook (-ptgw)
1413
public String pathToConditionCodeValueSet; // -pathToConditionCodeValueSet (-ptccvs)
1514
public Set<IOUtils.Encoding> outputFileEncodings; // -encoding (-e)
1615
public boolean writeConditionGroupers; // -writeconditiongroupers (-wcg)
1716
public boolean writeReportingSpecificationGroupers; // -writereportingspecificationgroupers (-wrsg)
1817
public boolean writeAdditionalContextGroupers; // -writeadditionalcontextgroupers (-wacg)
19-
}
18+
}

tooling/src/main/java/org/opencds/cqf/tooling/casereporting/tes/TESPackageGenerator.java

Lines changed: 818 additions & 587 deletions
Large diffs are not rendered by default.

tooling/src/main/java/org/opencds/cqf/tooling/constants/CaseReporting.java

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,43 @@ private CaseReporting() {}
1313
public static final String MANIFESTCANONICALTAIL = "tes-content-library";
1414
public static final String MANIFESTURL = CANONICALBASE + "/" + MANIFESTCANONICALTAIL;
1515
public static final String VSMUSAGECONTEXTTYPESYSTEMURL = "http://aphl.org/fhir/vsm/CodeSystem/usage-context-type";
16-
public static final String USAGECONTEXTTYPESYSTEMURL = "http://terminology.hl7.org/CodeSystem/usage-context-type";
1716
public static final String USPHUSAGECONTEXTURL = "http://hl7.org/fhir/us/ecr/CodeSystem/us-ph-usage-context";
18-
public static final String SEARCHPARAMSYSTEMLIBRARYDEPENDSON = "http://hl7.org/fhir/Library#relatedArtifact.dependsOn";
19-
public static final String SEARCHPARAMSYSTEMLIBRARYCONTEXTTYPEVALUE = "http://hl7.org/fhir/ValueSet#useContext.context-type-value";
20-
public static final String SEARCHPARAMUSECONTEXTVALUEGROUPERTYPECONDITIONGROUPER = "grouper-type$http://aphl.org/fhir/vsm/CodeSystem/usage-context-type|condition-grouper";
17+
public static final String SEARCHPARAMSYSTEMLIBRARYDEPENDSON =
18+
"http://hl7.org/fhir/Library#relatedArtifact.dependsOn";
19+
public static final String SEARCHPARAMSYSTEMLIBRARYCONTEXTTYPEVALUE =
20+
"http://hl7.org/fhir/ValueSet#useContext.context-type-value";
21+
public static final String SEARCHPARAMUSECONTEXTVALUEGROUPERTYPECONDITIONGROUPER =
22+
"grouper-type$http://aphl.org/fhir/vsm/CodeSystem/usage-context-type|condition-grouper";
2123

2224
// Condition Groupers Sheet Layout
2325
public static final int CONDITIONGROUPINGSSHEETINDEX = 1;
24-
public static final int CONDITIONGROUPINGIDENTIFIERINDEX = 1;
25-
public static final int CONDITIONGROUPINGGENERATEDNAMEINDEX = 2;
26-
public static final int CONDITIONGROUPINGTITLEINDEX = 3;
27-
public static final int REPORTINGSPECIFICATIONTITLEINDEX = 4;
28-
public static final int REPORTINGSPECIFICATIONCONDITIONCODEINDEX = 5;
29-
public static final int REPORTINGSPECIFICATIONCONDITIONDESCRIPTIONINDEX = 6;
26+
public static final int CONDITIONGROUPINGURLCOLINDEX = 1;
27+
public static final int CONDITIONGROUPINGTITLECOLINDEX = 3;
28+
public static final int REPORTINGSPECIFICATIONTITLECOLINDEX = 4;
29+
public static final int REPORTINGSPECIFICATIONCONDITIONCODECOLINDEX = 5;
30+
public static final int REPORTINGSPECIFICATIONCONDITIONDESCRIPTIONCOLINDEX = 6;
3031

3132
// Additional Context Groupers Sheet Layout
33+
// public static final int ADDITIONALCONTEXTGROUPERSHEETINDEX = 2;
34+
// public static final int ADDITIONALCONTEXTGROUPERTARGETCONDITIONGROUPERURLCOLINDEX = 0;
35+
// public static final int ADDITIONALCONTEXTGROUPERTARGETCONDITIONGROUPERTITLECOLINDEX = 1;
36+
// public static final int ADDITIONALCONTEXTGROUPERURLCOLINDEX = 2;
37+
// public static final int ADDITIONALCONTEXTGROUPERTITLECOLINDEX = 3;
38+
// public static final int ADDITIONALCONTEXTGROUPERVALUESETTITLEINDEX = 4;
39+
// public static final int ADDITIONALCONTEXTGROUPERVALUESETURLINDEX = 5;
40+
// public static final int ADDITIONALCONTEXTGROUPERVALUESETSYSTEMINDEX = 6;
41+
42+
// Additional Context Groupers Codes Sheet Layout
3243
public static final int ADDITIONALCONTEXTGROUPERSHEETINDEX = 2;
3344
public static final int ADDITIONALCONTEXTGROUPERTARGETCONDITIONGROUPERURLCOLINDEX = 0;
3445
public static final int ADDITIONALCONTEXTGROUPERTARGETCONDITIONGROUPERTITLECOLINDEX = 1;
3546
public static final int ADDITIONALCONTEXTGROUPERGENERATEDURLCOLINDEX = 2;
3647
public static final int ADDITIONALCONTEXTGROUPERGENERATEDTITLECOLINDEX = 3;
3748
public static final int ADDITIONALCONTEXTGROUPERTITLECOLINDEX = 4;
38-
public static final int ADDITIONALCONTEXTGROUPERCODECOLINDEX = 5;
39-
public static final int ADDITIONALCONTEXTGROUPERCODEDISPLAYCOLINDEX = 6;
40-
public static final int ADDITIONALCONTEXTGROUPERCODESYSTEMURLCOLINDEX = 7;
41-
}
49+
public static final int ADDITIONALCONTEXTGROUPERVALUESETURLCOLINDEX = 5;
50+
public static final int ADDITIONALCONTEXTGROUPERVALUESETTITLECOLINDEX = 6;
51+
public static final int ADDITIONALCONTEXTGROUPERVALUESETSYSTEMURLCOLINDEX = 7;
52+
public static final int ADDITIONALCONTEXTGROUPERCODECOLINDEX = 8;
53+
public static final int ADDITIONALCONTEXTGROUPERCODEDISPLAYCOLINDEX = 9;
54+
public static final int ADDITIONALCONTEXTGROUPERCODESYSTEMURLCOLINDEX = 10;
55+
}

tooling/src/main/java/org/opencds/cqf/tooling/terminology/SpreadsheetHelper.java

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
package org.opencds.cqf.tooling.terminology;
22

3+
import ca.uhn.fhir.context.FhirContext;
4+
import ca.uhn.fhir.parser.IParser;
35
import java.io.File;
46
import java.io.FileInputStream;
57
import java.io.FileOutputStream;
68
import java.io.IOException;
79
import java.util.Map;
810

9-
import org.apache.poi.ss.usermodel.Cell;
10-
import org.apache.poi.ss.usermodel.DataFormatter;
11-
import org.apache.poi.ss.usermodel.Row;
12-
import org.apache.poi.ss.usermodel.Workbook;
11+
import org.apache.poi.ss.usermodel.*;
1312
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
14-
15-
import ca.uhn.fhir.context.FhirContext;
16-
import ca.uhn.fhir.parser.IParser;
1713
import org.opencds.cqf.tooling.utilities.IOUtils;
1814

1915
public class SpreadsheetHelper {
@@ -29,19 +25,17 @@ public static Workbook getWorkbook(String pathToSpreadsheet) {
2925

3026
private static String cleanseString(String rawValue) {
3127
StringBuilder newString = new StringBuilder(rawValue.length());
32-
for (int offset = 0; offset < rawValue.length();)
33-
{
28+
for (int offset = 0; offset < rawValue.length(); ) {
3429
int codePoint = rawValue.codePointAt(offset);
3530
offset += Character.charCount(codePoint);
3631

3732
// Replace invisible control characters and unused code points
38-
switch (Character.getType(codePoint))
39-
{
40-
case Character.CONTROL: // \p{Cc}
41-
case Character.FORMAT: // \p{Cf}
33+
switch (Character.getType(codePoint)) {
34+
case Character.CONTROL: // \p{Cc}
35+
case Character.FORMAT: // \p{Cf}
4236
case Character.PRIVATE_USE: // \p{Co}
43-
case Character.SURROGATE: // \p{Cs}
44-
case Character.UNASSIGNED: // \p{Cn}
37+
case Character.SURROGATE: // \p{Cs}
38+
case Character.UNASSIGNED: // \p{Cn}
4539
newString.append('?');
4640
break;
4741
default:
@@ -54,20 +48,18 @@ private static String cleanseString(String rawValue) {
5448

5549
private static String cleanseStringNoReplacement(String rawValue) {
5650
StringBuilder newString = new StringBuilder(rawValue.length());
57-
for (int offset = 0; offset < rawValue.length();)
58-
{
51+
for (int offset = 0; offset < rawValue.length(); ) {
5952
int codePoint = rawValue.codePointAt(offset);
6053
offset += Character.charCount(codePoint);
6154

6255
// Replace invisible control characters and unused code points
63-
switch (Character.getType(codePoint))
64-
{
65-
case Character.CONTROL: // \p{Cc}
66-
case Character.FORMAT: // \p{Cf}
56+
switch (Character.getType(codePoint)) {
57+
case Character.CONTROL: // \p{Cc}
58+
case Character.FORMAT: // \p{Cf}
6759
case Character.PRIVATE_USE: // \p{Co}
68-
case Character.SURROGATE: // \p{Cs}
69-
case Character.UNASSIGNED: // \p{Cn}
70-
//just skip it
60+
case Character.SURROGATE: // \p{Cs}
61+
case Character.UNASSIGNED: // \p{Cn}
62+
// just skip it
7163
break;
7264
default:
7365
newString.append(Character.toChars(codePoint));
@@ -83,12 +75,11 @@ public static String protectedString(String rawValue, boolean replace) {
8375
return result;
8476
}
8577
result = result.trim();
86-
if(replace) {
78+
if (replace) {
8779
result = result.replaceAll("\\p{Cntrl}", "?");
8880
result = result.replaceAll("\\p{C}", "?");
8981
result = SpreadsheetHelper.cleanseString(result);
90-
}
91-
else{
82+
} else {
9283
result = result.replaceAll("\\p{Cntrl}", "");
9384
result = result.replaceAll("\\p{C}", "");
9485
result = SpreadsheetHelper.cleanseStringNoReplacement(result);
@@ -97,6 +88,7 @@ public static String protectedString(String rawValue, boolean replace) {
9788
}
9889

9990
private static DataFormatter dataFormatter;
91+
10092
public static DataFormatter getDataFormatter() {
10193
if (dataFormatter == null) {
10294
dataFormatter = new DataFormatter();
@@ -137,7 +129,25 @@ public static String getCellAsString(Row row, int cellIndex) {
137129
return null;
138130
}
139131

140-
//name.matches('[A-Z]([A-Za-z0-9_]){0,254}')
132+
public static String getCellAsStringEmptyForNull(Cell cell, FormulaEvaluator evaluator) {
133+
if (cell == null) return "";
134+
135+
DataFormatter formatter = SpreadsheetHelper.getDataFormatter();
136+
String raw = (evaluator == null) ? formatter.formatCellValue(cell) : formatter.formatCellValue(cell, evaluator);
137+
138+
// Normalize NBSP/newlines and trim to empty
139+
if (raw == null) return "";
140+
return raw.replace("\n", " ").replace('\u00A0', ' ').trim();
141+
}
142+
143+
public static String getCellAsStringEmptyForNull(Row row, int cellIndex, FormulaEvaluator evaluator) {
144+
if (row == null || cellIndex < 0) return "";
145+
// create a blank cell if missing so we never return null
146+
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
147+
return getCellAsStringEmptyForNull(cell, evaluator);
148+
}
149+
150+
// name.matches('[A-Z]([A-Za-z0-9_]){0,254}')
141151
public static String getFHIRName(String value) {
142152
String name = value.replaceAll("[^A-Za-z0-9_]", "");
143153
while (name.length() > 0 && !Character.isAlphabetic(name.charAt(0))) {
@@ -151,18 +161,23 @@ public static String getFHIRName(String value) {
151161
public static void resolveValueSet(org.hl7.fhir.dstu3.model.ValueSet vs, Map<Integer, ValueSet> codesBySystem) {
152162
vs.setCompose(new org.hl7.fhir.dstu3.model.ValueSet.ValueSetComposeComponent());
153163
for (Map.Entry<Integer, org.opencds.cqf.tooling.terminology.ValueSet> entry : codesBySystem.entrySet()) {
154-
org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent component = new org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent();
155-
component.setSystem(entry.getValue().getSystem()).setVersion(entry.getValue().getVersion()).setConcept(entry.getValue().getCodes());
164+
org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent component =
165+
new org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent();
166+
component
167+
.setSystem(entry.getValue().getSystem())
168+
.setVersion(entry.getValue().getVersion())
169+
.setConcept(entry.getValue().getCodes());
156170
vs.setCompose(vs.getCompose().addInclude(component));
157171
}
158172
}
159173

160174
public static void writeValueSetToFile(org.hl7.fhir.dstu3.model.ValueSet vs, String encoding, String outputPath) {
161-
String fileName = vs.getTitle() != null ? vs.getTitle().replaceAll("\\s", "").concat("." + encoding) : "valueset".concat("." + encoding);
162-
IParser parser =
163-
encoding == null
164-
? FhirContext.forDstu3Cached().newJsonParser()
165-
: encoding.toLowerCase().startsWith("j")
175+
String fileName = vs.getTitle() != null
176+
? vs.getTitle().replaceAll("\\s", "").concat("." + encoding)
177+
: "valueset".concat("." + encoding);
178+
IParser parser = encoding == null
179+
? FhirContext.forDstu3Cached().newJsonParser()
180+
: encoding.toLowerCase().startsWith("j")
166181
? FhirContext.forDstu3Cached().newJsonParser()
167182
: FhirContext.forDstu3Cached().newXmlParser();
168183
try (FileOutputStream writer = new FileOutputStream(IOUtils.concatFilePath(outputPath, fileName))) {

0 commit comments

Comments
 (0)