commit
76411218ac
|
@ -293,7 +293,6 @@ local.properties
|
||||||
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/t9-actual.xml
|
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/t9-actual.xml
|
||||||
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/dv1-actual.xml
|
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/dv1-actual.xml
|
||||||
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/t45-actual.xml
|
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/t45-actual.xml
|
||||||
/org.hl7.fhir.r4b
|
|
||||||
/org.hl7.fhir.r5/src/test/resources/gen/gen.xml
|
/org.hl7.fhir.r5/src/test/resources/gen/gen.xml
|
||||||
/org.hl7.fhir.r5/src/test/resources/graphql/*.out
|
/org.hl7.fhir.r5/src/test/resources/graphql/*.out
|
||||||
/org.hl7.fhir.validation/src/test/resources/comparison/output
|
/org.hl7.fhir.validation/src/test/resources/comparison/output
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
## Validator Changes
|
## Validator Changes
|
||||||
|
|
||||||
* no changes
|
* Handle reslicing within the same profile
|
||||||
|
* Fix up wrong handling of context on exists() in FHIRPath
|
||||||
|
* Add hints to profiles around behavior of pattern on repeating elements
|
||||||
|
* Ignore all tooling extensions when validating
|
||||||
|
*
|
||||||
|
|
||||||
## Other code changes
|
## Other code changes
|
||||||
|
|
||||||
|
|
|
@ -1168,7 +1168,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (diffMatches.get(0).hasType() && "Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode()) && !isValidType(diffMatches.get(0).getType().get(0), currentBase)) {
|
if (diffMatches.get(0).hasType() && "Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode()) && !isValidType(diffMatches.get(0).getType().get(0), currentBase)) {
|
||||||
throw new DefinitionException(context.formatMessage(I18nConstants.VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT, url, diffMatches.get(0).getPath(), diffMatches.get(0).getType().get(0), currentBase.typeSummary()));
|
throw new DefinitionException(context.formatMessage(I18nConstants.VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT, url, diffMatches.get(0).getPath(), diffMatches.get(0).getType().get(0), currentBase.typeSummary()));
|
||||||
}
|
}
|
||||||
if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
|
String id = diffMatches.get(0).getId();
|
||||||
|
String lid = tail(id);
|
||||||
|
if (lid.contains("/")) {
|
||||||
|
// the template comes from the snapshot of the base
|
||||||
|
generateIds(result.getElement(), url, srcSD.getType());
|
||||||
|
String baseId = id.substring(0, id.length()-lid.length()) + lid.substring(0, lid.indexOf("/")); // this is wrong if there's more than one reslice (todo: one thing at a time)
|
||||||
|
template = getById(result.getElement(), baseId);
|
||||||
|
|
||||||
|
} else if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
|
||||||
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
||||||
if (sd == null && xver != null && xver.matchingUrl(p.getValue())) {
|
if (sd == null && xver != null && xver.matchingUrl(p.getValue())) {
|
||||||
|
@ -1928,6 +1936,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ElementDefinition getById(List<ElementDefinition> list, String baseId) {
|
||||||
|
for (ElementDefinition t : list) {
|
||||||
|
if (baseId.equals(t.getId())) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateConstraintSources(ElementDefinition ed, String url) {
|
private void updateConstraintSources(ElementDefinition ed, String url) {
|
||||||
for (ElementDefinitionConstraintComponent c : ed.getConstraint()) {
|
for (ElementDefinitionConstraintComponent c : ed.getConstraint()) {
|
||||||
if (!c.hasSource()) {
|
if (!c.hasSource()) {
|
||||||
|
@ -2507,19 +2524,22 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (webUrl != null) {
|
if (webUrl != null) {
|
||||||
// also, must touch up the markdown
|
// also, must touch up the markdown
|
||||||
if (element.hasDefinition())
|
if (element.hasDefinition())
|
||||||
element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true));
|
element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, false));
|
||||||
if (element.hasComment())
|
if (element.hasComment())
|
||||||
element.setComment(processRelativeUrls(element.getComment(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true));
|
element.setComment(processRelativeUrls(element.getComment(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, false));
|
||||||
if (element.hasRequirements())
|
if (element.hasRequirements())
|
||||||
element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true));
|
element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, false));
|
||||||
if (element.hasMeaningWhenMissing())
|
if (element.hasMeaningWhenMissing())
|
||||||
element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true));
|
element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String processRelativeUrls(String markdown, String webUrl, String basePath, List<String> resourceNames, Set<String> filenames, boolean processRelatives) {
|
public static String processRelativeUrls(String markdown, String webUrl, String basePath, List<String> resourceNames, Set<String> baseFilenames, Set<String> localFilenames, boolean processRelatives) {
|
||||||
|
if (markdown == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < markdown.length()) {
|
while (i < markdown.length()) {
|
||||||
|
@ -2540,7 +2560,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
// This code is trying to guess which relative references are actually to the
|
// This code is trying to guess which relative references are actually to the
|
||||||
// base specification.
|
// base specification.
|
||||||
//
|
//
|
||||||
if (isLikelySourceURLReference(url, resourceNames, filenames)) {
|
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
|
||||||
b.append("](");
|
b.append("](");
|
||||||
b.append(basePath);
|
b.append(basePath);
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
|
@ -2549,7 +2569,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
// disabled 7-Dec 2021 GDG - we don't want to fool with relative URLs at all?
|
// disabled 7-Dec 2021 GDG - we don't want to fool with relative URLs at all?
|
||||||
// re-enabled 11-Feb 2022 GDG - we do want to do this. At least, $assemble in davinci-dtr, where the markdown comes from the SDC IG, and an SDC local reference must be changed to point to SDC. in this case, it's called when generating snapshots
|
// re-enabled 11-Feb 2022 GDG - we do want to do this. At least, $assemble in davinci-dtr, where the markdown comes from the SDC IG, and an SDC local reference must be changed to point to SDC. in this case, it's called when generating snapshots
|
||||||
// added processRelatives parameter to deal with this (well, to try)
|
// added processRelatives parameter to deal with this (well, to try)
|
||||||
if (processRelatives && webUrl != null) {
|
if (processRelatives && webUrl != null && !issLocalFileName(url, localFilenames)) {
|
||||||
// System.out.println("Making "+url+" relative to '"+webUrl+"'");
|
// System.out.println("Making "+url+" relative to '"+webUrl+"'");
|
||||||
b.append(webUrl);
|
b.append(webUrl);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2570,7 +2590,19 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isLikelySourceURLReference(String url, List<String> resourceNames, Set<String> filenames) {
|
public static boolean issLocalFileName(String url, Set<String> localFilenames) {
|
||||||
|
if (localFilenames != null) {
|
||||||
|
for (String n : localFilenames) {
|
||||||
|
if (url.startsWith(n.toLowerCase())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isLikelySourceURLReference(String url, List<String> resourceNames, Set<String> baseFilenames, Set<String> localFilenames) {
|
||||||
if (resourceNames != null) {
|
if (resourceNames != null) {
|
||||||
for (String n : resourceNames) {
|
for (String n : resourceNames) {
|
||||||
if (url.startsWith(n.toLowerCase()+".html")) {
|
if (url.startsWith(n.toLowerCase()+".html")) {
|
||||||
|
@ -2581,8 +2613,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filenames != null) {
|
if (localFilenames != null) {
|
||||||
for (String n : filenames) {
|
for (String n : localFilenames) {
|
||||||
|
if (url.startsWith(n.toLowerCase())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (baseFilenames != null) {
|
||||||
|
for (String n : baseFilenames) {
|
||||||
if (url.startsWith(n.toLowerCase())) {
|
if (url.startsWith(n.toLowerCase())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2814,7 +2853,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
ElementDefinition e = profile.getSnapshot().getElement().get(0);
|
ElementDefinition e = profile.getSnapshot().getElement().get(0);
|
||||||
String webroot = profile.getUserString("webroot");
|
String webroot = profile.getUserString("webroot");
|
||||||
|
|
||||||
base.setDefinition(processRelativeUrls(e.getDefinition(), webroot, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true));
|
if (e.hasDefinition()) {
|
||||||
|
base.setDefinition(processRelativeUrls(e.getDefinition(), webroot, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, true));
|
||||||
|
}
|
||||||
base.setShort(e.getShort());
|
base.setShort(e.getShort());
|
||||||
if (e.hasCommentElement())
|
if (e.hasCommentElement())
|
||||||
base.setCommentElement(e.getCommentElement());
|
base.setCommentElement(e.getCommentElement());
|
||||||
|
@ -5247,7 +5288,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String tail(String path) {
|
private String tail(String path) {
|
||||||
if (path.contains("."))
|
if (path == null) {
|
||||||
|
return "";
|
||||||
|
} else if (path.contains("."))
|
||||||
return path.substring(path.lastIndexOf('.')+1);
|
return path.substring(path.lastIndexOf('.')+1);
|
||||||
else
|
else
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -1172,7 +1172,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (diffMatches.get(0).hasType() && "Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode()) && !isValidType(diffMatches.get(0).getType().get(0), currentBase)) {
|
if (diffMatches.get(0).hasType() && "Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode()) && !isValidType(diffMatches.get(0).getType().get(0), currentBase)) {
|
||||||
throw new DefinitionException(context.formatMessage(I18nConstants.VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT, url, diffMatches.get(0).getPath(), diffMatches.get(0).getType().get(0), currentBase.typeSummary()));
|
throw new DefinitionException(context.formatMessage(I18nConstants.VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT, url, diffMatches.get(0).getPath(), diffMatches.get(0).getType().get(0), currentBase.typeSummary()));
|
||||||
}
|
}
|
||||||
if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
|
String id = diffMatches.get(0).getId();
|
||||||
|
String lid = tail(id);
|
||||||
|
if (lid.contains("/")) {
|
||||||
|
// the template comes from the snapshot of the base
|
||||||
|
generateIds(result.getElement(), url, srcSD.getType());
|
||||||
|
String baseId = id.substring(0, id.length()-lid.length()) + lid.substring(0, lid.indexOf("/")); // this is wrong if there's more than one reslice (todo: one thing at a time)
|
||||||
|
template = getById(result.getElement(), baseId);
|
||||||
|
|
||||||
|
} else if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
|
||||||
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
||||||
if (sd == null && xver != null && xver.matchingUrl(p.getValue())) {
|
if (sd == null && xver != null && xver.matchingUrl(p.getValue())) {
|
||||||
|
@ -1932,6 +1940,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ElementDefinition getById(List<ElementDefinition> list, String baseId) {
|
||||||
|
for (ElementDefinition t : list) {
|
||||||
|
if (baseId.equals(t.getId())) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateConstraintSources(ElementDefinition ed, String url) {
|
private void updateConstraintSources(ElementDefinition ed, String url) {
|
||||||
for (ElementDefinitionConstraintComponent c : ed.getConstraint()) {
|
for (ElementDefinitionConstraintComponent c : ed.getConstraint()) {
|
||||||
if (!c.hasSource()) {
|
if (!c.hasSource()) {
|
||||||
|
@ -4844,6 +4861,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
String valueSet = ext.getExtensionString("valueSet");
|
String valueSet = ext.getExtensionString("valueSet");
|
||||||
String doco = ext.getExtensionString("documentation");
|
String doco = ext.getExtensionString("documentation");
|
||||||
UsageContext usage = (ext.hasExtension("usage")) ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
UsageContext usage = (ext.hasExtension("usage")) ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
||||||
|
boolean any = "any".equals(ext.getExtensionString("scope"));
|
||||||
|
|
||||||
//
|
//
|
||||||
// purpose: code - defines how the binding is used
|
// purpose: code - defines how the binding is used
|
||||||
// usage : UsageContext - defines the contexts in which this binding is used for it's purpose
|
// usage : UsageContext - defines the contexts in which this binding is used for it's purpose
|
||||||
|
@ -5275,7 +5294,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String tail(String path) {
|
private String tail(String path) {
|
||||||
if (path.contains("."))
|
if (path == null) {
|
||||||
|
return "";
|
||||||
|
} else if (path.contains("."))
|
||||||
return path.substring(path.lastIndexOf('.')+1);
|
return path.substring(path.lastIndexOf('.')+1);
|
||||||
else
|
else
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BuildExtensions extends ToolingExtensions {
|
||||||
|
|
||||||
|
public static final String EXT_DESCRIPTION = "http://hl7.org/fhir/build/StructureDefinition/description";
|
||||||
|
public static final String EXT_TITLE = "http://hl7.org/fhir/build/StructureDefinition/title";
|
||||||
|
public static final String EXT_EXAMPLE_TYPE = "http://hl7.org/fhir/build/CodeSystem/example-type";
|
||||||
|
public static final String EXT_NOT_REGISTERED = "http://hl7.org/fhir/build/StructureDefinition/registered";
|
||||||
|
public static final String EXT_IG = "http://hl7.org/fhir/build/StructureDefinition/ig";
|
||||||
|
public static final String EXT_EXAMPLE_FOR = "http://hl7.org/fhir/build/StructureDefinition/example-for";
|
||||||
|
public static final String EXT_PATH = "http://hl7.org/fhir/build/StructureDefinition/path";
|
||||||
|
public static final String EXT_FOOTER = "http://hl7.org/fhir/build/StructureDefinition/footer";
|
||||||
|
public static final String EXT_FOOTER2 = "http://hl7.org/fhir/build/StructureDefinition/footer2";
|
||||||
|
public static final String EXT_ENTERED_IN_ERROR_STATUS = "http://hl7.org/fhir/build/StructureDefinition/entered-in-error-status";
|
||||||
|
public static final String EXT_PROPOSED_ORDER = "http://hl7.org/fhir/build/StructureDefinition/proposed-order";
|
||||||
|
public static final String EXT_HINT = "http://hl7.org/fhir/build/StructureDefinition/hint";
|
||||||
|
public static final String EXT_LAYOUT = "http://hl7.org/fhir/build/StructureDefinition/layout";
|
||||||
|
public static final String EXT_TODO = "http://hl7.org/fhir/build/StructureDefinition/todo";
|
||||||
|
public static final String EXT_COMMITTEE_NOTES = "http://hl7.org/fhir/build/StructureDefinition/committee-notes";
|
||||||
|
public static final String EXT_UML_DIR = "http://hl7.org/fhir/build/StructureDefinition/uml-dir";
|
||||||
|
public static final String EXT_UML_BREAK = "http://hl7.org/fhir/build/StructureDefinition/uml-break";
|
||||||
|
public static final String EXT_SVG = "http://hl7.org/fhir/build/StructureDefinition/svg";
|
||||||
|
public static final String EXT_OCL = "http://hl7.org/fhir/build/StructureDefinition/ocl";
|
||||||
|
public static final String EXT_FIXED_NAME = "http://hl7.org/fhir/build/StructureDefinition/fixed-name";
|
||||||
|
public static final String EXT_TURTLE = "http://hl7.org/fhir/build/StructureDefinition/turtle";
|
||||||
|
public static final String EXT_NAME = "http://hl7.org/fhir/build/StructureDefinition/name";
|
||||||
|
public static final String EXT_V2_MAP = "http://hl7.org/fhir/build/StructureDefinition/v2-map";
|
||||||
|
public static final String EXT_V3_MAP = "http://hl7.org/fhir/build/StructureDefinition/v3-map";
|
||||||
|
public static final String EXT_BINDING_DEFINITION = "http://hl7.org/fhir/build/StructureDefinition/binding-definition";
|
||||||
|
public static final String EXT_URI = "http://hl7.org/fhir/build/StructureDefinition/uri";
|
||||||
|
public static final String EXT_WEBSITE = "http://hl7.org/fhir/build/StructureDefinition/website";
|
||||||
|
public static final String EXT_EMAIL = "http://hl7.org/fhir/build/StructureDefinition/email";
|
||||||
|
public static final String EXT_COPYRIGHT = "http://hl7.org/fhir/build/StructureDefinition/copyright";
|
||||||
|
public static final String EXT_CS_OID = "http://hl7.org/fhir/build/StructureDefinition/cs-oid";
|
||||||
|
public static final String EXT_VS_OID = "http://hl7.org/fhir/build/StructureDefinition/vs-oid";
|
||||||
|
public static final String EXT_STATUS = "http://hl7.org/fhir/build/StructureDefinition/status";
|
||||||
|
public static final String EXT_INTRODUCTION = "http://hl7.org/fhir/build/StructureDefinition/introduction";
|
||||||
|
public static final String EXT_NOTES = "http://hl7.org/fhir/build/StructureDefinition/notes";
|
||||||
|
public static final String EXT_CODE = "http://hl7.org/fhir/build/StructureDefinition/code";
|
||||||
|
public static final String EXT_TYPE = "http://hl7.org/fhir/build/StructureDefinition/type";
|
||||||
|
public static final String EXT_SUMMARY = "http://hl7.org/fhir/build/StructureDefinition/summary";
|
||||||
|
// public static final String EXT_EXPLANATION = "http://hl7.org/fhir/build/StructureDefinition/explanation";
|
||||||
|
public static final String EXT_NO_BINDING = "http://hl7.org/fhir/build/StructureDefinition/no-binding";
|
||||||
|
public static final String EXT_OP_EXAMPLE = "http://hl7.org/fhir/build/StructureDefinition/example";
|
||||||
|
public static final String EXT_OP_EXAMPLE_CONTENT = "content";
|
||||||
|
public static final String EXT_OP_EXAMPLE_COMMENT = "comment";
|
||||||
|
public static final String EXT_OP_EXAMPLE_RESPONSE = "response";
|
||||||
|
public static final String EXT_OP_EXAMPLE_LIST = "list";
|
||||||
|
public static final String EXT_TEMPLATE = "http://hl7.org/fhir/build/StructureDefinition/template";
|
||||||
|
public static final String EXT_BINDING_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName";
|
||||||
|
|
||||||
|
|
||||||
|
public static List<String> allConsts() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Field field : BuildExtensions.class.getDeclaredFields()) {
|
||||||
|
int modifiers = field.getModifiers();
|
||||||
|
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
|
||||||
|
try {
|
||||||
|
list.add(field.get(field.getType()).toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.addAll(ToolingExtensions.allConsts());
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -84,12 +84,12 @@ import ca.uhn.fhir.util.ElementUtil;
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
list of conditions and the following disclaimer.
|
list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
* 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
|
endorse or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
|
@ -408,8 +408,8 @@ public class FHIRPathEngine {
|
||||||
* @param item
|
* @param item
|
||||||
* @param name
|
* @param name
|
||||||
* @param result
|
* @param result
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
*/
|
*/
|
||||||
protected void getChildrenByName(Base item, String name, List<Base> result) throws FHIRException {
|
protected void getChildrenByName(Base item, String name, List<Base> result) throws FHIRException {
|
||||||
String tn = null;
|
String tn = null;
|
||||||
if (isAllowPolymorphicNames()) {
|
if (isAllowPolymorphicNames()) {
|
||||||
|
@ -640,10 +640,10 @@ public class FHIRPathEngine {
|
||||||
} else if (left.getHour() > right.getHour()) {
|
} else if (left.getHour() > right.getHour()) {
|
||||||
return 1;
|
return 1;
|
||||||
// hour is not a valid precision
|
// hour is not a valid precision
|
||||||
// } else if (dateLeft.getPrecision() == TemporalPrecisionEnum.YEAR && dateRight.getPrecision() == TemporalPrecisionEnum.YEAR) {
|
// } else if (dateLeft.getPrecision() == TemporalPrecisionEnum.YEAR && dateRight.getPrecision() == TemporalPrecisionEnum.YEAR) {
|
||||||
// return 0;
|
// return 0;
|
||||||
// } else if (dateLeft.getPrecision() == TemporalPrecisionEnum.HOUR || dateRight.getPrecision() == TemporalPrecisionEnum.HOUR) {
|
// } else if (dateLeft.getPrecision() == TemporalPrecisionEnum.HOUR || dateRight.getPrecision() == TemporalPrecisionEnum.HOUR) {
|
||||||
// return null;
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left.getMinute() < right.getMinute()) {
|
if (left.getMinute() < right.getMinute()) {
|
||||||
|
@ -676,7 +676,7 @@ public class FHIRPathEngine {
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public List<Base> evaluate(Base base, ExpressionNode ExpressionNode) throws FHIRException {
|
public List<Base> evaluate(Base base, ExpressionNode ExpressionNode) throws FHIRException {
|
||||||
List<Base> list = new ArrayList<Base>();
|
List<Base> list = new ArrayList<Base>();
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
list.add(base);
|
list.add(base);
|
||||||
|
@ -691,10 +691,10 @@ public class FHIRPathEngine {
|
||||||
* @param base - the object against which the path is being evaluated
|
* @param base - the object against which the path is being evaluated
|
||||||
* @param path - the FHIR Path statement to use
|
* @param path - the FHIR Path statement to use
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public List<Base> evaluate(Base base, String path) throws FHIRException {
|
public List<Base> evaluate(Base base, String path) throws FHIRException {
|
||||||
ExpressionNode exp = parse(path);
|
ExpressionNode exp = parse(path);
|
||||||
List<Base> list = new ArrayList<Base>();
|
List<Base> list = new ArrayList<Base>();
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
|
@ -710,10 +710,10 @@ public class FHIRPathEngine {
|
||||||
* @param base - the object against which the path is being evaluated
|
* @param base - the object against which the path is being evaluated
|
||||||
* @param ExpressionNode - the parsed ExpressionNode statement to use
|
* @param ExpressionNode - the parsed ExpressionNode statement to use
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public List<Base> evaluate(Object appContext, Resource focusResource, Resource rootResource, Base base, ExpressionNode ExpressionNode) throws FHIRException {
|
public List<Base> evaluate(Object appContext, Resource focusResource, Resource rootResource, Base base, ExpressionNode ExpressionNode) throws FHIRException {
|
||||||
List<Base> list = new ArrayList<Base>();
|
List<Base> list = new ArrayList<Base>();
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
list.add(base);
|
list.add(base);
|
||||||
|
@ -746,10 +746,10 @@ public class FHIRPathEngine {
|
||||||
* @param base - the object against which the path is being evaluated
|
* @param base - the object against which the path is being evaluated
|
||||||
* @param path - the FHIR Path statement to use
|
* @param path - the FHIR Path statement to use
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public List<Base> evaluate(Object appContext, Resource focusResource, Resource rootResource, Base base, String path) throws FHIRException {
|
public List<Base> evaluate(Object appContext, Resource focusResource, Resource rootResource, Base base, String path) throws FHIRException {
|
||||||
ExpressionNode exp = parse(path);
|
ExpressionNode exp = parse(path);
|
||||||
List<Base> list = new ArrayList<Base>();
|
List<Base> list = new ArrayList<Base>();
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
|
@ -765,10 +765,10 @@ public class FHIRPathEngine {
|
||||||
* @param base - the object against which the path is being evaluated
|
* @param base - the object against which the path is being evaluated
|
||||||
* @param path - the FHIR Path statement to use
|
* @param path - the FHIR Path statement to use
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public boolean evaluateToBoolean(Resource focusResource, Resource rootResource, Base base, String path) throws FHIRException {
|
public boolean evaluateToBoolean(Resource focusResource, Resource rootResource, Base base, String path) throws FHIRException {
|
||||||
return convertToBoolean(evaluate(null, focusResource, rootResource, base, path));
|
return convertToBoolean(evaluate(null, focusResource, rootResource, base, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,7 +815,7 @@ public class FHIRPathEngine {
|
||||||
* @param base - the object against which the path is being evaluated
|
* @param base - the object against which the path is being evaluated
|
||||||
* @param path - the FHIR Path statement to use
|
* @param path - the FHIR Path statement to use
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @
|
* @
|
||||||
*/
|
*/
|
||||||
public String evaluateToString(Base base, String path) throws FHIRException {
|
public String evaluateToString(Base base, String path) throws FHIRException {
|
||||||
|
@ -935,7 +935,7 @@ public class FHIRPathEngine {
|
||||||
return focusResource;
|
return focusResource;
|
||||||
}
|
}
|
||||||
public Base getRootResource() {
|
public Base getRootResource() {
|
||||||
return rootResource;
|
return rootResource;
|
||||||
}
|
}
|
||||||
public Base getThisItem() {
|
public Base getThisItem() {
|
||||||
return thisItem;
|
return thisItem;
|
||||||
|
@ -1386,8 +1386,8 @@ public class FHIRPathEngine {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry) throws FHIRException {
|
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry) throws FHIRException {
|
||||||
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
|
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
|
||||||
List<Base> work = new ArrayList<Base>();
|
List<Base> work = new ArrayList<Base>();
|
||||||
switch (exp.getKind()) {
|
switch (exp.getKind()) {
|
||||||
case Unary:
|
case Unary:
|
||||||
|
@ -1441,13 +1441,13 @@ public class FHIRPathEngine {
|
||||||
} else {
|
} else {
|
||||||
work2 = execute(context, focus, next, true);
|
work2 = execute(context, focus, next, true);
|
||||||
work = operate(context, work, last.getOperation(), work2, last);
|
work = operate(context, work, last.getOperation(), work2, last);
|
||||||
// System.out.println("Result of {'"+last.toString()+" "+last.getOperation().toCode()+" "+next.toString()+"'}: "+focus.toString());
|
// System.out.println("Result of {'"+last.toString()+" "+last.getOperation().toCode()+" "+next.toString()+"'}: "+focus.toString());
|
||||||
}
|
}
|
||||||
last = next;
|
last = next;
|
||||||
next = next.getOpNext();
|
next = next.getOpNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// System.out.println("Result of {'"+exp.toString()+"'}: "+work.toString());
|
// System.out.println("Result of {'"+exp.toString()+"'}: "+work.toString());
|
||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1972,7 +1972,7 @@ public class FHIRPathEngine {
|
||||||
} else if (left instanceof DecimalType || right instanceof DecimalType) {
|
} else if (left instanceof DecimalType || right instanceof DecimalType) {
|
||||||
return decEqual(left.primitiveValue(), right.primitiveValue());
|
return decEqual(left.primitiveValue(), right.primitiveValue());
|
||||||
} else if (left.isPrimitive() && right.isPrimitive()) {
|
} else if (left.isPrimitive() && right.isPrimitive()) {
|
||||||
return Base.equals(left.primitiveValue(), right.primitiveValue());
|
return Base.equals(left.primitiveValue(), right.primitiveValue());
|
||||||
} else {
|
} else {
|
||||||
return Base.compareDeep(left, right, false);
|
return Base.compareDeep(left, right, false);
|
||||||
}
|
}
|
||||||
|
@ -2183,7 +2183,7 @@ public class FHIRPathEngine {
|
||||||
|
|
||||||
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary", "canonical", "url"};
|
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary", "canonical", "url"};
|
||||||
|
|
||||||
private List<Base> opLessThan(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opLessThan(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
if (left.size() == 0 || right.size() == 0)
|
if (left.size() == 0 || right.size() == 0)
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
|
|
||||||
|
@ -2231,7 +2231,7 @@ public class FHIRPathEngine {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opGreater(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opGreater(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
if (left.size() == 0 || right.size() == 0)
|
if (left.size() == 0 || right.size() == 0)
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
|
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
|
||||||
|
@ -2278,7 +2278,7 @@ public class FHIRPathEngine {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opLessOrEqual(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opLessOrEqual(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
if (left.size() == 0 || right.size() == 0) {
|
if (left.size() == 0 || right.size() == 0) {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
@ -2328,7 +2328,7 @@ public class FHIRPathEngine {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opGreaterOrEqual(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opGreaterOrEqual(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
if (left.size() == 0 || right.size() == 0) {
|
if (left.size() == 0 || right.size() == 0) {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
@ -2376,34 +2376,34 @@ public class FHIRPathEngine {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opMemberOf(ExecutionContext context, List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opMemberOf(ExecutionContext context, List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
boolean ans = false;
|
boolean ans = false;
|
||||||
String url = right.get(0).primitiveValue();
|
String url = right.get(0).primitiveValue();
|
||||||
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, url) : worker.fetchResource(ValueSet.class, url);
|
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, url) : worker.fetchResource(ValueSet.class, url);
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
for (Base l : left) {
|
for (Base l : left) {
|
||||||
if (Utilities.existsInList(l.fhirType(), "code", "string", "uri")) {
|
if (Utilities.existsInList(l.fhirType(), "code", "string", "uri")) {
|
||||||
if (worker.validateCode(terminologyServiceOptions.guessSystem() , TypeConvertor.castToCoding(l), vs).isOk()) {
|
if (worker.validateCode(terminologyServiceOptions.guessSystem() , TypeConvertor.castToCoding(l), vs).isOk()) {
|
||||||
ans = true;
|
ans = true;
|
||||||
}
|
}
|
||||||
} else if (l.fhirType().equals("Coding")) {
|
} else if (l.fhirType().equals("Coding")) {
|
||||||
if (worker.validateCode(terminologyServiceOptions, TypeConvertor.castToCoding(l), vs).isOk()) {
|
if (worker.validateCode(terminologyServiceOptions, TypeConvertor.castToCoding(l), vs).isOk()) {
|
||||||
ans = true;
|
ans = true;
|
||||||
}
|
}
|
||||||
} else if (l.fhirType().equals("CodeableConcept")) {
|
} else if (l.fhirType().equals("CodeableConcept")) {
|
||||||
CodeableConcept cc = TypeConvertor.castToCodeableConcept(l);
|
CodeableConcept cc = TypeConvertor.castToCodeableConcept(l);
|
||||||
ValidationResult vr = worker.validateCode(terminologyServiceOptions, cc, vs);
|
ValidationResult vr = worker.validateCode(terminologyServiceOptions, cc, vs);
|
||||||
// System.out.println("~~~ "+DataRenderer.display(worker, cc)+ " memberOf "+url+": "+vr.toString());
|
// System.out.println("~~~ "+DataRenderer.display(worker, cc)+ " memberOf "+url+": "+vr.toString());
|
||||||
if (vr.isOk()) {
|
if (vr.isOk()) {
|
||||||
ans = true;
|
ans = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// System.out.println("unknown type in opMemberOf: "+l.fhirType());
|
// System.out.println("unknown type in opMemberOf: "+l.fhirType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return makeBoolean(ans);
|
return makeBoolean(ans);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opIn(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
private List<Base> opIn(List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
if (left.size() == 0) {
|
if (left.size() == 0) {
|
||||||
|
@ -2432,7 +2432,7 @@ public class FHIRPathEngine {
|
||||||
|
|
||||||
private List<Base> opContains(List<Base> left, List<Base> right, ExpressionNode expr) {
|
private List<Base> opContains(List<Base> left, List<Base> right, ExpressionNode expr) {
|
||||||
if (left.size() == 0 || right.size() == 0) {
|
if (left.size() == 0 || right.size() == 0) {
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
boolean ans = true;
|
boolean ans = true;
|
||||||
for (Base r : right) {
|
for (Base r : right) {
|
||||||
|
@ -2936,7 +2936,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> execute(ExecutionContext context, Base item, ExpressionNode exp, boolean atEntry) throws FHIRException {
|
private List<Base> execute(ExecutionContext context, Base item, ExpressionNode exp, boolean atEntry) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (atEntry && context.appInfo != null && hostServices != null) {
|
if (atEntry && context.appInfo != null && hostServices != null) {
|
||||||
// we'll see if the name matches a constant known by the context.
|
// we'll see if the name matches a constant known by the context.
|
||||||
|
@ -2946,7 +2946,7 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (atEntry && Character.isUpperCase(exp.getName().charAt(0))) {// special case for start up
|
if (atEntry && exp.getName() != null && Character.isUpperCase(exp.getName().charAt(0))) {// special case for start up
|
||||||
StructureDefinition sd = worker.fetchTypeDefinition(item.fhirType());
|
StructureDefinition sd = worker.fetchTypeDefinition(item.fhirType());
|
||||||
if (sd == null) {
|
if (sd == null) {
|
||||||
// logical model
|
// logical model
|
||||||
|
@ -3006,12 +3006,14 @@ public class FHIRPathEngine {
|
||||||
if (exp.getFunction() == Function.Is || exp.getFunction() == Function.As || exp.getFunction() == Function.OfType) {
|
if (exp.getFunction() == Function.Is || exp.getFunction() == Function.As || exp.getFunction() == Function.OfType) {
|
||||||
paramTypes.add(new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
paramTypes.add(new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||||
} else {
|
} else {
|
||||||
|
int i = 0;
|
||||||
for (ExpressionNode expr : exp.getParameters()) {
|
for (ExpressionNode expr : exp.getParameters()) {
|
||||||
if (exp.getFunction() == Function.Where || exp.getFunction() == Function.All || exp.getFunction() == Function.Select || exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate) {
|
if (isExpressionParameter(exp, i)) {
|
||||||
paramTypes.add(executeType(changeThis(context, focus), focus, expr, true));
|
paramTypes.add(executeType(changeThis(context, focus), focus, expr, true));
|
||||||
} else {
|
} else {
|
||||||
paramTypes.add(executeType(context, focus, expr, true));
|
paramTypes.add(executeType(context, context.thisItem, expr, true));
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (exp.getFunction()) {
|
switch (exp.getFunction()) {
|
||||||
|
@ -3344,6 +3346,17 @@ public class FHIRPathEngine {
|
||||||
throw new Error("not Implemented yet");
|
throw new Error("not Implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isExpressionParameter(ExpressionNode exp, int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return exp.getFunction() == Function.Where || exp.getFunction() == Function.Exists || exp.getFunction() == Function.All || exp.getFunction() == Function.Select || exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
|
||||||
|
case 1:
|
||||||
|
return exp.getFunction() == Function.Trace;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void checkParamTypes(ExpressionNode expr, String funcName, List<TypeDetails> paramTypes, TypeDetails... typeSet) throws PathEngineException {
|
private void checkParamTypes(ExpressionNode expr, String funcName, List<TypeDetails> paramTypes, TypeDetails... typeSet) throws PathEngineException {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -3390,9 +3403,9 @@ public class FHIRPathEngine {
|
||||||
|
|
||||||
private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty, ExpressionNode expr) throws PathEngineException {
|
private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty, ExpressionNode expr) throws PathEngineException {
|
||||||
if (canQty) {
|
if (canQty) {
|
||||||
if (!focus.hasType(primitiveTypes) && !focus.hasType("Quantity")) {
|
if (!focus.hasType(primitiveTypes) && !focus.hasType("Quantity")) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), "Quantity, "+primitiveTypes.toString());
|
throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), "Quantity, "+primitiveTypes.toString());
|
||||||
}
|
}
|
||||||
} else if (!focus.hasType(primitiveTypes)) {
|
} else if (!focus.hasType(primitiveTypes)) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), primitiveTypes.toString());
|
throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), primitiveTypes.toString());
|
||||||
}
|
}
|
||||||
|
@ -3426,7 +3439,7 @@ public class FHIRPathEngine {
|
||||||
// return s.equals("boolean") || s.equals("integer") || s.equals("decimal") || s.equals("base64Binary") || s.equals("instant") || s.equals("string") || s.equals("uri") || s.equals("date") || s.equals("dateTime") || s.equals("time") || s.equals("code") || s.equals("oid") || s.equals("id") || s.equals("unsignedInt") || s.equals("positiveInt") || s.equals("markdown");
|
// return s.equals("boolean") || s.equals("integer") || s.equals("decimal") || s.equals("base64Binary") || s.equals("instant") || s.equals("string") || s.equals("uri") || s.equals("date") || s.equals("dateTime") || s.equals("time") || s.equals("code") || s.equals("oid") || s.equals("id") || s.equals("unsignedInt") || s.equals("positiveInt") || s.equals("markdown");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private List<Base> evaluateFunction(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> evaluateFunction(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
switch (exp.getFunction()) {
|
switch (exp.getFunction()) {
|
||||||
case Empty : return funcEmpty(context, focus, exp);
|
case Empty : return funcEmpty(context, focus, exp);
|
||||||
case Not : return funcNot(context, focus, exp);
|
case Not : return funcNot(context, focus, exp);
|
||||||
|
@ -3534,24 +3547,24 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcSqrt(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcSqrt(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
if (focus.size() != 1) {
|
if (focus.size() != 1) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "sqrt", focus.size());
|
throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "sqrt", focus.size());
|
||||||
}
|
}
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new DecimalType(Math.sqrt(d)));
|
result.add(new DecimalType(Math.sqrt(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Base> funcAbs(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcAbs(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
|
@ -3561,12 +3574,12 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new DecimalType(Math.abs(d)));
|
result.add(new DecimalType(Math.abs(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else if (base.hasType("Quantity")) {
|
} else if (base.hasType("Quantity")) {
|
||||||
Quantity qty = (Quantity) base;
|
Quantity qty = (Quantity) base;
|
||||||
result.add(qty.copy().setValue(qty.getValue().abs()));
|
result.add(qty.copy().setValue(qty.getValue().abs()));
|
||||||
|
@ -3584,11 +3597,11 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {result.add(new IntegerType((int) Math.ceil(d)));
|
try {result.add(new IntegerType((int) Math.ceil(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ceiling", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ceiling", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
|
@ -3602,12 +3615,12 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new IntegerType((int) Math.floor(d)));
|
result.add(new IntegerType((int) Math.floor(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "floor", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "floor", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
|
@ -3622,12 +3635,12 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new DecimalType(Math.exp(d)));
|
result.add(new DecimalType(Math.exp(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "exp", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "exp", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
|
@ -3643,12 +3656,12 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new DecimalType(Math.log(d)));
|
result.add(new DecimalType(Math.log(d)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ln", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ln", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
|
@ -3696,12 +3709,12 @@ public class FHIRPathEngine {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer or decimal");
|
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer or decimal");
|
||||||
}
|
}
|
||||||
Double e = Double.parseDouble(n1.get(0).primitiveValue());
|
Double e = Double.parseDouble(n1.get(0).primitiveValue());
|
||||||
Double d = Double.parseDouble(base.primitiveValue());
|
Double d = Double.parseDouble(base.primitiveValue());
|
||||||
try {
|
try {
|
||||||
result.add(new DecimalType(Math.pow(d, e)));
|
result.add(new DecimalType(Math.pow(d, e)));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// just return nothing
|
// just return nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
|
@ -3715,11 +3728,11 @@ public class FHIRPathEngine {
|
||||||
Base base = focus.get(0);
|
Base base = focus.get(0);
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
|
||||||
String s = base.primitiveValue();
|
String s = base.primitiveValue();
|
||||||
if (s.contains(".")) {
|
if (s.contains(".")) {
|
||||||
s = s.substring(0, s.indexOf("."));
|
s = s.substring(0, s.indexOf("."));
|
||||||
}
|
}
|
||||||
result.add(new IntegerType(s));
|
result.add(new IntegerType(s));
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
|
||||||
}
|
}
|
||||||
|
@ -3750,26 +3763,26 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
||||||
public static String bytesToHex(byte[] bytes) {
|
public static String bytesToHex(byte[] bytes) {
|
||||||
char[] hexChars = new char[bytes.length * 2];
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
int v = bytes[j] & 0xFF;
|
int v = bytes[j] & 0xFF;
|
||||||
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
||||||
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
||||||
}
|
}
|
||||||
return new String(hexChars);
|
return new String(hexChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] hexStringToByteArray(String s) {
|
public static byte[] hexStringToByteArray(String s) {
|
||||||
int len = s.length();
|
int len = s.length();
|
||||||
byte[] data = new byte[len / 2];
|
byte[] data = new byte[len / 2];
|
||||||
for (int i = 0; i < len; i += 2) {
|
for (int i = 0; i < len; i += 2) {
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcEncode(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
private List<Base> funcEncode(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
String param = nl.get(0).primitiveValue();
|
String param = nl.get(0).primitiveValue();
|
||||||
|
|
||||||
|
@ -3788,7 +3801,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcDecode(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
private List<Base> funcDecode(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
|
@ -4047,7 +4060,7 @@ public class FHIRPathEngine {
|
||||||
} else if (l.fhirType().equals("CodeableConcept")) {
|
} else if (l.fhirType().equals("CodeableConcept")) {
|
||||||
return makeBoolean(worker.validateCode(terminologyServiceOptions, TypeConvertor.castToCodeableConcept(l), vs).isOk());
|
return makeBoolean(worker.validateCode(terminologyServiceOptions, TypeConvertor.castToCodeableConcept(l), vs).isOk());
|
||||||
} else {
|
} else {
|
||||||
// System.out.println("unknown type in funcMemberOf: "+l.fhirType());
|
// System.out.println("unknown type in funcMemberOf: "+l.fhirType());
|
||||||
return new ArrayList<Base>();
|
return new ArrayList<Base>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4190,18 +4203,18 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcToDateTime(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcToDateTime(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
// List<Base> result = new ArrayList<Base>();
|
// List<Base> result = new ArrayList<Base>();
|
||||||
// result.add(new BooleanType(convertToBoolean(focus)));
|
// result.add(new BooleanType(convertToBoolean(focus)));
|
||||||
// return result;
|
// return result;
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toDateTime");
|
throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toDateTime");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcToTime(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcToTime(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
// List<Base> result = new ArrayList<Base>();
|
// List<Base> result = new ArrayList<Base>();
|
||||||
// result.add(new BooleanType(convertToBoolean(focus)));
|
// result.add(new BooleanType(convertToBoolean(focus)));
|
||||||
// return result;
|
// return result;
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toTime");
|
throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toTime");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Base> funcToDecimal(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcToDecimal(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
|
@ -4253,7 +4266,7 @@ public class FHIRPathEngine {
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Base item : execute(context, focus, exp.getParameters().get(0), true)) {
|
for (Base item : execute(context, baseToList(context.thisItem), exp.getParameters().get(0), true)) {
|
||||||
if (!doContains(result, item)) {
|
if (!doContains(result, item)) {
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
|
@ -4402,10 +4415,21 @@ public class FHIRPathEngine {
|
||||||
pc.add(item);
|
pc.add(item);
|
||||||
added.addAll(execute(changeThis(context, item), pc, exp.getParameters().get(0), false));
|
added.addAll(execute(changeThis(context, item), pc, exp.getParameters().get(0), false));
|
||||||
}
|
}
|
||||||
more = !added.isEmpty();
|
more = false;
|
||||||
result.addAll(added);
|
|
||||||
current.clear();
|
current.clear();
|
||||||
current.addAll(added);
|
for (Base b : added) {
|
||||||
|
boolean isnew = true;
|
||||||
|
for (Base t : result) {
|
||||||
|
if (b.equalsDeep(t)) {
|
||||||
|
isnew = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isnew) {
|
||||||
|
result.add(b);
|
||||||
|
current.add(b);
|
||||||
|
more = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -4593,125 +4617,125 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcAllFalse(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcAllFalse(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (exp.getParameters().size() == 1) {
|
if (exp.getParameters().size() == 1) {
|
||||||
boolean all = true;
|
boolean all = true;
|
||||||
List<Base> pc = new ArrayList<Base>();
|
List<Base> pc = new ArrayList<Base>();
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
pc.clear();
|
pc.clear();
|
||||||
pc.add(item);
|
pc.add(item);
|
||||||
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
||||||
Equality v = asBool(res, exp);
|
Equality v = asBool(res, exp);
|
||||||
if (v != Equality.False) {
|
|
||||||
all = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.add(new BooleanType(all).noExtensions());
|
|
||||||
} else {
|
|
||||||
boolean all = true;
|
|
||||||
for (Base item : focus) {
|
|
||||||
if (!canConvertToBoolean(item)) {
|
|
||||||
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
|
||||||
}
|
|
||||||
|
|
||||||
Equality v = asBool(item, true);
|
|
||||||
if (v != Equality.False) {
|
if (v != Equality.False) {
|
||||||
all = false;
|
all = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(all).noExtensions());
|
result.add(new BooleanType(all).noExtensions());
|
||||||
}
|
} else {
|
||||||
return result;
|
boolean all = true;
|
||||||
}
|
for (Base item : focus) {
|
||||||
|
if (!canConvertToBoolean(item)) {
|
||||||
|
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
||||||
|
}
|
||||||
|
|
||||||
private List<Base> funcAnyFalse(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
Equality v = asBool(item, true);
|
||||||
List<Base> result = new ArrayList<Base>();
|
if (v != Equality.False) {
|
||||||
if (exp.getParameters().size() == 1) {
|
all = false;
|
||||||
boolean any = false;
|
break;
|
||||||
List<Base> pc = new ArrayList<Base>();
|
}
|
||||||
for (Base item : focus) {
|
}
|
||||||
pc.clear();
|
result.add(new BooleanType(all).noExtensions());
|
||||||
pc.add(item);
|
}
|
||||||
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
return result;
|
||||||
Equality v = asBool(res, exp);
|
}
|
||||||
|
|
||||||
|
private List<Base> funcAnyFalse(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
|
List<Base> result = new ArrayList<Base>();
|
||||||
|
if (exp.getParameters().size() == 1) {
|
||||||
|
boolean any = false;
|
||||||
|
List<Base> pc = new ArrayList<Base>();
|
||||||
|
for (Base item : focus) {
|
||||||
|
pc.clear();
|
||||||
|
pc.add(item);
|
||||||
|
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
||||||
|
Equality v = asBool(res, exp);
|
||||||
if (v == Equality.False) {
|
if (v == Equality.False) {
|
||||||
any = true;
|
any = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(any).noExtensions());
|
result.add(new BooleanType(any).noExtensions());
|
||||||
} else {
|
} else {
|
||||||
boolean any = false;
|
boolean any = false;
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
if (!canConvertToBoolean(item)) {
|
if (!canConvertToBoolean(item)) {
|
||||||
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
||||||
}
|
}
|
||||||
|
|
||||||
Equality v = asBool(item, true);
|
Equality v = asBool(item, true);
|
||||||
if (v == Equality.False) {
|
if (v == Equality.False) {
|
||||||
any = true;
|
any = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(any).noExtensions());
|
result.add(new BooleanType(any).noExtensions());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcAllTrue(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcAllTrue(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (exp.getParameters().size() == 1) {
|
if (exp.getParameters().size() == 1) {
|
||||||
boolean all = true;
|
boolean all = true;
|
||||||
List<Base> pc = new ArrayList<Base>();
|
List<Base> pc = new ArrayList<Base>();
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
pc.clear();
|
pc.clear();
|
||||||
pc.add(item);
|
pc.add(item);
|
||||||
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
||||||
Equality v = asBool(res, exp);
|
Equality v = asBool(res, exp);
|
||||||
if (v != Equality.True) {
|
if (v != Equality.True) {
|
||||||
all = false;
|
all = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(all).noExtensions());
|
result.add(new BooleanType(all).noExtensions());
|
||||||
} else {
|
} else {
|
||||||
boolean all = true;
|
boolean all = true;
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
if (!canConvertToBoolean(item)) {
|
if (!canConvertToBoolean(item)) {
|
||||||
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
||||||
}
|
}
|
||||||
Equality v = asBool(item, true);
|
Equality v = asBool(item, true);
|
||||||
if (v != Equality.True) {
|
if (v != Equality.True) {
|
||||||
all = false;
|
all = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(all).noExtensions());
|
result.add(new BooleanType(all).noExtensions());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcAnyTrue(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcAnyTrue(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (exp.getParameters().size() == 1) {
|
if (exp.getParameters().size() == 1) {
|
||||||
boolean any = false;
|
boolean any = false;
|
||||||
List<Base> pc = new ArrayList<Base>();
|
List<Base> pc = new ArrayList<Base>();
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
pc.clear();
|
pc.clear();
|
||||||
pc.add(item);
|
pc.add(item);
|
||||||
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
List<Base> res = execute(context, pc, exp.getParameters().get(0), true);
|
||||||
Equality v = asBool(res, exp);
|
Equality v = asBool(res, exp);
|
||||||
if (v == Equality.True) {
|
if (v == Equality.True) {
|
||||||
any = true;
|
any = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(any).noExtensions());
|
result.add(new BooleanType(any).noExtensions());
|
||||||
} else {
|
} else {
|
||||||
boolean any = false;
|
boolean any = false;
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
if (!canConvertToBoolean(item)) {
|
if (!canConvertToBoolean(item)) {
|
||||||
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
throw new FHIRException("Unable to convert '"+convertToString(item)+"' to a boolean");
|
||||||
|
@ -4719,16 +4743,16 @@ public class FHIRPathEngine {
|
||||||
|
|
||||||
Equality v = asBool(item, true);
|
Equality v = asBool(item, true);
|
||||||
if (v == Equality.True) {
|
if (v == Equality.True) {
|
||||||
any = true;
|
any = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new BooleanType(any).noExtensions());
|
result.add(new BooleanType(any).noExtensions());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canConvertToBoolean(Base item) {
|
private boolean canConvertToBoolean(Base item) {
|
||||||
return (item.isBooleanPrimitive());
|
return (item.isBooleanPrimitive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4778,7 +4802,7 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcMatches(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcMatches(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
||||||
|
|
||||||
|
@ -4798,29 +4822,30 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcMatchesFull(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcMatchesFull(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
|
||||||
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
|
||||||
|
|
||||||
if (focus.size() == 1 && !Utilities.noString(sw)) {
|
|
||||||
String st = convertToString(focus.get(0));
|
|
||||||
if (Utilities.noString(st)) {
|
|
||||||
result.add(new BooleanType(false).noExtensions());
|
|
||||||
} else {
|
|
||||||
Pattern p = Pattern.compile("(?s)" + sw);
|
|
||||||
Matcher m = p.matcher(st);
|
|
||||||
boolean ok = m.matches();
|
|
||||||
result.add(new BooleanType(ok).noExtensions());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.add(new BooleanType(false).noExtensions());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
private List<Base> funcContains(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
||||||
|
|
||||||
|
if (focus.size() == 1 && !Utilities.noString(sw)) {
|
||||||
|
String st = convertToString(focus.get(0));
|
||||||
|
if (Utilities.noString(st)) {
|
||||||
|
result.add(new BooleanType(false).noExtensions());
|
||||||
|
} else {
|
||||||
|
Pattern p = Pattern.compile("(?s)" + sw);
|
||||||
|
Matcher m = p.matcher(st);
|
||||||
|
boolean ok = m.matches();
|
||||||
|
result.add(new BooleanType(ok).noExtensions());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.add(new BooleanType(false).noExtensions());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Base> funcContains(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
|
List<Base> result = new ArrayList<Base>();
|
||||||
|
String sw = convertToString(execute(context, baseToList(context.thisItem), exp.getParameters().get(0), true));
|
||||||
|
|
||||||
if (focus.size() != 1) {
|
if (focus.size() != 1) {
|
||||||
result.add(new BooleanType(false).noExtensions());
|
result.add(new BooleanType(false).noExtensions());
|
||||||
} else if (Utilities.noString(sw)) {
|
} else if (Utilities.noString(sw)) {
|
||||||
|
@ -4836,6 +4861,12 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Base> baseToList(Base b) {
|
||||||
|
List<Base> res = new ArrayList<>();
|
||||||
|
res.add(b);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Base> funcLength(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
private List<Base> funcLength(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
if (focus.size() == 1) {
|
if (focus.size() == 1) {
|
||||||
|
@ -4856,7 +4887,7 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcStartsWith(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcStartsWith(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
String sw = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
||||||
|
|
||||||
|
@ -4927,7 +4958,7 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcSubstring(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcSubstring(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
List<Base> n1 = execute(context, focus, exp.getParameters().get(0), true);
|
List<Base> n1 = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
int i1 = Integer.parseInt(n1.get(0).primitiveValue());
|
int i1 = Integer.parseInt(n1.get(0).primitiveValue());
|
||||||
|
@ -5197,7 +5228,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Base> funcWhere(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcWhere(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
List<Base> pc = new ArrayList<Base>();
|
List<Base> pc = new ArrayList<Base>();
|
||||||
for (Base item : focus) {
|
for (Base item : focus) {
|
||||||
|
@ -5225,7 +5256,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Base> funcItem(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
private List<Base> funcItem(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
String s = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
String s = convertToString(execute(context, focus, exp.getParameters().get(0), true));
|
||||||
if (Utilities.isInteger(s) && Integer.parseInt(s) < focus.size()) {
|
if (Utilities.isInteger(s) && Integer.parseInt(s) < focus.size()) {
|
||||||
|
@ -5236,7 +5267,7 @@ public class FHIRPathEngine {
|
||||||
|
|
||||||
private List<Base> funcEmpty(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
private List<Base> funcEmpty(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
result.add(new BooleanType(ElementUtil.isEmpty(focus)).noExtensions());
|
result.add(new BooleanType(ElementUtil.isEmpty(focus)).noExtensions());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5576,7 +5607,7 @@ public class FHIRPathEngine {
|
||||||
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
|
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
|
||||||
System.out.println("t: "+t.getId());
|
System.out.println("t: "+t.getId());
|
||||||
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
|
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
|
||||||
null : worker.fetchResource(StructureDefinition.class, t.getType().get(0).getProfile().get(0).getValue());
|
null : worker.fetchResource(StructureDefinition.class, t.getType().get(0).getProfile().get(0).getValue());
|
||||||
while (exsd != null && !exsd.getBaseDefinition().equals("http://hl7.org/fhir/StructureDefinition/Extension")) {
|
while (exsd != null && !exsd.getBaseDefinition().equals("http://hl7.org/fhir/StructureDefinition/Extension")) {
|
||||||
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition());
|
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package org.hl7.fhir.r5.utils;
|
package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
@ -61,6 +64,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -941,5 +945,21 @@ public class ToolingExtensions {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> allConsts() {
|
||||||
|
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Field field : ToolingExtensions.class.getDeclaredFields()) {
|
||||||
|
int modifiers = field.getModifiers();
|
||||||
|
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
|
||||||
|
try {
|
||||||
|
list.add(field.get(field.getType()).toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -377,6 +377,8 @@ public class I18nConstants {
|
||||||
public static final String SD_ED_BIND_NO_BINDABLE = "SD_ED_BIND_NO_BINDABLE";
|
public static final String SD_ED_BIND_NO_BINDABLE = "SD_ED_BIND_NO_BINDABLE";
|
||||||
public static final String SD_ED_BIND_MULTIPLE_TYPES = "SD_ED_BIND_MULTIPLE_TYPES";
|
public static final String SD_ED_BIND_MULTIPLE_TYPES = "SD_ED_BIND_MULTIPLE_TYPES";
|
||||||
public static final String SD_VALUE_TYPE_IILEGAL = "SD_VALUE_TYPE_IILEGAL";
|
public static final String SD_VALUE_TYPE_IILEGAL = "SD_VALUE_TYPE_IILEGAL";
|
||||||
|
public static final String SD_VALUE_TYPE_REPEAT_HINT = "SD_VALUE_TYPE_REPEAT_HINT";
|
||||||
|
public static final String SD_VALUE_TYPE_REPEAT_WARNING_DOTNET = "SD_VALUE_TYPE_REPEAT_WARNING_DOTNET";
|
||||||
public static final String SD_NO_TYPES_OR_CONTENTREF = "SD_NO_TYPES_OR_CONTENTREF";
|
public static final String SD_NO_TYPES_OR_CONTENTREF = "SD_NO_TYPES_OR_CONTENTREF";
|
||||||
public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG";
|
public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG";
|
||||||
public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG";
|
public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG";
|
||||||
|
|
|
@ -543,7 +543,7 @@ FHIRPATH_LOCATION = (at {0})
|
||||||
FHIRPATH_UNKNOWN_CONTEXT = Unknown context evaluating FHIRPath expression: {0}
|
FHIRPATH_UNKNOWN_CONTEXT = Unknown context evaluating FHIRPath expression: {0}
|
||||||
FHIRPATH_UNKNOWN_CONTEXT_ELEMENT = Unknown context element evaluating FHIRPath expression: {0}
|
FHIRPATH_UNKNOWN_CONTEXT_ELEMENT = Unknown context element evaluating FHIRPath expression: {0}
|
||||||
FHIRPATH_ALIAS_COLLECTION = Attempt to alias a collection, not a singleton evaluating FHIRPath expression
|
FHIRPATH_ALIAS_COLLECTION = Attempt to alias a collection, not a singleton evaluating FHIRPath expression
|
||||||
FHIRPATH_UNKNOWN_NAME = Error evaluating FHIRPath expression: The name {0} is not valid for any of the possible types: {2}
|
FHIRPATH_UNKNOWN_NAME = Error evaluating FHIRPath expression: The name {0} is not valid for any of the possible types: {1}
|
||||||
FHIRPATH_UNKNOWN_CONSTANT = Error evaluating FHIRPath expression: Invalid FHIR Constant {0}
|
FHIRPATH_UNKNOWN_CONSTANT = Error evaluating FHIRPath expression: Invalid FHIR Constant {0}
|
||||||
FHIRPATH_CANNOT_USE = Error evaluating FHIRPath expression: Cannot use {0} in this context because {1}
|
FHIRPATH_CANNOT_USE = Error evaluating FHIRPath expression: Cannot use {0} in this context because {1}
|
||||||
FHIRPATH_CANT_COMPARE = Error evaluating FHIRPath expression: Unable to compare values of type {0} and {1}
|
FHIRPATH_CANT_COMPARE = Error evaluating FHIRPath expression: Unable to compare values of type {0} and {1}
|
||||||
|
@ -655,6 +655,8 @@ CODESYSTEM_CS_NO_SUPPLEMENT = CodeSystem {0} is a supplement, so can't be used a
|
||||||
CODESYSTEM_CS_SUPP_CANT_CHECK = CodeSystem {0} cannot be found, so can't check if concepts are valid
|
CODESYSTEM_CS_SUPP_CANT_CHECK = CodeSystem {0} cannot be found, so can't check if concepts are valid
|
||||||
CODESYSTEM_CS_SUPP_INVALID_CODE = The code ''{1}'' is not declared in the base CodeSystem {0} so is not valid in the supplement
|
CODESYSTEM_CS_SUPP_INVALID_CODE = The code ''{1}'' is not declared in the base CodeSystem {0} so is not valid in the supplement
|
||||||
SD_VALUE_TYPE_IILEGAL = The element {0} has a {1} of type {2}, which is not in the list of allowed types ({3})
|
SD_VALUE_TYPE_IILEGAL = The element {0} has a {1} of type {2}, which is not in the list of allowed types ({3})
|
||||||
|
SD_VALUE_TYPE_REPEAT_HINT = The repeating element has a {1}. The {1} will apply to all the repeats (this has not been clear to all users)
|
||||||
|
SD_VALUE_TYPE_REPEAT_WARNING_DOTNET = The repeating element has a {1} value for a primitive type. The DotNet validator will not apply this to all the repeats - this is an error
|
||||||
SD_NO_TYPES_OR_CONTENTREF = The element {0} has no assigned types, and no content reference
|
SD_NO_TYPES_OR_CONTENTREF = The element {0} has no assigned types, and no content reference
|
||||||
CODESYSTEM_CS_UNK_EXPANSION = The code provided ({2}) is not in the value set {0}, and a code is required from this value set. The system {1} is unknown.
|
CODESYSTEM_CS_UNK_EXPANSION = The code provided ({2}) is not in the value set {0}, and a code is required from this value set. The system {1} is unknown.
|
||||||
BUNDLE_SEARCH_NOSELF = SearchSet Bundles should have a self link that specifies what the search was
|
BUNDLE_SEARCH_NOSELF = SearchSet Bundles should have a self link that specifies what the search was
|
||||||
|
|
|
@ -132,6 +132,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.renderers.DataRenderer;
|
import org.hl7.fhir.r5.renderers.DataRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||||
|
import org.hl7.fhir.r5.utils.BuildExtensions;
|
||||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||||
|
@ -1686,6 +1687,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
} else if (SpecialExtensions.isKnownExtension(url)) {
|
} else if (SpecialExtensions.isKnownExtension(url)) {
|
||||||
ex = SpecialExtensions.getDefinition(url);
|
ex = SpecialExtensions.getDefinition(url);
|
||||||
|
} else if (Utilities.existsInList(url, BuildExtensions.allConsts())) {
|
||||||
|
// nothing
|
||||||
} else if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowUnknownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN_NOTHERE, url)) {
|
} else if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowUnknownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN_NOTHERE, url)) {
|
||||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, isKnownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN, url);
|
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, isKnownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN, url);
|
||||||
}
|
}
|
||||||
|
@ -1761,6 +1764,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
res.add(tr.getWorkingCode());
|
res.add(tr.getWorkingCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// special hacks
|
||||||
|
if (ex.getUrl().equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type")) {
|
||||||
|
res.add("uri");
|
||||||
|
res.add("url");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,9 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
// in a snapshot, we validate that fixedValue, pattern, and defaultValue, if present, are all of the right type
|
// in a snapshot, we validate that fixedValue, pattern, and defaultValue, if present, are all of the right type
|
||||||
if (snapshot && (element.getIdBase() != null) && (element.getIdBase().contains("."))) {
|
if (snapshot && (element.getIdBase() != null) && (element.getIdBase().contains("."))) {
|
||||||
if (rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !typeCodes.isEmpty() || element.hasChild("contentReference"), I18nConstants.SD_NO_TYPES_OR_CONTENTREF, element.getIdBase())) {
|
if (rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !typeCodes.isEmpty() || element.hasChild("contentReference"), I18nConstants.SD_NO_TYPES_OR_CONTENTREF, element.getIdBase())) {
|
||||||
|
// if we see fixed[x] or pattern[x] applied to a repeating element, we'll give the user a hint
|
||||||
|
boolean repeating = !Utilities.existsInList(element.getChildValue("max"), "0", "1");
|
||||||
|
|
||||||
Element v = element.getNamedChild("defaultValue");
|
Element v = element.getNamedChild("defaultValue");
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "defaultValue", v.fhirType(), typeCodes);
|
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "defaultValue", v.fhirType(), typeCodes);
|
||||||
|
@ -172,15 +175,31 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
v = element.getNamedChild("fixed");
|
v = element.getNamedChild("fixed");
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes);
|
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes);
|
||||||
|
hint(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "fixed");
|
||||||
|
if (isPrimitiveType(v.fhirType())) {
|
||||||
|
warning(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "fixed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
v = element.getNamedChild("pattern");
|
v = element.getNamedChild("pattern");
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes);
|
rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes);
|
||||||
|
hint(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "pattern");
|
||||||
|
if (isPrimitiveType(v.fhirType())) {
|
||||||
|
warning(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "pattern");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if we see fixed[x] or pattern[x] applied to a repeating element, we'll give the user a hint
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isPrimitiveType(String fhirType) {
|
||||||
|
StructureDefinition sd = context.fetchTypeDefinition(fhirType);
|
||||||
|
return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
|
||||||
|
}
|
||||||
|
|
||||||
private String boundType(Set<String> typeCodes) {
|
private String boundType(Set<String> typeCodes) {
|
||||||
for (String tc : typeCodes) {
|
for (String tc : typeCodes) {
|
||||||
if (Utilities.existsInList(tc, "code", "Coding", "CodeableConcept", "Quantity", "CodeableReference")) {
|
if (Utilities.existsInList(tc, "code", "Coding", "CodeableConcept", "Quantity", "CodeableReference")) {
|
||||||
|
@ -355,7 +374,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
private void validateTargetProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
private void validateTargetProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
||||||
String p = profile.primitiveValue();
|
String p = profile.primitiveValue();
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
|
||||||
if (code.equals("Reference")) {
|
if (code.equals("Reference") || code.equals("CodeableReference")) {
|
||||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||||
StructureDefinition t = determineBaseType(sd);
|
StructureDefinition t = determineBaseType(sd);
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
|
|
|
@ -234,7 +234,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
for (JsonElement je : content.getAsJsonArray("profiles")) {
|
for (JsonElement je : content.getAsJsonArray("profiles")) {
|
||||||
String filename = je.getAsString();
|
String filename = je.getAsString();
|
||||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||||
StructureDefinition sd = loadProfile(filename, contents, messages);
|
StructureDefinition sd = loadProfile(filename, contents, messages, val.isDebug());
|
||||||
val.getContext().cacheResource(sd);
|
val.getContext().cacheResource(sd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||||
System.out.println("Name: " + name + " - profile : " + profile.get("source").getAsString());
|
System.out.println("Name: " + name + " - profile : " + profile.get("source").getAsString());
|
||||||
version = content.has("version") ? content.get("version").getAsString() : Constants.VERSION;
|
version = content.has("version") ? content.get("version").getAsString() : Constants.VERSION;
|
||||||
sd = loadProfile(filename, contents, messages);
|
sd = loadProfile(filename, contents, messages, val.isDebug());
|
||||||
val.getContext().cacheResource(sd);
|
val.getContext().cacheResource(sd);
|
||||||
}
|
}
|
||||||
val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false);
|
val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false);
|
||||||
|
@ -348,9 +348,10 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StructureDefinition loadProfile(String filename, String contents, List<ValidationMessage> messages) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
public StructureDefinition loadProfile(String filename, String contents, List<ValidationMessage> messages, boolean debug) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
||||||
StructureDefinition sd = (StructureDefinition) loadResource(filename, contents);
|
StructureDefinition sd = (StructureDefinition) loadResource(filename, contents);
|
||||||
ProfileUtilities pu = new ProfileUtilities(TestingUtilities.getSharedWorkerContext(version), messages, null);
|
ProfileUtilities pu = new ProfileUtilities(TestingUtilities.getSharedWorkerContext(version), messages, null);
|
||||||
|
pu.setDebug(debug);
|
||||||
if (!sd.hasSnapshot()) {
|
if (!sd.hasSnapshot()) {
|
||||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext(version).fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
StructureDefinition base = TestingUtilities.getSharedWorkerContext(version).fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||||
pu.generateSnapshot(base, sd, sd.getUrl(), null, sd.getTitle());
|
pu.generateSnapshot(base, sd, sd.getUrl(), null, sd.getTitle());
|
||||||
|
|
|
@ -82,3 +82,25 @@ v: {
|
||||||
"system" : "urn:ietf:bcp:47"
|
"system" : "urn:ietf:bcp:47"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
|
||||||
|
"code" : "IRCP",
|
||||||
|
"display" : "information recipient"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/participation-role-type", "version": "4.5.0", "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"NO_MEMBERSHIP_CHECK", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"severity" : "error",
|
||||||
|
"error" : "Error from server: Unable to find value set http://hl7.org/fhir/ValueSet/provenance-participant-type",
|
||||||
|
"class" : "SERVER_ERROR"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-RoleClass",
|
||||||
|
"code" : "PROV",
|
||||||
|
"display" : "healthcare provider"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/participation-role-type", "version": "4.5.0", "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"NO_MEMBERSHIP_CHECK", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"severity" : "error",
|
||||||
|
"error" : "Error from server: Unable to find value set http://hl7.org/fhir/ValueSet/provenance-participant-type",
|
||||||
|
"class" : "SERVER_ERROR"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/security-source-type",
|
||||||
|
"code" : "4",
|
||||||
|
"display" : "Application Server"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Application Server",
|
||||||
|
"code" : "4",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/security-source-type"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/security-source-type",
|
||||||
|
"code" : "4"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/audit-source-type--0", "version": "4.5.0", "lang":"null", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Application Server",
|
||||||
|
"code" : "4",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/security-source-type"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
|
@ -0,0 +1,11 @@
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ActReason",
|
||||||
|
"code" : "HTEST"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "test health data",
|
||||||
|
"code" : "HTEST",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ActReason"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
|
@ -0,0 +1,21 @@
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
|
||||||
|
"code" : "IRCP"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/participation-role-type--5", "version": "4.5.0", "lang":"null", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "information recipient",
|
||||||
|
"code" : "IRCP",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
|
||||||
|
"code" : "IRCP"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "information recipient",
|
||||||
|
"code" : "IRCP",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
|
@ -0,0 +1,21 @@
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-RoleClass",
|
||||||
|
"code" : "PROV"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/participation-role-type--1", "version": "4.5.0", "lang":"null", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "healthcare provider",
|
||||||
|
"code" : "PROV",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-RoleClass"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-RoleClass",
|
||||||
|
"code" : "PROV"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "healthcare provider",
|
||||||
|
"code" : "PROV",
|
||||||
|
"system" : "http://terminology.hl7.org/CodeSystem/v3-RoleClass"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
2
pom.xml
2
pom.xml
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hapi_fhir_version>5.4.0</hapi_fhir_version>
|
<hapi_fhir_version>5.4.0</hapi_fhir_version>
|
||||||
<validator_test_case_version>1.1.95</validator_test_case_version>
|
<validator_test_case_version>1.1.96-SNAPSHOT</validator_test_case_version>
|
||||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||||
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
||||||
<maven_surefire_version>3.0.0-M5</maven_surefire_version>
|
<maven_surefire_version>3.0.0-M5</maven_surefire_version>
|
||||||
|
|
Loading…
Reference in New Issue