use of org.hl7.fhir.validation.instance.utils.ElementInfo in project kindling by HL7.
the class XVerPathsGenerator method process.
private void process(ElementDefn ed, String path) {
ElementInfo ei = new ElementInfo();
ei.path = path;
r5List.add(ei);
ElementInfo r4 = r4List.get(path);
if (ed.getTypes().size() > 0) {
// leaf
for (TypeRef tr : ed.getTypes()) {
if (r4 == null || !r4.types.contains(tr.summary())) {
ei.types.add(tr.summary());
}
}
} else {
for (ElementDefn child : ed.getElements()) {
if (r4 == null || !r4.elements.contains(child.getName())) {
ei.elements.add(child.getName());
}
process(child, path + "." + child.getName());
}
}
}
use of org.hl7.fhir.validation.instance.utils.ElementInfo in project kindling by HL7.
the class XVerPathsGenerator method loadR4.
private void loadR4() throws IOException {
JsonObject r4 = JsonTrackingParser.parseJson(new File(r4Source));
for (Entry<String, JsonElement> e : r4.entrySet()) {
JsonObject eo = (JsonObject) e.getValue();
ElementInfo ei = new ElementInfo();
if (eo.has("types")) {
for (JsonElement s : eo.getAsJsonArray("types")) {
ei.types.add(s.getAsString());
}
}
if (eo.has("elements")) {
for (JsonElement s : eo.getAsJsonArray("elements")) {
ei.elements.add(s.getAsString());
}
}
if (!ei.elements.isEmpty() || !ei.types.isEmpty()) {
r4List.put(e.getKey(), ei);
}
}
}
use of org.hl7.fhir.validation.instance.utils.ElementInfo in project kindling by HL7.
the class XVerPathsGenerator method execute.
public void execute() throws IOException {
// load the R4 content; can't be an extension if it already matches R4
loadR4();
// iterate all the elements, building a list
for (String s : sorted(definitions.getTypes().keySet())) {
ElementDefn ed = definitions.getTypes().get(s);
process(ed);
}
for (String s : sorted(definitions.getBaseResources().keySet())) {
ResourceDefn ed = definitions.getBaseResources().get(s);
process(ed.getRoot());
}
for (String s : sorted(definitions.getResources().keySet())) {
ResourceDefn ed = definitions.getResources().get(s);
process(ed.getRoot());
}
StringBuilder r5 = new StringBuilder();
r5.append("{\r\n");
int i = 0;
for (ElementInfo ei : r5List) {
r5.append(" \"" + ei.path + "\": { ");
if (ei.types.size() > 0) {
r5.append("\"types\": [");
boolean first = true;
for (String s : ei.types) {
if (first)
first = false;
else
r5.append(", ");
r5.append("\"" + s + "\"");
}
r5.append("]");
} else if (ei.elements.size() > 0) {
r5.append("\"elements\": [");
boolean first = true;
for (String s : ei.elements) {
if (first)
first = false;
else
r5.append(", ");
r5.append("\"" + s + "\"");
}
r5.append("]");
}
i++;
if (i == r5List.size()) {
r5.append(" }\r\n");
} else {
r5.append(" },\r\n");
}
}
r5.append("}\r\n");
TextFile.stringToFile(r5.toString(), dest);
}
use of org.hl7.fhir.validation.instance.utils.ElementInfo in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method idStatusForEntry.
private IdStatus idStatusForEntry(Element ep, ElementInfo ei) {
if (isBundleEntry(ei.getPath())) {
Element req = ep.getNamedChild("request");
Element resp = ep.getNamedChild("response");
Element fullUrl = ep.getNamedChild(FULL_URL);
Element method = null;
Element url = null;
if (req != null) {
method = req.getNamedChild("method");
url = req.getNamedChild("url");
}
if (resp != null) {
return IdStatus.OPTIONAL;
}
if (method == null) {
if (fullUrl == null)
return IdStatus.REQUIRED;
else if (fullUrl.primitiveValue().startsWith("urn:uuid:") || fullUrl.primitiveValue().startsWith("urn:oid:"))
return IdStatus.OPTIONAL;
else
return IdStatus.REQUIRED;
} else {
String s = method.primitiveValue();
if (s.equals("PUT")) {
if (url == null)
return IdStatus.REQUIRED;
else
// or maybe prohibited? not clear
return IdStatus.OPTIONAL;
} else if (s.equals("POST"))
// this should be prohibited, but see task 9102
return IdStatus.OPTIONAL;
else
// actually, we should never get to here; a bundle entry with method get/delete should not have a resource
return IdStatus.OPTIONAL;
}
} else if (isParametersEntry(ei.getPath()) || isBundleOutcome(ei.getPath()))
return IdStatus.OPTIONAL;
else
return IdStatus.REQUIRED;
}
use of org.hl7.fhir.validation.instance.utils.ElementInfo in project org.hl7.fhir.core by hapifhir.
the class InstanceValidator method checkChildByDefinition.
public void checkChildByDefinition(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition, Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl, ElementDefinition checkDefn, boolean isSlice) {
List<String> profiles = new ArrayList<String>();
String type = null;
ElementDefinition typeDefn = null;
checkMustSupport(profile, ei);
if (checkDefn.getType().size() == 1 && !"*".equals(checkDefn.getType().get(0).getWorkingCode()) && !"Element".equals(checkDefn.getType().get(0).getWorkingCode()) && !"BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode())) {
type = checkDefn.getType().get(0).getWorkingCode();
String stype = ei.getElement().fhirType();
if (checkDefn.isChoice() && !stype.equals(type)) {
if ("Extension".equals(profile.getType())) {
// error will be raised elsewhere
} else {
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
}
}
// Excluding reference is a kludge to get around versioning issues
if (checkDefn.getType().get(0).hasProfile()) {
for (CanonicalType p : checkDefn.getType().get(0).getProfile()) {
profiles.add(p.getValue());
}
}
} else if (checkDefn.getType().size() == 1 && "*".equals(checkDefn.getType().get(0).getWorkingCode())) {
String prefix = tail(checkDefn.getPath());
assert prefix.endsWith("[x]");
type = ei.getName().substring(prefix.length() - 3);
if (isPrimitiveType(type))
type = Utilities.uncapitalize(type);
if (checkDefn.getType().get(0).hasProfile()) {
for (CanonicalType p : checkDefn.getType().get(0).getProfile()) {
profiles.add(p.getValue());
}
}
} else if (checkDefn.getType().size() > 1) {
String prefix = tail(checkDefn.getPath());
assert typesAreAllReference(checkDefn.getType()) || checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR) || prefix.endsWith("[x]") || isResourceAndTypes(checkDefn) : "Multiple Types allowed, but name is wrong @ " + checkDefn.getPath() + ": " + checkDefn.typeSummaryVB();
if (checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR)) {
type = ei.getElement().getType();
} else if (ei.getElement().isResource()) {
type = ei.getElement().fhirType();
} else {
prefix = prefix.substring(0, prefix.length() - 3);
for (TypeRefComponent t : checkDefn.getType()) if ((prefix + Utilities.capitalize(t.getWorkingCode())).equals(ei.getName())) {
type = t.getWorkingCode();
// Excluding reference is a kludge to get around versioning issues
if (t.hasProfile() && !type.equals("Reference"))
profiles.add(t.getProfile().get(0).getValue());
}
}
if (type == null) {
TypeRefComponent trc = checkDefn.getType().get(0);
if (trc.getWorkingCode().equals("Reference"))
type = "Reference";
else
rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTYPE, ei.getName(), describeTypes(checkDefn.getType()));
}
} else if (checkDefn.getContentReference() != null) {
typeDefn = resolveNameReference(profile.getSnapshot(), checkDefn.getContentReference());
} else if (checkDefn.getType().size() == 1 && ("Element".equals(checkDefn.getType().get(0).getWorkingCode()) || "BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode()))) {
if (checkDefn.getType().get(0).hasProfile()) {
CanonicalType pu = checkDefn.getType().get(0).getProfile().get(0);
if (pu.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT))
profiles.add(pu.getValue() + "#" + pu.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT));
else
profiles.add(pu.getValue());
}
}
if (type != null) {
if (type.startsWith("@")) {
checkDefn = findElement(profile, type.substring(1));
if (isSlice) {
ei.slice = ei.definition;
} else {
ei.definition = ei.definition;
}
type = null;
}
}
NodeStack localStack = stack.push(ei.getElement(), "*".equals(ei.getDefinition().getBase().getMax()) && ei.count == -1 ? 0 : ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
// if (debug) {
// System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl());
// }
String localStackLiteralPath = localStack.getLiteralPath();
String eiPath = ei.getPath();
if (!eiPath.equals(localStackLiteralPath)) {
assert (eiPath.equals(localStackLiteralPath)) : "ei.path: " + ei.getPath() + " - localStack.getLiteralPath: " + localStackLiteralPath;
}
boolean thisIsCodeableConcept = false;
String thisExtension = null;
boolean checkDisplay = true;
SpecialElement special = ei.getElement().getSpecial();
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, ei.getElement(), ei.getElement(), localStack, false);
} else {
checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, resource, ei.getElement(), localStack, false);
}
ei.getElement().markValidation(profile, checkDefn);
boolean elementValidated = false;
if (type != null) {
if (isPrimitiveType(type)) {
checkPrimitive(hostContext, errors, ei.getPath(), type, checkDefn, ei.getElement(), profile, stack);
} else {
if (checkDefn.hasFixed()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getUrl(), checkDefn.getSliceName(), null, false);
}
if (checkDefn.hasPattern()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getPattern(), profile.getUrl(), checkDefn.getSliceName(), null, true);
}
}
if (type.equals("Identifier")) {
checkIdentifier(errors, ei.getPath(), ei.getElement(), checkDefn);
} else if (type.equals("Coding")) {
checkCoding(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack);
} else if (type.equals("Quantity")) {
checkQuantity(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack);
} else if (type.equals("Attachment")) {
checkAttachment(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack);
} else if (type.equals("CodeableConcept")) {
checkDisplay = checkCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack);
thisIsCodeableConcept = true;
} else if (type.equals("Reference")) {
checkReference(hostContext, errors, ei.getPath(), ei.getElement(), profile, checkDefn, actualType, localStack);
// We only check extensions if we're not in a complex extension or if the element we're dealing with is not defined as part of that complex extension
} else if (type.equals("Extension")) {
Element eurl = ei.getElement().getNamedChild("url");
if (rule(errors, IssueType.INVALID, ei.getPath(), eurl != null, I18nConstants.EXTENSION_EXT_URL_NOTFOUND)) {
String url = eurl.primitiveValue();
thisExtension = url;
if (rule(errors, IssueType.INVALID, ei.getPath(), !Utilities.noString(url), I18nConstants.EXTENSION_EXT_URL_NOTFOUND)) {
if (rule(errors, IssueType.INVALID, ei.getPath(), (extensionUrl != null) || Utilities.isAbsoluteUrl(url), I18nConstants.EXTENSION_EXT_URL_ABSOLUTE)) {
checkExtension(hostContext, errors, ei.getPath(), resource, element, ei.getElement(), checkDefn, profile, localStack, stack, extensionUrl);
}
}
}
} else if (type.equals("Resource") || isResource(type)) {
validateContains(hostContext, errors, ei.getPath(), checkDefn, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei), // if
profile);
elementValidated = true;
// (str.matches(".*([.,/])work\\1$"))
} else if (Utilities.isAbsoluteUrl(type)) {
StructureDefinition defn = context.fetchTypeDefinition(type);
if (defn != null && hasMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep())) {
List<String> txtype = getMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep());
if (txtype.contains("CodeableConcept")) {
checkTerminologyCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack, defn);
thisIsCodeableConcept = true;
} else if (txtype.contains("Coding")) {
checkTerminologyCoding(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack, defn);
}
}
}
} else {
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), checkDefn != null, I18nConstants.VALIDATION_VAL_CONTENT_UNKNOWN, ei.getName()))
validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, false, true, null);
}
StructureDefinition p = null;
String tail = null;
if (profiles.isEmpty()) {
if (type != null) {
p = getProfileForType(type, checkDefn.getType());
// If dealing with a primitive type, then we need to check the current child against
// the invariants (constraints) on the current element, because otherwise it only gets
// checked against the primary type's invariants: LLoyd
// if (p.getKind() == StructureDefinitionKind.PRIMITIVETYPE) {
// checkInvariants(hostContext, errors, ei.path, profile, ei.definition, null, null, resource, ei.element);
// }
rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_NOTYPE, type);
}
} else if (profiles.size() == 1) {
String url = profiles.get(0);
if (url.contains("#")) {
tail = url.substring(url.indexOf("#") + 1);
url = url.substring(0, url.indexOf("#"));
}
p = this.context.fetchResource(StructureDefinition.class, url);
rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, profiles.get(0));
} else {
elementValidated = true;
HashMap<String, List<ValidationMessage>> goodProfiles = new HashMap<String, List<ValidationMessage>>();
HashMap<String, List<ValidationMessage>> badProfiles = new HashMap<String, List<ValidationMessage>>();
for (String typeProfile : profiles) {
String url = typeProfile;
tail = null;
if (url.contains("#")) {
tail = url.substring(url.indexOf("#") + 1);
url = url.substring(0, url.indexOf("#"));
}
p = this.context.fetchResource(StructureDefinition.class, typeProfile);
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, typeProfile)) {
List<ValidationMessage> profileErrors = new ArrayList<ValidationMessage>();
validateElement(hostContext, profileErrors, p, getElementByTail(p, tail), profile, checkDefn, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
if (hasErrors(profileErrors))
badProfiles.put(typeProfile, profileErrors);
else
goodProfiles.put(typeProfile, profileErrors);
}
}
if (goodProfiles.size() == 1) {
errors.addAll(goodProfiles.values().iterator().next());
} else if (goodProfiles.size() == 0) {
rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOMATCH, StringUtils.join("; ", profiles));
for (String m : badProfiles.keySet()) {
p = this.context.fetchResource(StructureDefinition.class, m);
for (ValidationMessage message : badProfiles.get(m)) {
message.setMessage(message.getMessage() + " (validating against " + p.getUrl() + (p.hasVersion() ? "|" + p.getVersion() : "") + " [" + p.getName() + "])");
errors.add(message);
}
}
} else {
warning(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_MULTIPLEMATCHES, StringUtils.join("; ", goodProfiles.keySet()));
for (String m : goodProfiles.keySet()) {
p = this.context.fetchResource(StructureDefinition.class, m);
for (ValidationMessage message : goodProfiles.get(m)) {
message.setMessage(message.getMessage() + " (validating against " + p.getUrl() + (p.hasVersion() ? "|" + p.getVersion() : "") + " [" + p.getName() + "])");
errors.add(message);
}
}
}
}
if (p != null) {
trackUsage(p, hostContext, element);
if (!elementValidated) {
if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER)
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, checkDefn, ei.getElement(), ei.getElement(), type, localStack.resetIds(), thisIsCodeableConcept, checkDisplay, thisExtension);
else
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, checkDefn, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
}
int index = profile.getSnapshot().getElement().indexOf(checkDefn);
if (index < profile.getSnapshot().getElement().size() - 1) {
String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath();
if (!nextPath.equals(checkDefn.getPath()) && nextPath.startsWith(checkDefn.getPath()))
validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
}
}
}
Aggregations