get .ofType() working in discriminators (round #1!) + Improve Error message when snapshot can't be generated
This commit is contained in:
parent
c86b8114dd
commit
04c7111eb6
|
@ -208,6 +208,34 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TypedElementDefinition {
|
||||
private ElementDefinition element;
|
||||
private String type;
|
||||
public TypedElementDefinition(ElementDefinition element, String type) {
|
||||
super();
|
||||
this.element = element;
|
||||
this.type = type;
|
||||
}
|
||||
public TypedElementDefinition(ElementDefinition element) {
|
||||
super();
|
||||
this.element = element;
|
||||
}
|
||||
public ElementDefinition getElement() {
|
||||
return element;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public List<TypeRefComponent> getTypes() {
|
||||
List<TypeRefComponent> res = new ArrayList<ElementDefinition.TypeRefComponent>();
|
||||
for (TypeRefComponent tr : element.getType()) {
|
||||
if (type == null || type.equals(tr.getCode())) {
|
||||
res.add(tr);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
private IWorkerContext worker;
|
||||
private IEvaluationContext hostServices;
|
||||
private StringBuilder log = new StringBuilder();
|
||||
|
@ -5442,63 +5470,63 @@ public class FHIRPathEngine {
|
|||
* @throws PathEngineException
|
||||
* @throws DefinitionException
|
||||
*/
|
||||
public ElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, ElementDefinition element, StructureDefinition source) throws DefinitionException {
|
||||
public TypedElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, TypedElementDefinition element, StructureDefinition source) throws DefinitionException {
|
||||
StructureDefinition sd = profile;
|
||||
ElementDefinition focus = null;
|
||||
TypedElementDefinition focus = null;
|
||||
boolean okToNotResolve = false;
|
||||
|
||||
if (expr.getKind() == Kind.Name) {
|
||||
if (element.hasSlicing()) {
|
||||
ElementDefinition slice = pickMandatorySlice(sd, element);
|
||||
if (element.getElement().hasSlicing()) {
|
||||
ElementDefinition slice = pickMandatorySlice(sd, element.getElement());
|
||||
if (slice == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NAME_ALREADY_SLICED, element.getId());
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NAME_ALREADY_SLICED, element.getElement().getId());
|
||||
}
|
||||
element = slice;
|
||||
element = new TypedElementDefinition(slice);
|
||||
}
|
||||
|
||||
if (expr.getName().equals("$this")) {
|
||||
focus = element;
|
||||
} else {
|
||||
List<ElementDefinition> childDefinitions;
|
||||
childDefinitions = profileUtilities.getChildMap(sd, element);
|
||||
childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
||||
// if that's empty, get the children of the type
|
||||
if (childDefinitions.isEmpty()) {
|
||||
|
||||
sd = fetchStructureByType(element, expr);
|
||||
if (sd == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND, element.getType().get(0).getProfile(), element.getId());
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND, element.getElement().getType().get(0).getProfile(), element.getElement().getId());
|
||||
}
|
||||
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
|
||||
}
|
||||
for (ElementDefinition t : childDefinitions) {
|
||||
if (tailMatches(t, expr.getName()) && !t.hasSlicing()) { // GG: slicing is a problem here. This is for an exetnsion with a fixed value (type slicing)
|
||||
focus = t;
|
||||
focus = new TypedElementDefinition(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (expr.getKind() == Kind.Function) {
|
||||
if ("resolve".equals(expr.getName())) {
|
||||
if (!element.hasType()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE, element.getId());
|
||||
if (element.getTypes().size() == 0) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE, element.getElement().getId());
|
||||
}
|
||||
if (element.getType().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_MULTIPLE_TYPES, element.getId());
|
||||
if (element.getTypes().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_MULTIPLE_TYPES, element.getElement().getId());
|
||||
}
|
||||
if (!element.getType().get(0).hasTarget()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE, element.getId(), element.getType().get(0).getCode()+")");
|
||||
if (!element.getTypes().get(0).hasTarget()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE, element.getElement().getId(), element.getElement().getType().get(0).getCode()+")");
|
||||
}
|
||||
if (element.getType().get(0).getTargetProfile().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getId());
|
||||
if (element.getTypes().get(0).getTargetProfile().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getElement().getId());
|
||||
}
|
||||
sd = worker.fetchResource(StructureDefinition.class, element.getType().get(0).getTargetProfile().get(0).getValue());
|
||||
sd = worker.fetchResource(StructureDefinition.class, element.getTypes().get(0).getTargetProfile().get(0).getValue());
|
||||
if (sd == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getType().get(0).getTargetProfile(), element.getId());
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getTypes().get(0).getTargetProfile(), element.getElement().getId());
|
||||
}
|
||||
focus = sd.getSnapshot().getElementFirstRep();
|
||||
focus = new TypedElementDefinition(sd.getSnapshot().getElementFirstRep());
|
||||
} else if ("extension".equals(expr.getName())) {
|
||||
String targetUrl = expr.getParameters().get(0).getConstant().primitiveValue();
|
||||
List<ElementDefinition> childDefinitions = profileUtilities.getChildMap(sd, element);
|
||||
List<ElementDefinition> childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
||||
for (ElementDefinition t : childDefinitions) {
|
||||
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
|
||||
System.out.println("t: "+t.getId());
|
||||
|
@ -5511,29 +5539,33 @@ public class FHIRPathEngine {
|
|||
if (profileUtilities.getChildMap(sd, t).isEmpty()) {
|
||||
sd = exsd;
|
||||
}
|
||||
focus = t;
|
||||
focus = new TypedElementDefinition(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (focus == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND_EXTENSION, expr.toString(), targetUrl, element.getId(), sd.getUrl());
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND_EXTENSION, expr.toString(), targetUrl, element.getElement().getId(), sd.getUrl());
|
||||
}
|
||||
} else if ("ofType".equals(expr.getName())) {
|
||||
if (!element.hasType()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_NONE, element.getId());
|
||||
if (!element.getElement().hasType()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_NONE, element.getElement().getId());
|
||||
}
|
||||
if (element.getType().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE, element.getId());
|
||||
List<String> atn = new ArrayList<>();
|
||||
for (TypeRefComponent tr : element.getTypes()) {
|
||||
if (!tr.hasCode()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NO_CODE, element.getElement().getId());
|
||||
}
|
||||
atn.add(tr.getCode());
|
||||
}
|
||||
if (!element.getType().get(0).hasCode()) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NO_CODE, element.getId());
|
||||
}
|
||||
String atn = element.getType().get(0).getCode();
|
||||
String stn = expr.getParameters().get(0).getName();
|
||||
okToNotResolve = true;
|
||||
if ((atn.equals(stn))) {
|
||||
focus = element;
|
||||
if ((atn.contains(stn))) {
|
||||
if (element.getTypes().size() > 1) {
|
||||
focus = new TypedElementDefinition(element.getElement(), stn);
|
||||
} else {
|
||||
focus = element;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_NAME, expr.getName());
|
||||
|
@ -5548,7 +5580,7 @@ public class FHIRPathEngine {
|
|||
if (okToNotResolve) {
|
||||
return null;
|
||||
} else {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND, expr.toString(), source.getUrl(), element.getId(), profile.getUrl());
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND, expr.toString(), source.getUrl(), element.getElement().getId(), profile.getUrl());
|
||||
}
|
||||
} else if (expr.getInner() == null) {
|
||||
return focus;
|
||||
|
@ -5568,20 +5600,20 @@ public class FHIRPathEngine {
|
|||
}
|
||||
|
||||
|
||||
private StructureDefinition fetchStructureByType(ElementDefinition ed, ExpressionNode expr) throws DefinitionException {
|
||||
if (ed.getType().size() == 0) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NOTYPE, ed.getId());
|
||||
private StructureDefinition fetchStructureByType(TypedElementDefinition ed, ExpressionNode expr) throws DefinitionException {
|
||||
if (ed.getTypes().size() == 0) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NOTYPE, ed.getElement().getId());
|
||||
}
|
||||
if (ed.getType().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_TYPES, ed.getId());
|
||||
if (ed.getTypes().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_TYPES, ed.getElement().getId());
|
||||
}
|
||||
if (ed.getType().get(0).getProfile().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getId());
|
||||
if (ed.getTypes().get(0).getProfile().size() > 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getElement().getId());
|
||||
}
|
||||
if (ed.getType().get(0).hasProfile()) {
|
||||
return worker.fetchResource(StructureDefinition.class, ed.getType().get(0).getProfile().get(0).getValue());
|
||||
if (ed.getTypes().get(0).hasProfile()) {
|
||||
return worker.fetchResource(StructureDefinition.class, ed.getTypes().get(0).getProfile().get(0).getValue());
|
||||
} else {
|
||||
return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), worker.getOverrideVersionNs()));
|
||||
return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getTypes().get(0).getCode(), worker.getOverrideVersionNs()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla
|
|||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.TypedElementDefinition;
|
||||
import org.hl7.fhir.r5.utils.validation.*;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
|
@ -3370,7 +3371,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
discriminator = discriminator.substring(0, discriminator.length() - 10);
|
||||
}
|
||||
|
||||
ElementDefinition ed = null;
|
||||
TypedElementDefinition ted = null;
|
||||
String fp = fixExpr(discriminator, null);
|
||||
ExpressionNode expr = null;
|
||||
try {
|
||||
|
@ -3380,10 +3381,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
throw new FHIRException(context.formatMessage(I18nConstants.DISCRIMINATOR_BAD_PATH, e.getMessage(), fp), e);
|
||||
}
|
||||
long t2 = System.nanoTime();
|
||||
ed = fpe.evaluateDefinition(expr, profile, element, srcProfile);
|
||||
ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile);
|
||||
timeTracker.sd(t2);
|
||||
if (ed != null)
|
||||
elements.add(ed);
|
||||
if (ted != null)
|
||||
elements.add(ted.getElement());
|
||||
|
||||
for (TypeRefComponent type : element.getType()) {
|
||||
for (CanonicalType p : type.getProfile()) {
|
||||
|
@ -3405,10 +3406,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
expr = fpe.parse(fp);
|
||||
t2 = System.nanoTime();
|
||||
ed = fpe.evaluateDefinition(expr, profile, element, srcProfile);
|
||||
ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile);
|
||||
timeTracker.sd(t2);
|
||||
if (ed != null)
|
||||
elements.add(ed);
|
||||
if (ted != null)
|
||||
elements.add(ted.getElement());
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
|
@ -4452,7 +4453,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), defn.hasSnapshot(), I18nConstants.VALIDATION_VAL_PROFILE_NOSNAPSHOT)) {
|
||||
if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), defn.hasSnapshot(), I18nConstants.VALIDATION_VAL_PROFILE_NOSNAPSHOT, defn.getUrl())) {
|
||||
List<ValidationMessage> localErrors = new ArrayList<ValidationMessage>();
|
||||
resTracker.startValidating(defn);
|
||||
trackUsage(defn, hostContext, element);
|
||||
|
@ -4644,7 +4645,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_EXPL, special.toHuman(), resourceName, typeForResource.getProfile().get(0).asStringValue())) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else if (typeForResource.getProfile().isEmpty()) {
|
||||
|
@ -4654,7 +4655,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_TYPE, special.toHuman(), resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else {
|
||||
|
@ -4663,7 +4664,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
b.append(u.asStringValue());
|
||||
}
|
||||
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, typeForResource.getCode(), b.toString());
|
||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, special.toHuman(), typeForResource.getCode(), b.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue