FHIRPath changes for as - case and singleton issues
This commit is contained in:
parent
d6cc2f46d0
commit
2628f6fac1
|
@ -61,6 +61,7 @@ import org.hl7.fhir.utilities.MergedList;
|
||||||
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
||||||
import org.hl7.fhir.utilities.SourceLocation;
|
import org.hl7.fhir.utilities.SourceLocation;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
@ -260,6 +261,8 @@ public class FHIRPathEngine {
|
||||||
private boolean allowPolymorphicNames;
|
private boolean allowPolymorphicNames;
|
||||||
private boolean doImplicitStringConversion;
|
private boolean doImplicitStringConversion;
|
||||||
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
||||||
|
private boolean doNotEnforceAsSingletonRule;
|
||||||
|
private boolean doNotEnforceAsCaseSensitive;
|
||||||
|
|
||||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||||
// the application can implement them by providing a constant resolver
|
// the application can implement them by providing a constant resolver
|
||||||
|
@ -369,8 +372,15 @@ public class FHIRPathEngine {
|
||||||
primitiveTypes.add(sd.getName());
|
primitiveTypes.add(sd.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initFlags() {
|
||||||
|
if (!VersionUtilities.isR5VerOrLater(worker.getVersion())) {
|
||||||
|
doNotEnforceAsCaseSensitive = true;
|
||||||
|
doNotEnforceAsSingletonRule = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- 3 methods to override in children -------------------------------------------------------
|
// --- 3 methods to override in children -------------------------------------------------------
|
||||||
// if you don't override, it falls through to the using the base reference implementation
|
// if you don't override, it falls through to the using the base reference implementation
|
||||||
|
@ -453,6 +463,22 @@ public class FHIRPathEngine {
|
||||||
this.doImplicitStringConversion = doImplicitStringConversion;
|
this.doImplicitStringConversion = doImplicitStringConversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDoNotEnforceAsSingletonRule() {
|
||||||
|
return doNotEnforceAsSingletonRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoNotEnforceAsSingletonRule(boolean doNotEnforceAsSingletonRule) {
|
||||||
|
this.doNotEnforceAsSingletonRule = doNotEnforceAsSingletonRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDoNotEnforceAsCaseSensitive() {
|
||||||
|
return doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoNotEnforceAsCaseSensitive(boolean doNotEnforceAsCaseSensitive) {
|
||||||
|
this.doNotEnforceAsCaseSensitive = doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
// --- public API -------------------------------------------------------
|
// --- public API -------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Parse a path for later use using execute
|
* Parse a path for later use using execute
|
||||||
|
@ -1789,11 +1815,11 @@ public class FHIRPathEngine {
|
||||||
if (!isKnownType(tn)) {
|
if (!isKnownType(tn)) {
|
||||||
throw new PathEngineException("The type "+tn+" is not valid");
|
throw new PathEngineException("The type "+tn+" is not valid");
|
||||||
}
|
}
|
||||||
if (left.size() > 1) {
|
if (!doNotEnforceAsSingletonRule && left.size() > 1) {
|
||||||
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+")");
|
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+", '"+expr.toString()+"')");
|
||||||
}
|
}
|
||||||
for (Base nextLeft : left) {
|
for (Base nextLeft : left) {
|
||||||
if (tn.equals(nextLeft.fhirType())) {
|
if (compareTypeNames(tn, nextLeft.fhirType())) {
|
||||||
result.add(nextLeft);
|
result.add(nextLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1801,9 +1827,19 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean compareTypeNames(String left, String right) {
|
||||||
|
if (doNotEnforceAsCaseSensitive) {
|
||||||
|
return left.equalsIgnoreCase(right);
|
||||||
|
} else {
|
||||||
|
return left.equals(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isKnownType(String tn) {
|
private boolean isKnownType(String tn) {
|
||||||
if (!tn.contains(".")) {
|
if (!tn.contains(".")) {
|
||||||
|
if (Utilities.existsInList(tn, "String", "Boolean", "Integer", "Decimal", "Quantity", "DateTime", "Time", "SimpleTypeInfo", "ClassInfo")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return worker.fetchTypeDefinition(tn) != null;
|
return worker.fetchTypeDefinition(tn) != null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -4584,7 +4620,7 @@ public class FHIRPathEngine {
|
||||||
if (!isKnownType(tn)) {
|
if (!isKnownType(tn)) {
|
||||||
throw new PathEngineException("The type "+tn+" is not valid");
|
throw new PathEngineException("The type "+tn+" is not valid");
|
||||||
}
|
}
|
||||||
if (focus.size() > 1) {
|
if (!doNotEnforceAsSingletonRule && focus.size() > 1) {
|
||||||
throw new PathEngineException("Attempt to use as() on more than one item ("+focus.size()+")");
|
throw new PathEngineException("Attempt to use as() on more than one item ("+focus.size()+")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4603,7 +4639,7 @@ public class FHIRPathEngine {
|
||||||
} else {
|
} else {
|
||||||
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
||||||
while (sd != null) {
|
while (sd != null) {
|
||||||
if (tnp.equals(sd.getType())) {
|
if (compareTypeNames(tnp, sd.getType())) {
|
||||||
result.add(b);
|
result.add(b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,9 @@ public class FHIRPathTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fp.setDoNotEnforceAsCaseSensitive(false);
|
||||||
|
fp.setDoNotEnforceAsSingletonRule(false);
|
||||||
|
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
try {
|
try {
|
||||||
outcome = fp.evaluate(res, node);
|
outcome = fp.evaluate(res, node);
|
||||||
|
|
|
@ -62,6 +62,7 @@ import org.hl7.fhir.utilities.MergedList;
|
||||||
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
||||||
import org.hl7.fhir.utilities.SourceLocation;
|
import org.hl7.fhir.utilities.SourceLocation;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
@ -257,6 +258,8 @@ public class FHIRPathEngine {
|
||||||
private boolean allowPolymorphicNames;
|
private boolean allowPolymorphicNames;
|
||||||
private boolean doImplicitStringConversion;
|
private boolean doImplicitStringConversion;
|
||||||
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
||||||
|
private boolean doNotEnforceAsSingletonRule;
|
||||||
|
private boolean doNotEnforceAsCaseSensitive;
|
||||||
|
|
||||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||||
// the application can implement them by providing a constant resolver
|
// the application can implement them by providing a constant resolver
|
||||||
|
@ -366,8 +369,15 @@ public class FHIRPathEngine {
|
||||||
primitiveTypes.add(sd.getName());
|
primitiveTypes.add(sd.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initFlags() {
|
||||||
|
if (!VersionUtilities.isR5VerOrLater(worker.getVersion())) {
|
||||||
|
doNotEnforceAsCaseSensitive = true;
|
||||||
|
doNotEnforceAsSingletonRule = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- 3 methods to override in children -------------------------------------------------------
|
// --- 3 methods to override in children -------------------------------------------------------
|
||||||
// if you don't override, it falls through to the using the base reference implementation
|
// if you don't override, it falls through to the using the base reference implementation
|
||||||
|
@ -450,6 +460,22 @@ public class FHIRPathEngine {
|
||||||
this.doImplicitStringConversion = doImplicitStringConversion;
|
this.doImplicitStringConversion = doImplicitStringConversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDoNotEnforceAsSingletonRule() {
|
||||||
|
return doNotEnforceAsSingletonRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoNotEnforceAsSingletonRule(boolean doNotEnforceAsSingletonRule) {
|
||||||
|
this.doNotEnforceAsSingletonRule = doNotEnforceAsSingletonRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDoNotEnforceAsCaseSensitive() {
|
||||||
|
return doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoNotEnforceAsCaseSensitive(boolean doNotEnforceAsCaseSensitive) {
|
||||||
|
this.doNotEnforceAsCaseSensitive = doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
// --- public API -------------------------------------------------------
|
// --- public API -------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Parse a path for later use using execute
|
* Parse a path for later use using execute
|
||||||
|
@ -1785,11 +1811,11 @@ public class FHIRPathEngine {
|
||||||
if (!isKnownType(tn)) {
|
if (!isKnownType(tn)) {
|
||||||
throw new PathEngineException("The type "+tn+" is not valid");
|
throw new PathEngineException("The type "+tn+" is not valid");
|
||||||
}
|
}
|
||||||
if (left.size() > 1) {
|
if (!doNotEnforceAsSingletonRule && left.size() > 1) {
|
||||||
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+")");
|
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+", '"+expr.toString()+"')");
|
||||||
}
|
}
|
||||||
for (Base nextLeft : left) {
|
for (Base nextLeft : left) {
|
||||||
if (tn.equals(nextLeft.fhirType())) {
|
if (compareTypeNames(tn, nextLeft.fhirType())) {
|
||||||
result.add(nextLeft);
|
result.add(nextLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1797,9 +1823,19 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean compareTypeNames(String left, String right) {
|
||||||
|
if (doNotEnforceAsCaseSensitive) {
|
||||||
|
return left.equalsIgnoreCase(right);
|
||||||
|
} else {
|
||||||
|
return left.equals(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isKnownType(String tn) {
|
private boolean isKnownType(String tn) {
|
||||||
if (!tn.contains(".")) {
|
if (!tn.contains(".")) {
|
||||||
|
if (Utilities.existsInList(tn, "String", "Boolean", "Integer", "Decimal", "Quantity", "DateTime", "Time", "SimpleTypeInfo", "ClassInfo")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return worker.fetchTypeDefinition(tn) != null;
|
return worker.fetchTypeDefinition(tn) != null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -4580,7 +4616,7 @@ public class FHIRPathEngine {
|
||||||
if (!isKnownType(tn)) {
|
if (!isKnownType(tn)) {
|
||||||
throw new PathEngineException("The type "+tn+" is not valid");
|
throw new PathEngineException("The type "+tn+" is not valid");
|
||||||
}
|
}
|
||||||
if (focus.size() > 1) {
|
if (!doNotEnforceAsSingletonRule && focus.size() > 1) {
|
||||||
throw new PathEngineException("Attempt to use as() on more than one item ("+focus.size()+")");
|
throw new PathEngineException("Attempt to use as() on more than one item ("+focus.size()+")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4599,7 +4635,7 @@ public class FHIRPathEngine {
|
||||||
} else {
|
} else {
|
||||||
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
||||||
while (sd != null) {
|
while (sd != null) {
|
||||||
if (tnp.equals(sd.getType())) {
|
if (compareTypeNames(tnp, sd.getType())) {
|
||||||
result.add(b);
|
result.add(b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,9 @@ public class FHIRPathTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fp.setDoNotEnforceAsCaseSensitive(false);
|
||||||
|
fp.setDoNotEnforceAsSingletonRule(false);
|
||||||
|
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
try {
|
try {
|
||||||
outcome = fp.evaluate(res, node);
|
outcome = fp.evaluate(res, node);
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.hl7.fhir.utilities.MergedList;
|
||||||
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
import org.hl7.fhir.utilities.MergedList.MergeNode;
|
||||||
import org.hl7.fhir.utilities.SourceLocation;
|
import org.hl7.fhir.utilities.SourceLocation;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
@ -264,6 +265,7 @@ public class FHIRPathEngine {
|
||||||
private boolean doImplicitStringConversion;
|
private boolean doImplicitStringConversion;
|
||||||
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
||||||
private boolean doNotEnforceAsSingletonRule;
|
private boolean doNotEnforceAsSingletonRule;
|
||||||
|
private boolean doNotEnforceAsCaseSensitive;
|
||||||
|
|
||||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||||
// the application can implement them by providing a constant resolver
|
// the application can implement them by providing a constant resolver
|
||||||
|
@ -373,8 +375,15 @@ public class FHIRPathEngine {
|
||||||
primitiveTypes.add(sd.getName());
|
primitiveTypes.add(sd.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initFlags() {
|
||||||
|
if (!VersionUtilities.isR5VerOrLater(worker.getVersion())) {
|
||||||
|
doNotEnforceAsCaseSensitive = true;
|
||||||
|
doNotEnforceAsSingletonRule = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- 3 methods to override in children -------------------------------------------------------
|
// --- 3 methods to override in children -------------------------------------------------------
|
||||||
// if you don't override, it falls through to the using the base reference implementation
|
// if you don't override, it falls through to the using the base reference implementation
|
||||||
|
@ -465,6 +474,14 @@ public class FHIRPathEngine {
|
||||||
this.doNotEnforceAsSingletonRule = doNotEnforceAsSingletonRule;
|
this.doNotEnforceAsSingletonRule = doNotEnforceAsSingletonRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDoNotEnforceAsCaseSensitive() {
|
||||||
|
return doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoNotEnforceAsCaseSensitive(boolean doNotEnforceAsCaseSensitive) {
|
||||||
|
this.doNotEnforceAsCaseSensitive = doNotEnforceAsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
// --- public API -------------------------------------------------------
|
// --- public API -------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Parse a path for later use using execute
|
* Parse a path for later use using execute
|
||||||
|
@ -1804,7 +1821,7 @@ public class FHIRPathEngine {
|
||||||
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+", '"+expr.toString()+"')");
|
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+", '"+expr.toString()+"')");
|
||||||
}
|
}
|
||||||
for (Base nextLeft : left) {
|
for (Base nextLeft : left) {
|
||||||
if (tn.equals(nextLeft.fhirType())) {
|
if (compareTypeNames(tn, nextLeft.fhirType())) {
|
||||||
result.add(nextLeft);
|
result.add(nextLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1812,6 +1829,13 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean compareTypeNames(String left, String right) {
|
||||||
|
if (doNotEnforceAsCaseSensitive) {
|
||||||
|
return left.equalsIgnoreCase(right);
|
||||||
|
} else {
|
||||||
|
return left.equals(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isKnownType(String tn) {
|
private boolean isKnownType(String tn) {
|
||||||
if (!tn.contains(".")) {
|
if (!tn.contains(".")) {
|
||||||
|
@ -4617,7 +4641,7 @@ public class FHIRPathEngine {
|
||||||
} else {
|
} else {
|
||||||
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
StructureDefinition sd = worker.fetchTypeDefinition(b.fhirType());
|
||||||
while (sd != null) {
|
while (sd != null) {
|
||||||
if (tnp.equals(sd.getType())) {
|
if (compareTypeNames(tnp, sd.getType())) {
|
||||||
result.add(b);
|
result.add(b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue