fix validator bug (issue 47)
This commit is contained in:
parent
70ce1ded74
commit
3b76303d83
|
@ -1,7 +1,7 @@
|
|||
package org.hl7.fhir.convertors.conv40_50;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
||||
import org.hl7.fhir.r5.model.SearchParameter.SearchModifierCodeEnumFactory;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_40_50;
|
||||
|
||||
|
||||
|
@ -222,7 +222,7 @@ public class SearchParameter extends VersionConvertor_40_50 {
|
|||
public static org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode> convertSearchModifierCode(org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode> src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode> tgt = new org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode>();
|
||||
org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode> tgt = new org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode>(new org.hl7.fhir.r5.model.SearchParameter.SearchModifierCodeEnumFactory());
|
||||
copyEnumeration(src, tgt);
|
||||
switch (src.getValue()) {
|
||||
case MISSING: tgt.setValue(org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode.MISSING);
|
||||
|
@ -245,7 +245,7 @@ public class SearchParameter extends VersionConvertor_40_50 {
|
|||
public static org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode> convertSearchModifierCode(org.hl7.fhir.r5.model.Enumeration<org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode> src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode> tgt = new org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode>();
|
||||
org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode> tgt = new org.hl7.fhir.r4.model.Enumeration<org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode>(new org.hl7.fhir.r4.model.SearchParameter.SearchModifierCodeEnumFactory());
|
||||
copyEnumeration(src, tgt);
|
||||
switch (src.getValue()) {
|
||||
case MISSING: tgt.setValue( org.hl7.fhir.r4.model.SearchParameter.SearchModifierCode.MISSING);
|
||||
|
|
|
@ -374,8 +374,10 @@ public class ExpressionNode {
|
|||
b.append(" '");
|
||||
b.append(Utilities.escapeJson(q.getUnit()));
|
||||
b.append("'");
|
||||
} else
|
||||
} else if (constant.primitiveValue() != null)
|
||||
b.append(Utilities.escapeJson(constant.primitiveValue()));
|
||||
else
|
||||
b.append(Utilities.escapeJson(constant.toString()));
|
||||
break;
|
||||
case Group:
|
||||
b.append("(");
|
||||
|
|
|
@ -114,6 +114,11 @@ public class FHIRPathEngine {
|
|||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String primitiveValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassTypeInfo extends Base {
|
||||
|
|
|
@ -3734,15 +3734,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
|
||||
// System.out.println(" "+stack.getLiteralPath()+" "+Long.toString((System.nanoTime() - time) / 1000000));
|
||||
// time = System.nanoTime();
|
||||
if (resource.getName().equals("contained")) {
|
||||
NodeStack ancestor = stack;
|
||||
while (!ancestor.element.isResource() || ancestor.element.getName().equals("contained"))
|
||||
ancestor = ancestor.parent;
|
||||
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, ancestor.element, element);
|
||||
} else
|
||||
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element);
|
||||
if (definition.getFixed()!=null)
|
||||
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), definition.getSliceName(), null);
|
||||
checkInvariants(hostContext, errors, profile, definition, resource, element, stack);
|
||||
|
||||
|
||||
// get the list of direct defined children, including slices
|
||||
|
@ -3750,7 +3742,6 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
if (childDefinitions.isEmpty()) {
|
||||
if (actualType == null)
|
||||
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
||||
|
||||
StructureDefinition dt = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + actualType);
|
||||
if (dt == null)
|
||||
throw new DefinitionException("Unable to resolve actual type " + actualType);
|
||||
|
@ -3758,133 +3749,21 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
childDefinitions = ProfileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0));
|
||||
}
|
||||
|
||||
// 1. List the children, and remember their exact path (convenience)
|
||||
List<ElementInfo> children = new ArrayList<InstanceValidator.ElementInfo>();
|
||||
ChildIterator iter = new ChildIterator(stack.getLiteralPath(), element);
|
||||
while (iter.next())
|
||||
children.add(new ElementInfo(iter.name(), iter.element(), iter.path(), iter.count()));
|
||||
List<ElementInfo> children = listChildren(element, stack);
|
||||
List<String> problematicPaths = assignChildren(hostContext, errors, profile, resource, stack, childDefinitions, children);
|
||||
|
||||
// 2. assign children to a definition
|
||||
// for each definition, for each child, check whether it belongs in the slice
|
||||
ElementDefinition slicer = null;
|
||||
boolean unsupportedSlicing = false;
|
||||
List<String> problematicPaths = new ArrayList<String>();
|
||||
String slicingPath = null;
|
||||
int sliceOffset = 0;
|
||||
for (int i = 0; i < childDefinitions.size(); i++) {
|
||||
ElementDefinition ed = childDefinitions.get(i);
|
||||
boolean childUnsupportedSlicing = false;
|
||||
boolean process = true;
|
||||
if (ed.hasSlicing() && !ed.getSlicing().getOrdered())
|
||||
slicingPath = ed.getPath();
|
||||
else if (slicingPath!=null && ed.getPath().equals(slicingPath))
|
||||
; // nothing
|
||||
else if (slicingPath != null && !ed.getPath().startsWith(slicingPath))
|
||||
slicingPath = null;
|
||||
// where are we with slicing
|
||||
if (ed.hasSlicing()) {
|
||||
if (slicer != null && slicer.getPath().equals(ed.getPath())) {
|
||||
String errorContext = "profile " + profile.getUrl();
|
||||
if (!resource.getChildValue("id").isEmpty())
|
||||
errorContext += "; instance " + resource.getChildValue("id");
|
||||
throw new DefinitionException("Slice encountered midway through path on " + slicer.getPath() + "; " + errorContext);
|
||||
}
|
||||
slicer = ed;
|
||||
process = false;
|
||||
sliceOffset = i;
|
||||
} else if (slicer != null && !slicer.getPath().equals(ed.getPath()))
|
||||
slicer = null;
|
||||
|
||||
// if (process) {
|
||||
for (ElementInfo ei : children) {
|
||||
unsupportedSlicing = matchSlice(hostContext, errors, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei);
|
||||
}
|
||||
// }
|
||||
}
|
||||
int last = -1;
|
||||
int lastSlice = -1;
|
||||
for (ElementInfo ei : children) {
|
||||
String sliceInfo = "";
|
||||
if (slicer != null)
|
||||
sliceInfo = " (slice: " + slicer.getPath()+")";
|
||||
//Lloyd: Removed this because there's no need for extension-specific logic here
|
||||
/* if (ei.path.endsWith(".extension"))
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ei.definition != null, "Element is unknown or does not match any slice (url=\"" + ei.element.getNamedChildValue("url") + "\")" + (profile==null ? "" : " for profile " + profile.getUrl()));
|
||||
else if (!unsupportedSlicing)*/
|
||||
if (!unsupportedSlicing)
|
||||
if (ei.additionalSlice && ei.definition != null) {
|
||||
if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) ||
|
||||
ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) {
|
||||
hint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for the profile " + profile.getUrl()));
|
||||
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for profile " + profile.getUrl() + " and slicing is CLOSED"));
|
||||
}
|
||||
} else {
|
||||
// Don't raise this if we're in an abstract profile, like Resource
|
||||
if (!profile.getAbstract())
|
||||
hint(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "Could not verify slice for profile " + profile.getUrl());
|
||||
}
|
||||
// TODO: Should get the order of elements correct when parsing elements that are XML attributes vs. elements
|
||||
boolean isXmlAttr = false;
|
||||
if (ei.definition!=null)
|
||||
for (Enumeration<PropertyRepresentation> r : ei.definition.getRepresentation()) {
|
||||
if (r.getValue() == PropertyRepresentation.XMLATTR) {
|
||||
isXmlAttr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ToolingExtensions.readBoolExtension(profile, "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order")) {
|
||||
boolean ok = (ei.definition == null) || (ei.index >= last) || isXmlAttr;
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ok, "As specified by profile " + profile.getUrl() + ", Element '"+ei.name+"' is out of order");
|
||||
}
|
||||
if (ei.slice != null && ei.index == last && ei.slice.getSlicing().getOrdered())
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, (ei.definition == null) || (ei.sliceindex >= lastSlice) || isXmlAttr, "As specified by profile " + profile.getUrl() + ", Element '"+ei.name+"' is out of order in ordered slice");
|
||||
if (ei.definition == null || !isXmlAttr)
|
||||
last = ei.index;
|
||||
if (ei.slice != null)
|
||||
lastSlice = ei.sliceindex;
|
||||
else
|
||||
lastSlice = -1;
|
||||
}
|
||||
|
||||
// 3. report any definitions that have a cardinality problem
|
||||
for (ElementDefinition ed : childDefinitions) {
|
||||
if (ed.getRepresentation().isEmpty()) { // ignore xml attributes
|
||||
int count = 0;
|
||||
List<ElementDefinition> slices = null;
|
||||
if (ed.hasSlicing())
|
||||
slices = ProfileUtilities.getSliceList(profile, ed);
|
||||
for (ElementInfo ei : children)
|
||||
if (ei.definition == ed)
|
||||
count++;
|
||||
else if (slices!=null) {
|
||||
for (ElementDefinition sed : slices) {
|
||||
if (ei.definition == sed) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
String location = "Profile " + profile.getUrl() + ", Element '" + stack.getLiteralPath() + "." + tail(ed.getPath()) + (ed.hasSliceName()? "[" + ed.getSliceName() + (ed.hasLabel() ? " ("+ed.getLabel()+")" : "")+"]": "") + "'";
|
||||
if (ed.getMin() > 0) {
|
||||
if (problematicPaths.contains(ed.getPath()))
|
||||
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), location + "': Unable to check minimum required (" + Integer.toString(ed.getMin()) + ") due to lack of slicing validation");
|
||||
else
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), location + ": minimum required = " + Integer.toString(ed.getMin()) + ", but only found " + Integer.toString(count));
|
||||
}
|
||||
if (ed.hasMax() && !ed.getMax().equals("*")) {
|
||||
if (problematicPaths.contains(ed.getPath()))
|
||||
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), location + ": Unable to check max allowed (" + ed.getMax() + ") due to lack of slicing validation");
|
||||
else
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), location + ": max allowed = " + ed.getMax() + ", but found " + Integer.toString(count));
|
||||
}
|
||||
}
|
||||
}
|
||||
checkCardinalities(errors, profile, element, stack, childDefinitions, children, problematicPaths);
|
||||
// 4. check order if any slices are ordered. (todo)
|
||||
|
||||
// 5. inspect each child for validity
|
||||
for (ElementInfo ei : children) {
|
||||
checkChild(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkChild(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition,
|
||||
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei)
|
||||
throws FHIRException, IOException, DefinitionException {
|
||||
List<String> profiles = new ArrayList<String>();
|
||||
if (ei.definition != null) {
|
||||
String type = null;
|
||||
|
@ -4069,6 +3948,9 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
}
|
||||
if (p!=null) {
|
||||
if (!elementValidated) {
|
||||
if (ei.element.getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.element.getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.element.getSpecial() == SpecialElement.PARAMETER )
|
||||
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, ei.element, ei.element, type, localStack, thisIsCodeableConcept, checkDisplay);
|
||||
else
|
||||
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept, checkDisplay);
|
||||
}
|
||||
int index = profile.getSnapshot().getElement().indexOf(ei.definition);
|
||||
|
@ -4080,6 +3962,152 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkCardinalities(List<ValidationMessage> errors, StructureDefinition profile, Element element, NodeStack stack,
|
||||
List<ElementDefinition> childDefinitions, List<ElementInfo> children, List<String> problematicPaths) throws DefinitionException {
|
||||
// 3. report any definitions that have a cardinality problem
|
||||
for (ElementDefinition ed : childDefinitions) {
|
||||
if (ed.getRepresentation().isEmpty()) { // ignore xml attributes
|
||||
int count = 0;
|
||||
List<ElementDefinition> slices = null;
|
||||
if (ed.hasSlicing())
|
||||
slices = ProfileUtilities.getSliceList(profile, ed);
|
||||
for (ElementInfo ei : children)
|
||||
if (ei.definition == ed)
|
||||
count++;
|
||||
else if (slices!=null) {
|
||||
for (ElementDefinition sed : slices) {
|
||||
if (ei.definition == sed) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
String location = "Profile " + profile.getUrl() + ", Element '" + stack.getLiteralPath() + "." + tail(ed.getPath()) + (ed.hasSliceName()? "[" + ed.getSliceName() + (ed.hasLabel() ? " ("+ed.getLabel()+")" : "")+"]": "") + "'";
|
||||
if (ed.getMin() > 0) {
|
||||
if (problematicPaths.contains(ed.getPath()))
|
||||
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), location + "': Unable to check minimum required (" + Integer.toString(ed.getMin()) + ") due to lack of slicing validation");
|
||||
else
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), location + ": minimum required = " + Integer.toString(ed.getMin()) + ", but only found " + Integer.toString(count));
|
||||
}
|
||||
if (ed.hasMax() && !ed.getMax().equals("*")) {
|
||||
if (problematicPaths.contains(ed.getPath()))
|
||||
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), location + ": Unable to check max allowed (" + ed.getMax() + ") due to lack of slicing validation");
|
||||
else
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), location + ": max allowed = " + ed.getMax() + ", but found " + Integer.toString(count));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> assignChildren(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, Element resource,
|
||||
NodeStack stack, List<ElementDefinition> childDefinitions, List<ElementInfo> children) throws DefinitionException, IOException {
|
||||
// 2. assign children to a definition
|
||||
// for each definition, for each child, check whether it belongs in the slice
|
||||
ElementDefinition slicer = null;
|
||||
boolean unsupportedSlicing = false;
|
||||
List<String> problematicPaths = new ArrayList<String>();
|
||||
String slicingPath = null;
|
||||
int sliceOffset = 0;
|
||||
for (int i = 0; i < childDefinitions.size(); i++) {
|
||||
ElementDefinition ed = childDefinitions.get(i);
|
||||
boolean childUnsupportedSlicing = false;
|
||||
boolean process = true;
|
||||
if (ed.hasSlicing() && !ed.getSlicing().getOrdered())
|
||||
slicingPath = ed.getPath();
|
||||
else if (slicingPath!=null && ed.getPath().equals(slicingPath))
|
||||
; // nothing
|
||||
else if (slicingPath != null && !ed.getPath().startsWith(slicingPath))
|
||||
slicingPath = null;
|
||||
// where are we with slicing
|
||||
if (ed.hasSlicing()) {
|
||||
if (slicer != null && slicer.getPath().equals(ed.getPath())) {
|
||||
String errorContext = "profile " + profile.getUrl();
|
||||
if (!resource.getChildValue("id").isEmpty())
|
||||
errorContext += "; instance " + resource.getChildValue("id");
|
||||
throw new DefinitionException("Slice encountered midway through path on " + slicer.getPath() + "; " + errorContext);
|
||||
}
|
||||
slicer = ed;
|
||||
process = false;
|
||||
sliceOffset = i;
|
||||
} else if (slicer != null && !slicer.getPath().equals(ed.getPath()))
|
||||
slicer = null;
|
||||
|
||||
// if (process) {
|
||||
for (ElementInfo ei : children) {
|
||||
unsupportedSlicing = matchSlice(hostContext, errors, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei);
|
||||
}
|
||||
// }
|
||||
}
|
||||
int last = -1;
|
||||
int lastSlice = -1;
|
||||
for (ElementInfo ei : children) {
|
||||
String sliceInfo = "";
|
||||
if (slicer != null)
|
||||
sliceInfo = " (slice: " + slicer.getPath()+")";
|
||||
//Lloyd: Removed this because there's no need for extension-specific logic here
|
||||
/* if (ei.path.endsWith(".extension"))
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ei.definition != null, "Element is unknown or does not match any slice (url=\"" + ei.element.getNamedChildValue("url") + "\")" + (profile==null ? "" : " for profile " + profile.getUrl()));
|
||||
else if (!unsupportedSlicing)*/
|
||||
if (!unsupportedSlicing)
|
||||
if (ei.additionalSlice && ei.definition != null) {
|
||||
if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) ||
|
||||
ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) {
|
||||
hint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for the profile " + profile.getUrl()));
|
||||
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for profile " + profile.getUrl() + " and slicing is CLOSED"));
|
||||
}
|
||||
} else {
|
||||
// Don't raise this if we're in an abstract profile, like Resource
|
||||
if (!profile.getAbstract())
|
||||
hint(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "Could not verify slice for profile " + profile.getUrl());
|
||||
}
|
||||
// TODO: Should get the order of elements correct when parsing elements that are XML attributes vs. elements
|
||||
boolean isXmlAttr = false;
|
||||
if (ei.definition!=null)
|
||||
for (Enumeration<PropertyRepresentation> r : ei.definition.getRepresentation()) {
|
||||
if (r.getValue() == PropertyRepresentation.XMLATTR) {
|
||||
isXmlAttr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ToolingExtensions.readBoolExtension(profile, "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order")) {
|
||||
boolean ok = (ei.definition == null) || (ei.index >= last) || isXmlAttr;
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ok, "As specified by profile " + profile.getUrl() + ", Element '"+ei.name+"' is out of order");
|
||||
}
|
||||
if (ei.slice != null && ei.index == last && ei.slice.getSlicing().getOrdered())
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, (ei.definition == null) || (ei.sliceindex >= lastSlice) || isXmlAttr, "As specified by profile " + profile.getUrl() + ", Element '"+ei.name+"' is out of order in ordered slice");
|
||||
if (ei.definition == null || !isXmlAttr)
|
||||
last = ei.index;
|
||||
if (ei.slice != null)
|
||||
lastSlice = ei.sliceindex;
|
||||
else
|
||||
lastSlice = -1;
|
||||
}
|
||||
return problematicPaths;
|
||||
}
|
||||
|
||||
public List<ElementInfo> listChildren(Element element, NodeStack stack) {
|
||||
// 1. List the children, and remember their exact path (convenience)
|
||||
List<ElementInfo> children = new ArrayList<InstanceValidator.ElementInfo>();
|
||||
ChildIterator iter = new ChildIterator(stack.getLiteralPath(), element);
|
||||
while (iter.next())
|
||||
children.add(new ElementInfo(iter.name(), iter.element(), iter.path(), iter.count()));
|
||||
return children;
|
||||
}
|
||||
|
||||
public void checkInvariants(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition,
|
||||
Element resource, Element element, NodeStack stack) throws FHIRException {
|
||||
if (resource.getName().equals("contained")) {
|
||||
NodeStack ancestor = stack;
|
||||
while (!ancestor.element.isResource() || ancestor.element.getName().equals("contained"))
|
||||
ancestor = ancestor.parent;
|
||||
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, ancestor.element, element);
|
||||
} else
|
||||
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element);
|
||||
if (definition.getFixed()!=null)
|
||||
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), definition.getSliceName(), null);
|
||||
}
|
||||
|
||||
public boolean matchSlice(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, NodeStack stack,
|
||||
|
|
|
@ -94,8 +94,8 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
this.content = content;
|
||||
}
|
||||
|
||||
// private static final String DEF_TX = "http://tx.fhir.org";
|
||||
private static final String DEF_TX = "http://local.fhir.org:960";
|
||||
private static final String DEF_TX = "http://tx.fhir.org";
|
||||
// private static final String DEF_TX = "http://local.fhir.org:960";
|
||||
private static ValidationEngine ve;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<type value="collection"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Binary>
|
||||
<id value="1"/>
|
||||
<contentType value="text/plain"/>
|
||||
<data value="VGVzdA=="/>
|
||||
</Binary>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -0,0 +1,22 @@
|
|||
<Parameters xmlns="http://hl7.org/fhir">
|
||||
<meta>
|
||||
<profile value="http://example.org/fhir/StructureDefinition/param-profile"/>
|
||||
</meta>
|
||||
<parameter>
|
||||
<name value="bundleparam"/>
|
||||
<resource>
|
||||
<Bundle>
|
||||
<type value="collection"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Binary>
|
||||
<id value="1"/>
|
||||
<contentType value="text/plain"/>
|
||||
<data value="VGVzdA=="/>
|
||||
</Binary>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
||||
</resource>
|
||||
</parameter>
|
||||
</Parameters>
|
|
@ -0,0 +1,15 @@
|
|||
<Parameters xmlns="http://hl7.org/fhir">
|
||||
<meta>
|
||||
<profile value="http://example.org/fhir/StructureDefinition/param-profile"/>
|
||||
</meta>
|
||||
<parameter>
|
||||
<name value="binaryparam"/>
|
||||
<resource>
|
||||
<Binary>
|
||||
<id value="1"/>
|
||||
<contentType value="text/plain"/>
|
||||
<data value="VGVzdA=="/>
|
||||
</Binary>
|
||||
</resource>
|
||||
</parameter>
|
||||
</Parameters>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StructureDefinition xmlns="http://hl7.org/fhir">
|
||||
<url value="http://example.org/fhir/StructureDefinition/param-profile"/>
|
||||
<name value="ParamProfile"/>
|
||||
<status value="draft"/>
|
||||
<fhirVersion value="4.0.0"/>
|
||||
<kind value="resource"/>
|
||||
<abstract value="false"/>
|
||||
<type value="Parameters"/>
|
||||
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Parameters"/>
|
||||
<derivation value="constraint"/>
|
||||
<differential>
|
||||
<element id="Parameters.parameter">
|
||||
<path value="Parameters.parameter"/>
|
||||
<slicing>
|
||||
<discriminator>
|
||||
<type value="value"/>
|
||||
<path value="name"/>
|
||||
</discriminator>
|
||||
<rules value="open"/>
|
||||
</slicing>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p1">
|
||||
<path value="Parameters.parameter"/>
|
||||
<sliceName value="p1"/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p1.name">
|
||||
<path value="Parameters.parameter.name"/>
|
||||
<fixedString value="binaryparam"/>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p1.resource">
|
||||
<path value="Parameters.parameter.resource"/>
|
||||
<type>
|
||||
<code value="Resource"/>
|
||||
<profile value="http://example.org/fhir/StructureDefinition/text-binary"/>
|
||||
</type>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p2">
|
||||
<path value="Parameters.parameter"/>
|
||||
<sliceName value="p2"/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p2.name">
|
||||
<path value="Parameters.parameter.name"/>
|
||||
<fixedString value="bundleparam"/>
|
||||
</element>
|
||||
<element id="Parameters.parameter:p2.resource">
|
||||
<path value="Parameters.parameter.resource"/>
|
||||
<type>
|
||||
<code value="Resource"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Bundle"/>
|
||||
</type>
|
||||
</element>
|
||||
</differential>
|
||||
</StructureDefinition>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StructureDefinition xmlns="http://hl7.org/fhir">
|
||||
<id value="text-binary"/>
|
||||
<url value="http://example.org/fhir/StructureDefinition/text-binary"/>
|
||||
<name value="TextBinary"/>
|
||||
<status value="draft"/>
|
||||
<description value="Text represented as a FHIR Binary resource"/>
|
||||
<fhirVersion value="4.0.0"/>
|
||||
<kind value="resource"/>
|
||||
<abstract value="false"/>
|
||||
<type value="Binary"/>
|
||||
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Binary"/>
|
||||
<derivation value="constraint"/>
|
||||
<differential>
|
||||
<element id="Binary">
|
||||
<path value="Binary"/>
|
||||
</element>
|
||||
<element id="Binary.contentType">
|
||||
<path value="Binary.contentType"/>
|
||||
<short value="MimeType for a test"/>
|
||||
<fixedCode value="text/plain"/>
|
||||
</element>
|
||||
</differential>
|
||||
</StructureDefinition>
|
||||
|
|
@ -176,7 +176,8 @@
|
|||
}
|
||||
},
|
||||
"medication-atc.json": {
|
||||
"errorCount": 0,
|
||||
"errorCount": 1,
|
||||
"errors-for-debugging" : ["ERROR: Medication.extension[2].valueCodeableConcept.coding: The code \"N02AA\" is not valid in the system http://www.whocc.no/atc; The code provided (http://www.whocc.no/atc#N02AA) is not valid in the value set All codes known to the system"],
|
||||
"allowed-extension-domain": "https://api-v8-r4.hspconsortium.org/DrugFormulary0/open"
|
||||
},
|
||||
"bp.json": {
|
||||
|
@ -781,6 +782,14 @@
|
|||
"loinc-lang-nl-3.xml" : {
|
||||
"errorCount": 0,
|
||||
"warningCount": 0
|
||||
},
|
||||
"azatadha/example-params-1.xml" : {
|
||||
"errorCount": 0,
|
||||
"warningCount": 1,
|
||||
"profile": {
|
||||
"source": "azatadha/param-profile.xml",
|
||||
"errorCount": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ pause
|
|||
call mvn versions:set -DnewVersion=%newver%-SNAPSHOT
|
||||
call git commit -a -m "Release new version"
|
||||
call git push origin master
|
||||
call "C:\tools\fnr.exe" --cl --dir "C:\work\org.hl7.fhir\build" --fileMask "*.java" --includeSubDirectories --find "%oldver%-SNAPSHOT" --replace "%newver%-SNAPSHOT"
|
||||
call "C:\tools\fnr.exe" --cl --dir "C:\work\org.hl7.fhir\build" --fileMask "*.xml" --find "%oldver%-SNAPSHOT" --replace "%newver%-SNAPSHOT"
|
||||
call "C:\tools\fnr.exe" --cl --dir "C:\work\org.hl7.fhir\fhir-ig-publisher" --fileMask "*.xml" --find "%oldver%-SNAPSHOT" --replace "%newver%-SNAPSHOT"
|
||||
call "C:\tools\fnr.exe" --cl --dir "C:\work\org.hl7.fhir\latest-ig-publisher" --fileMask "*.html" --find "%oldver%" --replace "%newver%"
|
||||
call "C:\tools\fnr.exe" --cl --dir "C:\work\org.hl7.fhir\latest-ig-publisher" --fileMask "*.json" --find "%oldver%" --replace "%newver%"
|
||||
call mvn deploy
|
||||
|
|
Loading…
Reference in New Issue