Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core
This commit is contained in:
commit
b5602e79fd
|
@ -1,7 +1,27 @@
|
||||||
## Validator Changes
|
## Validator Changes
|
||||||
|
|
||||||
* no changes
|
* fix NPE in validator around Extension context
|
||||||
|
* Handle secondary terminology server errors properly
|
||||||
|
* Fix questionnaire response status checking
|
||||||
|
* Add versions to message about multiple matching profiles
|
||||||
|
* hide API-Key from appearing on the tx log
|
||||||
|
* Add supplements for used systems as well as for value set systems when validating on server
|
||||||
|
* fix missing port from server when doing tx-registry redirections
|
||||||
|
|
||||||
## Other code changes
|
## Other code changes
|
||||||
|
|
||||||
* no changes
|
* New release of pubpack
|
||||||
|
* Fix r4b liquid tests
|
||||||
|
* Refactor Liquid engine and add support for forLoop and capture
|
||||||
|
* Add support for liquid on csv files
|
||||||
|
* Add support for using Liquid on plain JSON directly and add support for markdownify filter
|
||||||
|
* Many improvements to Profile Code Generation
|
||||||
|
* Start working on using new IG infrastructure for Tx tests
|
||||||
|
* Questionnaire rendering improvements
|
||||||
|
* Merge Functionality for CapabilityStatement.import
|
||||||
|
* Do not use metadata from data type profiles on elements when generating snapshots
|
||||||
|
* Fix presentation issues and union and intersection links in previous version comparison
|
||||||
|
* Fix filter comparison logic when comparing valuesets
|
||||||
|
* Fix version issues in snapshot generation tests
|
||||||
|
* Eliminate id from snapshot generation test case comparison
|
||||||
|
* Change rules around stripping extensions when generating snapshots
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
@ -2,6 +2,7 @@ package org.hl7.fhir.convertors.loaders;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
|
||||||
|
@ -9,6 +10,7 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.VersionUtilities;
|
import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
|
@ -53,4 +55,52 @@ public class XVersionLoader {
|
||||||
throw new FHIRException("Unknown version " + version + " loading resource");
|
throw new FHIRException("Unknown version " + version + " loading resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void saveXml(String version, Resource resource, OutputStream stream) throws FHIRFormatError, IOException {
|
||||||
|
if (Utilities.noString(version)) {
|
||||||
|
new org.hl7.fhir.r5.formats.XmlParser().compose(stream, resource, true);
|
||||||
|
}
|
||||||
|
switch (VersionUtilities.getMajMin(version)) {
|
||||||
|
case "1.0":
|
||||||
|
new org.hl7.fhir.dstu2.formats.XmlParser().compose(stream, VersionConvertorFactory_10_50.convertResource(resource), true);
|
||||||
|
return;
|
||||||
|
case "1.4":
|
||||||
|
new org.hl7.fhir.dstu2016may.formats.XmlParser().compose(stream, VersionConvertorFactory_14_50.convertResource(resource), true);
|
||||||
|
return;
|
||||||
|
case "3.0":
|
||||||
|
new org.hl7.fhir.dstu3.formats.XmlParser().compose(stream, VersionConvertorFactory_30_50.convertResource(resource), true);
|
||||||
|
return;
|
||||||
|
case "4.0":
|
||||||
|
new org.hl7.fhir.r4.formats.XmlParser().compose(stream, VersionConvertorFactory_40_50.convertResource(resource), true);
|
||||||
|
return;
|
||||||
|
case "5.0":
|
||||||
|
new org.hl7.fhir.r5.formats.XmlParser().compose(stream, resource, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new FHIRException("Unknown version " + version + " loading resource");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveJson(String version, Resource resource, OutputStream stream) throws FHIRException, IOException {
|
||||||
|
if (Utilities.noString(version)) {
|
||||||
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(stream, resource);
|
||||||
|
}
|
||||||
|
switch (VersionUtilities.getMajMin(version)) {
|
||||||
|
case "1.0":
|
||||||
|
new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(stream, VersionConvertorFactory_10_50.convertResource(resource));
|
||||||
|
return;
|
||||||
|
case "1.4":
|
||||||
|
new org.hl7.fhir.dstu2016may.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY).compose(stream, VersionConvertorFactory_14_50.convertResource(resource));
|
||||||
|
return;
|
||||||
|
case "3.0":
|
||||||
|
new org.hl7.fhir.dstu3.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu3.formats.IParser.OutputStyle.PRETTY).compose(stream, VersionConvertorFactory_30_50.convertResource(resource));
|
||||||
|
return;
|
||||||
|
case "4.0":
|
||||||
|
new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).compose(stream, VersionConvertorFactory_40_50.convertResource(resource));
|
||||||
|
return;
|
||||||
|
case "5.0":
|
||||||
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(org.hl7.fhir.r5.formats.IParser.OutputStyle.PRETTY).compose(stream, resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new FHIRException("Unknown version " + version + " loading resource");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,7 +439,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
||||||
try {
|
try {
|
||||||
feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException("An error has occurred while trying to retrieve history since last update", e);
|
handleException("An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -714,7 +714,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
||||||
try {
|
try {
|
||||||
feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException("An error has occurred while trying to retrieve history since last update", e);
|
handleException("An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,7 +413,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
||||||
try {
|
try {
|
||||||
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException("An error has occurred while trying to retrieve history since last update", e);
|
handleException("An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ package org.hl7.fhir.r4.profilemodel;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
@ -352,6 +354,7 @@ public class PEBuilder {
|
||||||
list = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
|
list = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
|
||||||
}
|
}
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
|
Set<String> names = new HashSet<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < list.size()) {
|
while (i < list.size()) {
|
||||||
ElementDefinition defn = list.get(i);
|
ElementDefinition defn = list.get(i);
|
||||||
|
@ -361,7 +364,8 @@ public class PEBuilder {
|
||||||
// DebugUtilities.breakpoint();
|
// DebugUtilities.breakpoint();
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
PEDefinitionElement pe = new PEDefinitionElement(this, profile, defn, parent.path());
|
String name = uniquefy(names, defn.getName());
|
||||||
|
PEDefinitionElement pe = new PEDefinitionElement(this, name, profile, defn, parent.path());
|
||||||
pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
|
pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
|
||||||
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
||||||
pe.setMustHaveValue(definition.getMustHaveValue());
|
pe.setMustHaveValue(definition.getMustHaveValue());
|
||||||
|
@ -376,14 +380,14 @@ public class PEBuilder {
|
||||||
while (i < list.size() && list.get(i).getPath().equals(defn.getPath())) {
|
while (i < list.size() && list.get(i).getPath().equals(defn.getPath())) {
|
||||||
StructureDefinition ext = getExtensionDefinition(list.get(i));
|
StructureDefinition ext = getExtensionDefinition(list.get(i));
|
||||||
if (ext != null) {
|
if (ext != null) {
|
||||||
res.add(new PEDefinitionExtension(this, list.get(i).getSliceName(), profile, list.get(i), defn, ext, parent.path()));
|
res.add(new PEDefinitionExtension(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, ext, parent.path()));
|
||||||
} else if (isTypeSlicing(defn)) {
|
} else if (isTypeSlicing(defn)) {
|
||||||
res.add(new PEDefinitionTypeSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn, parent.path()));
|
res.add(new PEDefinitionTypeSlice(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, parent.path()));
|
||||||
} else {
|
} else {
|
||||||
if (ProfileUtilities.isComplexExtension(profile) && defn.getPath().endsWith(".extension")) {
|
if (ProfileUtilities.isComplexExtension(profile) && defn.getPath().endsWith(".extension")) {
|
||||||
res.add(new PEDefinitionSubExtension(this, profile, list.get(i), parent.path()));
|
res.add(new PEDefinitionSubExtension(this, profile, list.get(i), parent.path()));
|
||||||
} else {
|
} else {
|
||||||
res.add(new PEDefinitionSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn, parent.path()));
|
res.add(new PEDefinitionSlice(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, parent.path()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -409,6 +413,18 @@ public class PEBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String uniquefy(Set<String> names, String name) {
|
||||||
|
if (names.contains(name)) {
|
||||||
|
int i = 0;
|
||||||
|
while (names.contains(name+i)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
name = name+i;
|
||||||
|
}
|
||||||
|
names.add(name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
protected PEDefinition makeChild(PEDefinition parent, StructureDefinition profileStructure, ElementDefinition definition) {
|
protected PEDefinition makeChild(PEDefinition parent, StructureDefinition profileStructure, ElementDefinition definition) {
|
||||||
PEDefinitionElement pe = new PEDefinitionElement(this, profileStructure, definition, parent.path());
|
PEDefinitionElement pe = new PEDefinitionElement(this, profileStructure, definition, parent.path());
|
||||||
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
||||||
|
|
|
@ -42,6 +42,10 @@ public class PEDefinitionElement extends PEDefinition {
|
||||||
super(builder, definition.getName(), profile, definition, ppath);
|
super(builder, definition.getName(), profile, definition, ppath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PEDefinitionElement(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition definition, String ppath) {
|
||||||
|
super(builder, name, profile, definition, ppath);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listTypes(List<PEType> types) {
|
public void listTypes(List<PEType> types) {
|
||||||
for (TypeRefComponent t : definition.getType()) {
|
for (TypeRefComponent t : definition.getType()) {
|
||||||
|
|
|
@ -30,15 +30,14 @@ package org.hl7.fhir.r4.profilemodel.gen;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import org.hl7.fhir.r4.context.IWorkerContext;
|
import org.hl7.fhir.r4.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r4.model.ElementDefinition;
|
import org.hl7.fhir.r4.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent;
|
import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||||
|
@ -48,34 +47,34 @@ import org.hl7.fhir.r4.model.Type;
|
||||||
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r4.profilemodel.PEBuilder;
|
import org.hl7.fhir.r4.profilemodel.PEBuilder;
|
||||||
import org.hl7.fhir.r4.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
import org.hl7.fhir.r4.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
||||||
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
|
||||||
import org.hl7.fhir.r4.profilemodel.PEDefinition;
|
import org.hl7.fhir.r4.profilemodel.PEDefinition;
|
||||||
import org.hl7.fhir.r4.profilemodel.PEType;
|
import org.hl7.fhir.r4.profilemodel.PEType;
|
||||||
|
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||||
import org.hl7.fhir.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The easiest way to generate code is to use the FHIR Validator, which can generate java classes for profiles
|
* The easiest way to generate code is to use the FHIR Validator, which can generate java classes for profiles
|
||||||
* using this code. Parameters:
|
* using this code. Parameters:
|
||||||
*
|
*
|
||||||
* -codegen -version r4 -ig hl7.fhir.dk.core#3.2.0 -profiles http://hl7.dk/fhir/core/StructureDefinition/dk-core-gln-identifier,http://hl7.dk/fhir/core/StructureDefinition/dk-core-patient -output /Users/grahamegrieve/temp/codegen -package-name org.hl7.fhir.test
|
* -codegen -version r4 -ig hl7.fhir.dk.core#3.2.0 -profiles http://hl7.dk/fhir/core/StructureDefinition/dk-core-gln-identifier,http://hl7.dk/fhir/core/StructureDefinition/dk-core-patient -output /Users/grahamegrieve/temp/codegen -package-name org.hl7.fhir.test
|
||||||
*
|
*
|
||||||
* Parameter Documentation:
|
* Parameter Documentation:
|
||||||
* -codegen: tells the validator to generate code
|
* -codegen: tells the validator to generate code
|
||||||
* -version {r4|5}: which version to generate for
|
* -version {r4|5}: which version to generate for
|
||||||
* -ig {name}: loads an IG (and it's dependencies) - see -ig documentation for the validator
|
* -ig {name}: loads an IG (and it's dependencies) - see -ig documentation for the validator
|
||||||
* -profiles {list}: a comma separated list of profile URLs to generate code for
|
* -profiles {list}: a comma separated list of profile URLs to generate code for
|
||||||
* -output {folder}: the folder where to generate the output java class source code
|
* -output {folder}: the folder where to generate the output java class source code
|
||||||
* -package-name {name}: the name of the java package to generate in
|
* -package-name {name}: the name of the java package to generate in
|
||||||
*
|
*
|
||||||
* options
|
* options
|
||||||
* -option {name}: a code generation option, one of:
|
* -option {name}: a code generation option, one of:
|
||||||
*
|
*
|
||||||
* narrative: generate code for the resource narrative (recommended: don't - leave that for the native resource level)
|
* narrative: generate code for the resource narrative (recommended: don't - leave that for the native resource level)
|
||||||
* meta: generate code the what's in meta
|
* meta: generate code the what's in meta
|
||||||
* contained: generate code for contained resources
|
* contained: generate code for contained resources
|
||||||
* all-elements: generate code for all elements, not just the key elements (makes the code verbose)
|
* all-elements: generate code for all elements, not just the key elements (makes the code verbose)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -87,12 +86,12 @@ public class PECodeGenerator {
|
||||||
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
return sdf.format(new Date());
|
return sdf.format(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum ExtensionPolicy {
|
public enum ExtensionPolicy {
|
||||||
None, Complexes, Primitives;
|
None, Complexes, Primitives;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PEGenClass {
|
private class PEGenClass {
|
||||||
private String name;
|
private String name;
|
||||||
private String base;
|
private String base;
|
||||||
|
@ -101,7 +100,7 @@ public class PECodeGenerator {
|
||||||
private boolean isResource;
|
private boolean isResource;
|
||||||
private Set<String> unfixed = new HashSet<>();
|
private Set<String> unfixed = new HashSet<>();
|
||||||
private Set<String> enumNames = new HashSet<>();
|
private Set<String> enumNames = new HashSet<>();
|
||||||
|
|
||||||
private StringBuilder inits = new StringBuilder();
|
private StringBuilder inits = new StringBuilder();
|
||||||
private StringBuilder fields = new StringBuilder();
|
private StringBuilder fields = new StringBuilder();
|
||||||
private StringBuilder enums = new StringBuilder();
|
private StringBuilder enums = new StringBuilder();
|
||||||
|
@ -114,7 +113,7 @@ public class PECodeGenerator {
|
||||||
public void genId() {
|
public void genId() {
|
||||||
if (isResource) {
|
if (isResource) {
|
||||||
genField(true, "id", "String", "id", "", false, "", 0, 1, null);
|
genField(true, "id", "String", "id", "", false, "", 0, 1, null);
|
||||||
genAccessors(true, false, "id", "id", "String", "", "String", "String", "Id", "Ids", false, "", false, false, null);
|
genAccessors(true, false, "id", "id", "String", "", "String", "String", "Id", "Ids", false, "", false, false, null);
|
||||||
genLoad(true, false, "id", "id", "id", "IdType", "", "String", "String", "Id", "Ids", false, false, null, false);
|
genLoad(true, false, "id", "id", "id", "IdType", "", "String", "String", "Id", "Ids", false, false, null, false);
|
||||||
genSave(true, false, "id", "id", "id", "IdType", "", "String", "String", "Id", "Ids", false, false, false, null, false);
|
genSave(true, false, "id", "id", "id", "IdType", "", "String", "String", "Id", "Ids", false, false, false, null, false);
|
||||||
genClear(false, "id", "String");
|
genClear(false, "id", "String");
|
||||||
|
@ -128,14 +127,14 @@ public class PECodeGenerator {
|
||||||
w(b, " */");
|
w(b, " */");
|
||||||
w(b);
|
w(b);
|
||||||
}
|
}
|
||||||
w(b, "// Generated by the HAPI Java Profile Generator, "+genDate);
|
w(b, "// Generated by the HAPI Java Profile Generator, "+genDate);
|
||||||
w(b);
|
w(b);
|
||||||
jdoc(b, doco, 0, true);
|
jdoc(b, doco, 0, true);
|
||||||
w(b, "public class "+name+" extends PEGeneratedBase {");
|
w(b, "public class "+name+" extends PEGeneratedBase {");
|
||||||
w(b);
|
w(b);
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
w(b, " public static final String CANONICAL_URL = \""+url+"\";");
|
w(b, " public static final String CANONICAL_URL = \""+url+"\";");
|
||||||
w(b);
|
w(b);
|
||||||
}
|
}
|
||||||
if (enums.length() > 0) {
|
if (enums.length() > 0) {
|
||||||
w(b, enums.toString());
|
w(b, enums.toString());
|
||||||
|
@ -172,7 +171,7 @@ public class PECodeGenerator {
|
||||||
w(b, " PEInstance src = builder.buildPEInstance(CANONICAL_URL, source);");
|
w(b, " PEInstance src = builder.buildPEInstance(CANONICAL_URL, source);");
|
||||||
w(b, " theThing.load(src);");
|
w(b, " theThing.load(src);");
|
||||||
w(b, " return theThing;");
|
w(b, " return theThing;");
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
w(b);
|
w(b);
|
||||||
} else {
|
} else {
|
||||||
jdoc(b, "Used when loading other models ", 2, true);
|
jdoc(b, "Used when loading other models ", 2, true);
|
||||||
|
@ -181,13 +180,13 @@ public class PECodeGenerator {
|
||||||
w(b, " theThing.workerContext = source.getContext();");
|
w(b, " theThing.workerContext = source.getContext();");
|
||||||
w(b, " theThing.load(source);");
|
w(b, " theThing.load(source);");
|
||||||
w(b, " return theThing;");
|
w(b, " return theThing;");
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
}
|
}
|
||||||
w(b);
|
w(b);
|
||||||
w(b, " public void load(PEInstance src) {");
|
w(b, " public void load(PEInstance src) {");
|
||||||
w(b, " clear();");
|
w(b, " clear();");
|
||||||
w(b, load.toString());
|
w(b, load.toString());
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
w(b);
|
w(b);
|
||||||
|
|
||||||
if (isResource) {
|
if (isResource) {
|
||||||
|
@ -201,7 +200,7 @@ public class PECodeGenerator {
|
||||||
w(b, " public "+base+" build() {");
|
w(b, " public "+base+" build() {");
|
||||||
w(b, " "+base+" theThing = new "+base+"();");
|
w(b, " "+base+" theThing = new "+base+"();");
|
||||||
w(b, " PEBuilder builder = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true);");
|
w(b, " PEBuilder builder = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true);");
|
||||||
w(b, " PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, theThing);");
|
w(b, " PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, theThing);");
|
||||||
w(b, " save(tgt, false);");
|
w(b, " save(tgt, false);");
|
||||||
w(b, " return theThing;");
|
w(b, " return theThing;");
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
|
@ -217,21 +216,21 @@ public class PECodeGenerator {
|
||||||
}
|
}
|
||||||
w(b, " public void save(PEInstance tgt, boolean nulls) {");
|
w(b, " public void save(PEInstance tgt, boolean nulls) {");
|
||||||
w(b, save.toString());
|
w(b, save.toString());
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
w(b);
|
w(b);
|
||||||
if (inits.length() > 0) {
|
if (inits.length() > 0) {
|
||||||
w(b, " private void initFixedValues() {");
|
w(b, " private void initFixedValues() {");
|
||||||
w(b, inits.toString());
|
w(b, inits.toString());
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
w(b);
|
w(b);
|
||||||
}
|
}
|
||||||
w(b, accessors.toString());
|
w(b, accessors.toString());
|
||||||
w(b);
|
w(b);
|
||||||
w(b, " public void clear() {");
|
w(b, " public void clear() {");
|
||||||
w(b, clear.toString());
|
w(b, clear.toString());
|
||||||
w(b, " }");
|
w(b, " }");
|
||||||
w(b);
|
w(b);
|
||||||
w(b, "}");
|
w(b, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateEnum(PEDefinition source, PEDefinition field) {
|
private String generateEnum(PEDefinition source, PEDefinition field) {
|
||||||
|
@ -241,9 +240,14 @@ public class PECodeGenerator {
|
||||||
org.hl7.fhir.r4.model.ValueSet vs = workerContext.fetchResource(org.hl7.fhir.r4.model.ValueSet.class, binding.getValueSet());
|
org.hl7.fhir.r4.model.ValueSet vs = workerContext.fetchResource(org.hl7.fhir.r4.model.ValueSet.class, binding.getValueSet());
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
ValueSetExpansionOutcome vse = workerContext.expandVS(vs, false, false);
|
ValueSetExpansionOutcome vse = workerContext.expandVS(vs, false, false);
|
||||||
|
Set<String> codes = new HashSet<>();
|
||||||
|
boolean hasDups = false;
|
||||||
if (vse.isOk()) {
|
if (vse.isOk()) {
|
||||||
String baseName = Utilities.nmtokenize(Utilities.singularise(vs.getName()));
|
String baseName = Utilities.nmtokenize(Utilities.singularise(vs.getName()));
|
||||||
String name = baseName;
|
String name = baseName;
|
||||||
|
if (workerContext.getResourceNames().contains(name)) {
|
||||||
|
name = name+"Type";
|
||||||
|
}
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while (enumNames.contains(name)) {
|
while (enumNames.contains(name)) {
|
||||||
c++;
|
c++;
|
||||||
|
@ -253,26 +257,40 @@ public class PECodeGenerator {
|
||||||
for (int i = 0; i < vse.getValueset().getExpansion().getContains().size(); i++) {
|
for (int i = 0; i < vse.getValueset().getExpansion().getContains().size(); i++) {
|
||||||
ValueSetExpansionContainsComponent cc = vse.getValueset().getExpansion().getContains().get(i);
|
ValueSetExpansionContainsComponent cc = vse.getValueset().getExpansion().getContains().get(i);
|
||||||
String code = Utilities.javaTokenize(cc.getCode(), true).toUpperCase();
|
String code = Utilities.javaTokenize(cc.getCode(), true).toUpperCase();
|
||||||
|
if (Utilities.isInteger(code)) {
|
||||||
|
code = "C_"+code;
|
||||||
|
}
|
||||||
if (cc.getAbstract()) {
|
if (cc.getAbstract()) {
|
||||||
code = "_"+code;
|
code = "_"+code;
|
||||||
}
|
}
|
||||||
|
if (codes.contains(code)) {
|
||||||
|
char sfx = 'A';
|
||||||
|
while (codes.contains(code+sfx)) {
|
||||||
|
sfx++;
|
||||||
|
}
|
||||||
|
code = code + sfx;
|
||||||
|
hasDups = true;
|
||||||
|
}
|
||||||
|
codes.add(code);
|
||||||
cc.setUserData("java.code", code);
|
cc.setUserData("java.code", code);
|
||||||
w(enums, " "+code+(i < vse.getValueset().getExpansion().getContains().size() - 1 ? "," : ";")+" // \""+cc.getDisplay()+"\" = "+cc.getSystem()+"#"+cc.getCode());
|
w(enums, " "+code+(i < vse.getValueset().getExpansion().getContains().size() - 1 ? "," : ";")+" // \""+cc.getDisplay()+"\" = "+cc.getSystem()+"#"+cc.getCode());
|
||||||
}
|
}
|
||||||
w(enums, "");
|
w(enums, "");
|
||||||
w(enums, " public static "+name+" fromCode(String s) {");
|
if (!hasDups) {
|
||||||
w(enums, " switch (s) {");
|
w(enums, " public static "+name+" fromCode(String s) {");
|
||||||
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
w(enums, " switch (s) {");
|
||||||
w(enums, " case \""+cc.getCode()+"\": return "+cc.getUserString("java.code")+";");
|
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
||||||
|
w(enums, " case \""+cc.getCode()+"\": return "+cc.getUserString("java.code")+";");
|
||||||
|
}
|
||||||
|
w(enums, " default: return null;");
|
||||||
|
w(enums, " }");
|
||||||
|
w(enums, " }");
|
||||||
|
w(enums, "");
|
||||||
}
|
}
|
||||||
w(enums, " default: return null;");
|
|
||||||
w(enums, " }");
|
|
||||||
w(enums, " }");
|
|
||||||
w(enums, "");
|
|
||||||
w(enums, " public static "+name+" fromCoding(Coding c) {");
|
w(enums, " public static "+name+" fromCoding(Coding c) {");
|
||||||
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
||||||
if (cc.hasVersion()) {
|
if (cc.hasVersion()) {
|
||||||
w(enums, " if (\""+cc.getSystem()+"\".equals(c.getSystem()) && \""+cc.getCode()+"\".equals(c.getCode()) && (!c.hasVersion() || \""+cc.getVersion()+"\".equals(c.getVersion()))) {");
|
w(enums, " if (\""+cc.getSystem()+"\".equals(c.getSystem()) && \""+cc.getCode()+"\".equals(c.getCode()) && (!c.hasVersion() || \""+cc.getVersion()+"\".equals(c.getVersion()))) {");
|
||||||
} else {
|
} else {
|
||||||
w(enums, " if (\""+cc.getSystem()+"\".equals(c.getSystem()) && \""+cc.getCode()+"\".equals(c.getCode())) {");
|
w(enums, " if (\""+cc.getSystem()+"\".equals(c.getSystem()) && \""+cc.getCode()+"\".equals(c.getCode())) {");
|
||||||
}
|
}
|
||||||
|
@ -302,16 +320,18 @@ public class PECodeGenerator {
|
||||||
w(enums, " }");
|
w(enums, " }");
|
||||||
w(enums, " }");
|
w(enums, " }");
|
||||||
w(enums, "");
|
w(enums, "");
|
||||||
|
|
||||||
w(enums, " public String toCode() {");
|
if (!hasDups) {
|
||||||
w(enums, " switch (this) {");
|
w(enums, " public String toCode() {");
|
||||||
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
w(enums, " switch (this) {");
|
||||||
w(enums, " case "+cc.getUserString("java.code")+": return \""+cc.getCode()+"\";");
|
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
||||||
|
w(enums, " case "+cc.getUserString("java.code")+": return \""+cc.getCode()+"\";");
|
||||||
|
}
|
||||||
|
w(enums, " default: return null;");
|
||||||
|
w(enums, " }");
|
||||||
|
w(enums, " }");
|
||||||
|
w(enums, "");
|
||||||
}
|
}
|
||||||
w(enums, " default: return null;");
|
|
||||||
w(enums, " }");
|
|
||||||
w(enums, " }");
|
|
||||||
w(enums, "");
|
|
||||||
w(enums, " public Coding toCoding() {");
|
w(enums, " public Coding toCoding() {");
|
||||||
w(enums, " switch (this) {");
|
w(enums, " switch (this) {");
|
||||||
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {
|
||||||
|
@ -337,6 +357,7 @@ public class PECodeGenerator {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void defineField(PEDefinition source, PEDefinition field) {
|
private void defineField(PEDefinition source, PEDefinition field) {
|
||||||
if (field.types().size() == 1) {
|
if (field.types().size() == 1) {
|
||||||
StructureDefinition sd = workerContext.fetchTypeDefinition(field.types().get(0).getUrl());
|
StructureDefinition sd = workerContext.fetchTypeDefinition(field.types().get(0).getUrl());
|
||||||
|
@ -377,8 +398,8 @@ public class PECodeGenerator {
|
||||||
if (isPrim && field.hasFixedValue()) {
|
if (isPrim && field.hasFixedValue()) {
|
||||||
genFixed(name, ptype, field.getFixedValue());
|
genFixed(name, ptype, field.getFixedValue());
|
||||||
}
|
}
|
||||||
genAccessors(isPrim, isAbstract, name, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.documentation(), field.hasFixedValue(), isEnum, field.definition());
|
genAccessors(isPrim, isAbstract, name, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.documentation(), field.hasFixedValue(), isEnum, field.definition());
|
||||||
genLoad(isPrim, isAbstract, name, sname, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.hasFixedValue(), field.types().get(0), isEnum);
|
genLoad(isPrim, isAbstract, name, sname, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.hasFixedValue(), field.types().get(0), isEnum);
|
||||||
genSave(isPrim, isAbstract, name, sname, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.hasFixedValue(), isExtension, field.types().get(0), isEnum);
|
genSave(isPrim, isAbstract, name, sname, field.name(), type, init, ptype, ltype, cname, csname, field.isList(), field.hasFixedValue(), isExtension, field.types().get(0), isEnum);
|
||||||
genClear(field.isList(), name, ptype);
|
genClear(field.isList(), name, ptype);
|
||||||
}
|
}
|
||||||
|
@ -386,10 +407,10 @@ public class PECodeGenerator {
|
||||||
// ignoring polymorphics for now
|
// ignoring polymorphics for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genClear(boolean list, String name, String ptype) {
|
private void genClear(boolean list, String name, String ptype) {
|
||||||
if (list) {
|
if (list) {
|
||||||
w(clear, " "+name+".clear();");
|
w(clear, " "+name+".clear();");
|
||||||
} else if ("boolean".equals(ptype)) {
|
} else if ("boolean".equals(ptype)) {
|
||||||
w(clear, " "+name+" = false;");
|
w(clear, " "+name+" = false;");
|
||||||
} else if ("int".equals(ptype)) {
|
} else if ("int".equals(ptype)) {
|
||||||
|
@ -398,16 +419,25 @@ public class PECodeGenerator {
|
||||||
w(clear, " "+name+" = null;");
|
w(clear, " "+name+" = null;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genLoad(boolean isPrim, boolean isAbstract, String name, String sname, String fname, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, boolean isFixed, PEType typeInfo, boolean isEnum) {
|
private void genLoad(boolean isPrim, boolean isAbstract, String name, String sname, String fname, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, boolean isFixed, PEType typeInfo, boolean isEnum) {
|
||||||
if (isList) {
|
if (isList) {
|
||||||
w(load, " for (PEInstance item : src.children(\""+fname+"\")) {");
|
w(load, " for (PEInstance item : src.children(\""+fname+"\")) {");
|
||||||
if ("BackboneElement".equals(type)) {
|
if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
||||||
w(load, " "+name+".add(("+type+") item.asElement());");
|
w(load, " "+name+".add("+type+".fromSource(src.child(\""+fname+"\")));");
|
||||||
} else if (!Strings.isNullOrEmpty(typeInfo.getUrl()) && typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
|
||||||
w(load, " "+name+".add(("+type+") item.asDataType());");
|
} else if ("BackboneElement".equals(type)) {
|
||||||
|
w(load, " "+name+".add(("+type+") item.asElement());");
|
||||||
|
} else if (isEnum) {
|
||||||
|
if ("CodeableConcept".equals(typeInfo.getName())) {
|
||||||
|
w(load, " "+name+".add("+type+".fromCodeableConcept((CodeableConcept) item.asDataType()));");
|
||||||
|
} else if ("Coding".equals(typeInfo.getName())) {
|
||||||
|
w(load, " "+name+".add("+type+".fromCoding((Coding) item.asDataType()));");
|
||||||
|
} else {
|
||||||
|
w(load, " "+name+".add("+type+".fromCode(item.asDataType().primitiveValue()));");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+".add("+type+".fromSource(item));");
|
w(load, " "+name+".add(("+type+") item.asDataType());");
|
||||||
}
|
}
|
||||||
w(load, " }");
|
w(load, " }");
|
||||||
} else if (isEnum) {
|
} else if (isEnum) {
|
||||||
|
@ -418,27 +448,31 @@ public class PECodeGenerator {
|
||||||
w(load, " "+name+" = "+type+".fromCoding((Coding) src.child(\""+fname+"\").asDataType());");
|
w(load, " "+name+" = "+type+".fromCoding((Coding) src.child(\""+fname+"\").asDataType());");
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+" = "+type+".fromCode(src.child(\""+fname+"\").asDataType().primitiveValue());");
|
w(load, " "+name+" = "+type+".fromCode(src.child(\""+fname+"\").asDataType().primitiveValue());");
|
||||||
}
|
}
|
||||||
w(load, " }");
|
w(load, " }");
|
||||||
} else if (isPrim) {
|
} else if (isPrim) {
|
||||||
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
||||||
if ("CodeType".equals(type)) {
|
if ("CodeType".equals(type)) {
|
||||||
// might be code or enum
|
// might be code or enum
|
||||||
w(load, " "+name+" = src.child(\""+fname+"\").asDataType().primitiveValue();");
|
w(load, " "+name+" = src.child(\""+fname+"\").asDataType().primitiveValue();");
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+" = (("+type+") src.child(\""+fname+"\").asDataType()).getValue();");
|
w(load, " "+name+" = (("+type+") src.child(\""+fname+"\").asDataType()).getValue();");
|
||||||
}
|
}
|
||||||
w(load, " }");
|
w(load, " }");
|
||||||
} else if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
} else if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
||||||
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
||||||
w(load, " "+name+" = "+type+".fromSource(src.child(\""+fname+"\"));");
|
w(load, " "+name+" = "+type+".fromSource(src.child(\""+fname+"\"));");
|
||||||
w(load, " }");
|
w(load, " }");
|
||||||
} else {
|
} else {
|
||||||
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
w(load, " if (src.hasChild(\""+fname+"\")) {");
|
||||||
if ("BackboneElement".equals(type)) {
|
if ("BackboneElement".equals(type)) {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asElement();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asElement();");
|
||||||
} else if (Utilities.existsInList(type, workerContext.getResourceNames())) {
|
} else if (Utilities.existsInList(type, workerContext.getResourceNames())) {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asResource();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asResource();");
|
||||||
|
} else if("Reference".equals(type)) {
|
||||||
|
w(load, " "+type+" ref = ("+type+") src.child(\""+fname+"\").asDataType();");
|
||||||
|
w(load, " if(!ref.isEmpty())");
|
||||||
|
w(load, " "+name+" = ref;");
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asDataType();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asDataType();");
|
||||||
}
|
}
|
||||||
|
@ -450,10 +484,20 @@ public class PECodeGenerator {
|
||||||
w(save, " tgt.clear(\""+fname+"\");");
|
w(save, " tgt.clear(\""+fname+"\");");
|
||||||
if (isList) {
|
if (isList) {
|
||||||
w(save, " for ("+type+" item : "+name+") {");
|
w(save, " for ("+type+" item : "+name+") {");
|
||||||
if (isExtension && !Strings.isNullOrEmpty(typeInfo.getUrl()) && typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
if (isExtension) {
|
||||||
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", item);");
|
if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
||||||
} else if (isExtension) {
|
w(save, " item.save(tgt.makeChild(\""+fname+"\"), false);");
|
||||||
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", item.getData());");
|
} else {
|
||||||
|
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", item);");
|
||||||
|
}
|
||||||
|
} else if (isEnum) {
|
||||||
|
if ("CodeableConcept".equals(typeInfo.getName())) {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCodeableConcept());");
|
||||||
|
} else if ("Coding".equals(typeInfo.getName())) {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCoding());");
|
||||||
|
} else {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCode());");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w(save, " tgt.addChild(\""+fname+"\", item);");
|
w(save, " tgt.addChild(\""+fname+"\", item);");
|
||||||
}
|
}
|
||||||
|
@ -466,8 +510,8 @@ public class PECodeGenerator {
|
||||||
w(save, " tgt.addChild(\""+fname+"\", "+name+".toCoding());");
|
w(save, " tgt.addChild(\""+fname+"\", "+name+".toCoding());");
|
||||||
} else {
|
} else {
|
||||||
w(save, " tgt.addChild(\""+fname+"\", "+name+".toCode());");
|
w(save, " tgt.addChild(\""+fname+"\", "+name+".toCode());");
|
||||||
}
|
}
|
||||||
w(save, " }");
|
w(save, " }");
|
||||||
} else if (isPrim) {
|
} else if (isPrim) {
|
||||||
if ("boolean".equals(ptype)) {
|
if ("boolean".equals(ptype)) {
|
||||||
w(save, " if (true) { // for now, at least");
|
w(save, " if (true) { // for now, at least");
|
||||||
|
@ -479,7 +523,7 @@ public class PECodeGenerator {
|
||||||
if (isExtension) {
|
if (isExtension) {
|
||||||
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", new "+type+"("+name+"));");
|
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", new "+type+"("+name+"));");
|
||||||
} else if (Utilities.existsInList(type, "DateType", "InstantType", "DateTimeType")) {
|
} else if (Utilities.existsInList(type, "DateType", "InstantType", "DateTimeType")) {
|
||||||
w(save, " tgt.addChild(\""+fname+"\", new "+type+"("+name+"));");
|
w(save, " tgt.addChild(\""+fname+"\", new "+type+"("+name+"));");
|
||||||
} else {
|
} else {
|
||||||
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value\", new "+type+"("+name+"));");
|
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value\", new "+type+"("+name+"));");
|
||||||
}
|
}
|
||||||
|
@ -511,7 +555,7 @@ public class PECodeGenerator {
|
||||||
if (isFixed) {
|
if (isFixed) {
|
||||||
w(accessors, " public boolean has"+cname+"() {");
|
w(accessors, " public boolean has"+cname+"() {");
|
||||||
w(accessors, " return true;");
|
w(accessors, " return true;");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
} else {
|
} else {
|
||||||
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
|
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
|
||||||
w(accessors, " this."+name+" = value;");
|
w(accessors, " this."+name+" = value;");
|
||||||
|
@ -520,13 +564,13 @@ public class PECodeGenerator {
|
||||||
w(accessors);
|
w(accessors);
|
||||||
w(accessors, " public boolean has"+cname+"() {");
|
w(accessors, " public boolean has"+cname+"() {");
|
||||||
if ("boolean".equals(ptype)) {
|
if ("boolean".equals(ptype)) {
|
||||||
w(accessors, " return true; // not "+name+" != false ?");
|
w(accessors, " return true; // not "+name+" != false ?");
|
||||||
} else if ("int".equals(ptype)) {
|
} else if ("int".equals(ptype)) {
|
||||||
w(accessors, " return "+name+" != 0;");
|
w(accessors, " return "+name+" != 0;");
|
||||||
} else {
|
} else {
|
||||||
w(accessors, " return "+name+" != null;");
|
w(accessors, " return "+name+" != null;");
|
||||||
}
|
}
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isPrim && !isList) {
|
if (isPrim && !isList) {
|
||||||
|
@ -553,24 +597,31 @@ public class PECodeGenerator {
|
||||||
w(accessors, " return "+name+" != null && !"+name+".isEmpty();");
|
w(accessors, " return "+name+" != null && !"+name+".isEmpty();");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors);
|
w(accessors);
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
w(accessors, " public "+type+" add"+csname+"() {");
|
if (!isEnum) {
|
||||||
w(accessors, " "+type+" theThing = new "+type+"();");
|
w(accessors, " public "+type+" add"+csname+"() {");
|
||||||
w(accessors, " get"+cname+"().add(theThing);");
|
w(accessors, " "+type+" theThing = new "+type+"();");
|
||||||
w(accessors, " return theThing;");
|
w(accessors, " get"+cname+"().add(theThing);");
|
||||||
w(accessors, " }");
|
w(accessors, " return theThing;");
|
||||||
w(accessors);
|
w(accessors, " }");
|
||||||
|
w(accessors);
|
||||||
|
} else {
|
||||||
|
w(accessors, " public void add"+csname+"("+type+" theThing) {");
|
||||||
|
w(accessors, " get"+cname+"().add(theThing);");
|
||||||
|
w(accessors, " }");
|
||||||
|
w(accessors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w(accessors, " public boolean has"+csname+"("+type+" item) {");
|
w(accessors, " public boolean has"+csname+"("+type+" item) {");
|
||||||
w(accessors, " return has"+cname+"() && "+name+".contains(item);");
|
w(accessors, " return has"+cname+"() && "+name+".contains(item);");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors);
|
w(accessors);
|
||||||
w(accessors, " public void remove"+csname+"("+type+" item) {");
|
w(accessors, " public void remove"+csname+"("+type+" item) {");
|
||||||
w(accessors, " if (has"+csname+"(item)) {");
|
w(accessors, " if (has"+csname+"(item)) {");
|
||||||
w(accessors, " "+name+".remove(item);");
|
w(accessors, " "+name+".remove(item);");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors);
|
w(accessors);
|
||||||
} else if (isPrim) {
|
} else if (isPrim) {
|
||||||
if (!isFixed) {
|
if (!isFixed) {
|
||||||
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
|
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
|
||||||
|
@ -586,7 +637,7 @@ public class PECodeGenerator {
|
||||||
w(accessors, " public boolean has"+cname+"() {");
|
w(accessors, " public boolean has"+cname+"() {");
|
||||||
w(accessors, " return "+name+" != null && "+name+".hasValue();");
|
w(accessors, " return "+name+" != null && "+name+".hasValue();");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors);
|
w(accessors);
|
||||||
} else {
|
} else {
|
||||||
if (!isFixed) {
|
if (!isFixed) {
|
||||||
w(accessors, " public "+this.name+" set"+cname+"("+type+" value) {");
|
w(accessors, " public "+this.name+" set"+cname+"("+type+" value) {");
|
||||||
|
@ -610,7 +661,7 @@ public class PECodeGenerator {
|
||||||
w(fields, " @BindingStrength(\""+ed.getBinding().getStrength().toCode()+"\") @ValueSet(\""+ed.getBinding().getValueSet()+"\")");
|
w(fields, " @BindingStrength(\""+ed.getBinding().getStrength().toCode()+"\") @ValueSet(\""+ed.getBinding().getValueSet()+"\")");
|
||||||
}
|
}
|
||||||
if (ed.getMustSupport()) {
|
if (ed.getMustSupport()) {
|
||||||
w(fields, " @MustSupport(true)");
|
w(fields, " @MustSupport(true)");
|
||||||
}
|
}
|
||||||
if (ed.hasLabel() || ed.hasDefinition()) {
|
if (ed.hasLabel() || ed.hasDefinition()) {
|
||||||
String s = "";
|
String s = "";
|
||||||
|
@ -620,7 +671,7 @@ public class PECodeGenerator {
|
||||||
if (ed.hasDefinition()) {
|
if (ed.hasDefinition()) {
|
||||||
s = s + " @Definition(\""+Utilities.escapeJava(ed.getDefinition())+"\")";
|
s = s + " @Definition(\""+Utilities.escapeJava(ed.getDefinition())+"\")";
|
||||||
}
|
}
|
||||||
w(fields, " "+s);
|
w(fields, " "+s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isPrim && extensionPolicy != ExtensionPolicy.Primitives && !isList) {
|
if (isPrim && extensionPolicy != ExtensionPolicy.Primitives && !isList) {
|
||||||
|
@ -628,7 +679,7 @@ public class PECodeGenerator {
|
||||||
} else if (isList) {
|
} else if (isList) {
|
||||||
w(fields, " private "+ltype+" "+name+" = new ArrayList<>();"+nn+" // "+shortDoco);
|
w(fields, " private "+ltype+" "+name+" = new ArrayList<>();"+nn+" // "+shortDoco);
|
||||||
} else {
|
} else {
|
||||||
w(fields, " private "+ltype+" "+name+";"+nn+" // "+shortDoco);
|
w(fields, " private "+ltype+" "+name+";"+nn+" // "+shortDoco);
|
||||||
}
|
}
|
||||||
w(fields, "");
|
w(fields, "");
|
||||||
}
|
}
|
||||||
|
@ -768,8 +819,9 @@ public class PECodeGenerator {
|
||||||
PEDefinition source = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition(canonical);
|
PEDefinition source = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition(canonical);
|
||||||
w(imports, "import java.util.List;");
|
w(imports, "import java.util.List;");
|
||||||
w(imports, "import java.util.ArrayList;");
|
w(imports, "import java.util.ArrayList;");
|
||||||
w(imports, "import javax.annotation.Nullable;");
|
|
||||||
w(imports, "import java.util.Date;\r\n");
|
w(imports, "import java.util.Date;\r\n");
|
||||||
|
w(imports, "import java.math.BigDecimal;");
|
||||||
|
w(imports, "import javax.annotation.Nullable;");
|
||||||
w(imports);
|
w(imports);
|
||||||
w(imports, "import org.hl7.fhir."+version+".context.IWorkerContext;");
|
w(imports, "import org.hl7.fhir."+version+".context.IWorkerContext;");
|
||||||
w(imports, "import org.hl7.fhir."+version+".model.*;");
|
w(imports, "import org.hl7.fhir."+version+".model.*;");
|
||||||
|
@ -785,7 +837,7 @@ public class PECodeGenerator {
|
||||||
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.ValueSet;");
|
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.ValueSet;");
|
||||||
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.MustSupport;");
|
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.MustSupport;");
|
||||||
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.Definition;");
|
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.Definition;");
|
||||||
|
|
||||||
|
|
||||||
PEGenClass cls = genClass(source);
|
PEGenClass cls = genClass(source);
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
|
@ -810,7 +862,7 @@ public class PECodeGenerator {
|
||||||
w(b, pfx+" *");
|
w(b, pfx+" *");
|
||||||
}
|
}
|
||||||
w(b, pfx+" */");
|
w(b, pfx+" */");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> naturalLines(String line) {
|
private List<String> naturalLines(String line) {
|
||||||
|
@ -839,7 +891,7 @@ public class PECodeGenerator {
|
||||||
|
|
||||||
private void w(StringBuilder b, String line) {
|
private void w(StringBuilder b, String line) {
|
||||||
b.append(line);
|
b.append(line);
|
||||||
w(b);
|
w(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PEGenClass genClass(PEDefinition source) {
|
private PEGenClass genClass(PEDefinition source) {
|
||||||
|
@ -854,7 +906,7 @@ public class PECodeGenerator {
|
||||||
if (genForField(source, child)) {
|
if (genForField(source, child)) {
|
||||||
cls.defineField(source, child);
|
cls.defineField(source, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
||||||
try {
|
try {
|
||||||
feed = client.issueGetFeedRequest(new URI(url), withVer(getPreferredResourceFormat(), "4.0"), timeoutLong);
|
feed = client.issueGetFeedRequest(new URI(url), withVer(getPreferredResourceFormat(), "4.0"), timeoutLong);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException(0, "An error has occurred while trying to retrieve history since last update", e);
|
handleException(0, "An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hl7.fhir.r4.utils.client.EFhirClientException;
|
||||||
import org.hl7.fhir.r4.utils.client.ResourceFormat;
|
import org.hl7.fhir.r4.utils.client.ResourceFormat;
|
||||||
import org.hl7.fhir.utilities.MimeType;
|
import org.hl7.fhir.utilities.MimeType;
|
||||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.http.*;
|
import org.hl7.fhir.utilities.http.*;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
||||||
|
|
||||||
|
@ -179,7 +180,11 @@ public class FhirRequestBuilder {
|
||||||
boolean ok = code >= 200 && code < 300;
|
boolean ok = code >= 200 && code < 300;
|
||||||
if (response.getContent() == null) {
|
if (response.getContent() == null) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw new EFhirClientException(response.getMessage());
|
if (Utilities.noString(response.getMessage())) {
|
||||||
|
throw new EFhirClientException(response.getMessagefromCode());
|
||||||
|
} else {
|
||||||
|
throw new EFhirClientException(response.getMessage());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -399,7 +399,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
|
||||||
try {
|
try {
|
||||||
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException("An error has occurred while trying to retrieve history since last update", e);
|
handleException("An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.hl7.fhir.r4b.utils.ResourceUtilities;
|
||||||
import org.hl7.fhir.r4b.utils.client.EFhirClientException;
|
import org.hl7.fhir.r4b.utils.client.EFhirClientException;
|
||||||
import org.hl7.fhir.r4b.utils.client.ResourceFormat;
|
import org.hl7.fhir.r4b.utils.client.ResourceFormat;
|
||||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.http.*;
|
import org.hl7.fhir.utilities.http.*;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
||||||
|
|
||||||
|
@ -174,7 +175,11 @@ public class FhirRequestBuilder {
|
||||||
boolean ok = code >= 200 && code < 300;
|
boolean ok = code >= 200 && code < 300;
|
||||||
if (response.getContent() == null) {
|
if (response.getContent() == null) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw new EFhirClientException(response.getMessage());
|
if (Utilities.noString(response.getMessage())) {
|
||||||
|
throw new EFhirClientException(response.getMessagefromCode());
|
||||||
|
} else {
|
||||||
|
throw new EFhirClientException(response.getMessage());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class LiquidEngineTests implements ILiquidEngineIncludeResolver {
|
||||||
|
|
||||||
public static Stream<Arguments> data() throws ParserConfigurationException, SAXException, IOException {
|
public static Stream<Arguments> data() throws ParserConfigurationException, SAXException, IOException {
|
||||||
testdoc = (JsonObject) new com.google.gson.JsonParser()
|
testdoc = (JsonObject) new com.google.gson.JsonParser()
|
||||||
.parse(TestingUtilities.loadTestResource("r5", "liquid", "liquid-tests.json"));
|
.parse(TestingUtilities.loadTestResource("r4b", "liquid", "liquid-tests.json"));
|
||||||
JsonArray tests = testdoc.getAsJsonArray("tests");
|
JsonArray tests = testdoc.getAsJsonArray("tests");
|
||||||
List<Arguments> objects = new ArrayList<>();
|
List<Arguments> objects = new ArrayList<>();
|
||||||
for (JsonElement n : tests) {
|
for (JsonElement n : tests) {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.comparison.StructureDefinitionComparer.ProfileComparison;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
|
||||||
|
@ -16,16 +18,26 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.CodeSystemRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlDocument;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public class CodeSystemComparer extends CanonicalResourceComparer {
|
public class CodeSystemComparer extends CanonicalResourceComparer {
|
||||||
|
@ -628,4 +640,14 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
|
||||||
return "CodeSystem";
|
return "CodeSystem";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XhtmlNode renderUnion(CodeSystemComparison comp, String id, String prefix, String corePath) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||||
|
CodeSystemRenderer csr = new CodeSystemRenderer(new RenderingContext(session.getContextLeft(), null, new ValidationOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER));
|
||||||
|
return csr.buildNarrative(ResourceWrapper.forResource(csr.getContext(), comp.union));
|
||||||
|
}
|
||||||
|
|
||||||
|
public XhtmlNode renderIntersection(CodeSystemComparison comp, String id, String prefix, String corePath) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||||
|
CodeSystemRenderer csr = new CodeSystemRenderer(new RenderingContext(session.getContextLeft(), null, new ValidationOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER));
|
||||||
|
return csr.buildNarrative(ResourceWrapper.forResource(csr.getContext(), comp.intersection));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,7 +12,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.exceptions.PathEngineException;
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
import org.hl7.fhir.r5.comparison.CapabilityStatementComparer.CapabilityStatementComparison;
|
import org.hl7.fhir.r5.comparison.CapabilityStatementComparer.CapabilityStatementComparison;
|
||||||
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
|
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
|
||||||
|
@ -28,12 +30,13 @@ import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.StringType;
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
import org.hl7.fhir.r5.model.Tuple;
|
import org.hl7.fhir.r5.model.Tuple;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine;
|
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
|
||||||
import org.hl7.fhir.utilities.FhirPublication;
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
import org.hl7.fhir.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
@ -109,7 +112,7 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||||
if (comp.fhirType().equals(name)) {
|
if (comp.fhirType().equals(name)) {
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
b.append("<tr><td colspan=\"4\"><b>"+Utilities.pluralize(name, 2)+"</b></td></tr>\r\n");
|
b.append("<tr><td colspan=\"6\"><b>"+Utilities.pluralize(name, 2)+"</b></td></tr>\r\n");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
renderComparison(id, comp);
|
renderComparison(id, comp);
|
||||||
|
@ -143,7 +146,7 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderComparison(String id, ResourceComparison comp) throws IOException {
|
private void renderComparison(String id, ResourceComparison comp) throws IOException, FHIRFormatError, DefinitionException, FHIRException, EOperationOutcome {
|
||||||
if (comp instanceof ProfileComparison) {
|
if (comp instanceof ProfileComparison) {
|
||||||
renderProfile(id, (ProfileComparison) comp);
|
renderProfile(id, (ProfileComparison) comp);
|
||||||
} else if (comp instanceof ValueSetComparison) {
|
} else if (comp instanceof ValueSetComparison) {
|
||||||
|
@ -169,7 +172,7 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||||
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException {
|
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException, FHIRFormatError, DefinitionException, FHIRException, EOperationOutcome {
|
||||||
String template = templates.get("CodeSystem");
|
String template = templates.get("CodeSystem");
|
||||||
Map<String, Base> vars = new HashMap<>();
|
Map<String, Base> vars = new HashMap<>();
|
||||||
CodeSystemComparer cs = new CodeSystemComparer(session);
|
CodeSystemComparer cs = new CodeSystemComparer(session);
|
||||||
|
@ -183,17 +186,32 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||||
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
|
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
|
||||||
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
|
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
|
||||||
vars.put("concepts", new StringType(new XhtmlComposer(true).compose(cs.renderConcepts(comp, "", ""))));
|
vars.put("concepts", new StringType(new XhtmlComposer(true).compose(cs.renderConcepts(comp, "", ""))));
|
||||||
|
|
||||||
String cnt = processTemplate(template, "CodeSystem", vars);
|
String cnt = processTemplate(template, "CodeSystem", vars);
|
||||||
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
||||||
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
|
||||||
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
|
||||||
|
|
||||||
|
String union = new XhtmlComposer(true).compose(cs.renderUnion(comp, "", folder, "http://hl7.org/fhir"));
|
||||||
|
String intersection = new XhtmlComposer(true).compose(cs.renderIntersection(comp, "", folder, "http://hl7.org/fhir"));
|
||||||
|
vars.put("union", new StringType(union));
|
||||||
|
vars.put("intersection", new StringType(intersection));
|
||||||
|
|
||||||
|
template = templates.get("CodeSystem-Union");
|
||||||
|
cnt = processTemplate(template, "CodeSystem-Union", vars);
|
||||||
|
TextFile.stringToFile(cnt, file(comp.getId()+"-union.html"));
|
||||||
|
|
||||||
|
template = templates.get("CodeSystem-Intersection");
|
||||||
|
cnt = processTemplate(template, "CodeSystem-Intersection", vars);
|
||||||
|
TextFile.stringToFile(cnt, file(comp.getId()+"-intersection.html"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String file(String name) throws IOException {
|
private String file(String name) throws IOException {
|
||||||
return Utilities.path(folder, name);
|
return Utilities.path(folder, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException {
|
private void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException, EOperationOutcome {
|
||||||
String template = templates.get("ValueSet");
|
String template = templates.get("ValueSet");
|
||||||
Map<String, Base> vars = new HashMap<>();
|
Map<String, Base> vars = new HashMap<>();
|
||||||
ValueSetComparer cs = new ValueSetComparer(session);
|
ValueSetComparer cs = new ValueSetComparer(session);
|
||||||
|
@ -212,6 +230,19 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||||
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
TextFile.stringToFile(cnt, file(comp.getId()+".html"));
|
||||||
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
|
||||||
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
|
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
|
||||||
|
|
||||||
|
String union = new XhtmlComposer(true).compose(cs.renderUnion(comp, "", folder, "http://hl7.org/fhir"));
|
||||||
|
String intersection = new XhtmlComposer(true).compose(cs.renderIntersection(comp, "", folder, "http://hl7.org/fhir"));
|
||||||
|
vars.put("union", new StringType(union));
|
||||||
|
vars.put("intersection", new StringType(intersection));
|
||||||
|
|
||||||
|
template = templates.get("ValueSet-Union");
|
||||||
|
cnt = processTemplate(template, "ValueSet-Union", vars);
|
||||||
|
TextFile.stringToFile(cnt, file(comp.getId()+"-union.html"));
|
||||||
|
|
||||||
|
template = templates.get("ValueSet-Intersection");
|
||||||
|
cnt = processTemplate(template, "ValueSet-Intersection", vars);
|
||||||
|
TextFile.stringToFile(cnt, file(comp.getId()+"-intersection.html"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderProfile(String id, ProfileComparison comp) throws IOException {
|
private void renderProfile(String id, ProfileComparison comp) throws IOException {
|
||||||
|
|
|
@ -202,7 +202,7 @@ public class ResourceComparer {
|
||||||
s = s + "<td><a href=\""+getId()+".html\">Failed<a></td>";
|
s = s + "<td><a href=\""+getId()+".html\">Failed<a></td>";
|
||||||
color = COLOR_ISSUE;
|
color = COLOR_ISSUE;
|
||||||
}
|
}
|
||||||
s = s + "<td>"+(e != null ? Utilities.escapeXml(e.getMessage()) : "")+"</td>";
|
s = s + "<td colspan=\"3\">"+(e != null ? Utilities.escapeXml(e.getMessage()) : "")+"</td>";
|
||||||
return "<tr style=\"background-color: "+color+"\">"+s+"</tr>\r\n";
|
return "<tr style=\"background-color: "+color+"\">"+s+"</tr>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.model.CanonicalType;
|
import org.hl7.fhir.r5.model.CanonicalType;
|
||||||
import org.hl7.fhir.r5.model.Element;
|
import org.hl7.fhir.r5.model.Element;
|
||||||
|
@ -16,10 +18,18 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.CodeSystemRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.ValueSetRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||||
|
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||||
|
@ -165,7 +175,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
||||||
intersection.getInclude().add(csI);
|
intersection.getInclude().add(csI);
|
||||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
||||||
res.getIncludes().getChildren().add(sm);
|
res.getIncludes().getChildren().add(sm);
|
||||||
def = compareDefinitions("ValueSet.compose.exclude["+right.getInclude().indexOf(r)+"]", l, r, sm, csM, csI, res) || def;
|
def = compareDefinitions("ValueSet.compose.include["+right.getInclude().indexOf(r)+"]", l, r, sm, csM, csI, res) || def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ConceptSetComponent r : right.getInclude()) {
|
for (ConceptSetComponent r : right.getInclude()) {
|
||||||
|
@ -341,7 +351,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
||||||
intersection.getFilter().add(ci);
|
intersection.getFilter().add(ci);
|
||||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
||||||
combined.getChildren().add(sm);
|
combined.getChildren().add(sm);
|
||||||
if (!compareFilters(l, r, sm, cu, ci)) {
|
if (compareFilters(l, r, sm, cu, ci)) {
|
||||||
res.updateContentState(true);
|
res.updateContentState(true);
|
||||||
session.markChanged(r, l);
|
session.markChanged(r, l);
|
||||||
}
|
}
|
||||||
|
@ -420,7 +430,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
||||||
cu.setOp(l.getOp());
|
cu.setOp(l.getOp());
|
||||||
cu.setValue(l.getValue());
|
cu.setValue(l.getValue());
|
||||||
}
|
}
|
||||||
return !l.getProperty().equals(r.getProperty());
|
return !l.getValue().equals(r.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CanonicalType findInList(List<CanonicalType> matches, CanonicalType item, List<CanonicalType> source) {
|
private CanonicalType findInList(List<CanonicalType> matches, CanonicalType item, List<CanonicalType> source) {
|
||||||
|
@ -904,4 +914,15 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public XhtmlNode renderUnion(ValueSetComparison comp, String id, String prefix, String corePath) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||||
|
ValueSetRenderer vsr = new ValueSetRenderer(new RenderingContext(session.getContextLeft(), null, new ValidationOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER));
|
||||||
|
return vsr.buildNarrative(ResourceWrapper.forResource(vsr.getContext(), comp.union));
|
||||||
|
}
|
||||||
|
|
||||||
|
public XhtmlNode renderIntersection(ValueSetComparison comp, String id, String prefix, String corePath) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||||
|
ValueSetRenderer vsr = new ValueSetRenderer(new RenderingContext(session.getContextLeft(), null, new ValidationOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER));
|
||||||
|
return vsr.buildNarrative(ResourceWrapper.forResource(vsr.getContext(), comp.intersection));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -794,6 +794,19 @@ public class ProfileUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < derived.getSnapshot().getElement().size(); i++) {
|
||||||
|
ElementDefinition ed = derived.getSnapshot().getElement().get(i);
|
||||||
|
if (ed.getType().size() > 1) {
|
||||||
|
List<TypeRefComponent> toRemove = new ArrayList<ElementDefinition.TypeRefComponent>();
|
||||||
|
for (TypeRefComponent tr : ed.getType()) {
|
||||||
|
ElementDefinition typeSlice = findTypeSlice(derived.getSnapshot().getElement(), i, ed.getPath(), tr.getWorkingCode());
|
||||||
|
if (typeSlice != null && typeSlice.prohibited()) {
|
||||||
|
toRemove.add(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ed.getType().removeAll(toRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (derived.getKind() != StructureDefinitionKind.LOGICAL && !derived.getSnapshot().getElementFirstRep().getType().isEmpty())
|
if (derived.getKind() != StructureDefinitionKind.LOGICAL && !derived.getSnapshot().getElementFirstRep().getType().isEmpty())
|
||||||
throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_, derived.getSnapshot().getElementFirstRep().getPath(), derived.getUrl(), base.getUrl()));
|
throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_, derived.getSnapshot().getElementFirstRep().getPath(), derived.getUrl(), base.getUrl()));
|
||||||
mappingDetails.update();
|
mappingDetails.update();
|
||||||
|
@ -992,6 +1005,34 @@ public class ProfileUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ElementDefinition findTypeSlice(List<ElementDefinition> list, int i, String path, String typeCode) {
|
||||||
|
for (int j = i+1; j < list.size(); j++) {
|
||||||
|
ElementDefinition ed = list.get(j);
|
||||||
|
if (pathMatches(path, ed) && typeMatches(ed, typeCode)) {
|
||||||
|
return ed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean pathMatches(String path, ElementDefinition ed) {
|
||||||
|
String p = ed.getPath();
|
||||||
|
if (path.equals(p)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (path.endsWith("[x]")) { // it should
|
||||||
|
path = path.substring(0, path.length()-3);
|
||||||
|
if (p.startsWith(path) && p.length() > path.length() && !p.substring(path.length()).contains(".")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean typeMatches(ElementDefinition ed, String typeCode) {
|
||||||
|
return ed.getType().size() == 1 && typeCode.equals(ed.getTypeFirstRep().getWorkingCode());
|
||||||
|
}
|
||||||
|
|
||||||
private void checkTypeParameters(StructureDefinition base, StructureDefinition derived) {
|
private void checkTypeParameters(StructureDefinition base, StructureDefinition derived) {
|
||||||
String bt = ToolingExtensions.readStringExtension(base, ToolingExtensions.EXT_TYPE_PARAMETER);
|
String bt = ToolingExtensions.readStringExtension(base, ToolingExtensions.EXT_TYPE_PARAMETER);
|
||||||
if (!derived.hasExtension(ToolingExtensions.EXT_TYPE_PARAMETER)) {
|
if (!derived.hasExtension(ToolingExtensions.EXT_TYPE_PARAMETER)) {
|
||||||
|
@ -2409,7 +2450,10 @@ public class ProfileUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before applying changes, apply them to what's in the profile
|
// Before applying changes, apply them to what's in the profile
|
||||||
|
// but only if it's an extension or a resource
|
||||||
|
|
||||||
StructureDefinition profile = null;
|
StructureDefinition profile = null;
|
||||||
boolean msg = true;
|
boolean msg = true;
|
||||||
if (base.hasSliceName()) {
|
if (base.hasSliceName()) {
|
||||||
|
@ -2441,7 +2485,7 @@ public class ProfileUtilities {
|
||||||
msg = false;
|
msg = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (profile != null) {
|
if (profile != null && (profile.getKind() == StructureDefinitionKind.RESOURCE || "Extension".equals(profile.getType()))) {
|
||||||
if (profile.getSnapshot().getElement().isEmpty()) {
|
if (profile.getSnapshot().getElement().isEmpty()) {
|
||||||
throw new DefinitionException(context.formatMessage(I18nConstants.SNAPSHOT_IS_EMPTY, profile.getVersionedUrl()));
|
throw new DefinitionException(context.formatMessage(I18nConstants.SNAPSHOT_IS_EMPTY, profile.getVersionedUrl()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
private Object lock = new Object(); // used as a lock for the data that follows
|
private Object lock = new Object(); // used as a lock for the data that follows
|
||||||
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
|
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
|
||||||
|
|
||||||
protected final TerminologyClientManager terminologyClientManager = new TerminologyClientManager(new TerminologyClientR5.TerminologyClientR5Factory(), UUID.randomUUID().toString());
|
|
||||||
private boolean minimalMemory = false;
|
private boolean minimalMemory = false;
|
||||||
|
|
||||||
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
|
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
|
||||||
|
@ -279,6 +278,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
protected boolean noTerminologyServer;
|
protected boolean noTerminologyServer;
|
||||||
private int expandCodesLimit = 1000;
|
private int expandCodesLimit = 1000;
|
||||||
protected org.hl7.fhir.r5.context.ILoggingService logger = new SystemOutLoggingService();
|
protected org.hl7.fhir.r5.context.ILoggingService logger = new SystemOutLoggingService();
|
||||||
|
protected final TerminologyClientManager terminologyClientManager = new TerminologyClientManager(new TerminologyClientR5.TerminologyClientR5Factory(), UUID.randomUUID().toString(), logger);
|
||||||
protected Parameters expParameters;
|
protected Parameters expParameters;
|
||||||
private Map<String, PackageInformation> packages = new HashMap<>();
|
private Map<String, PackageInformation> packages = new HashMap<>();
|
||||||
|
|
||||||
|
@ -1375,7 +1375,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Parameters pIn = constructParameters(options, code);
|
Parameters pIn = constructParameters(options, code);
|
||||||
res = validateOnServer(tc, vs, pIn, options);
|
res = validateOnServer2(tc, vs, pIn, options, systems);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR);
|
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -1645,7 +1645,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
txLog("$validate "+txCache.summary(code)+" for "+ txCache.summary(vs)+" on "+tc.getAddress());
|
txLog("$validate "+txCache.summary(code)+" for "+ txCache.summary(vs)+" on "+tc.getAddress());
|
||||||
try {
|
try {
|
||||||
Parameters pIn = constructParameters(options, code);
|
Parameters pIn = constructParameters(options, code);
|
||||||
res = validateOnServer(tc, vs, pIn, options);
|
res = validateOnServer2(tc, vs, pIn, options, systems);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
issues.clear();
|
issues.clear();
|
||||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXCEPTION);
|
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXCEPTION);
|
||||||
|
@ -1727,6 +1727,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValidationResult validateOnServer(TerminologyClientContext tc, ValueSet vs, Parameters pin, ValidationOptions options) throws FHIRException {
|
protected ValidationResult validateOnServer(TerminologyClientContext tc, ValueSet vs, Parameters pin, ValidationOptions options) throws FHIRException {
|
||||||
|
return validateOnServer2(tc, vs, pin, options, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ValidationResult validateOnServer2(TerminologyClientContext tc, ValueSet vs, Parameters pin, ValidationOptions options, Set<String> systems) throws FHIRException {
|
||||||
|
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
||||||
|
@ -1737,7 +1741,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addServerValidationParameters(tc, vs, pin, options);
|
addServerValidationParameters(tc, vs, pin, options, systems);
|
||||||
|
|
||||||
if (txLog != null) {
|
if (txLog != null) {
|
||||||
txLog.clearLastId();
|
txLog.clearLastId();
|
||||||
|
@ -1755,6 +1759,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addServerValidationParameters(TerminologyClientContext terminologyClientContext, ValueSet vs, Parameters pin, ValidationOptions options) {
|
protected void addServerValidationParameters(TerminologyClientContext terminologyClientContext, ValueSet vs, Parameters pin, ValidationOptions options) {
|
||||||
|
addServerValidationParameters(terminologyClientContext, vs, pin, options, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addServerValidationParameters(TerminologyClientContext terminologyClientContext, ValueSet vs, Parameters pin, ValidationOptions options, Set<String> systems) {
|
||||||
boolean cache = false;
|
boolean cache = false;
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
if (terminologyClientContext != null && terminologyClientContext.isTxCaching() && terminologyClientContext.getCacheId() != null && vs.getUrl() != null && terminologyClientContext.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) {
|
if (terminologyClientContext != null && terminologyClientContext.isTxCaching() && terminologyClientContext.getCacheId() != null && vs.getUrl() != null && terminologyClientContext.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) {
|
||||||
|
@ -1777,6 +1785,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
cache = true;
|
cache = true;
|
||||||
addDependentResources(terminologyClientContext, pin, vs);
|
addDependentResources(terminologyClientContext, pin, vs);
|
||||||
}
|
}
|
||||||
|
if (systems != null) {
|
||||||
|
for (String s : systems) {
|
||||||
|
cache = addDependentCodeSystem(terminologyClientContext, pin, s, null) || cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
pin.addParameter().setName("cache-id").setValue(new IdType(terminologyClientManager.getCacheId()));
|
pin.addParameter().setName("cache-id").setValue(new IdType(terminologyClientManager.getCacheId()));
|
||||||
for (ParametersParameterComponent pp : pin.getParameter()) {
|
for (ParametersParameterComponent pp : pin.getParameter()) {
|
||||||
if (pp.getName().equals("profile")) {
|
if (pp.getName().equals("profile")) {
|
||||||
|
@ -1823,13 +1836,20 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src);
|
String sys = inc.getSystem();
|
||||||
|
cache = addDependentCodeSystem(tc, pin, sys, src) || cache;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addDependentCodeSystem(TerminologyClientContext tc, Parameters pin, String sys, Resource src) {
|
||||||
|
boolean cache = false;
|
||||||
|
CodeSystem cs = fetchResource(CodeSystem.class, sys, src);
|
||||||
if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
|
if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
|
||||||
cache = checkAddToParams(tc, pin, cs) || cache;
|
cache = checkAddToParams(tc, pin, cs) || cache;
|
||||||
}
|
}
|
||||||
for (CodeSystem supp : codeSystems.getSupplements(cs)) {
|
for (CodeSystem supp : codeSystems.getSupplements(cs)) {
|
||||||
//if (supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem())) {
|
//if (supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem())) {
|
||||||
assert supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem());
|
assert supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(sys);
|
||||||
cache = checkAddToParams(tc, pin, supp) || cache;
|
cache = checkAddToParams(tc, pin, supp) || cache;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -2031,6 +2051,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
|
|
||||||
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger) {
|
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
getTxClientManager().setLogger(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameters getExpansionParameters() {
|
public Parameters getExpansionParameters() {
|
||||||
|
|
|
@ -63,8 +63,13 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
|
||||||
file.println("\r\n--- "+id+" -----------------\r\nRequest: \r\n");
|
file.println("\r\n--- "+id+" -----------------\r\nRequest: \r\n");
|
||||||
file.println(method+" "+url+" HTTP/1.0");
|
file.println(method+" "+url+" HTTP/1.0");
|
||||||
if (headers != null) {
|
if (headers != null) {
|
||||||
for (String s : headers)
|
for (String s : headers) {
|
||||||
file.println(s);
|
if (s.startsWith("Api-Key")) {
|
||||||
|
file.println("Api-Key: xxxxxxxxxxxxxxxx");
|
||||||
|
} else {
|
||||||
|
file.println(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
file.println("");
|
file.println("");
|
||||||
|
|
|
@ -476,7 +476,7 @@ public class Element extends Base implements NamedItem {
|
||||||
} else {
|
} else {
|
||||||
Element ne = new Element(child).setFormat(format);
|
Element ne = new Element(child).setFormat(format);
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
numberChildren();
|
ne.index = children.getSizeByName(ne.getListName()) - 1;
|
||||||
childForValue = ne;
|
childForValue = ne;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -564,7 +564,7 @@ public class Element extends Base implements NamedItem {
|
||||||
} else {
|
} else {
|
||||||
Element ne = new Element(child).setFormat(format);
|
Element ne = new Element(child).setFormat(format);
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
numberChildren();
|
ne.index = children.getSizeByName(ne.getListName()) - 1;
|
||||||
return ne;
|
return ne;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,6 +574,7 @@ public class Element extends Base implements NamedItem {
|
||||||
if (p.getName().equals(name)) {
|
if (p.getName().equals(name)) {
|
||||||
Element ne = new Element(name, p).setFormat(format);
|
Element ne = new Element(name, p).setFormat(format);
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
|
ne.index = children.getSizeByName(ne.getListName()) - 1;
|
||||||
return ne;
|
return ne;
|
||||||
} else if (p.getDefinition().isChoice() && name.startsWith(p.getName().replace("[x]", ""))) {
|
} else if (p.getDefinition().isChoice() && name.startsWith(p.getName().replace("[x]", ""))) {
|
||||||
String type = name.substring(p.getName().length()-3);
|
String type = name.substring(p.getName().length()-3);
|
||||||
|
@ -583,6 +584,7 @@ public class Element extends Base implements NamedItem {
|
||||||
Element ne = new Element(name, p).setFormat(format);
|
Element ne = new Element(name, p).setFormat(format);
|
||||||
ne.setType(type);
|
ne.setType(type);
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
|
ne.index = children.getSizeByName(ne.getListName()) - 1;
|
||||||
return ne;
|
return ne;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -606,6 +608,7 @@ public class Element extends Base implements NamedItem {
|
||||||
if (p.getName().equals(name)) {
|
if (p.getName().equals(name)) {
|
||||||
Element ne = new Element(name, p).setFormat(format);
|
Element ne = new Element(name, p).setFormat(format);
|
||||||
children.add(ne);
|
children.add(ne);
|
||||||
|
ne.index = children.getSizeByName(ne.getListName()) - 1;
|
||||||
return ne;
|
return ne;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1664,4 +1667,4 @@ public class Element extends Base implements NamedItem {
|
||||||
return this.elided;
|
return this.elided;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,9 @@ import java.util.List;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
|
||||||
|
@ -144,7 +145,11 @@ public class Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Element build(IWorkerContext context, StructureDefinition sd) {
|
public static Element build(IWorkerContext context, StructureDefinition sd) {
|
||||||
Property p = new Property(context, sd.getSnapshot().getElementFirstRep(), sd);
|
return build(context, sd, new ProfileUtilities(context, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Element build(IWorkerContext context, StructureDefinition sd, ProfileUtilities profileUtilities) {
|
||||||
|
Property p = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, profileUtilities, new ContextUtilities(context));
|
||||||
Element e = new Element(p.getName(), p);
|
Element e = new Element(p.getName(), p);
|
||||||
e.setPath(sd.getType());
|
e.setPath(sd.getType());
|
||||||
return e;
|
return e;
|
||||||
|
|
|
@ -189,6 +189,13 @@ public class FHIRPathEngine {
|
||||||
// the application can implement them by providing a constant resolver
|
// the application can implement them by providing a constant resolver
|
||||||
public interface IEvaluationContext {
|
public interface IEvaluationContext {
|
||||||
|
|
||||||
|
public abstract class FunctionDefinition {
|
||||||
|
public abstract String name();
|
||||||
|
public abstract FunctionDetails details();
|
||||||
|
public abstract TypeDetails check(FHIRPathEngine engine, Object appContext, TypeDetails focus, List<TypeDetails> parameters);
|
||||||
|
public abstract List<Base> execute(FHIRPathEngine engine, Object appContext, List<Base> focus, List<List<Base>> parameters);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constant reference - e.g. a reference to a name that must be resolved in context.
|
* A constant reference - e.g. a reference to a name that must be resolved in context.
|
||||||
* The % will be removed from the constant name before this is invoked.
|
* The % will be removed from the constant name before this is invoked.
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
package org.hl7.fhir.r5.liquid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonArray;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonElement;
|
||||||
|
|
||||||
|
// this class exists to allow the Liquid Engine to be used against raw JSON
|
||||||
|
|
||||||
|
public class BaseCSVWrapper extends Base {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private List<String> columns;
|
||||||
|
private List<String> values;
|
||||||
|
private List<List<String>> rows;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
private BaseCSVWrapper() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseCSVWrapper forRows(List<String> columns, List<List<String>> rows) {
|
||||||
|
BaseCSVWrapper self = new BaseCSVWrapper();
|
||||||
|
self.columns = columns;
|
||||||
|
self.rows = rows;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseCSVWrapper forRow(List<String> columns, List<String> values) {
|
||||||
|
BaseCSVWrapper self = new BaseCSVWrapper();
|
||||||
|
self.columns = columns;
|
||||||
|
self.values = values;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseCSVWrapper forCell(String value) {
|
||||||
|
BaseCSVWrapper self = new BaseCSVWrapper();
|
||||||
|
self.value = value;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String fhirType() {
|
||||||
|
if (values != null || rows != null) {
|
||||||
|
return "Object";
|
||||||
|
} else if (Utilities.existsInList(value, "true", "false")) {
|
||||||
|
return "boolean";
|
||||||
|
} else if (Utilities.isInteger(value)) {
|
||||||
|
return "integer";
|
||||||
|
} else if (Utilities.isDecimal(value, true)) {
|
||||||
|
return "decimal";
|
||||||
|
} else if (Utilities.isAbsoluteUrl(value)) {
|
||||||
|
return "url";
|
||||||
|
} else {
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdBase() {
|
||||||
|
if (columns == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = columns.indexOf("id");
|
||||||
|
if (i > -1) {
|
||||||
|
return values.get(i);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdBase(String value) {
|
||||||
|
throw new Error("BaseCSVWrapper is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("BaseCSVWrapper is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirPublication getFHIRPublicationVersion() {
|
||||||
|
return FhirPublication.R5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
|
||||||
|
if (rows != null && "rows".equals(name)) {
|
||||||
|
Base[] l = new Base[rows.size()];
|
||||||
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
|
l[i] = BaseCSVWrapper.forRow(columns, rows.get(i));
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
if (values != null) {
|
||||||
|
int i = columns.indexOf(name);
|
||||||
|
if (i > -1) {
|
||||||
|
Base[] l = new Base[1];
|
||||||
|
l[0] = BaseCSVWrapper.forCell(values.get(i));
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.getProperty(hash, name, checkValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrimitive() {
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String primitiveValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package org.hl7.fhir.r5.liquid;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonArray;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonElement;
|
||||||
|
|
||||||
|
// this class exists to allow the Liquid Engine to be used against raw JSON
|
||||||
|
|
||||||
|
public class BaseJsonWrapper extends Base {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private JsonElement j;
|
||||||
|
|
||||||
|
public BaseJsonWrapper(JsonElement j) {
|
||||||
|
super();
|
||||||
|
this.j = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String fhirType() {
|
||||||
|
switch (j.type()) {
|
||||||
|
case BOOLEAN: return "boolean";
|
||||||
|
case NUMBER: return "decimal";
|
||||||
|
case OBJECT: return "Object";
|
||||||
|
case STRING: return "string";
|
||||||
|
default:
|
||||||
|
throw new Error("Shouldn't get here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdBase() {
|
||||||
|
if (j.isJsonObject()) {
|
||||||
|
return j.asJsonObject().asString("id");
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdBase(String value) {
|
||||||
|
throw new Error("BaseJsonWrapper is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("BaseJsonWrapper is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirPublication getFHIRPublicationVersion() {
|
||||||
|
return FhirPublication.R5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
|
||||||
|
if (j.isJsonObject() && j.asJsonObject().has(name)) {
|
||||||
|
JsonElement e = j.asJsonObject().get(name);
|
||||||
|
if (e.isJsonArray()) {
|
||||||
|
JsonArray a = e.asJsonArray();
|
||||||
|
Base[] l = new Base[a.size()];
|
||||||
|
for (int i = 0; i < a.size(); i++) {
|
||||||
|
l[i] = new BaseJsonWrapper(a.get(i));
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
} else {
|
||||||
|
Base[] l = new Base[1];
|
||||||
|
l[0] = new BaseJsonWrapper(e);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return super.getProperty(hash, name, checkValid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (j.isJsonPrimitive()) {
|
||||||
|
return j.asString();
|
||||||
|
} else {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrimitive() {
|
||||||
|
return j.isJsonPrimitive();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String primitiveValue() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package org.hl7.fhir.r5.liquid;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext.FunctionDefinition;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.TypeDetails;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.r5.model.IntegerType;
|
||||||
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
|
||||||
|
import com.microsoft.schemas.office.visio.x2012.main.impl.FunctionDefTypeImpl;
|
||||||
|
|
||||||
|
public class GlobalObject extends Base {
|
||||||
|
|
||||||
|
private DateTimeType dt;
|
||||||
|
private StringType pathToSpec;
|
||||||
|
|
||||||
|
public GlobalObject(DateTimeType td, StringType pathToSpec) {
|
||||||
|
super();
|
||||||
|
this.dt = td;
|
||||||
|
this.pathToSpec = pathToSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String fhirType() {
|
||||||
|
return "GlobalObject";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdBase() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdBase(String value) {
|
||||||
|
throw new Error("Read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirPublication getFHIRPublicationVersion() {
|
||||||
|
return FhirPublication.R5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
|
||||||
|
if ("dateTime".equals(name)) {
|
||||||
|
return wrap(dt);
|
||||||
|
} else if ("path".equals(name)) {
|
||||||
|
return wrap(pathToSpec);
|
||||||
|
} else {
|
||||||
|
return super.getProperty(hash, name, checkValid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Base[] wrap(Base b) {
|
||||||
|
Base[] l = new Base[1];
|
||||||
|
l[0] = b;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Base> executeFunction(FHIRPathEngine engine, Object appContext, List<Base> focus, String functionName, List<List<Base>> parameters) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GlobalObjectRandomFunction extends FunctionDefinition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "random";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FunctionDetails details() {
|
||||||
|
return new FunctionDetails("Generate a Random Number", 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeDetails check(FHIRPathEngine engine, Object appContext, TypeDetails focus, List<TypeDetails> parameters) {
|
||||||
|
if (focus.hasType("GlobalObject")) {
|
||||||
|
return new TypeDetails(CollectionStatus.SINGLETON, "integer");
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Base> execute(FHIRPathEngine engine, Object appContext, List<Base> focus, List<List<Base>> parameters) {
|
||||||
|
List<Base> list = new ArrayList<>();
|
||||||
|
int scale = Utilities.parseInt(parameters.get(0).get(0).primitiveValue(), 100)+ 1;
|
||||||
|
list.add(new IntegerType((int)(Math.random() * scale)));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hl7.fhir.r5.utils;
|
package org.hl7.fhir.r5.liquid;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -42,13 +42,19 @@ import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.fhirpath.ExpressionNode;
|
import org.hl7.fhir.r5.fhirpath.ExpressionNode;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRLexer;
|
import org.hl7.fhir.r5.fhirpath.FHIRLexer;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||||
import org.hl7.fhir.r5.fhirpath.TypeDetails;
|
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.ExpressionNodeWithOffset;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.ExpressionNodeWithOffset;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.TypeDetails;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.BooleanType;
|
||||||
|
import org.hl7.fhir.r5.model.IntegerType;
|
||||||
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
import org.hl7.fhir.r5.model.Tuple;
|
import org.hl7.fhir.r5.model.Tuple;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
@ -56,6 +62,94 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public class LiquidEngine implements IEvaluationContext {
|
public class LiquidEngine implements IEvaluationContext {
|
||||||
|
|
||||||
|
public static class LiquidForLoopObject extends Base {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 6951452522873320076L;
|
||||||
|
private boolean first;
|
||||||
|
private int index;
|
||||||
|
private int index0;
|
||||||
|
private int rindex;
|
||||||
|
private int rindex0;
|
||||||
|
private boolean last;
|
||||||
|
private int length;
|
||||||
|
private LiquidForLoopObject parentLoop;
|
||||||
|
|
||||||
|
|
||||||
|
public LiquidForLoopObject(int size, int i, int offset, int limit, LiquidForLoopObject parentLoop) {
|
||||||
|
super();
|
||||||
|
this.parentLoop = parentLoop;
|
||||||
|
if (offset == -1) {
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
if (limit == -1) {
|
||||||
|
limit = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
first = i == offset;
|
||||||
|
index = i+1-offset;
|
||||||
|
index0 = i-offset;
|
||||||
|
rindex = (limit-offset) - 1 - i;
|
||||||
|
rindex0 = (limit-offset) - i;
|
||||||
|
length = limit-offset;
|
||||||
|
last = i == (limit-offset)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdBase() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdBase(String value) {
|
||||||
|
throw new Error("forLoop is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("forLoop is read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirPublication getFHIRPublicationVersion() {
|
||||||
|
return FhirPublication.R5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
|
||||||
|
switch (name) {
|
||||||
|
case "parentLoop" : return wrap(parentLoop);
|
||||||
|
case "first" : return wrap(new BooleanType(first));
|
||||||
|
case "last" : return wrap(new BooleanType(last));
|
||||||
|
case "index" : return wrap(new IntegerType(index));
|
||||||
|
case "index0" : return wrap(new IntegerType(index0));
|
||||||
|
case "rindex" : return wrap(new IntegerType(rindex));
|
||||||
|
case "rindex0" : return wrap(new IntegerType(rindex0));
|
||||||
|
case "length" : return wrap(new IntegerType(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getProperty(hash, name, checkValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Base[] wrap(Base b) {
|
||||||
|
Base[] l = new Base[1];
|
||||||
|
l[0] = b;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "forLoop";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String fhirType() {
|
||||||
|
return "ForLoop";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public interface ILiquidRenderingSupport {
|
public interface ILiquidRenderingSupport {
|
||||||
String renderForLiquid(Object appContext, Base i) throws FHIRException;
|
String renderForLiquid(Object appContext, Base i) throws FHIRException;
|
||||||
}
|
}
|
||||||
|
@ -68,16 +162,19 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
private FHIRPathEngine engine;
|
private FHIRPathEngine engine;
|
||||||
private ILiquidEngineIncludeResolver includeResolver;
|
private ILiquidEngineIncludeResolver includeResolver;
|
||||||
private ILiquidRenderingSupport renderingSupport;
|
private ILiquidRenderingSupport renderingSupport;
|
||||||
|
private MarkDownProcessor processor = new MarkDownProcessor(Dialect.COMMON_MARK);
|
||||||
|
private Map<String, Base> vars = new HashMap<>();
|
||||||
|
|
||||||
private class LiquidEngineContext {
|
private class LiquidEngineContext {
|
||||||
private Object externalContext;
|
private Object externalContext;
|
||||||
private Map<String, Base> loopVars = new HashMap<>();
|
private Map<String, Base> loopVars = new HashMap<>();
|
||||||
private Map<String, Base> globalVars = new HashMap<>();
|
private Map<String, Base> globalVars = new HashMap<>();
|
||||||
|
|
||||||
public LiquidEngineContext(Object externalContext) {
|
public LiquidEngineContext(Object externalContext, Map<String, Base> vars) {
|
||||||
super();
|
super();
|
||||||
this.externalContext = externalContext;
|
this.externalContext = externalContext;
|
||||||
globalVars = new HashMap<>();
|
globalVars = new HashMap<>();
|
||||||
|
globalVars.putAll(vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiquidEngineContext(Object externalContext, LiquidEngineContext existing) {
|
public LiquidEngineContext(Object externalContext, LiquidEngineContext existing) {
|
||||||
|
@ -119,13 +216,17 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
this.renderingSupport = renderingSupport;
|
this.renderingSupport = renderingSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, Base> getVars() {
|
||||||
|
return vars;
|
||||||
|
}
|
||||||
|
|
||||||
public LiquidDocument parse(String source, String sourceName) throws FHIRException {
|
public LiquidDocument parse(String source, String sourceName) throws FHIRException {
|
||||||
return new LiquidParser(source).parse(sourceName);
|
return new LiquidParser(source).parse(sourceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String evaluate(LiquidDocument document, Base resource, Object appContext) throws FHIRException {
|
public String evaluate(LiquidDocument document, Base resource, Object appContext) throws FHIRException {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
LiquidEngineContext ctxt = new LiquidEngineContext(appContext);
|
LiquidEngineContext ctxt = new LiquidEngineContext(appContext, vars );
|
||||||
for (LiquidNode n : document.body) {
|
for (LiquidNode n : document.body) {
|
||||||
n.evaluate(b, resource, ctxt);
|
n.evaluate(b, resource, ctxt);
|
||||||
}
|
}
|
||||||
|
@ -162,12 +263,24 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum LiquidFilter {
|
private enum LiquidFilter {
|
||||||
PREPEND;
|
PREPEND,
|
||||||
|
MARKDOWNIFY,
|
||||||
|
UPCASE,
|
||||||
|
DOWNCASE;
|
||||||
|
|
||||||
public static LiquidFilter fromCode(String code) {
|
public static LiquidFilter fromCode(String code) {
|
||||||
if ("prepend".equals(code)) {
|
if ("prepend".equals(code)) {
|
||||||
return PREPEND;
|
return PREPEND;
|
||||||
}
|
}
|
||||||
|
if ("markdownify".equals(code)) {
|
||||||
|
return MARKDOWNIFY;
|
||||||
|
}
|
||||||
|
if ("upcase".equals(code)) {
|
||||||
|
return UPCASE;
|
||||||
|
}
|
||||||
|
if ("downcase".equals(code)) {
|
||||||
|
return DOWNCASE;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,12 +334,25 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
} else switch (i.filter) {
|
} else switch (i.filter) {
|
||||||
case PREPEND:
|
case PREPEND:
|
||||||
t = stmtToString(ctxt, engine.evaluate(ctxt, resource, resource, resource, i.expression)) + t;
|
t = stmtToString(ctxt, engine.evaluate(ctxt, resource, resource, resource, i.expression)) + t;
|
||||||
|
break;
|
||||||
|
case MARKDOWNIFY:
|
||||||
|
t = processMarkdown(t);
|
||||||
|
break;
|
||||||
|
case UPCASE:
|
||||||
|
t = t.toUpperCase();
|
||||||
|
break;
|
||||||
|
case DOWNCASE:
|
||||||
|
t = t.toLowerCase();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.append(t);
|
b.append(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String processMarkdown(String t) {
|
||||||
|
return processor.process(t, "liquid");
|
||||||
|
}
|
||||||
|
|
||||||
private String stmtToString(LiquidEngineContext ctxt, List<Base> items) {
|
private String stmtToString(LiquidEngineContext ctxt, List<Base> items) {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
@ -375,6 +501,7 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
Collections.reverse(list);
|
Collections.reverse(list);
|
||||||
}
|
}
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
LiquidForLoopObject parentLoop = (LiquidForLoopObject) lctxt.globalVars.get("forLoop");
|
||||||
for (Base o : list) {
|
for (Base o : list) {
|
||||||
if (offset >= 0 && i < offset) {
|
if (offset >= 0 && i < offset) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -383,6 +510,8 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
if (limit >= 0 && i == limit) {
|
if (limit >= 0 && i == limit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
LiquidForLoopObject forloop = new LiquidForLoopObject(list.size(), i, offset, limit, parentLoop);
|
||||||
|
lctxt.globalVars.put("forLoop", forloop);
|
||||||
if (lctxt.globalVars.containsKey(varName)) {
|
if (lctxt.globalVars.containsKey(varName)) {
|
||||||
throw new FHIRException(engine.getWorker().formatMessage(I18nConstants.LIQUID_VARIABLE_ALREADY_ASSIGNED, varName));
|
throw new FHIRException(engine.getWorker().formatMessage(I18nConstants.LIQUID_VARIABLE_ALREADY_ASSIGNED, varName));
|
||||||
}
|
}
|
||||||
|
@ -403,6 +532,7 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
lctxt.globalVars.put("forLoop", parentLoop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +579,20 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class LiquidCapture extends LiquidNode {
|
||||||
|
private String varName;
|
||||||
|
private List<LiquidNode> body = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evaluate(StringBuilder b, Base resource, LiquidEngineContext ctxt) throws FHIRException {
|
||||||
|
StringBuilder bc = new StringBuilder();
|
||||||
|
for (LiquidNode n : body) {
|
||||||
|
n.evaluate(bc, resource, ctxt);
|
||||||
|
}
|
||||||
|
ctxt.globalVars.put(varName, new StringType(bc.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class LiquidInclude extends LiquidNode {
|
private class LiquidInclude extends LiquidNode {
|
||||||
private String page;
|
private String page;
|
||||||
private Map<String, ExpressionNode> params = new HashMap<>();
|
private Map<String, ExpressionNode> params = new HashMap<>();
|
||||||
|
@ -489,6 +633,9 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
|
|
||||||
public LiquidParser(String source) {
|
public LiquidParser(String source) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
if (source == null) {
|
||||||
|
throw new FHIRException("No Liquid source to parse");
|
||||||
|
}
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,6 +716,8 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
list.add(parseInclude(cnt.substring(7).trim()));
|
list.add(parseInclude(cnt.substring(7).trim()));
|
||||||
else if (cnt.startsWith("assign "))
|
else if (cnt.startsWith("assign "))
|
||||||
list.add(parseAssign(cnt.substring(6).trim()));
|
list.add(parseAssign(cnt.substring(6).trim()));
|
||||||
|
else if (cnt.startsWith("capture "))
|
||||||
|
list.add(parseCapture(cnt.substring(7).trim()));
|
||||||
else
|
else
|
||||||
throw new FHIRException(engine.getWorker().formatMessage(I18nConstants.LIQUID_UNKNOWN_FLOW_STMT,name, cnt));
|
throw new FHIRException(engine.getWorker().formatMessage(I18nConstants.LIQUID_UNKNOWN_FLOW_STMT,name, cnt));
|
||||||
} else { // next2() == '{'
|
} else { // next2() == '{'
|
||||||
|
@ -697,6 +846,16 @@ public class LiquidEngine implements IEvaluationContext {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LiquidNode parseCapture(String cnt) throws FHIRException {
|
||||||
|
int i = 0;
|
||||||
|
while (i < cnt.length() && !Character.isWhitespace(cnt.charAt(i)))
|
||||||
|
i++;
|
||||||
|
LiquidCapture res = new LiquidCapture();
|
||||||
|
res.varName = cnt.substring(0, i);
|
||||||
|
parseList(res.body, true, new String[] { "endcapture" });
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private LiquidNode parseAssign(String cnt) throws FHIRException {
|
private LiquidNode parseAssign(String cnt) throws FHIRException {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (!Character.isWhitespace(cnt.charAt(i)))
|
while (!Character.isWhitespace(cnt.charAt(i)))
|
|
@ -36,7 +36,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||||
import org.hl7.fhir.utilities.FhirPublication;
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
|
@ -629,4 +629,10 @@ public abstract class Base implements Serializable, IBase, IElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract FhirPublication getFHIRPublicationVersion();
|
public abstract FhirPublication getFHIRPublicationVersion();
|
||||||
|
|
||||||
|
public List<Base> executeFunction(FHIRPathEngine engine, Object appContext, List<Base> focus, String functionName, List<List<Base>> parameters) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,9 @@ package org.hl7.fhir.r5.profilemodel;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
@ -352,6 +354,7 @@ public class PEBuilder {
|
||||||
list = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
|
list = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
|
||||||
}
|
}
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
|
Set<String> names = new HashSet<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < list.size()) {
|
while (i < list.size()) {
|
||||||
ElementDefinition defn = list.get(i);
|
ElementDefinition defn = list.get(i);
|
||||||
|
@ -361,7 +364,8 @@ public class PEBuilder {
|
||||||
// DebugUtilities.breakpoint();
|
// DebugUtilities.breakpoint();
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
PEDefinitionElement pe = new PEDefinitionElement(this, profile, defn, parent.path());
|
String name = uniquefy(names, defn.getName());
|
||||||
|
PEDefinitionElement pe = new PEDefinitionElement(this, name, profile, defn, parent.path());
|
||||||
pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
|
pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
|
||||||
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
||||||
pe.setMustHaveValue(definition.getMustHaveValue());
|
pe.setMustHaveValue(definition.getMustHaveValue());
|
||||||
|
@ -376,14 +380,14 @@ public class PEBuilder {
|
||||||
while (i < list.size() && list.get(i).getPath().equals(defn.getPath())) {
|
while (i < list.size() && list.get(i).getPath().equals(defn.getPath())) {
|
||||||
StructureDefinition ext = getExtensionDefinition(list.get(i));
|
StructureDefinition ext = getExtensionDefinition(list.get(i));
|
||||||
if (ext != null) {
|
if (ext != null) {
|
||||||
res.add(new PEDefinitionExtension(this, list.get(i).getSliceName(), profile, list.get(i), defn, ext, parent.path()));
|
res.add(new PEDefinitionExtension(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, ext, parent.path()));
|
||||||
} else if (isTypeSlicing(defn)) {
|
} else if (isTypeSlicing(defn)) {
|
||||||
res.add(new PEDefinitionTypeSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn, parent.path()));
|
res.add(new PEDefinitionTypeSlice(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, parent.path()));
|
||||||
} else {
|
} else {
|
||||||
if (ProfileUtilities.isComplexExtension(profile) && defn.getPath().endsWith(".extension")) {
|
if (ProfileUtilities.isComplexExtension(profile) && defn.getPath().endsWith(".extension")) {
|
||||||
res.add(new PEDefinitionSubExtension(this, profile, list.get(i), parent.path()));
|
res.add(new PEDefinitionSubExtension(this, profile, list.get(i), parent.path()));
|
||||||
} else {
|
} else {
|
||||||
res.add(new PEDefinitionSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn, parent.path()));
|
res.add(new PEDefinitionSlice(this, uniquefy(names, list.get(i).getSliceName()), profile, list.get(i), defn, parent.path()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -409,6 +413,18 @@ public class PEBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String uniquefy(Set<String> names, String name) {
|
||||||
|
if (names.contains(name)) {
|
||||||
|
int i = 0;
|
||||||
|
while (names.contains(name+i)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
name = name+i;
|
||||||
|
}
|
||||||
|
names.add(name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
protected PEDefinition makeChild(PEDefinition parent, StructureDefinition profileStructure, ElementDefinition definition) {
|
protected PEDefinition makeChild(PEDefinition parent, StructureDefinition profileStructure, ElementDefinition definition) {
|
||||||
PEDefinitionElement pe = new PEDefinitionElement(this, profileStructure, definition, parent.path());
|
PEDefinitionElement pe = new PEDefinitionElement(this, profileStructure, definition, parent.path());
|
||||||
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
|
||||||
|
|
|
@ -42,6 +42,10 @@ public class PEDefinitionElement extends PEDefinition {
|
||||||
super(builder, definition.getName(), profile, definition, ppath);
|
super(builder, definition.getName(), profile, definition, ppath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PEDefinitionElement(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition definition, String ppath) {
|
||||||
|
super(builder, name, profile, definition, ppath);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listTypes(List<PEType> types) {
|
public void listTypes(List<PEType> types) {
|
||||||
for (TypeRefComponent t : definition.getType()) {
|
for (TypeRefComponent t : definition.getType()) {
|
||||||
|
|
|
@ -1,62 +1,28 @@
|
||||||
package org.hl7.fhir.r5.profilemodel.gen;
|
package org.hl7.fhir.r5.profilemodel.gen;
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, \
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this \
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, \
|
|
||||||
this list of conditions and the following disclaimer in the documentation \
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
|
||||||
endorse or promote products derived from this software without specific
|
|
||||||
prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND \
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \
|
|
||||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \
|
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \
|
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR \
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \
|
|
||||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
|
||||||
import org.hl7.fhir.r5.model.DataType;
|
import org.hl7.fhir.r5.model.DataType;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||||
import org.hl7.fhir.r5.model.Identifier;
|
|
||||||
import org.hl7.fhir.r5.model.Observation;
|
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.profilemodel.PEBuilder;
|
import org.hl7.fhir.r5.profilemodel.PEBuilder;
|
||||||
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
||||||
import org.hl7.fhir.r5.profilemodel.gen.PECodeGenerator.ExtensionPolicy;
|
import org.hl7.fhir.r5.profilemodel.PEDefinition;
|
||||||
|
import org.hl7.fhir.r5.profilemodel.PEType;
|
||||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.utils.UserDataNames;
|
import org.hl7.fhir.r5.utils.UserDataNames;
|
||||||
import org.hl7.fhir.r5.profilemodel.PEDefinition;
|
|
||||||
import org.hl7.fhir.r5.profilemodel.PEInstance;
|
|
||||||
import org.hl7.fhir.r5.profilemodel.PEType;
|
|
||||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||||
import org.hl7.fhir.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
@ -252,6 +218,9 @@ public class PECodeGenerator {
|
||||||
if (vse.isOk()) {
|
if (vse.isOk()) {
|
||||||
String baseName = Utilities.nmtokenize(Utilities.singularise(vs.getName()));
|
String baseName = Utilities.nmtokenize(Utilities.singularise(vs.getName()));
|
||||||
String name = baseName;
|
String name = baseName;
|
||||||
|
if (workerContext.getResourceNames().contains(name)) {
|
||||||
|
name = name+"Type";
|
||||||
|
}
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while (enumNames.contains(name)) {
|
while (enumNames.contains(name)) {
|
||||||
c++;
|
c++;
|
||||||
|
@ -427,8 +396,19 @@ public class PECodeGenerator {
|
||||||
private void genLoad(boolean isPrim, boolean isAbstract, String name, String sname, String fname, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, boolean isFixed, PEType typeInfo, boolean isEnum) {
|
private void genLoad(boolean isPrim, boolean isAbstract, String name, String sname, String fname, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, boolean isFixed, PEType typeInfo, boolean isEnum) {
|
||||||
if (isList) {
|
if (isList) {
|
||||||
w(load, " for (PEInstance item : src.children(\""+fname+"\")) {");
|
w(load, " for (PEInstance item : src.children(\""+fname+"\")) {");
|
||||||
if ("BackboneElement".equals(type)) {
|
if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
||||||
|
w(load, " "+name+".add("+type+".fromSource(src.child(\""+fname+"\")));");
|
||||||
|
|
||||||
|
} else if ("BackboneElement".equals(type)) {
|
||||||
w(load, " "+name+".add(("+type+") item.asElement());");
|
w(load, " "+name+".add(("+type+") item.asElement());");
|
||||||
|
} else if (isEnum) {
|
||||||
|
if ("CodeableConcept".equals(typeInfo.getName())) {
|
||||||
|
w(load, " "+name+".add("+type+".fromCodeableConcept((CodeableConcept) item.asDataType()));");
|
||||||
|
} else if ("Coding".equals(typeInfo.getName())) {
|
||||||
|
w(load, " "+name+".add("+type+".fromCoding((Coding) item.asDataType()));");
|
||||||
|
} else {
|
||||||
|
w(load, " "+name+".add("+type+".fromCode(item.asDataType().primitiveValue()));");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+".add(("+type+") item.asDataType());");
|
w(load, " "+name+".add(("+type+") item.asDataType());");
|
||||||
}
|
}
|
||||||
|
@ -462,6 +442,10 @@ public class PECodeGenerator {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asElement();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asElement();");
|
||||||
} else if (Utilities.existsInList(type, workerContext.getResourceNames())) {
|
} else if (Utilities.existsInList(type, workerContext.getResourceNames())) {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asResource();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asResource();");
|
||||||
|
} else if("Reference".equals(type)) {
|
||||||
|
w(load, " "+type+" ref = ("+type+") src.child(\""+fname+"\").asDataType();");
|
||||||
|
w(load, " if(!ref.isEmpty())");
|
||||||
|
w(load, " "+name+" = ref;");
|
||||||
} else {
|
} else {
|
||||||
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asDataType();");
|
w(load, " "+name+" = ("+type+") src.child(\""+fname+"\").asDataType();");
|
||||||
}
|
}
|
||||||
|
@ -474,7 +458,19 @@ public class PECodeGenerator {
|
||||||
if (isList) {
|
if (isList) {
|
||||||
w(save, " for ("+type+" item : "+name+") {");
|
w(save, " for ("+type+" item : "+name+") {");
|
||||||
if (isExtension) {
|
if (isExtension) {
|
||||||
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", item);");
|
if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
|
||||||
|
w(save, " item.save(tgt.makeChild(\""+fname+"\"), false);");
|
||||||
|
} else {
|
||||||
|
w(save, " tgt.makeChild(\""+fname+"\").data().setProperty(\"value[x]\", item);");
|
||||||
|
}
|
||||||
|
} else if (isEnum) {
|
||||||
|
if ("CodeableConcept".equals(typeInfo.getName())) {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCodeableConcept());");
|
||||||
|
} else if ("Coding".equals(typeInfo.getName())) {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCoding());");
|
||||||
|
} else {
|
||||||
|
w(save, " tgt.addChild(\""+fname+"\", item.toCode());");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w(save, " tgt.addChild(\""+fname+"\", item);");
|
w(save, " tgt.addChild(\""+fname+"\", item);");
|
||||||
}
|
}
|
||||||
|
@ -574,13 +570,20 @@ public class PECodeGenerator {
|
||||||
w(accessors, " return "+name+" != null && !"+name+".isEmpty();");
|
w(accessors, " return "+name+" != null && !"+name+".isEmpty();");
|
||||||
w(accessors, " }");
|
w(accessors, " }");
|
||||||
w(accessors);
|
w(accessors);
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
w(accessors, " public "+type+" add"+csname+"() {");
|
if (!isEnum) {
|
||||||
w(accessors, " "+type+" theThing = new "+type+"();");
|
w(accessors, " public "+type+" add"+csname+"() {");
|
||||||
w(accessors, " get"+cname+"().add(theThing);");
|
w(accessors, " "+type+" theThing = new "+type+"();");
|
||||||
w(accessors, " return theThing;");
|
w(accessors, " get"+cname+"().add(theThing);");
|
||||||
w(accessors, " }");
|
w(accessors, " return theThing;");
|
||||||
w(accessors);
|
w(accessors, " }");
|
||||||
|
w(accessors);
|
||||||
|
} else {
|
||||||
|
w(accessors, " public void add"+csname+"("+type+" theThing) {");
|
||||||
|
w(accessors, " get"+cname+"().add(theThing);");
|
||||||
|
w(accessors, " }");
|
||||||
|
w(accessors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w(accessors, " public boolean has"+csname+"("+type+" item) {");
|
w(accessors, " public boolean has"+csname+"("+type+" item) {");
|
||||||
w(accessors, " return has"+cname+"() && "+name+".contains(item);");
|
w(accessors, " return has"+cname+"() && "+name+".contains(item);");
|
||||||
|
@ -789,8 +792,9 @@ public class PECodeGenerator {
|
||||||
PEDefinition source = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition(canonical);
|
PEDefinition source = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition(canonical);
|
||||||
w(imports, "import java.util.List;");
|
w(imports, "import java.util.List;");
|
||||||
w(imports, "import java.util.ArrayList;");
|
w(imports, "import java.util.ArrayList;");
|
||||||
w(imports, "import javax.annotation.Nullable;");
|
|
||||||
w(imports, "import java.util.Date;\r\n");
|
w(imports, "import java.util.Date;\r\n");
|
||||||
|
w(imports, "import java.math.BigDecimal;");
|
||||||
|
w(imports, "import javax.annotation.Nullable;");
|
||||||
w(imports);
|
w(imports);
|
||||||
w(imports, "import org.hl7.fhir."+version+".context.IWorkerContext;");
|
w(imports, "import org.hl7.fhir."+version+".context.IWorkerContext;");
|
||||||
w(imports, "import org.hl7.fhir."+version+".model.*;");
|
w(imports, "import org.hl7.fhir."+version+".model.*;");
|
||||||
|
@ -807,7 +811,7 @@ public class PECodeGenerator {
|
||||||
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.MustSupport;");
|
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.MustSupport;");
|
||||||
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.Definition;");
|
w(imports, "import org.hl7.fhir."+version+".profilemodel.gen.Definition;");
|
||||||
|
|
||||||
|
|
||||||
PEGenClass cls = genClass(source);
|
PEGenClass cls = genClass(source);
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
w(b, "package "+pkgName+";");
|
w(b, "package "+pkgName+";");
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
||||||
|
|
||||||
for (ResourceWrapper cont : dr.children("contained")) {
|
for (ResourceWrapper cont : dr.children("contained")) {
|
||||||
x.hr();
|
x.hr();
|
||||||
RendererFactory.factory(cont, context.forContained()).buildNarrative(status, x, cont);
|
RendererFactory.factory(cont, context.forContained()).setInner(true).buildNarrative(status, x, cont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,14 @@ import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.ILiquidRenderingSupport;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.DataType;
|
import org.hl7.fhir.r5.model.DataType;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine;
|
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidRenderingSupport;
|
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
x.hr();
|
x.hr();
|
||||||
RendererFactory.factory(cont, context.forContained()).buildNarrative(status, x, cont);
|
RendererFactory.factory(cont, context.forContained()).setInner(true).buildNarrative(status, x, cont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +565,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
||||||
if (i.has("answerValueSet")) {
|
if (i.has("answerValueSet")) {
|
||||||
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
|
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
|
||||||
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null));
|
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null));
|
||||||
if (Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) {
|
if (Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) {
|
||||||
ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1));
|
ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1));
|
||||||
if (vs == null) {
|
if (vs == null) {
|
||||||
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
|
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
|
||||||
|
|
|
@ -76,6 +76,7 @@ public class RendererFactory {
|
||||||
case "Patient": return new PatientRenderer(context);
|
case "Patient": return new PatientRenderer(context);
|
||||||
case "Provenance": return new ProvenanceRenderer(context);
|
case "Provenance": return new ProvenanceRenderer(context);
|
||||||
case "Parameters": return new ParametersRenderer(context);
|
case "Parameters": return new ParametersRenderer(context);
|
||||||
|
case "Questionnaire": return new QuestionnaireRenderer(context);
|
||||||
case "QuestionnaireResponse": return new QuestionnaireResponseRenderer(context);
|
case "QuestionnaireResponse": return new QuestionnaireResponseRenderer(context);
|
||||||
}
|
}
|
||||||
if (resource.isDirect()) {
|
if (resource.isDirect()) {
|
||||||
|
|
|
@ -51,6 +51,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
|
|
||||||
protected XVerExtensionManager xverManager;
|
protected XVerExtensionManager xverManager;
|
||||||
protected boolean multiLangMode;
|
protected boolean multiLangMode;
|
||||||
|
protected boolean inner;
|
||||||
|
|
||||||
|
|
||||||
public ResourceRenderer(RenderingContext context) {
|
public ResourceRenderer(RenderingContext context) {
|
||||||
|
@ -70,6 +71,15 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInner() {
|
||||||
|
return inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceRenderer setInner(boolean inner) {
|
||||||
|
this.inner = inner;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just build the narrative that would go in the resource (per @renderResource()), but don't put it in the resource
|
* Just build the narrative that would go in the resource (per @renderResource()), but don't put it in the resource
|
||||||
* @param dr
|
* @param dr
|
||||||
|
@ -837,9 +847,9 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
XhtmlNode p = x.para().attribute("class", "res-header-id");
|
XhtmlNode p = x.para().attribute("class", "res-header-id");
|
||||||
String ft = context.getTranslatedCode(r.fhirType(), "http://hl7.org/fhir/fhir-types");
|
String ft = context.getTranslatedCode(r.fhirType(), "http://hl7.org/fhir/fhir-types");
|
||||||
if (desc == null) {
|
if (desc == null) {
|
||||||
p.b().tx(context.formatPhrase(context.isTechnicalMode() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, ""));
|
p.b().tx(context.formatPhrase(context.isTechnicalMode() && !isInner() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, ""));
|
||||||
} else {
|
} else {
|
||||||
p.b().tx(context.formatPhrase(context.isTechnicalMode() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, desc));
|
p.b().tx(context.formatPhrase(context.isTechnicalMode() && !isInner() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// first thing we do is lay down the resource anchors.
|
// first thing we do is lay down the resource anchors.
|
||||||
|
@ -1464,7 +1474,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
context.addAnchor(id);
|
context.addAnchor(id);
|
||||||
x.an(context.prefixAnchor(id));
|
x.an(context.prefixAnchor(id));
|
||||||
}
|
}
|
||||||
RendererFactory.factory(c, context.forContained()).buildNarrative(status, x, c);
|
RendererFactory.factory(c, context.forContained()).setInner(true).buildNarrative(status, x, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,7 @@ public class ResourceWrapperModel extends ResourceWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWebPath() {
|
public String getWebPath() {
|
||||||
return null;
|
return model.getWebPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCodeSystemUri() {
|
public String getCodeSystemUri() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||||
import org.hl7.fhir.r5.context.CanonicalResourceManager;
|
import org.hl7.fhir.r5.context.CanonicalResourceManager;
|
||||||
|
import org.hl7.fhir.r5.context.ILoggingService;
|
||||||
import org.hl7.fhir.r5.model.Bundle;
|
import org.hl7.fhir.r5.model.Bundle;
|
||||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
|
@ -27,6 +28,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseType;
|
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseType;
|
||||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ServerOptionList;
|
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ServerOptionList;
|
||||||
|
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5.TerminologyClientR5Factory;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedCodeSystem;
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedCodeSystem;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
|
||||||
|
@ -86,11 +88,14 @@ public class TerminologyClientManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InternalLogEvent {
|
public class InternalLogEvent {
|
||||||
|
private boolean error;
|
||||||
private String message;
|
private String message;
|
||||||
private String server;
|
private String server;
|
||||||
private String vs;
|
private String vs;
|
||||||
private String systems;
|
private String systems;
|
||||||
private String choices;
|
private String choices;
|
||||||
|
private String context;
|
||||||
|
private String request;
|
||||||
protected InternalLogEvent(String message, String server, String vs, String systems, String choices) {
|
protected InternalLogEvent(String message, String server, String vs, String systems, String choices) {
|
||||||
super();
|
super();
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
@ -99,9 +104,12 @@ public class TerminologyClientManager {
|
||||||
this.systems = systems;
|
this.systems = systems;
|
||||||
this.choices = choices;
|
this.choices = choices;
|
||||||
}
|
}
|
||||||
protected InternalLogEvent(String message) {
|
protected InternalLogEvent(String message, String ctxt, String request) {
|
||||||
super();
|
super();
|
||||||
|
error = true;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
this.context = ctxt;
|
||||||
|
this.request = request;
|
||||||
}
|
}
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return message;
|
return message;
|
||||||
|
@ -118,7 +126,15 @@ public class TerminologyClientManager {
|
||||||
public String getServer() {
|
public String getServer() {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
public boolean isError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
public String getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
public String getRequest() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String UNRESOLVED_VALUESET = "--unknown--";
|
public static final String UNRESOLVED_VALUESET = "--unknown--";
|
||||||
|
@ -142,10 +158,13 @@ public class TerminologyClientManager {
|
||||||
|
|
||||||
private boolean useEcosystem;
|
private boolean useEcosystem;
|
||||||
|
|
||||||
public TerminologyClientManager(ITerminologyClientFactory factory, String cacheId) {
|
private ILoggingService logger;
|
||||||
|
|
||||||
|
public TerminologyClientManager(ITerminologyClientFactory factory, String cacheId, ILoggingService logger) {
|
||||||
super();
|
super();
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.cacheId = cacheId;
|
this.cacheId = cacheId;
|
||||||
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCacheId() {
|
public String getCacheId() {
|
||||||
|
@ -301,15 +320,24 @@ public class TerminologyClientManager {
|
||||||
serverList = decideWhichServer(s);
|
serverList = decideWhichServer(s);
|
||||||
// testing support
|
// testing support
|
||||||
try {
|
try {
|
||||||
serverList.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
|
serverList.replace("tx.fhir.org", host());
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
}
|
}
|
||||||
resMap.put(s, serverList);
|
// resMap.put(s, serverList);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
return serverList;
|
return serverList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String host() throws MalformedURLException {
|
||||||
|
URL url = new URL(getMasterClient().getAddress());
|
||||||
|
if (url.getPort() > 0) {
|
||||||
|
return url.getHost()+":"+url.getPort();
|
||||||
|
} else {
|
||||||
|
return url.getHost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ServerOptionList decideWhichServer(String url) {
|
private ServerOptionList decideWhichServer(String url) {
|
||||||
if (IGNORE_TX_REGISTRY || !useEcosystem) {
|
if (IGNORE_TX_REGISTRY || !useEcosystem) {
|
||||||
return new ServerOptionList(getMasterClient().getAddress());
|
return new ServerOptionList(getMasterClient().getAddress());
|
||||||
|
@ -346,11 +374,11 @@ public class TerminologyClientManager {
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "Error resolving system "+url+": "+e.getMessage()+" ("+request+")";
|
String msg = "Error resolving system "+url+": "+e.getMessage();
|
||||||
if (!hasMessage(msg)) {
|
if (!hasMessage(msg)) {
|
||||||
internalLog.add(new InternalLogEvent(msg));
|
internalLog.add(new InternalLogEvent(msg, url, request));
|
||||||
}
|
}
|
||||||
if (!monitorServiceURL.contains("tx.fhir.org")) {
|
if (logger.isDebugLogging()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,7 +554,7 @@ public class TerminologyClientManager {
|
||||||
}
|
}
|
||||||
if (server.contains("://tx.fhir.org")) {
|
if (server.contains("://tx.fhir.org")) {
|
||||||
try {
|
try {
|
||||||
server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
|
server = server.replace("tx.fhir.org", host());
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,12 +599,13 @@ public class TerminologyClientManager {
|
||||||
ValueSet vs = (ValueSet) client.getClient().read("ValueSet", rid);
|
ValueSet vs = (ValueSet) client.getClient().read("ValueSet", rid);
|
||||||
return new SourcedValueSet(server, vs);
|
return new SourcedValueSet(server, vs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
String msg = "Error resolving valueSet "+canonical+": "+e.getMessage();
|
||||||
String msg = "Error resolving valueSet "+canonical+": "+e.getMessage()+" ("+request+")";
|
|
||||||
if (!hasMessage(msg)) {
|
if (!hasMessage(msg)) {
|
||||||
internalLog.add(new InternalLogEvent(msg));
|
internalLog.add(new InternalLogEvent(msg, canonical, request));
|
||||||
|
}
|
||||||
|
if (logger.isDebugLogging()) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -607,7 +636,7 @@ public class TerminologyClientManager {
|
||||||
}
|
}
|
||||||
if (server.contains("://tx.fhir.org")) {
|
if (server.contains("://tx.fhir.org")) {
|
||||||
try {
|
try {
|
||||||
server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
|
server = server.replace("tx.fhir.org", host());
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -651,12 +680,13 @@ public class TerminologyClientManager {
|
||||||
CodeSystem vs = (CodeSystem) client.getClient().read("CodeSystem", rid);
|
CodeSystem vs = (CodeSystem) client.getClient().read("CodeSystem", rid);
|
||||||
return new SourcedCodeSystem(server, vs);
|
return new SourcedCodeSystem(server, vs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
String msg = "Error resolving CodeSystem "+canonical+": "+e.getMessage();
|
||||||
String msg = "Error resolving valueSet "+canonical+": "+e.getMessage()+" ("+request+")";
|
|
||||||
if (!hasMessage(msg)) {
|
if (!hasMessage(msg)) {
|
||||||
internalLog.add(new InternalLogEvent(msg));
|
internalLog.add(new InternalLogEvent(msg, canonical, request));
|
||||||
|
}
|
||||||
|
if (logger.isDebugLogging()) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,4 +703,14 @@ public class TerminologyClientManager {
|
||||||
public List<InternalLogEvent> getInternalLog() {
|
public List<InternalLogEvent> getInternalLog() {
|
||||||
return internalLog;
|
return internalLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ILoggingService getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogger(ILoggingService logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ public class CompareUtilities extends BaseTestingUtilities {
|
||||||
case "$url$": return "\"A URL\"";
|
case "$url$": return "\"A URL\"";
|
||||||
case "$token$": return "\"A Token\"";
|
case "$token$": return "\"A Token\"";
|
||||||
case "$version$": return variables.containsKey("version") ? variables.get("version") : "(anything)";
|
case "$version$": return variables.containsKey("version") ? variables.get("version") : "(anything)";
|
||||||
|
case "$semver$": return "A semver";
|
||||||
default: return "Unhandled template: "+expected;
|
default: return "Unhandled template: "+expected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,6 +559,7 @@ public class CompareUtilities extends BaseTestingUtilities {
|
||||||
case "$id$": return actualJsonString.matches("[A-Za-z0-9\\-\\.]{1,64}");
|
case "$id$": return actualJsonString.matches("[A-Za-z0-9\\-\\.]{1,64}");
|
||||||
case "$url$": return actualJsonString.matches("(https?://|www\\.)[-a-zA-Z0-9+&@#/%?=~_|!:.;]*[-a-zA-Z0-9+&@#/%=~_|]");
|
case "$url$": return actualJsonString.matches("(https?://|www\\.)[-a-zA-Z0-9+&@#/%?=~_|!:.;]*[-a-zA-Z0-9+&@#/%=~_|]");
|
||||||
case "$token$": return actualJsonString.matches("[0-9a-zA-Z_][0-9a-zA-Z_\\.\\-]*");
|
case "$token$": return actualJsonString.matches("[0-9a-zA-Z_][0-9a-zA-Z_\\.\\-]*");
|
||||||
|
case "$semver$": return actualJsonString.matches("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
|
||||||
case "$version$": return matchesVariable(actualJsonString, "version");
|
case "$version$": return matchesVariable(actualJsonString, "version");
|
||||||
default:
|
default:
|
||||||
throw new Error("Unhandled template: "+expectedJsonString);
|
throw new Error("Unhandled template: "+expectedJsonString);
|
||||||
|
|
|
@ -441,7 +441,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
||||||
try {
|
try {
|
||||||
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException(0, "An error has occurred while trying to retrieve history since last update", e);
|
handleException(0, "An error has occurred while trying to read a bundle", e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.hl7.fhir.r5.utils.client.EFhirClientException;
|
||||||
import org.hl7.fhir.r5.utils.client.ResourceFormat;
|
import org.hl7.fhir.r5.utils.client.ResourceFormat;
|
||||||
import org.hl7.fhir.utilities.MimeType;
|
import org.hl7.fhir.utilities.MimeType;
|
||||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.http.*;
|
import org.hl7.fhir.utilities.http.*;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
import org.hl7.fhir.utilities.xhtml.XhtmlUtils;
|
||||||
|
|
||||||
|
@ -162,7 +163,11 @@ public class FhirRequestBuilder {
|
||||||
boolean ok = code >= 200 && code < 300;
|
boolean ok = code >= 200 && code < 300;
|
||||||
if (response.getContent() == null) {
|
if (response.getContent() == null) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw new EFhirClientException(code, response.getMessage());
|
if (Utilities.noString(response.getMessage())) {
|
||||||
|
throw new EFhirClientException(code, response.getMessagefromCode());
|
||||||
|
} else {
|
||||||
|
throw new EFhirClientException(code, response.getMessage());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.hl7.fhir.r5.utils.structuremap;
|
package org.hl7.fhir.r5.utils.structuremap;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ public interface ITransformerServices {
|
||||||
// public boolean validateByValueSet(Coding code, String valuesetId);
|
// public boolean validateByValueSet(Coding code, String valuesetId);
|
||||||
public void log(String message); // log internal progress
|
public void log(String message); // log internal progress
|
||||||
|
|
||||||
public Base createType(Object appInfo, String name) throws FHIRException;
|
public Base createType(Object appInfo, String name, ProfileUtilities profileUtilities) throws FHIRException;
|
||||||
|
|
||||||
public Base createResource(Object appInfo, Base res, boolean atRootofTransform); // an already created resource is provided; this is to identify/store it
|
public Base createResource(Object appInfo, Base res, boolean atRootofTransform); // an already created resource is provided; this is to identify/store it
|
||||||
|
|
||||||
|
|
|
@ -1788,7 +1788,7 @@ public class StructureMapUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Base res = services != null ? services.createType(context.getAppInfo(), tn) : typeFactory(tn);
|
Base res = services != null ? services.createType(context.getAppInfo(), tn, profileUtilities) : typeFactory(tn);
|
||||||
if (res.isResource() && !res.fhirType().equals("Parameters")) {
|
if (res.isResource() && !res.fhirType().equals("Parameters")) {
|
||||||
// res.setIdBase(tgt.getParameter().size() > 1 ? getParamString(vars, tgt.getParameter().get(0)) : UUID.randomUUID().toString().toLowerCase());
|
// res.setIdBase(tgt.getParameter().size() > 1 ? getParamString(vars, tgt.getParameter().get(0)) : UUID.randomUUID().toString().toLowerCase());
|
||||||
if (services != null)
|
if (services != null)
|
||||||
|
@ -1929,7 +1929,7 @@ public class StructureMapUtilities {
|
||||||
if (sd == null) {
|
if (sd == null) {
|
||||||
throw new FHIRException("Unable to create type "+tn);
|
throw new FHIRException("Unable to create type "+tn);
|
||||||
} else {
|
} else {
|
||||||
return Manager.build(worker, sd);
|
return Manager.build(worker, sd, profileUtilities);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ResourceFactory.createResourceOrType(tn);
|
return ResourceFactory.createResourceOrType(tn);
|
||||||
|
|
|
@ -32,13 +32,13 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
public class BaseWorkerContextTests {
|
public class BaseWorkerContextTests {
|
||||||
|
@ -374,7 +374,7 @@ public class BaseWorkerContextTests {
|
||||||
|
|
||||||
TerminologyClientContext terminologyClientContext = context.getTxClientManager().getMaster();
|
TerminologyClientContext terminologyClientContext = context.getTxClientManager().getMaster();
|
||||||
|
|
||||||
Mockito.doReturn(createdValidationResult).when(context).validateOnServer(terminologyClientContext, valueSet, pIn, validationOptions);
|
Mockito.doReturn(createdValidationResult).when(context).validateOnServer2(same(terminologyClientContext), same(valueSet), same(pIn), same(validationOptions), eq(Collections.emptySet()));
|
||||||
|
|
||||||
ValidationContextCarrier ctxt = mock(ValidationContextCarrier.class);
|
ValidationContextCarrier ctxt = mock(ValidationContextCarrier.class);
|
||||||
|
|
||||||
|
@ -418,12 +418,12 @@ public class BaseWorkerContextTests {
|
||||||
|
|
||||||
Mockito.verify(valueSetCheckerSimple).validateCode("CodeableConcept", codeableConcept);
|
Mockito.verify(valueSetCheckerSimple).validateCode("CodeableConcept", codeableConcept);
|
||||||
Mockito.verify(terminologyCache).cacheValidation(eq(cacheToken), same(createdValidationResult), eq(false));
|
Mockito.verify(terminologyCache).cacheValidation(eq(cacheToken), same(createdValidationResult), eq(false));
|
||||||
Mockito.verify(context, times(0)).validateOnServer(any(), any(), any(), any());
|
Mockito.verify(context, times(0)).validateOnServer2(any(), any(), any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodableConceptWithServer() throws IOException {
|
public void testValidateCodeableConceptWithServer() throws IOException {
|
||||||
|
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
|
@ -433,7 +433,7 @@ public class BaseWorkerContextTests {
|
||||||
|
|
||||||
TerminologyClientContext terminologyClientContext = context.getTxClientManager().getMaster();
|
TerminologyClientContext terminologyClientContext = context.getTxClientManager().getMaster();
|
||||||
|
|
||||||
Mockito.doReturn(createdValidationResult).when(context).validateOnServer(terminologyClientContext, valueSet, pIn, validationOptions);
|
Mockito.doReturn(createdValidationResult).when(context).validateOnServer2(same(terminologyClientContext), same(valueSet), same(pIn),same(validationOptions), eq(Collections.emptySet()));
|
||||||
|
|
||||||
Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, codeableConcept, valueSet, expParameters);
|
Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, codeableConcept, valueSet, expParameters);
|
||||||
|
|
||||||
|
@ -443,7 +443,7 @@ public class BaseWorkerContextTests {
|
||||||
|
|
||||||
Mockito.verify(valueSetCheckerSimple, times(0)).validateCode("CodeableConcept", codeableConcept);
|
Mockito.verify(valueSetCheckerSimple, times(0)).validateCode("CodeableConcept", codeableConcept);
|
||||||
Mockito.verify(terminologyCache).cacheValidation(eq(cacheToken), same(createdValidationResult), eq(true));
|
Mockito.verify(terminologyCache).cacheValidation(eq(cacheToken), same(createdValidationResult), eq(true));
|
||||||
Mockito.verify(context).validateOnServer(terminologyClientContext, valueSet, pIn, validationOptions);
|
Mockito.verify(context).validateOnServer2(same(terminologyClientContext), same(valueSet), same(pIn), same(validationOptions), eq(Collections.emptySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -11,11 +11,11 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.apache.commons.collections4.map.HashedMap;
|
import org.apache.commons.collections4.map.HashedMap;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.formats.XmlParser;
|
import org.hl7.fhir.r5.formats.XmlParser;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.ILiquidEngineIncludeResolver;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine;
|
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidEngineIncludeResolver;
|
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
|
|
@ -115,6 +115,7 @@ public class SnapShotGenerationTests {
|
||||||
private StructureDefinition expected;
|
private StructureDefinition expected;
|
||||||
private StructureDefinition output;
|
private StructureDefinition output;
|
||||||
public AllowUnknownProfile allow;
|
public AllowUnknownProfile allow;
|
||||||
|
private boolean json;
|
||||||
|
|
||||||
public TestDetails(Element test) {
|
public TestDetails(Element test) {
|
||||||
super();
|
super();
|
||||||
|
@ -202,8 +203,14 @@ public class SnapShotGenerationTests {
|
||||||
source = (StructureDefinition) new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-input.json"));
|
source = (StructureDefinition) new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-input.json"));
|
||||||
else
|
else
|
||||||
source = (StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-input.xml"));
|
source = (StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-input.xml"));
|
||||||
if (!fail)
|
if (!fail) {
|
||||||
expected = (StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-expected.xml"));
|
if (TestingUtilities.findTestResource("r5", "snapshot-generation", id + "-expected.json")) {
|
||||||
|
json = true;
|
||||||
|
expected = (StructureDefinition) new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-expected.json"));
|
||||||
|
} else {
|
||||||
|
expected = (StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", id + "-expected.xml"));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!Utilities.noString(include))
|
if (!Utilities.noString(include))
|
||||||
included.add((StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", include + ".xml")));
|
included.add((StructureDefinition) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", include + ".xml")));
|
||||||
if (!Utilities.noString(register)) {
|
if (!Utilities.noString(register)) {
|
||||||
|
@ -589,12 +596,16 @@ public class SnapShotGenerationTests {
|
||||||
if (!fail) {
|
if (!fail) {
|
||||||
test.output = output;
|
test.output = output;
|
||||||
TestingUtilities.getSharedWorkerContext().cacheResource(output);
|
TestingUtilities.getSharedWorkerContext().cacheResource(output);
|
||||||
File dst = ManagedFileAccess.file(TestingUtilities.tempFile("snapshot", test.getId() + "-expected.xml"));
|
File dst = ManagedFileAccess.file(TestingUtilities.tempFile("snapshot", test.getId() + "-expected" + (test.json ? ".json" : ".xml")));
|
||||||
if (dst.exists())
|
if (dst.exists()) {
|
||||||
dst.delete();
|
dst.delete();
|
||||||
|
}
|
||||||
// IOUtils.copy(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", test.getId() + "-expected.xml"), ManagedFileAccess.outStream(dst));
|
// IOUtils.copy(TestingUtilities.loadTestResourceStream("r5", "snapshot-generation", test.getId() + "-expected.xml"), ManagedFileAccess.outStream(dst));
|
||||||
String actualFilePath = TestingUtilities.tempFile("snapshot", test.getId() + "-expected.xml");
|
if (test.json) {
|
||||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(actualFilePath), output);
|
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst.getAbsolutePath()), output);
|
||||||
|
} else {
|
||||||
|
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst.getAbsolutePath()), output);
|
||||||
|
}
|
||||||
StructureDefinition t1 = test.expected.copy();
|
StructureDefinition t1 = test.expected.copy();
|
||||||
t1.setText(null);
|
t1.setText(null);
|
||||||
StructureDefinition t2 = test.output.copy();
|
StructureDefinition t2 = test.output.copy();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||||
|
@ -52,6 +53,7 @@ public class StructureMapUtilitiesTest implements ITransformerServices {
|
||||||
StructureMap structureMap = scu.parse(fileMap, "cast");
|
StructureMap structureMap = scu.parse(fileMap, "cast");
|
||||||
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
||||||
scu.transform(null, source, structureMap, target);
|
scu.transform(null, source, structureMap, target);
|
||||||
|
checkNumberChildren(target, "");
|
||||||
FHIRPathEngine fp = new FHIRPathEngine(context);
|
FHIRPathEngine fp = new FHIRPathEngine(context);
|
||||||
Assertions.assertEquals("implicit",fp.evaluateToString(target, "extension[0].value"));
|
Assertions.assertEquals("implicit",fp.evaluateToString(target, "extension[0].value"));
|
||||||
Assertions.assertEquals("explicit",fp.evaluateToString(target, "extension[1].value"));
|
Assertions.assertEquals("explicit",fp.evaluateToString(target, "extension[1].value"));
|
||||||
|
@ -67,6 +69,7 @@ public class StructureMapUtilitiesTest implements ITransformerServices {
|
||||||
StructureMap structureMap = scu.parse(fileMap, "qr2patfordates");
|
StructureMap structureMap = scu.parse(fileMap, "qr2patfordates");
|
||||||
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
||||||
scu.transform(null, source, structureMap, target);
|
scu.transform(null, source, structureMap, target);
|
||||||
|
checkNumberChildren(target, "");
|
||||||
FHIRPathEngine fp = new FHIRPathEngine(context);
|
FHIRPathEngine fp = new FHIRPathEngine(context);
|
||||||
assertEquals("2023-10-26", fp.evaluateToString(target, "birthDate"));
|
assertEquals("2023-10-26", fp.evaluateToString(target, "birthDate"));
|
||||||
assertEquals("2023-09-20T13:19:13.502Z", fp.evaluateToString(target, "deceased"));
|
assertEquals("2023-09-20T13:19:13.502Z", fp.evaluateToString(target, "deceased"));
|
||||||
|
@ -81,6 +84,7 @@ public class StructureMapUtilitiesTest implements ITransformerServices {
|
||||||
StructureMap structureMap = scu.parse(fileMap, "whereclause");
|
StructureMap structureMap = scu.parse(fileMap, "whereclause");
|
||||||
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
Element target = Manager.build(context, scu.getTargetType(structureMap));
|
||||||
scu.transform(null, source, structureMap, target);
|
scu.transform(null, source, structureMap, target);
|
||||||
|
checkNumberChildren(target, "");
|
||||||
FHIRPathEngine fp = new FHIRPathEngine(context);
|
FHIRPathEngine fp = new FHIRPathEngine(context);
|
||||||
assertEquals("true", fp.evaluateToString(target, "rest.resource.interaction.where(code='create').exists()"));
|
assertEquals("true", fp.evaluateToString(target, "rest.resource.interaction.where(code='create').exists()"));
|
||||||
}
|
}
|
||||||
|
@ -134,13 +138,37 @@ public class StructureMapUtilitiesTest implements ITransformerServices {
|
||||||
Assertions.assertEquals("-quote", structureMap.getGroup().get(0).getRule().get(1).getSourceFirstRep().getElement());
|
Assertions.assertEquals("-quote", structureMap.getGroup().get(0).getRule().get(1).getSourceFirstRep().getElement());
|
||||||
Assertions.assertEquals("-backtick", structureMap.getGroup().get(0).getRule().get(2).getSourceFirstRep().getElement());
|
Assertions.assertEquals("-backtick", structureMap.getGroup().get(0).getRule().get(2).getSourceFirstRep().getElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assert indices are equal to Element.numberChildren()
|
||||||
|
private void checkNumberChildren(Element e, String indent) {
|
||||||
|
System.out.println(indent + e + ", index: " + e.getIndex());
|
||||||
|
String last = "";
|
||||||
|
int index = 0;
|
||||||
|
for (Element child : e.getChildren()) {
|
||||||
|
if (child.getProperty().isList()) {
|
||||||
|
if (last.equals(child.getName())) {
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
last = child.getName();
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
// child.index = index;
|
||||||
|
Assertions.assertEquals(index, child.getIndex());
|
||||||
|
} else {
|
||||||
|
// child.index = -1;
|
||||||
|
Assertions.assertEquals(-1, child.getIndex());
|
||||||
|
}
|
||||||
|
checkNumberChildren(child, indent + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(String message) {
|
public void log(String message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Base createType(Object appInfo, String name) throws FHIRException {
|
public Base createType(Object appInfo, String name, ProfileUtilities profileUtilities) throws FHIRException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
|
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
||||||
|
import org.hl7.fhir.r5.liquid.BaseJsonWrapper;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine;
|
||||||
|
import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument;
|
||||||
|
import org.hl7.fhir.r5.fhirpath.TypeDetails;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||||
|
import org.hl7.fhir.utilities.json.JsonException;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||||
|
import org.hl7.fhir.utilities.json.parser.JsonParser;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class LiquidJsonTest implements IEvaluationContext {
|
||||||
|
|
||||||
|
private IWorkerContext ctxt;
|
||||||
|
private ContextUtilities cu;
|
||||||
|
private ProfileUtilities pu;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testHistory() throws JsonException, IOException {
|
||||||
|
init();
|
||||||
|
|
||||||
|
JsonObject json = JsonParser.parseObject(TestingUtilities.loadTestResource("r5", "liquid-json", "history.json"));
|
||||||
|
LiquidEngine liquid = new LiquidEngine(ctxt, this);
|
||||||
|
LiquidDocument template = liquid.parse(TestingUtilities.loadTestResource("r5", "liquid-json", "history.liquid"), null);
|
||||||
|
BaseJsonWrapper base = new BaseJsonWrapper(json);
|
||||||
|
String s = liquid.evaluate(template, base, this).trim();
|
||||||
|
String expected = TestingUtilities.loadTestResource("r5", "liquid-json", "history.html").trim();
|
||||||
|
System.out.println(s);
|
||||||
|
Assertions.assertEquals(expected, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTestCases() throws JsonException, IOException {
|
||||||
|
init();
|
||||||
|
|
||||||
|
JsonObject json = JsonParser.parseObject(TestingUtilities.loadTestResource("r5", "liquid-json", "test-cases.json"));
|
||||||
|
LiquidEngine liquid = new LiquidEngine(ctxt, this);
|
||||||
|
LiquidDocument template = liquid.parse(TestingUtilities.loadTestResource("r5", "liquid-json", "test-cases.liquid"), null);
|
||||||
|
BaseJsonWrapper base = new BaseJsonWrapper(json);
|
||||||
|
String s = liquid.evaluate(template, base, this).trim();
|
||||||
|
String expected = TestingUtilities.loadTestResource("r5", "liquid-json", "test-cases.html").trim();
|
||||||
|
System.out.println(s);
|
||||||
|
Assertions.assertEquals(expected, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
if (pu == null) {
|
||||||
|
ctxt = TestingUtilities.getSharedWorkerContext();
|
||||||
|
cu = new ContextUtilities(ctxt);
|
||||||
|
pu = new ProfileUtilities(ctxt, null, cu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Base> resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException {
|
||||||
|
return new ArrayList<Base>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name,
|
||||||
|
boolean explicitConstant) throws PathEngineException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean log(String argument, List<Base> focus) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FunctionDetails resolveFunction(FHIRPathEngine engine, String functionName) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeDetails checkFunction(FHIRPathEngine engine, Object appContext, String functionName, TypeDetails focus,
|
||||||
|
List<TypeDetails> parameters) throws PathEngineException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Base> executeFunction(FHIRPathEngine engine, Object appContext, List<Base> focus, String functionName,
|
||||||
|
List<List<Base>> parameters) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base resolveReference(FHIRPathEngine engine, Object appContext, String url, Base refContext)
|
||||||
|
throws FHIRException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base item, String url)
|
||||||
|
throws FHIRException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean paramIsType(String name, int index) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,12 +53,12 @@ public class NamedItemList<T extends org.hl7.fhir.utilities.NamedItemList.NamedI
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(T e) {
|
public boolean add(T e) {
|
||||||
map = null;
|
addToMap(e);
|
||||||
return list.add(e);
|
return list.add(e);
|
||||||
}
|
}
|
||||||
public void add(int index, T e) {
|
public void add(int index, T e) {
|
||||||
|
addToMap(e);
|
||||||
list.add(index, e);
|
list.add(index, e);
|
||||||
map = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,7 +74,9 @@ public class NamedItemList<T extends org.hl7.fhir.utilities.NamedItemList.NamedI
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(Collection<? extends T> c) {
|
public boolean addAll(Collection<? extends T> c) {
|
||||||
map = null;
|
for(T e : c) {
|
||||||
|
addToMap(e);
|
||||||
|
}
|
||||||
return list.addAll(c);
|
return list.addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +117,14 @@ public class NamedItemList<T extends org.hl7.fhir.utilities.NamedItemList.NamedI
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSizeByName(String name) {
|
||||||
|
if (map == null) {
|
||||||
|
buildMap();
|
||||||
|
}
|
||||||
|
List<T> l = map.get(name);
|
||||||
|
return l == null ? 0 : l.size();
|
||||||
|
}
|
||||||
|
|
||||||
public T get(int c) {
|
public T get(int c) {
|
||||||
return list.get(c);
|
return list.get(c);
|
||||||
|
@ -123,15 +133,23 @@ public class NamedItemList<T extends org.hl7.fhir.utilities.NamedItemList.NamedI
|
||||||
private void buildMap() {
|
private void buildMap() {
|
||||||
map = new HashMap<>();
|
map = new HashMap<>();
|
||||||
for (T child : list) {
|
for (T child : list) {
|
||||||
String n = child.getListName();
|
addToMap(child);
|
||||||
List<T> l = map.get(n);
|
|
||||||
if (l == null) {
|
|
||||||
l = new ArrayList<>();
|
|
||||||
map.put(n,l);
|
|
||||||
}
|
|
||||||
l.add(child);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addToMap(T child) {
|
||||||
|
if (map == null) {
|
||||||
|
// map will be re-built anyway in next call to getByName
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String n = child.getListName();
|
||||||
|
List<T> l = map.get(n);
|
||||||
|
if (l == null) {
|
||||||
|
l = new ArrayList<>();
|
||||||
|
map.put(n,l);
|
||||||
|
}
|
||||||
|
l.add(child);
|
||||||
|
}
|
||||||
|
|
||||||
public void sort(Comparator<? super T> sorter) {
|
public void sort(Comparator<? super T> sorter) {
|
||||||
Collections.sort(list, sorter);
|
Collections.sort(list, sorter);
|
||||||
|
|
|
@ -628,9 +628,11 @@ public class Utilities {
|
||||||
|
|
||||||
public static String padRight(String src, char c, int len) {
|
public static String padRight(String src, char c, int len) {
|
||||||
StringBuilder s = new StringBuilder();
|
StringBuilder s = new StringBuilder();
|
||||||
s.append(src);
|
if (src != null) {
|
||||||
for (int i = 0; i < len - src.length(); i++)
|
s.append(src);
|
||||||
s.append(c);
|
for (int i = 0; i < len - src.length(); i++)
|
||||||
|
s.append(c);
|
||||||
|
}
|
||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,4 +56,74 @@ public class HTTPResult {
|
||||||
public String getContentAsString() {
|
public String getContentAsString() {
|
||||||
return new String(content, StandardCharsets.UTF_8);
|
return new String(content, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getMessagefromCode() {
|
||||||
|
switch (getCode()) {
|
||||||
|
case 100: return ""+getCode()+" Continue";
|
||||||
|
case 101: return ""+getCode()+" Switching Protocols";
|
||||||
|
case 102: return ""+getCode()+" Processing Deprecated";
|
||||||
|
case 103: return ""+getCode()+" Early Hints";
|
||||||
|
case 200: return ""+getCode()+" OK";
|
||||||
|
case 201: return ""+getCode()+" Created";
|
||||||
|
case 202: return ""+getCode()+" Accepted";
|
||||||
|
case 203: return ""+getCode()+" Non-Authoritative Information";
|
||||||
|
case 204: return ""+getCode()+" No Content";
|
||||||
|
case 205: return ""+getCode()+" Reset Content";
|
||||||
|
case 206: return ""+getCode()+" Partial Content";
|
||||||
|
case 207: return ""+getCode()+" Multi-Status";
|
||||||
|
case 208: return ""+getCode()+" Already Reported";
|
||||||
|
case 226: return ""+getCode()+" IM Used";
|
||||||
|
case 300: return ""+getCode()+" Multiple Choices";
|
||||||
|
case 301: return ""+getCode()+" Moved Permanently";
|
||||||
|
case 302: return ""+getCode()+" Found";
|
||||||
|
case 303: return ""+getCode()+" See Other";
|
||||||
|
case 304: return ""+getCode()+" Not Modified";
|
||||||
|
case 305: return ""+getCode()+" Use Proxy Deprecated";
|
||||||
|
case 306: return ""+getCode()+" unused";
|
||||||
|
case 307: return ""+getCode()+" Temporary Redirect";
|
||||||
|
case 308: return ""+getCode()+" Permanent Redirect";
|
||||||
|
case 400: return ""+getCode()+" Bad Request";
|
||||||
|
case 401: return ""+getCode()+" Unauthorized";
|
||||||
|
case 402: return ""+getCode()+" Payment Required";
|
||||||
|
case 403: return ""+getCode()+" Forbidden";
|
||||||
|
case 404: return ""+getCode()+" Not Found";
|
||||||
|
case 405: return ""+getCode()+" Method Not Allowed";
|
||||||
|
case 406: return ""+getCode()+" Not Acceptable";
|
||||||
|
case 407: return ""+getCode()+" Proxy Authentication Required";
|
||||||
|
case 408: return ""+getCode()+" Request Timeout";
|
||||||
|
case 409: return ""+getCode()+" Conflict";
|
||||||
|
case 410: return ""+getCode()+" Gone";
|
||||||
|
case 411: return ""+getCode()+" Length Required";
|
||||||
|
case 412: return ""+getCode()+" Precondition Failed";
|
||||||
|
case 413: return ""+getCode()+" Content Too Large";
|
||||||
|
case 414: return ""+getCode()+" URI Too Long";
|
||||||
|
case 415: return ""+getCode()+" Unsupported Media Type";
|
||||||
|
case 416: return ""+getCode()+" Range Not Satisfiable";
|
||||||
|
case 417: return ""+getCode()+" Expectation Failed";
|
||||||
|
case 418: return ""+getCode()+" I'm a teapot";
|
||||||
|
case 421: return ""+getCode()+" Misdirected Request";
|
||||||
|
case 422: return ""+getCode()+" Unprocessable Content";
|
||||||
|
case 423: return ""+getCode()+" Locked";
|
||||||
|
case 424: return ""+getCode()+" Failed Dependency";
|
||||||
|
case 425: return ""+getCode()+" Too Early Experimental";
|
||||||
|
case 426: return ""+getCode()+" Upgrade Required";
|
||||||
|
case 428: return ""+getCode()+" Precondition Required";
|
||||||
|
case 429: return ""+getCode()+" Too Many Requests";
|
||||||
|
case 431: return ""+getCode()+" Request Header Fields Too Large";
|
||||||
|
case 451: return ""+getCode()+" Unavailable For Legal Reasons";
|
||||||
|
case 500: return ""+getCode()+" Internal Server Error";
|
||||||
|
case 501: return ""+getCode()+" Not Implemented";
|
||||||
|
case 502: return ""+getCode()+" Bad Gateway";
|
||||||
|
case 503: return ""+getCode()+" Service Unavailable";
|
||||||
|
case 504: return ""+getCode()+" Gateway Timeout";
|
||||||
|
case 505: return ""+getCode()+" HTTP Version Not Supported";
|
||||||
|
case 506: return ""+getCode()+" Variant Also Negotiates";
|
||||||
|
case 507: return ""+getCode()+" Insufficient Storage";
|
||||||
|
case 508: return ""+getCode()+" Loop Detected";
|
||||||
|
case 510: return ""+getCode()+" Not Extended";
|
||||||
|
case 511: return ""+getCode()+" Network Authentication Required";
|
||||||
|
default: return "HTTP code "+code;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,6 @@ public class CommonPackages {
|
||||||
public static final String VER_XVER = "0.1.0";
|
public static final String VER_XVER = "0.1.0";
|
||||||
|
|
||||||
public static final String ID_PUBPACK = "hl7.fhir.pubpack";
|
public static final String ID_PUBPACK = "hl7.fhir.pubpack";
|
||||||
public static final String VER_PUBPACK = "0.1.9";
|
public static final String VER_PUBPACK = "0.2.0";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ public class FilesystemPackageCacheManagerLocks {
|
||||||
channel.close();
|
channel.close();
|
||||||
throw new IOException("Lock file exists, but is not locked by a process: " + lockFile.getName());
|
throw new IOException("Lock file exists, but is not locked by a process: " + lockFile.getName());
|
||||||
}
|
}
|
||||||
System.out.println("File is locked.");
|
System.out.println("File is locked ('"+lockFile.getAbsolutePath()+"').");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -178,8 +178,9 @@ public class HierarchicalTableGenerator {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTag(String tag) {
|
public Piece setTag(String tag) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Piece setText(String text) {
|
public Piece setText(String text) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@ import java.io.PrintWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
@ -34,9 +35,9 @@ public class TransformSupportServices implements ITransformerServices {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Base createType(Object appInfo, String name) throws FHIRException {
|
public Base createType(Object appInfo, String name, ProfileUtilities profileUtilities) throws FHIRException {
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, name);
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, name);
|
||||||
return Manager.build(context, sd);
|
return Manager.build(context, sd, profileUtilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2478,22 +2478,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
if (ctxt.getType() == ExtensionContextType.ELEMENT) {
|
if (ctxt.getType() == ExtensionContextType.ELEMENT) {
|
||||||
String en = ctxt.getExpression();
|
String en = ctxt.getExpression();
|
||||||
contexts.append("e:" + en);
|
|
||||||
String pu = null;
|
String pu = null;
|
||||||
if (en.contains("#")) {
|
if (en == null) {
|
||||||
pu = en.substring(0, en.indexOf("#"));
|
// nothing? It's an error in the extension definition, but that's properly reported elsewhere
|
||||||
en = en.substring(en.indexOf("#")+1);
|
|
||||||
} else {
|
} else {
|
||||||
//pu = en;
|
contexts.append("e:" + en);
|
||||||
}
|
if (en.contains("#")) {
|
||||||
if (Utilities.existsInList(en, "Element", "Any")) {
|
pu = en.substring(0, en.indexOf("#"));
|
||||||
ok = true;
|
en = en.substring(en.indexOf("#")+1);
|
||||||
} else if (en.equals("Resource") && container.isResource()) {
|
} else {
|
||||||
ok = true;
|
//pu = en;
|
||||||
} else if (en.equals("CanonicalResource") && containsAny(VersionUtilities.getExtendedCanonicalResourceNames(context.getVersion()), plist)) {
|
}
|
||||||
ok = true;
|
if (Utilities.existsInList(en, "Element", "Any")) {
|
||||||
} else if (hasElementName(plist, en) && pu == null) {
|
ok = true;
|
||||||
ok = true;
|
} else if (en.equals("Resource") && container.isResource()) {
|
||||||
|
ok = true;
|
||||||
|
} else if (en.equals("CanonicalResource") && containsAny(VersionUtilities.getExtendedCanonicalResourceNames(context.getVersion()), plist)) {
|
||||||
|
ok = true;
|
||||||
|
} else if (hasElementName(plist, en) && pu == null) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
@ -4316,7 +4320,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
Collections.sort(list, new StructureDefinitionSorterByUrl());
|
Collections.sort(list, new StructureDefinitionSorterByUrl());
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
for (StructureDefinition sd : list) {
|
for (StructureDefinition sd : list) {
|
||||||
b.append(sd.getUrl());
|
b.append(sd.getVersionedUrl());
|
||||||
}
|
}
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,14 +476,14 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
qok = warning(errors, NO_RULE_DATE, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
|
qok = warning(errors, NO_RULE_DATE, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
|
||||||
}
|
}
|
||||||
if (qok) {
|
if (qok) {
|
||||||
boolean inProgress = "in-progress".equals(element.getNamedChildValue("status", false));
|
boolean notCompleted = !Utilities.existsInList(element.getNamedChildValue("status", false), "completed", "amended");
|
||||||
ok = validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.q().getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element)) && ok;
|
ok = validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.q().getItem(), errors, element, stack, notCompleted, element, new QStack(qsrc, element)) && ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateQuestionnaireResponseItem(ValidationContext hostContext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
|
private boolean validateQuestionnaireResponseItem(ValidationContext hostContext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, Element element, NodeStack stack, boolean notCompleted, Element questionnaireResponseRoot, QStack qstack) {
|
||||||
BooleanHolder ok = new BooleanHolder();
|
BooleanHolder ok = new BooleanHolder();
|
||||||
|
|
||||||
String text = element.getNamedChildValue("text", false);
|
String text = element.getNamedChildValue("text", false);
|
||||||
|
@ -491,7 +491,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
|
|
||||||
List<Element> answers = new ArrayList<Element>();
|
List<Element> answers = new ArrayList<Element>();
|
||||||
element.getNamedChildren("answer", answers);
|
element.getNamedChildren("answer", answers);
|
||||||
if (inProgress)
|
if (notCompleted)
|
||||||
warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
|
warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
|
||||||
else if (myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe)) {
|
else if (myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe)) {
|
||||||
ok.see(rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId()));
|
ok.see(rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId()));
|
||||||
|
@ -586,7 +586,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
}
|
}
|
||||||
if (qItem.getType() != QuestionnaireItemType.GROUP) {
|
if (qItem.getType() != QuestionnaireItemType.GROUP) {
|
||||||
// if it's a group, we already have an error before getting here, so no need to hammer away on that
|
// if it's a group, we already have an error before getting here, so no need to hammer away on that
|
||||||
ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, answer, stack, inProgress, questionnaireResponseRoot, qstack));
|
ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, answer, stack, notCompleted, questionnaireResponseRoot, qstack));
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -601,7 +601,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
element.getNamedChildren("item", items);
|
element.getNamedChildren("item", items);
|
||||||
ok.see(rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP_ANSWER, qItem.getLinkId()));
|
ok.see(rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP_ANSWER, qItem.getLinkId()));
|
||||||
} else {
|
} else {
|
||||||
ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, element, stack, inProgress, questionnaireResponseRoot, qstack));
|
ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, element, stack, notCompleted, questionnaireResponseRoot, qstack));
|
||||||
}
|
}
|
||||||
return ok.ok();
|
return ok.ok();
|
||||||
}
|
}
|
||||||
|
@ -610,14 +610,14 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
return !answers.isEmpty() || !qItem.getRequired() || qItem.getType() == QuestionnaireItemType.GROUP;
|
return !answers.isEmpty() || !qItem.getRequired() || qItem.getType() == QuestionnaireItemType.GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateQuestionnaireResponseItem(ValidationContext hostcontext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<ElementWithIndex> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
|
private boolean validateQuestionnaireResponseItem(ValidationContext hostcontext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<ElementWithIndex> elements, NodeStack stack, boolean notCompleted, Element questionnaireResponseRoot, QStack qstack) {
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
if (elements.size() > 1) {
|
if (elements.size() > 1) {
|
||||||
ok = rulePlural(errors, NO_RULE_DATE, IssueType.INVALID, elements.get(1).getElement().line(), elements.get(1).getElement().col(), stack.getLiteralPath(), qItem.getRepeats(), elements.size(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId()) && ok;
|
ok = rulePlural(errors, NO_RULE_DATE, IssueType.INVALID, elements.get(1).getElement().line(), elements.get(1).getElement().col(), stack.getLiteralPath(), qItem.getRepeats(), elements.size(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId()) && ok;
|
||||||
}
|
}
|
||||||
for (ElementWithIndex element : elements) {
|
for (ElementWithIndex element : elements) {
|
||||||
NodeStack ns = stack.push(element.getElement(), element.getIndex(), null, null);
|
NodeStack ns = stack.push(element.getElement(), element.getIndex(), null, null);
|
||||||
ok = validateQuestionnaireResponseItem(hostcontext, qsrc, qItem, errors, element.getElement(), ns, inProgress, questionnaireResponseRoot, qstack.push(qItem, element.getElement())) && ok;
|
ok = validateQuestionnaireResponseItem(hostcontext, qsrc, qItem, errors, element.getElement(), ns, notCompleted, questionnaireResponseRoot, qstack.push(qItem, element.getElement())) && ok;
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +630,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateQuestionannaireResponseItems(ValidationContext hostContext, QuestionnaireWithContext qsrc, List<QuestionnaireItemComponent> qItems, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
|
private boolean validateQuestionannaireResponseItems(ValidationContext hostContext, QuestionnaireWithContext qsrc, List<QuestionnaireItemComponent> qItems, List<ValidationMessage> errors, Element element, NodeStack stack, boolean notCompleted, Element questionnaireResponseRoot, QStack qstack) {
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
List<Element> items = new ArrayList<Element>();
|
List<Element> items = new ArrayList<Element>();
|
||||||
element.getNamedChildren("item", items);
|
element.getNamedChildren("item", items);
|
||||||
|
@ -647,7 +647,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
if (qItem != null) {
|
if (qItem != null) {
|
||||||
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index > -1, misplacedItemError(qItem)) && ok;
|
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index > -1, misplacedItemError(qItem)) && ok;
|
||||||
NodeStack ns = stack.push(item, counter, null, null);
|
NodeStack ns = stack.push(item, counter, null, null);
|
||||||
ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, item, ns, inProgress, questionnaireResponseRoot, qstack.push(qItem, item)) && ok;
|
ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, item, ns, notCompleted, questionnaireResponseRoot, qstack.push(qItem, item)) && ok;
|
||||||
} else
|
} else
|
||||||
ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, item.line(), item.col(), stack.getLiteralPath(), index > -1, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTFOUND, linkId) && ok;
|
ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, item.line(), item.col(), stack.getLiteralPath(), index > -1, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTFOUND, linkId) && ok;
|
||||||
} else {
|
} else {
|
||||||
|
@ -670,12 +670,12 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
// ok, now we have a list of known items, grouped by linkId. We've made an error for anything out of order
|
// ok, now we have a list of known items, grouped by linkId. We've made an error for anything out of order
|
||||||
for (QuestionnaireItemComponent qItem : qItems) {
|
for (QuestionnaireItemComponent qItem : qItems) {
|
||||||
List<ElementWithIndex> mapItem = map.get(qItem.getLinkId());
|
List<ElementWithIndex> mapItem = map.get(qItem.getLinkId());
|
||||||
ok = validateQuestionnaireResponseItem(hostContext, qsrc, errors, element, stack, inProgress, questionnaireResponseRoot, qItem, mapItem, qstack) && ok;
|
ok = validateQuestionnaireResponseItem(hostContext, qsrc, errors, element, stack, notCompleted, questionnaireResponseRoot, qItem, mapItem, qstack) && ok;
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateQuestionnaireResponseItem(ValidationContext hostContext, QuestionnaireWithContext qsrc, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QuestionnaireItemComponent qItem, List<ElementWithIndex> mapItem, QStack qstack) {
|
public boolean validateQuestionnaireResponseItem(ValidationContext hostContext, QuestionnaireWithContext qsrc, List<ValidationMessage> errors, Element element, NodeStack stack, boolean notCompleted, Element questionnaireResponseRoot, QuestionnaireItemComponent qItem, List<ElementWithIndex> mapItem, QStack qstack) {
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
boolean enabled = myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe);
|
boolean enabled = myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe);
|
||||||
if (mapItem != null) {
|
if (mapItem != null) {
|
||||||
|
@ -687,14 +687,14 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively validate child items
|
// Recursively validate child items
|
||||||
ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, mapItem, stack, inProgress, questionnaireResponseRoot, qstack) && ok;
|
ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, mapItem, stack, notCompleted, questionnaireResponseRoot, qstack) && ok;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// item is missing, is the question enabled?
|
// item is missing, is the question enabled?
|
||||||
if (enabled && qItem.getRequired()) {
|
if (enabled && qItem.getRequired()) {
|
||||||
String message = context.formatMessage(I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
|
String message = context.formatMessage(I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
|
||||||
if (inProgress) {
|
if (notCompleted) {
|
||||||
warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message);
|
warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message);
|
||||||
} else {
|
} else {
|
||||||
ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message) && ok;
|
ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message) && ok;
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class TxTester {
|
||||||
public String describe();
|
public String describe();
|
||||||
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException;
|
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException;
|
||||||
public byte[] loadContent(String filename) throws FileNotFoundException, IOException;
|
public byte[] loadContent(String filename) throws FileNotFoundException, IOException;
|
||||||
|
public boolean hasContent(String filename) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String server;
|
private String server;
|
||||||
|
@ -172,7 +173,16 @@ public class TxTester {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String loadVersion() throws JsonException, IOException {
|
private String loadVersion() throws JsonException, IOException {
|
||||||
return processHistoryMarkdown(loader.loadContent("history.md"));
|
if (loader.hasContent("history.json")) {
|
||||||
|
return readHistory(loader.loadContent("history.json"));
|
||||||
|
} else {
|
||||||
|
return processHistoryMarkdown(loader.loadContent("history.md"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readHistory(byte[] content) throws JsonException, IOException {
|
||||||
|
JsonObject json = JsonParser.parseObject(content);
|
||||||
|
return json.getJsonObjects("versions").get(0).asString("version");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String processHistoryMarkdown(byte[] content) throws IOException {
|
public static String processHistoryMarkdown(byte[] content) throws IOException {
|
||||||
|
@ -650,6 +660,11 @@ public class TxTester {
|
||||||
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
||||||
return TextFile.fileToBytes(Utilities.path(folder, filename));
|
return TextFile.fileToBytes(Utilities.path(folder, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasContent(String filename) throws IOException {
|
||||||
|
return new File(Utilities.path(folder, filename)).exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
|
||||||
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
|
import org.hl7.fhir.r5.formats.JsonParser;
|
||||||
import org.hl7.fhir.r5.formats.XmlParser;
|
import org.hl7.fhir.r5.formats.XmlParser;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||||
|
@ -100,9 +101,10 @@ public class SnapShotGenerationXTests {
|
||||||
|
|
||||||
private List<Rule> rules = new ArrayList<>();
|
private List<Rule> rules = new ArrayList<>();
|
||||||
private StructureDefinition source;
|
private StructureDefinition source;
|
||||||
private StructureDefinition included;
|
private List<StructureDefinition> included = new ArrayList<StructureDefinition>();
|
||||||
private StructureDefinition expected;
|
private StructureDefinition expected;
|
||||||
private StructureDefinition output;
|
private StructureDefinition output;
|
||||||
|
public boolean outputIsJson;
|
||||||
|
|
||||||
public TestDetails(Element test) {
|
public TestDetails(Element test) {
|
||||||
super();
|
super();
|
||||||
|
@ -144,7 +146,7 @@ public class SnapShotGenerationXTests {
|
||||||
return fail;
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StructureDefinition getIncluded() {
|
public List<StructureDefinition> getIncluded() {
|
||||||
return included;
|
return included;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,15 +183,22 @@ public class SnapShotGenerationXTests {
|
||||||
source = (StructureDefinition) XVersionLoader.loadJson(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-input.json"));
|
source = (StructureDefinition) XVersionLoader.loadJson(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-input.json"));
|
||||||
else
|
else
|
||||||
source = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-input.xml"));
|
source = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-input.xml"));
|
||||||
if (!fail)
|
if (!fail) {
|
||||||
expected = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-output.xml"));
|
if (TestingUtilities.findTestResource("rX", "snapshot-generation", id + "-output.json")) {
|
||||||
|
outputIsJson = true;
|
||||||
|
expected = (StructureDefinition) XVersionLoader.loadJson(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-output.json"));
|
||||||
|
} else
|
||||||
|
expected = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", id + "-output.xml"));
|
||||||
|
}
|
||||||
if (!Utilities.noString(include))
|
if (!Utilities.noString(include))
|
||||||
included = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", include + ".xml"));
|
included.add((StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", include + ".xml")));
|
||||||
if (!Utilities.noString(register)) {
|
if (!Utilities.noString(register)) {
|
||||||
if (TestingUtilities.findTestResource("rX", "snapshot-generation", register + ".xml")) {
|
for (String r : register.split("\\,")) {
|
||||||
included = (StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", register + ".xml"));
|
if (TestingUtilities.findTestResource("rX", "snapshot-generation", r + ".xml")) {
|
||||||
} else {
|
included.add((StructureDefinition) XVersionLoader.loadXml(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", r + ".xml")));
|
||||||
included = (StructureDefinition) XVersionLoader.loadJson(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", register + ".json"));
|
} else {
|
||||||
|
included.add((StructureDefinition) XVersionLoader.loadJson(version, TestingUtilities.loadTestResourceStream("rX", "snapshot-generation", r + ".json")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +323,7 @@ public class SnapShotGenerationXTests {
|
||||||
else
|
else
|
||||||
return td.getOutput();
|
return td.getOutput();
|
||||||
case INCLUDE:
|
case INCLUDE:
|
||||||
return td.getIncluded();
|
return td.getIncluded().get(0);
|
||||||
default:
|
default:
|
||||||
throw new FHIRException("Not done yet");
|
throw new FHIRException("Not done yet");
|
||||||
}
|
}
|
||||||
|
@ -394,8 +403,11 @@ public class SnapShotGenerationXTests {
|
||||||
for (TestDetails t : tests) {
|
for (TestDetails t : tests) {
|
||||||
if (t.expected != null && url.equals(t.expected.getUrl()))
|
if (t.expected != null && url.equals(t.expected.getUrl()))
|
||||||
return t.expected;
|
return t.expected;
|
||||||
if (t.included != null && url.equals(t.included.getUrl()))
|
for (StructureDefinition sd : t.included) {
|
||||||
return t.included;
|
if (url.equals(sd.getUrl())) {
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -492,23 +504,26 @@ public class SnapShotGenerationXTests {
|
||||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||||
ProfileUtilities pu = new ProfileUtilities(UtilitiesXTests.context(version), messages, null);
|
ProfileUtilities pu = new ProfileUtilities(UtilitiesXTests.context(version), messages, null);
|
||||||
pu.setNewSlicingProcessing(true);
|
pu.setNewSlicingProcessing(true);
|
||||||
pu.setIds(test.included, false);
|
for (StructureDefinition sd : test.included) {
|
||||||
pu.setAllowUnknownProfile(AllowUnknownProfile.ALL_TYPES);
|
pu.setIds(sd, false);
|
||||||
StructureDefinition base = UtilitiesXTests.context(version).fetchResource(StructureDefinition.class, test.included.getBaseDefinition());
|
pu.setAllowUnknownProfile(AllowUnknownProfile.ALL_TYPES);
|
||||||
if (base != null) {
|
StructureDefinition base = UtilitiesXTests.context(version).fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||||
pu.generateSnapshot(base, test.included, test.included.getUrl(), "http://test.org/profile", test.included.getName());
|
if (base != null) {
|
||||||
}
|
pu.generateSnapshot(base, sd, sd.getUrl(), "http://test.org/profile", sd.getName());
|
||||||
if (!UtilitiesXTests.context(version).hasResource(StructureDefinition.class, test.included.getUrl()))
|
}
|
||||||
UtilitiesXTests.context(version).cacheResource(test.included);
|
if (!UtilitiesXTests.context(version).hasResource(StructureDefinition.class, sd.getUrl()))
|
||||||
int ec = 0;
|
UtilitiesXTests.context(version).cacheResource(sd);
|
||||||
for (ValidationMessage vm : messages) {
|
int ec = 0;
|
||||||
if (vm.getLevel() == IssueSeverity.ERROR) {
|
for (ValidationMessage vm : messages) {
|
||||||
System.out.println(vm.summary());
|
if (vm.getLevel() == IssueSeverity.ERROR) {
|
||||||
ec++;
|
System.out.println(vm.summary());
|
||||||
|
ec++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ec > 0) {
|
||||||
|
throw new FHIRException("register gen failed: " + messages.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ec > 0)
|
|
||||||
throw new FHIRException("register gen failed: " + messages.toString());
|
|
||||||
}
|
}
|
||||||
StructureDefinition base = getSD(test.getSource().getBaseDefinition());
|
StructureDefinition base = getSD(test.getSource().getBaseDefinition());
|
||||||
if (!base.getUrl().equals(test.getSource().getBaseDefinition()))
|
if (!base.getUrl().equals(test.getSource().getBaseDefinition()))
|
||||||
|
@ -553,14 +568,24 @@ public class SnapShotGenerationXTests {
|
||||||
if (!fail) {
|
if (!fail) {
|
||||||
test.output = output;
|
test.output = output;
|
||||||
UtilitiesXTests.context(version).cacheResource(output);
|
UtilitiesXTests.context(version).cacheResource(output);
|
||||||
File dst = ManagedFileAccess.file(UtilitiesXTests.tempFile("snapshot", test.getId() + "-output.xml"));
|
File dst = ManagedFileAccess.file(UtilitiesXTests.tempFile("snapshot", test.getId() + "-output" + (test.outputIsJson ? ".json" : ".xml")));
|
||||||
if (dst.exists())
|
if (dst.exists())
|
||||||
dst.delete();
|
dst.delete();
|
||||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(UtilitiesXTests.tempFile("snapshot", test.getId() + "-output.xml")), output);
|
if (test.outputIsJson) {
|
||||||
|
XVersionLoader.saveJson(version, output, ManagedFileAccess.outStream(dst.getAbsolutePath()));
|
||||||
|
} else {
|
||||||
|
XVersionLoader.saveXml(version, output, ManagedFileAccess.outStream(dst.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
if (test.outputIsJson) {
|
||||||
|
XVersionLoader.saveJson(version, test.expected, ManagedFileAccess.outStream(UtilitiesXTests.tempFile("snapshot", test.getId() + "-expected" + (test.outputIsJson ? ".json" : ".xml"))));
|
||||||
|
} else {
|
||||||
|
XVersionLoader.saveXml(version, test.expected, ManagedFileAccess.outStream(UtilitiesXTests.tempFile("snapshot", test.getId() + "-expected" + (test.outputIsJson ? ".json" : ".xml"))));
|
||||||
|
}
|
||||||
StructureDefinition t1 = test.expected.copy();
|
StructureDefinition t1 = test.expected.copy();
|
||||||
t1.setText(null);
|
t1.setText(null);
|
||||||
StructureDefinition t2 = test.output.copy();
|
StructureDefinition t2 = test.output.copy();
|
||||||
t2.setText(null);
|
t2.setText(null);
|
||||||
|
t1.setIdBase(t2.getIdBase());
|
||||||
Assertions.assertTrue(t1.equalsDeep(t2), "Output does not match expected");
|
Assertions.assertTrue(t1.equalsDeep(t2), "Output does not match expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,7 +596,6 @@ public class SnapShotGenerationXTests {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private StructureDefinition getSD(String url) throws DefinitionException, FHIRException, IOException {
|
private StructureDefinition getSD(String url) throws DefinitionException, FHIRException, IOException {
|
||||||
StructureDefinition sd = context.getByUrl(url);
|
StructureDefinition sd = context.getByUrl(url);
|
||||||
if (sd == null)
|
if (sd == null)
|
||||||
|
|
|
@ -147,4 +147,9 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
|
||||||
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
||||||
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasContent(String filename) throws IOException {
|
||||||
|
return TestingUtilities.findTestResource("tx", filename);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -188,4 +188,11 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
|
||||||
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
||||||
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasContent(String filename) throws IOException {
|
||||||
|
return TestingUtilities.findTestResource("tx", filename);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -174,4 +174,9 @@ public class OntoserverTests implements ITxTesterLoader {
|
||||||
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
public byte[] loadContent(String filename) throws FileNotFoundException, IOException {
|
||||||
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
return TestingUtilities.loadTestResourceBytes("tx", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasContent(String filename) throws IOException {
|
||||||
|
return TestingUtilities.findTestResource("tx", filename);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://fhir.de/CodeSystem/dkgev/Fachabteilungsschluessel-erweitert",
|
||||||
|
"code" : "3600"
|
||||||
|
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||||
|
"resourceType" : "Parameters",
|
||||||
|
"parameter" : [{
|
||||||
|
"name" : "profile-url",
|
||||||
|
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||||
|
}]
|
||||||
|
}}####
|
||||||
|
v: {
|
||||||
|
"display" : "Intensivmedizin",
|
||||||
|
"code" : "3600",
|
||||||
|
"system" : "http://fhir.de/CodeSystem/dkgev/Fachabteilungsschluessel-erweitert",
|
||||||
|
"version" : "1.5.0",
|
||||||
|
"server" : "http://tx-dev.fhir.org/r5",
|
||||||
|
"unknown-systems" : "",
|
||||||
|
"issues" : {
|
||||||
|
"resourceType" : "OperationOutcome"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
2
pom.xml
2
pom.xml
|
@ -23,7 +23,7 @@
|
||||||
<commons_io_version>2.17.0</commons_io_version>
|
<commons_io_version>2.17.0</commons_io_version>
|
||||||
<guava_version>32.0.1-jre</guava_version>
|
<guava_version>32.0.1-jre</guava_version>
|
||||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||||
<validator_test_case_version>1.6.8</validator_test_case_version>
|
<validator_test_case_version>1.6.9-SNAPSHOT</validator_test_case_version>
|
||||||
<jackson_version>2.17.0</jackson_version>
|
<jackson_version>2.17.0</jackson_version>
|
||||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||||
|
|
Loading…
Reference in New Issue