use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class MeasureValidator method validateMeasureReportGroups.
private void validateMeasureReportGroups(ValidatorHostContext hostContext, MeasureContext m, List<ValidationMessage> errors, Element mr, NodeStack stack, boolean inProgress) {
if (m.groups().size() == 0) {
// only validate the report groups if the measure has groups.
return;
}
List<MeasureGroupComponent> groups = new ArrayList<MeasureGroupComponent>();
List<Element> glist = mr.getChildrenByName("group");
if (glist.size() == 1 && m.groups().size() == 1) {
// if there's only one group, it can be ((and usually is) anonymous)
// but we still check that the code, if both have one, is consistent.
Element mrg = glist.get(0);
NodeStack ns = stack.push(mrg, 0, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
if (m.groups().get(0).hasCode() && mrg.hasChild("code")) {
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), hasUseableCode(cc), I18nConstants.MEASURE_MR_GRP_NO_USABLE_CODE)) {
rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc.matches(m.groups().get(0).getCode()), I18nConstants.MEASURE_MR_GRP_NO_WRONG_CODE, DataRenderer.display(context, cc), DataRenderer.display(context, m.groups().get(0).getCode()));
}
}
validateMeasureReportGroup(hostContext, m, m.groups().get(0), errors, mrg, ns, inProgress);
} else {
int i = 0;
for (Element mrg : glist) {
NodeStack ns = stack.push(mrg, i, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_NO_CODE)) {
MeasureGroupComponent mg = getGroupForCode(cc, m.measure());
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mg != null, I18nConstants.MEASURE_MR_GRP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !groups.contains(mg), I18nConstants.MEASURE_MR_GRP_DUPL_CODE)) {
groups.add(mg);
validateMeasureReportGroup(hostContext, m, mg, errors, mrg, ns, inProgress);
}
}
}
i++;
}
boolean dataCollection = isDataCollection(mr);
for (MeasureGroupComponent mg : m.groups()) {
if (!groups.contains(mg)) {
rule(errors, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg) || dataCollection, I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mg.getCode()));
}
}
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method listChildren.
public List<ElementInfo> listChildren(Element element, NodeStack stack) {
// 1. List the children, and remember their exact path (convenience)
List<ElementInfo> children = new ArrayList<ElementInfo>();
ChildIterator iter = new ChildIterator(this, stack.getLiteralPath(), element);
while (iter.next()) children.add(new ElementInfo(iter.name(), iter.element(), iter.path(), iter.count()));
return children;
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method checkCode.
// public API
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String version, String display, boolean checkDisplay, NodeStack stack) throws TerminologyServiceException {
long t = System.nanoTime();
boolean ss = context.supportsSystem(system);
timeTracker.tx(t, "ss " + system);
if (ss) {
t = System.nanoTime();
ValidationResult s = checkCodeOnServer(stack, code, system, version, display, checkDisplay);
timeTracker.tx(t, "vc " + system + "#" + code + " '" + display + "'");
if (s == null)
return true;
if (s.isOk()) {
if (s.getMessage() != null)
txWarning(errors, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, I18nConstants.TERMINOLOGY_PASSTHROUGH_TX_MESSAGE, s.getMessage(), system, code);
return true;
}
if (s.getErrorClass() != null && s.getErrorClass().isInfrastructure())
txWarning(errors, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, s.getMessage());
else if (s.getSeverity() == IssueSeverity.INFORMATION)
txHint(errors, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, s.getMessage());
else if (s.getSeverity() == IssueSeverity.WARNING)
txWarning(errors, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, s.getMessage());
else
return txRule(errors, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, I18nConstants.TERMINOLOGY_PASSTHROUGH_TX_MESSAGE, s.getMessage(), system, code);
return true;
} else if (system.startsWith("http://build.fhir.org") || system.startsWith("https://build.fhir.org")) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_WRONG_BUILD, system, suggestSystemForBuild(system));
return false;
} else if (system.startsWith("http://hl7.org/fhir") || system.startsWith("https://hl7.org/fhir") || system.startsWith("http://www.hl7.org/fhir") || system.startsWith("https://www.hl7.org/fhir")) {
if (SIDUtilities.isknownCodeSystem(system)) {
// else don't check these (for now)
return true;
} else if (system.startsWith("http://hl7.org/fhir/test")) {
// we don't validate these
return true;
} else if (system.endsWith(".html")) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_WRONG_HTML, system, suggestSystemForPage(system));
return false;
} else {
CodeSystem cs = getCodeSystem(system);
if (rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, cs != null, I18nConstants.TERMINOLOGY_TX_SYSTEM_UNKNOWN, system)) {
ConceptDefinitionComponent def = getCodeDefinition(cs, code);
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, def != null, I18nConstants.TERMINOLOGY_TX_CODE_UNKNOWN, system, code))
return warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, display == null || display.equals(def.getDisplay()), I18nConstants.TERMINOLOGY_TX_DISPLAY_WRONG, def.getDisplay());
}
return false;
}
} else if (context.isNoTerminologyServer() && Utilities.existsInList(system, "http://loinc.org", "http://unitsofmeasure.org", "http://hl7.org/fhir/sid/icd-9-cm", "http://snomed.info/sct", "http://www.nlm.nih.gov/research/umls/rxnorm")) {
// no checks in this case
return true;
} else if (startsWithButIsNot(system, "http://snomed.info/sct", "http://loinc.org", "http://unitsofmeasure.org", "http://www.nlm.nih.gov/research/umls/rxnorm")) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_INVALID, system);
return false;
} else {
try {
if (context.fetchResourceWithException(ValueSet.class, system) != null) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET, system);
// Lloyd: This error used to prohibit checking for downstream issues, but there are some cases where that checking needs to occur. Please talk to me before changing the code back.
}
boolean done = false;
if (system.startsWith("https:") && system.length() > 7) {
String ns = "http:" + system.substring(6);
CodeSystem cs = getCodeSystem(ns);
if (cs != null || Utilities.existsInList(system, "https://loinc.org", "https://unitsofmeasure.org", "https://snomed.info/sct", "https://www.nlm.nih.gov/research/umls/rxnorm")) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_HTTPS, system);
done = true;
}
}
hint(errors, IssueType.UNKNOWN, element.line(), element.col(), path, done, I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system);
return true;
} catch (Exception e) {
return true;
}
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method checkReference.
private void checkReference(ValidatorHostContext hostContext, List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition container, String parentType, NodeStack stack) throws FHIRException {
Reference reference = ObjectConverter.readAsReference(element);
String ref = reference.getReference();
if (Utilities.noString(ref)) {
if (!path.contains("element.pattern")) {
// this business rule doesn't apply to patterns
if (Utilities.noString(reference.getIdentifier().getSystem()) && Utilities.noString(reference.getIdentifier().getValue())) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !Utilities.noString(element.getNamedChildValue("display")), I18nConstants.REFERENCE_REF_NODISPLAY);
}
}
return;
} else if (Utilities.existsInList(ref, "http://tools.ietf.org/html/bcp47")) {
// special known URLs that can't be validated but are known to be valid
return;
}
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !isSuspiciousReference(ref), I18nConstants.REFERENCE_REF_SUSPICIOUS, ref);
ResolvedReference we = localResolve(ref, stack, errors, path, hostContext.getRootResource(), hostContext.getGroupingResource(), element);
String refType;
if (ref.startsWith("#")) {
refType = "contained";
} else {
if (we == null) {
refType = "remote";
} else {
refType = "bundled";
}
}
ReferenceValidationPolicy pol;
if (refType.equals("contained") || refType.equals("bundled")) {
pol = ReferenceValidationPolicy.CHECK_VALID;
} else {
if (policyAdvisor == null)
pol = ReferenceValidationPolicy.IGNORE;
else
pol = policyAdvisor.policyForReference(this, hostContext.getAppContext(), path, ref);
}
if (pol.checkExists()) {
if (we == null) {
if (!refType.equals("contained")) {
if (fetcher == null) {
throw new FHIRException(context.formatMessage(I18nConstants.RESOURCE_RESOLUTION_SERVICES_NOT_PROVIDED));
} else {
Element ext = null;
if (fetchCache.containsKey(ref)) {
ext = fetchCache.get(ref);
} else {
try {
ext = fetcher.fetch(this, hostContext.getAppContext(), ref);
} catch (IOException e) {
if (STACK_TRACE)
e.printStackTrace();
throw new FHIRException(e);
}
if (ext != null) {
setParents(ext);
fetchCache.put(ref, ext);
}
}
we = ext == null ? null : makeExternalRef(ext, path);
}
}
}
boolean ok = (allowExamples && (ref.contains("example.org") || ref.contains("acme.com"))) || (we != null || pol == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS);
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ok, I18nConstants.REFERENCE_REF_CANTRESOLVE, ref);
}
String ft;
if (we != null) {
ft = we.getType();
} else {
ft = tryParse(ref);
}
if (reference.hasType()) {
// R4 onwards...
// the type has to match the specified
String tu = isAbsolute(reference.getType()) ? reference.getType() : "http://hl7.org/fhir/StructureDefinition/" + reference.getType();
TypeRefComponent containerType = container.getType("Reference");
if (!containerType.hasTargetProfile(tu) && !containerType.hasTargetProfile("http://hl7.org/fhir/StructureDefinition/Resource") && !containerType.getTargetProfile().isEmpty()) {
boolean matchingResource = false;
for (CanonicalType target : containerType.getTargetProfile()) {
StructureDefinition sd = resolveProfile(profile, target.asStringValue());
if (rule(errors, IssueType.NOTFOUND, element.line(), element.col(), path, sd != null, I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, target.asStringValue())) {
if (("http://hl7.org/fhir/StructureDefinition/" + sd.getType()).equals(tu)) {
matchingResource = true;
break;
}
}
}
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, matchingResource, I18nConstants.REFERENCE_REF_WRONGTARGET, reference.getType(), container.getType("Reference").getTargetProfile());
}
// the type has to match the actual
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ft == null || ft.equals(reference.getType()), I18nConstants.REFERENCE_REF_BADTARGETTYPE, reference.getType(), ft);
}
if (we != null && pol.checkType()) {
if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ft != null, I18nConstants.REFERENCE_REF_NOTYPE)) {
// we validate as much as we can. First, can we infer a type from the profile?
boolean ok = false;
TypeRefComponent type = getReferenceTypeRef(container.getType());
if (type.hasTargetProfile() && !type.hasTargetProfile("http://hl7.org/fhir/StructureDefinition/Resource")) {
Set<String> types = new HashSet<>();
List<StructureDefinition> profiles = new ArrayList<>();
for (UriType u : type.getTargetProfile()) {
StructureDefinition sd = resolveProfile(profile, u.getValue());
if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, sd != null, I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, u.getValue())) {
types.add(sd.getType());
if (ft.equals(sd.getType())) {
ok = true;
profiles.add(sd);
}
}
}
if (!pol.checkValid()) {
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() > 0, I18nConstants.REFERENCE_REF_CANTMATCHTYPE, ref, StringUtils.join("; ", type.getTargetProfile()));
} else {
Map<StructureDefinition, List<ValidationMessage>> badProfiles = new HashMap<>();
Map<StructureDefinition, List<ValidationMessage>> goodProfiles = new HashMap<>();
int goodCount = 0;
for (StructureDefinition pr : profiles) {
List<ValidationMessage> profileErrors = new ArrayList<ValidationMessage>();
validateResource(we.hostContext(hostContext, pr), profileErrors, we.getResource(), we.getFocus(), pr, IdStatus.OPTIONAL, we.getStack().resetIds());
if (!hasErrors(profileErrors)) {
goodCount++;
goodProfiles.put(pr, profileErrors);
trackUsage(pr, hostContext, element);
} else {
badProfiles.put(pr, profileErrors);
}
}
if (goodCount == 1) {
if (showMessagesFromReferences) {
for (ValidationMessage vm : goodProfiles.values().iterator().next()) {
if (!errors.contains(vm)) {
errors.add(vm);
}
}
}
} else if (goodProfiles.size() == 0) {
if (!isShowMessagesFromReferences()) {
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
for (StructureDefinition sd : badProfiles.keySet()) {
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
}
} else {
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() == 1, I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
for (List<ValidationMessage> messages : badProfiles.values()) {
for (ValidationMessage vm : messages) {
if (!errors.contains(vm)) {
errors.add(vm);
}
}
}
}
} else {
if (!isShowMessagesFromReferences()) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
for (StructureDefinition sd : badProfiles.keySet()) {
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
}
} else {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
for (List<ValidationMessage> messages : goodProfiles.values()) {
for (ValidationMessage vm : messages) {
if (!errors.contains(vm)) {
errors.add(vm);
}
}
}
}
}
}
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ok, I18nConstants.REFERENCE_REF_BADTARGETTYPE, ft, types.toString());
}
if (type.hasAggregation() && !noCheckAggregation) {
boolean modeOk = false;
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (Enumeration<AggregationMode> mode : type.getAggregation()) {
b.append(mode.getCode());
if (mode.getValue().equals(AggregationMode.CONTAINED) && refType.equals("contained"))
modeOk = true;
else if (mode.getValue().equals(AggregationMode.BUNDLED) && refType.equals("bundled"))
modeOk = true;
else if (mode.getValue().equals(AggregationMode.REFERENCED) && (refType.equals("bundled") || refType.equals("remote")))
modeOk = true;
}
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, modeOk, I18nConstants.REFERENCE_REF_AGGREGATION, refType, b.toString());
}
}
}
if (we == null) {
TypeRefComponent type = getReferenceTypeRef(container.getType());
boolean okToRef = !type.hasAggregation() || type.hasAggregation(AggregationMode.REFERENCED);
rule(errors, IssueType.REQUIRED, -1, -1, path, okToRef, I18nConstants.REFERENCE_REF_NOTFOUND_BUNDLE, ref);
}
if (we == null && ft != null && assumeValidRestReferences) {
// if we == null, we inferred ft from the reference. if we are told to treat this as gospel
TypeRefComponent type = getReferenceTypeRef(container.getType());
Set<String> types = new HashSet<>();
StructureDefinition sdFT = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + ft);
boolean ok = false;
for (CanonicalType tp : type.getTargetProfile()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, tp.getValue());
if (sd != null) {
types.add(sd.getType());
}
StructureDefinition sdF = sdFT;
while (sdF != null) {
if (sdF.getType().equals(sd.getType())) {
ok = true;
break;
}
sdF = sdF.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sdF.getBaseDefinition()) : null;
}
}
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || ok, I18nConstants.REFERENCE_REF_BADTARGETTYPE2, ft, ref, types);
}
if (pol == ReferenceValidationPolicy.CHECK_VALID) {
// todo....
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method assignChildren.
public List<String> assignChildren(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, Element resource, NodeStack stack, List<ElementDefinition> childDefinitions, List<ElementInfo> children) throws DefinitionException {
// 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(context.formatMessage(I18nConstants.SLICE_ENCOUNTERED_MIDWAY_THROUGH_SET_PATH___ID___, slicer.getPath(), slicer.getId(), errorContext));
}
slicer = ed;
process = false;
sliceOffset = i;
} else if (slicer != null && !slicer.getPath().equals(ed.getPath()))
slicer = null;
for (ElementInfo ei : children) {
if (ei.sliceInfo == null) {
ei.sliceInfo = new ArrayList<>();
}
unsupportedSlicing = matchSlice(hostContext, errors, ei.sliceInfo, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei);
}
}
int last = -1;
ElementInfo lastei = null;
int lastSlice = -1;
for (ElementInfo ei : children) {
String sliceInfo = "";
if (slicer != null) {
sliceInfo = " (slice: " + slicer.getPath() + ")";
}
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" */
{
slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.getPath(), false, isProfile(slicer) || isCritical(ei.sliceInfo), context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : " defined in the profile " + profile.getUrl()), context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo), errorSummaryForSlicingAsText(ei.sliceInfo));
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.getPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTSLICE, (profile == null ? "" : " defined in the profile " + profile.getUrl()), errorSummaryForSlicing(ei.sliceInfo));
}
} else {
// Don't raise this if we're in an abstract profile, like Resource
if (!profile.getAbstract()) {
rule(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.getPath(), (ei.definition != null), I18nConstants.VALIDATION_VAL_PROFILE_NOTALLOWED, 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.getPath(), ok, I18nConstants.VALIDATION_VAL_PROFILE_OUTOFORDER, profile.getUrl(), ei.getName(), lastei == null ? "(null)" : lastei.getName());
}
if (ei.slice != null && ei.index == last && ei.slice.getSlicing().getOrdered()) {
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.getPath(), (ei.definition == null) || (ei.sliceindex >= lastSlice) || isXmlAttr, I18nConstants.VALIDATION_VAL_PROFILE_SLICEORDER, profile.getUrl(), ei.getName());
}
if (ei.definition == null || !isXmlAttr) {
last = ei.index;
lastei = ei;
}
if (ei.slice != null) {
lastSlice = ei.sliceindex;
} else {
lastSlice = -1;
}
}
return problematicPaths;
}
Aggregations