Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexporter - Update randomCode fn to take output type as an optional second param #1527

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/mitre/synthea/export/FhirR4.java
Original file line number Diff line number Diff line change
Expand Up @@ -3385,7 +3385,7 @@ private static Type convertFhirDateTime(long datetime, boolean time) {
* @param system The system identifier, such as a URI. Optional; may be null.
* @return The converted CodeableConcept
*/
private static CodeableConcept mapCodeToCodeableConcept(Code from, String system) {
public static CodeableConcept mapCodeToCodeableConcept(Code from, String system) {
CodeableConcept to = new CodeableConcept();
system = system == null ? null : ExportHelper.getSystemURI(system);
from.system = ExportHelper.getSystemURI(from.system);
Expand Down
24 changes: 17 additions & 7 deletions src/main/java/org/mitre/synthea/export/flexporter/Actions.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.DateTimeType;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.Meta;
Expand Down Expand Up @@ -822,7 +823,7 @@
} else if (flag.equals("getAttribute")) {
return getAttribute(person, flagValues);
} else if (flag.equals("randomCode")) {
return randomCode(flagValues[0]);
return randomCode(flagValues);
}

return null;
Expand Down Expand Up @@ -900,13 +901,22 @@
return fieldValues.get(0);
}

private static Map<String, String> randomCode(String valueSetUrl) {
private static Object randomCode(String... args) {
String valueSetUrl = args[0];
String outputType = (args.length > 1) ? args[1] : "Coding";
Code code = RandomCodeGenerator.getCode(valueSetUrl,
(int) (Math.random() * Integer.MAX_VALUE));
Map<String, String> codeAsMap = Map.of(
"system", code.system,
"code", code.code,
"display", code.display == null ? "" : code.display);
return codeAsMap;

if (outputType.equalsIgnoreCase("code")) {
return code.code;
} else if (outputType.equalsIgnoreCase("Coding")) {
return new Coding(code.system, code.code, code.display);
} else if (outputType.equalsIgnoreCase("CodeableConcept")) {
return FhirR4.mapCodeToCodeableConcept(code, null);
} else {
throw new IllegalArgumentException("Unexpected output type for randomCode: " + outputType

Check warning on line 917 in src/main/java/org/mitre/synthea/export/flexporter/Actions.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/mitre/synthea/export/flexporter/Actions.java#L917

Added line #L917 was not covered by tests
+ ". Valid values are: code, Coding, CodeableConcept");
}

}
}
23 changes: 21 additions & 2 deletions src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import okhttp3.ResponseBody;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.routines.UrlValidator;
import org.hl7.fhir.r4.model.OperationOutcome;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.r4.model.ValueSet.ConceptReferenceComponent;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
Expand Down Expand Up @@ -117,8 +119,25 @@
ResponseBody body = response.body();
if (body != null) {
IParser parser = FhirR4.getContext().newJsonParser();
ValueSet valueSet = (ValueSet) parser.parseResource(body.charStream());
loadValueSet(valueSetUri, valueSet);
Resource resource = (Resource) parser.parseResource(body.charStream());
if (resource instanceof ValueSet) {
loadValueSet(valueSetUri, (ValueSet)resource);
} else if (resource instanceof OperationOutcome) {
OperationOutcome oo = (OperationOutcome)resource;
parser.setPrettyPrint(true);
System.err.println(parser.encodeResourceToString(oo));
String details = oo.getIssueFirstRep().getDetails().getText();

Check warning on line 129 in src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java#L126-L129

Added lines #L126 - L129 were not covered by tests

throw new RuntimeException(

Check warning on line 131 in src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java#L131

Added line #L131 was not covered by tests
"Received OperationOutcome in ValueSet expand response. Detail: "
+ details + ". See log for full resource");
} else {
parser.setPrettyPrint(true);
System.err.println(parser.encodeResourceToString(resource));
throw new RuntimeException(

Check warning on line 137 in src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java#L135-L137

Added lines #L135 - L137 were not covered by tests
"Unexpected resourceType received in expand ValueSet response: "
+ resource.getResourceType() + ". See log for full resource");

Check warning on line 139 in src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/mitre/synthea/helpers/RandomCodeGenerator.java#L139

Added line #L139 was not covered by tests
}
} else {
throw new RuntimeException("Value Set Expansion contained no body");
}
Expand Down
64 changes: 64 additions & 0 deletions src/test/java/org/mitre/synthea/export/flexporter/ActionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@
import org.hl7.fhir.r4.model.ServiceRequest;
import org.hl7.fhir.r4.model.TimeType;
import org.hl7.fhir.r4.model.Type;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mitre.synthea.engine.Module;
import org.mitre.synthea.engine.State;
import org.mitre.synthea.export.FhirR4;
import org.mitre.synthea.helpers.RandomCodeGenerator;
import org.mitre.synthea.world.agents.Person;

public class ActionsTest {
Expand Down Expand Up @@ -817,4 +820,65 @@ public void testGetAttribute() throws Exception {
assertEquals("Robert Rainbow", name.getText());
}

@Test
public void testRandomCode() {
Bundle b = new Bundle();
b.setType(BundleType.COLLECTION);

ValueSet statusVs = constructValueSet(
"http://hl7.org/fhir/encounter-status",
"planned", "finished", "cancelled");
RandomCodeGenerator.loadValueSet("http://example.org/encounterStatus", statusVs);

ValueSet classVs = constructValueSet(
"http://terminology.hl7.org/CodeSystem/v3-ActCode",
"AMB", "EMER", "ACUTE");
RandomCodeGenerator.loadValueSet("http://example.org/encounterClass", classVs);

ValueSet typeVs = constructValueSet(
"http://terminology.hl7.org/CodeSystem/encounter-type",
"ADMS", "OKI");
RandomCodeGenerator.loadValueSet("http://example.org/encounterType", typeVs);

Map<String, Object> action = getActionByName("testRandomCode");
Actions.applyAction(b, action, null, null);

Encounter e = (Encounter) b.getEntryFirstRep().getResource();

Encounter.EncounterStatus status = e.getStatus();
assertNotNull(status);
assertTrue(status == Encounter.EncounterStatus.PLANNED
|| status == Encounter.EncounterStatus.FINISHED
|| status == Encounter.EncounterStatus.CANCELLED);

Coding encClass = e.getClass_();
assertNotNull(encClass);
assertEquals("http://terminology.hl7.org/CodeSystem/v3-ActCode", encClass.getSystem());
String code = encClass.getCode();
assertTrue(code.equals("AMB") || code.equals("EMER") || code.equals("ACUTE"));

CodeableConcept type = e.getTypeFirstRep();
assertNotNull(type);
Coding typeCoding = type.getCodingFirstRep();
assertNotNull(typeCoding);
assertEquals("http://terminology.hl7.org/CodeSystem/encounter-type", typeCoding.getSystem());
code = typeCoding.getCode();
assertTrue(code.equals("ADMS") || code.equals("OKI"));
}

private ValueSet constructValueSet(String system, String... codes) {
ValueSet vs = new ValueSet();

// populates the codes so that they can be read in RandomCodeGenerator.loadValueSet
ConceptSetComponent csc = new ConceptSetComponent();
csc.setSystem(system);
for (String code : codes) {
csc.addConcept().setCode(code).setDisplay(code);
}

vs.getCompose().getInclude().add(csc);

return vs;
}

}
11 changes: 11 additions & 0 deletions src/test/resources/flexporter/test_mapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ actions:
location: ServiceRequest.authoredOn
value: $getField([Procedure.performed]) # datetime choice type

- name: testRandomCode
create_resource:
- resourceType: Encounter
fields:
- location: Encounter.status
value: $randomCode([http://example.org/encounterStatus,code])
- location: Encounter.class
value: $randomCode([http://example.org/encounterClass])
- location: Encounter.type
value: $randomCode([http://example.org/encounterType,CodeableConcept])


- name: testExecuteScript
execute_script:
Expand Down
Loading