Skip to content

Commit

Permalink
Update randomCode fn to take output type as an optional second param
Browse files Browse the repository at this point in the history
  • Loading branch information
dehall committed Nov 8, 2024
1 parent 2cc0a62 commit e83ae2f
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 10 deletions.
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 @@ private static Object getValue(Bundle bundle, String valueDef, Resource currentR
} 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 @@ private static Base findValue(Bundle bundle, String... args) {
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 @@ private static synchronized void expandValueSet(String valueSetUri) {
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

0 comments on commit e83ae2f

Please sign in to comment.