Merge pull request #7 from fhircat/ShExGenerator_R5_2023
ShEx Generator Updates for FHIR R5 Spec
This commit is contained in:
commit
d76f953e23
|
@ -50,6 +50,13 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- ShEx -->
|
||||
<dependency>
|
||||
<groupId>es.weso</groupId>
|
||||
<artifactId>shexs_2.12</artifactId>
|
||||
<version>0.2.31</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON Parsers -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,168 @@
|
|||
package org.hl7.fhir.r5.test;
|
||||
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ShexGeneratorTestUtils {
|
||||
public class resDef {
|
||||
public String name;
|
||||
public String url;
|
||||
public String info;
|
||||
|
||||
public resDef(String _name, String _url, String _info){
|
||||
this.name = _name;
|
||||
this.url = _url;
|
||||
this.info = _info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return " " + name + "[ " + url + " ] ";
|
||||
}
|
||||
}
|
||||
|
||||
public enum RESOURCE_CATEGORY{
|
||||
LOGICAL_NAMES, STRUCTURE_DEFINITIONS, EXTENSIONS, PROFILES, ALL
|
||||
}
|
||||
public List<resDef> getSDs(List<StructureDefinition> sds, RESOURCE_CATEGORY cat) {
|
||||
List<resDef> selSDs = new ArrayList<resDef>();
|
||||
sds.forEach((StructureDefinition sd) -> {
|
||||
switch(cat) {
|
||||
case STRUCTURE_DEFINITIONS:
|
||||
if (sd.getType().trim().equals(sd.getName().trim()))
|
||||
selSDs.add(new resDef(sd.getName(), sd.getUrl(), getSDInfo(sd)));
|
||||
break;
|
||||
case LOGICAL_NAMES:
|
||||
if (sd.getBaseDefinition() == null)
|
||||
selSDs.add(new resDef(sd.getName(), sd.getUrl(), getSDInfo(sd)));
|
||||
break;
|
||||
case EXTENSIONS:
|
||||
if ("Extension".equals(sd.getType()))
|
||||
selSDs.add(new resDef(sd.getName(), sd.getUrl(), getSDInfo(sd)));
|
||||
break;
|
||||
case PROFILES:
|
||||
if (!((sd.getBaseDefinition() == null) ||
|
||||
("Extension".equals(sd.getType())) ||
|
||||
(sd.getType().trim().equals(sd.getName().trim()))))
|
||||
selSDs.add(new resDef(sd.getName(), sd.getUrl(), getSDInfo(sd)));
|
||||
break;
|
||||
default:
|
||||
selSDs.add(new resDef(sd.getName(), sd.getUrl(), getSDInfo(sd)));
|
||||
}
|
||||
});
|
||||
|
||||
Collections.sort(selSDs, new Comparator<resDef>() {
|
||||
@Override
|
||||
public int compare(resDef o1, resDef o2) {
|
||||
return o1.name.compareTo(o2.name);
|
||||
}
|
||||
});
|
||||
|
||||
return selSDs;
|
||||
}
|
||||
public static List<String> getMetaStructureDefinitionsToSkip(){
|
||||
List<String> skipSDs = new ArrayList<String>();
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ActivityDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/AdministrableProductDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ChargeItemDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ClinicalUseDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/CodeSystem");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ConceptMap");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/CompartmentDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/CompartmentDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/DeviceDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ElementDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/EventDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/GraphDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/GuidanceResponse");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/Library");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ManufacturedItemDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/Measure");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/MeasureReport");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/MedicinalProductDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/MessageDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/NamingSystem");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ObservationDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/OperationDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/PackagedProductDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ParameterDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/PlanDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/SearchParameter");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/SpecimenDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/StructureDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/SubstanceDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/Task");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/TerminologyCapabilities");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/TriggerDefinition");
|
||||
skipSDs.add("http://hl7.org/fhir/StructureDefinition/ValueSet");
|
||||
return skipSDs;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method prepares selected extensions to test the policy in which ShEx Generator
|
||||
* only translates selected resource extensions
|
||||
* @return List<String> List of selected resource extensions for testing
|
||||
*/
|
||||
public static List<String> getSelectedExtensions(){
|
||||
List<String> selectedExtesnsions = new ArrayList<String>();
|
||||
selectedExtesnsions.add("http://fhir-registry.smarthealthit.org/StructureDefinition/capabilities");
|
||||
selectedExtesnsions.add("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
|
||||
return selectedExtesnsions;
|
||||
}
|
||||
|
||||
public static String getSDInfo(StructureDefinition sd) {
|
||||
if (sd != null) {
|
||||
String kind = " ";
|
||||
try {
|
||||
kind = sd.getKind().name();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Kind is null");
|
||||
}
|
||||
String name = " ";
|
||||
try {
|
||||
name = sd.getName();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Name is null");
|
||||
}
|
||||
String type = " ";
|
||||
try {
|
||||
type = sd.getType();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Type is null");
|
||||
}
|
||||
String derv = " ";
|
||||
try {
|
||||
derv = sd.getDerivation().name();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Derivation is null");
|
||||
}
|
||||
String url = " ";
|
||||
try {
|
||||
url = sd.getUrl();
|
||||
} catch (Exception e) {
|
||||
System.out.println("URL is null");
|
||||
}
|
||||
String base = " ";
|
||||
try {
|
||||
base = sd.getBaseDefinition();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Base is null");
|
||||
}
|
||||
return kind + "\t" + name + "\t" + type + "\t" + derv + "\t" + url + "\t" + base;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void printList(String title, List<ShexGeneratorTestUtils.resDef> items) {
|
||||
System.out.println("************************************************************************");
|
||||
System.out.println("Printing " + title);
|
||||
System.out.println("************************************************************************");
|
||||
items.forEach((resDef item) -> {
|
||||
System.out.println(item.name + " [" + item.url + "]");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,18 +4,37 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import es.weso.shex.Schema;
|
||||
import es.weso.shex.validator.ShExsValidator;
|
||||
import es.weso.shex.validator.ShExsValidatorBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.fhir.ucum.UcumException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.conformance.ShExGenerator;
|
||||
import org.hl7.fhir.r5.conformance.ShExGenerator.HTMLLinkPolicy;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hl7.fhir.r5.test.ShexGeneratorTestUtils.printList;
|
||||
|
||||
public class ShexGeneratorTests {
|
||||
public static List<String> selectedExtesnsions = new ArrayList<String>();
|
||||
|
||||
public ShExGenerator shexGenerator;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
}
|
||||
|
||||
private void doTest(String name) throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
StructureDefinition sd = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
|
||||
|
@ -24,8 +43,11 @@ public class ShexGeneratorTests {
|
|||
}
|
||||
Path outPath = FileSystems.getDefault().getPath(System.getProperty("java.io.tmpdir"), name.toLowerCase() + ".shex");
|
||||
TextFile.stringToFile(new ShExGenerator(TestingUtilities.getSharedWorkerContext()).generate(HTMLLinkPolicy.NONE, sd), outPath.toString());
|
||||
}
|
||||
|
||||
// For Testing Schema Processing and Constraint Mapping related Development
|
||||
// If you un-comment the following lines, please comment all other lines in this method.
|
||||
//this.doTestThis(name.toLowerCase(), name, false, ShExGenerator.ConstraintTranslationPolicy.ALL, false, true);
|
||||
}
|
||||
@Test
|
||||
public void testId() throws FHIRException, IOException, UcumException {
|
||||
doTest("id");
|
||||
|
@ -75,4 +97,193 @@ public class ShexGeneratorTests {
|
|||
public void testSignature() throws FHIRException, IOException, UcumException {
|
||||
doTest("Signature");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws FHIRException, IOException, UcumException {
|
||||
doTest("string");
|
||||
}
|
||||
|
||||
private void doTestThis(String shortName, String name, boolean useSelectedExtensions, ShExGenerator.ConstraintTranslationPolicy policy, boolean debugMode, boolean validateShEx) {
|
||||
IWorkerContext ctx = TestingUtilities.getSharedWorkerContext();
|
||||
StructureDefinition sd = ctx.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
|
||||
if (sd == null) {
|
||||
throw new FHIRException("StructuredDefinition for " + name + " was null");
|
||||
}
|
||||
//Path outPath = FileSystems.getDefault().getPath(System.getProperty("java.io.tmpdir"), name.toLowerCase() + ".shex");
|
||||
Path outPath = FileSystems.getDefault().getPath(System.getProperty("user.home") + "/runtime_environments/ShExSchemas", shortName + ".shex");
|
||||
try {
|
||||
this.shexGenerator = new ShExGenerator(ctx);
|
||||
|
||||
this.shexGenerator.debugMode = debugMode;
|
||||
this.shexGenerator.constraintPolicy = policy;
|
||||
|
||||
// ShEx Generator skips resources which are at Meta level of FHIR Resource definitions
|
||||
this.shexGenerator.setExcludedStructureDefinitionUrls(
|
||||
ShexGeneratorTestUtils.getMetaStructureDefinitionsToSkip());
|
||||
|
||||
// when ShEx translates only selected resource extensions
|
||||
if (useSelectedExtensions) {
|
||||
List<StructureDefinition> selExtns = new ArrayList<StructureDefinition>();
|
||||
for (String eUrl : ShexGeneratorTestUtils.getSelectedExtensions()) {
|
||||
StructureDefinition esd = ctx.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(eUrl, null));
|
||||
if (esd != null)
|
||||
selExtns.add(esd);
|
||||
}
|
||||
this.shexGenerator.setSelectedExtension(selExtns);
|
||||
}
|
||||
|
||||
String schema = this.shexGenerator.generate(HTMLLinkPolicy.NONE, sd);
|
||||
if (!schema.isEmpty()) {
|
||||
|
||||
if (validateShEx) {
|
||||
try {
|
||||
ShExsValidator validator = ShExsValidatorBuilder.fromStringSync(schema, "ShexC");
|
||||
Schema sch = validator.schema();
|
||||
|
||||
Assert.assertNotNull(sch);
|
||||
System.out.println("VALIDATION PASSED for ShEx Schema " + sd.getName());
|
||||
} catch (Exception e) {
|
||||
System.out.println("VALIDATION FAILED for ShEx Schema " + sd.getName());
|
||||
//System.out.println("\t\t\tMessage: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
TextFile.stringToFile(schema, outPath.toString());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void doTestAll() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.ALL, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process all extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL
|
||||
// Process all types of constraints, do not skip
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void doTestGenericExtensionsOnlyPolicy() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.ALL, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process all extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.GENERIC_ONLY
|
||||
// Process generic constraints only, ignore constraints of type 'context of use'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void doTestContextOfUseExtensionsOnlyPolicy() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.ALL, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process all extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.CONTEXT_OF_USE_ONLY
|
||||
// Process constraints only where context of use found, skip otherwise
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void doTestSelectedExtensions() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.ALL, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
true, //Process only given/selected extensions, ignore other extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL // Process all type of constraints
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testStructureDefinitionsOnly() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.STRUCTURE_DEFINITIONS, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process only given/selected extensions, ignore other extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL // Process all type of constraints
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testExtensionsOnly() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.EXTENSIONS, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process only given/selected extensions, ignore other extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL // Process all type of constraints
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testLogicalNamesOnly() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.LOGICAL_NAMES, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process only given/selected extensions, ignore other extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL // Process all type of constraints
|
||||
);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testProfilesOnly() throws FileNotFoundException, IOException, FHIRException, UcumException {
|
||||
List<StructureDefinition> sds = TestingUtilities.getSharedWorkerContext().fetchResourcesByType(StructureDefinition.class);
|
||||
processSDList(
|
||||
ShexGeneratorTestUtils.RESOURCE_CATEGORY.PROFILES, // Processing All kinds of Structure Definitions
|
||||
sds, // List of Structure Definitions
|
||||
false, //Process only given/selected extensions, ignore other extensions
|
||||
ShExGenerator.ConstraintTranslationPolicy.ALL // Process all type of constraints
|
||||
);
|
||||
}
|
||||
|
||||
private void processSDList(ShexGeneratorTestUtils.RESOURCE_CATEGORY cat,
|
||||
List<StructureDefinition> sds,
|
||||
boolean useSelectedExtensions,
|
||||
ShExGenerator.ConstraintTranslationPolicy policy) {
|
||||
if ((sds == null) || (sds.isEmpty())) {
|
||||
throw new FHIRException("No StructuredDefinition found!");
|
||||
}
|
||||
|
||||
ShexGeneratorTestUtils shexTestUtils = new ShexGeneratorTestUtils();
|
||||
List<ShexGeneratorTestUtils.resDef> sdDefs = shexTestUtils.getSDs(sds, cat);
|
||||
|
||||
printList(cat.toString(), sdDefs);
|
||||
System.out.println("************************************************************************");
|
||||
System.out.println("Processing " + cat);
|
||||
System.out.println("************************************************************************");
|
||||
|
||||
sdDefs.forEach((ShexGeneratorTestUtils.resDef resDef) -> {
|
||||
String name = resDef.url;
|
||||
if (resDef.url.indexOf("/") != -1) {
|
||||
String els[] = resDef.url.split("/");
|
||||
name = els[els.length - 1];
|
||||
}
|
||||
System.out.println("******************** " + resDef + " *********************");
|
||||
doTestThis(name, resDef.url, useSelectedExtensions, policy, true, true);
|
||||
});
|
||||
|
||||
System.out.println("************************ END PROCESSING ******************************");
|
||||
|
||||
System.out.println("************************************************************************");
|
||||
List<String> skipped = this.shexGenerator.getExcludedStructureDefinitionUrls();
|
||||
System.out.println("Total Items processed: " + sds.size());
|
||||
System.out.println("************************************************************************");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue