Merge pull request #1653 from hapifhir/2024-06-gg-ig-validation
2024 06 gg ig validation
This commit is contained in:
commit
239231bb91
|
@ -806,7 +806,21 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
}
|
||||
|
||||
public boolean hasPackage(String idAndver) {
|
||||
return loadedPackages.contains(idAndver);
|
||||
if (loadedPackages.contains(idAndver)) {
|
||||
return true;
|
||||
}
|
||||
// not clear whether the same logic should apply to other cross-version packages?
|
||||
if (idAndver.startsWith("hl7.fhir.uv.extensions")) {
|
||||
String v = idAndver.substring(idAndver.lastIndexOf("#")+1);
|
||||
for (String s : loadedPackages) {
|
||||
String v2 = s.substring(s.lastIndexOf("#")+1);
|
||||
if (s.startsWith("hl7.fhir.uv.extensions.") && VersionUtilities.versionsMatch(v, v2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1068,7 +1068,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
ed = xverManager.makeDefinition(url);
|
||||
new ContextUtilities(getContext().getWorker()).generateSnapshot(ed);
|
||||
getContext().getWorker().cacheResource(ed);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.getName().equals("modifierExtension") && ed == null) {
|
||||
throw new DefinitionException("Unknown modifier extension "+url);
|
||||
|
@ -1076,11 +1076,6 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
PropertyWrapper pe = map.get(p.getName()+"["+url+"]");
|
||||
if (pe == null) {
|
||||
if (ed == null) {
|
||||
if (url != null && url.startsWith("http://hl7.org/fhir") && !url.startsWith("http://hl7.org/fhir/us")) {
|
||||
if (!ProfileUtilities.isSuppressIgnorableExceptions()) {
|
||||
throw new DefinitionException("unknown extension "+url);
|
||||
}
|
||||
}
|
||||
// System.out.println("unknown extension "+url);
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex), null);
|
||||
} else {
|
||||
|
|
|
@ -800,21 +800,6 @@ public class RenderingContext extends RenderingI18nContext {
|
|||
return t.asStringValue();
|
||||
}
|
||||
|
||||
public String getTranslated(ResourceElement t) {
|
||||
if (locale != null) {
|
||||
for (ResourceElement e : t.extensions(ToolingExtensions.EXT_TRANSLATION)) {
|
||||
String l = e.extensionString("lang");
|
||||
if (l != null && l.equals(locale.toString())) {
|
||||
String v = e.extensionString("content");
|
||||
if (v != null) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return t.primitiveValue();
|
||||
}
|
||||
|
||||
public StringType getTranslatedElement(PrimitiveType<?> t) {
|
||||
if (locale != null) {
|
||||
StringType v = ToolingExtensions.getLanguageTranslationElement(t, locale.toString());
|
||||
|
|
|
@ -1,605 +0,0 @@
|
|||
package org.hl7.fhir.r5.renderers.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Narrative;
|
||||
import org.hl7.fhir.r5.model.Property;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.utils.client.network.FhirRequestBuilder;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
/**
|
||||
* This class is used to walk through the resources when rendering, whether
|
||||
* the resource is a native resource or loaded by the element model
|
||||
*/
|
||||
public class ResourceElement {
|
||||
|
||||
public enum ElementKind {
|
||||
PrimitiveType,
|
||||
DataType,
|
||||
BackboneElement,
|
||||
ContainedResource,
|
||||
InlineResource,
|
||||
BundleEntry,
|
||||
IndependentResource
|
||||
}
|
||||
|
||||
private ContextUtilities context;
|
||||
private ResourceElement parent;
|
||||
private String name; // null at root
|
||||
private int index; // -1 if not repeating
|
||||
private ElementKind kind;
|
||||
|
||||
private Base element;
|
||||
private Element model;
|
||||
|
||||
private List<ResourceElement> children;
|
||||
|
||||
public ResourceElement(ContextUtilities context, Resource resource) {
|
||||
this.context = context;
|
||||
this.parent = null;
|
||||
this.name = null;
|
||||
this.index = -1;
|
||||
this.kind = ElementKind.IndependentResource;
|
||||
this.element = resource;
|
||||
}
|
||||
|
||||
public ResourceElement(ContextUtilities context, DataType type) {
|
||||
this.context = context;
|
||||
this.parent = null;
|
||||
this.name = null;
|
||||
this.index = -1;
|
||||
this.kind = null;
|
||||
this.element = type;
|
||||
}
|
||||
|
||||
public ResourceElement(ContextUtilities context, ResourceElement parent, String name, int index, ElementKind kind, Base element) {
|
||||
this.context = context;
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.kind = kind;
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public ResourceElement(ContextUtilities context, Element resource) {
|
||||
this.context = context;
|
||||
this.parent = null;
|
||||
this.name = null;
|
||||
this.index = -1;
|
||||
this.kind = ElementKind.IndependentResource;
|
||||
this.model = resource;
|
||||
}
|
||||
|
||||
public ResourceElement(ContextUtilities context, ResourceElement parent, String name, int index, ElementKind kind, Element em) {
|
||||
this.context = context;
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.kind = kind;
|
||||
this.model = em;
|
||||
}
|
||||
|
||||
public String fhirVersion() {
|
||||
if (element != null) {
|
||||
return element.getFHIRPublicationVersion().toCode();
|
||||
} else {
|
||||
return model.getFHIRPublicationVersion().toCode();
|
||||
}
|
||||
}
|
||||
public String path() {
|
||||
if (parent == null) {
|
||||
return fhirType();
|
||||
} else {
|
||||
return parent.path()+"." + (index == -1 ? name : name+"["+index+"]");
|
||||
}
|
||||
}
|
||||
|
||||
public ElementKind kind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String fhirType() {
|
||||
if (kind == ElementKind.BackboneElement) {
|
||||
return basePath();
|
||||
} else if (element != null) {
|
||||
return element.fhirType();
|
||||
} else {
|
||||
return model.fhirType();
|
||||
}
|
||||
}
|
||||
|
||||
private String basePath() {
|
||||
if (parent == null || this.isResource()) {
|
||||
return this.fhirType();
|
||||
} else {
|
||||
return parent.basePath()+"."+name;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
if (element != null) {
|
||||
return element.isPrimitive();
|
||||
} else {
|
||||
return model.isPrimitive();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPrimitiveValue() {
|
||||
if (element != null) {
|
||||
return element.hasPrimitiveValue();
|
||||
} else {
|
||||
return model.hasPrimitiveValue();
|
||||
}
|
||||
}
|
||||
|
||||
public String primitiveValue() {
|
||||
if (element != null) {
|
||||
return element.primitiveValue();
|
||||
} else {
|
||||
return model.primitiveValue();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPrimitive(String name) {
|
||||
ResourceElement child = child(name);
|
||||
return child != null && child.isPrimitive();
|
||||
}
|
||||
|
||||
public boolean hasPrimitiveValue(String name) {
|
||||
ResourceElement child = child(name);
|
||||
return child != null && child.hasPrimitiveValue();
|
||||
}
|
||||
|
||||
public String primitiveValue(String name) {
|
||||
ResourceElement child = child(name);
|
||||
return child == null ? null : child.primitiveValue();
|
||||
}
|
||||
|
||||
public String primitiveValueMN(String... names) {
|
||||
ResourceElement child = childMN(names);
|
||||
return child == null ? null : child.primitiveValue();
|
||||
}
|
||||
|
||||
public String firstPrimitiveValue(String name) {
|
||||
ResourceElement child = firstChild(name);
|
||||
return child == null ? null : child.primitiveValue();
|
||||
}
|
||||
|
||||
private void loadChildren() {
|
||||
if (children == null) {
|
||||
children = new ArrayList<>();
|
||||
if (element != null) {
|
||||
loadElementChildren();
|
||||
} else {
|
||||
loadModelChildren();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadModelChildren() {
|
||||
for (Element child : model.getChildren()) {
|
||||
String name = child.getProperty().isChoice() ? child.getProperty().getName() : child.getName();
|
||||
int index = child.isList() ? child.getIndex() : -1;
|
||||
ElementKind kind = determineModelKind(child);
|
||||
children.add(new ResourceElement(context, this, name, index, kind, child));
|
||||
}
|
||||
}
|
||||
|
||||
private ElementKind determineModelKind(Element child) {
|
||||
if (child.isPrimitive()) {
|
||||
return ElementKind.PrimitiveType;
|
||||
} else if (child.fhirType().contains("Backbone")) {
|
||||
return ElementKind.BackboneElement;
|
||||
} else if (child.getProperty().getContextUtils().isDatatype(child.fhirType())) {
|
||||
return ElementKind.DataType;
|
||||
} else if (!child.isResource()) {
|
||||
return ElementKind.BackboneElement;
|
||||
} else if (parent == null) {
|
||||
return ElementKind.IndependentResource;
|
||||
} else switch (child.getSpecial()) {
|
||||
case BUNDLE_ENTRY:
|
||||
return ElementKind.BundleEntry;
|
||||
case BUNDLE_ISSUES:
|
||||
return ElementKind.InlineResource;
|
||||
case BUNDLE_OUTCOME:
|
||||
return ElementKind.InlineResource;
|
||||
case CONTAINED:
|
||||
return ElementKind.ContainedResource;
|
||||
case PARAMETER:
|
||||
return ElementKind.InlineResource;
|
||||
default:
|
||||
return ElementKind.IndependentResource;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadElementChildren() {
|
||||
for (Property p : element.children()) {
|
||||
String name = p.getName();
|
||||
int i = 0;
|
||||
for (Base v : p.getValues()) {
|
||||
ElementKind kind = determineModelKind(p, v);
|
||||
int index = p.isList() ? i : -1;
|
||||
children.add(new ResourceElement(context, this, name, index, kind, v));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ElementKind determineModelKind(Property p, Base v) {
|
||||
if (v.isPrimitive()) {
|
||||
return ElementKind.PrimitiveType;
|
||||
} else if (context.isDatatype(v.fhirType())) {
|
||||
return ElementKind.DataType;
|
||||
} else if (!v.isResource()) {
|
||||
return ElementKind.BackboneElement;
|
||||
} else if (parent == null) {
|
||||
return ElementKind.IndependentResource;
|
||||
} else if ("Bundle.entry".equals(fhirType()) && "resource".equals(p.getName())) {
|
||||
return ElementKind.BundleEntry;
|
||||
} else if ("Bundle".equals(fhirType()) && "outcome".equals(p.getName())) {
|
||||
return ElementKind.InlineResource;
|
||||
} else if ("Bundle".equals(fhirType()) && "issues".equals(p.getName())) {
|
||||
return ElementKind.InlineResource;
|
||||
} else if (isResource() && "contained".equals(p.getName())) {
|
||||
return ElementKind.ContainedResource;
|
||||
} else {
|
||||
return ElementKind.InlineResource;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ResourceElement> children() {
|
||||
loadChildren();
|
||||
return children;
|
||||
}
|
||||
|
||||
public List<ResourceElement> children(String name) {
|
||||
loadChildren();
|
||||
List<ResourceElement> list = new ArrayList<ResourceElement>();
|
||||
for (ResourceElement e : children) {
|
||||
if (name.equals(e.name())) {
|
||||
list.add(e);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* For when an item has been renamed - find by any of the names
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public List<ResourceElement> childrenMN(String... names) {
|
||||
loadChildren();
|
||||
List<ResourceElement> list = new ArrayList<ResourceElement>();
|
||||
for (ResourceElement e : children) {
|
||||
for (String name : names) {
|
||||
if (name.equals(e.name())) {
|
||||
list.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public ResourceElement child(String name) {
|
||||
loadChildren();
|
||||
|
||||
ResourceElement res = null;
|
||||
|
||||
for (ResourceElement e : children) {
|
||||
if (name.equals(e.name()) || (name+"[x]").equals(e.name())) {
|
||||
if (res == null) {
|
||||
res = e;
|
||||
} else {
|
||||
throw new Error("Duplicated element '"+name+"' @ '"+path()+"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* For when an item has been renamed - find by any of the names
|
||||
* @param names
|
||||
* @return
|
||||
*/
|
||||
public ResourceElement childMN(String... names) {
|
||||
loadChildren();
|
||||
|
||||
ResourceElement res = null;
|
||||
|
||||
for (ResourceElement e : children) {
|
||||
for (String name : names) {
|
||||
if (name.equals(e.name()) || (name+"[x]").equals(e.name())) {
|
||||
if (res == null) {
|
||||
res = e;
|
||||
} else {
|
||||
throw new Error("Duplicated element '"+name+"' @ '"+path()+"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean has(String name) {
|
||||
for (ResourceElement e : children) {
|
||||
if (name.equals(e.name())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ResourceElement resource() {
|
||||
ResourceElement e = this.parent;
|
||||
while (e != null && !e.isResource()) {
|
||||
e = e.parent;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public boolean isResource() {
|
||||
if (element != null) {
|
||||
return element.isResource();
|
||||
} else {
|
||||
return model.isResource();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChildren() {
|
||||
loadChildren();
|
||||
return !children.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasExtension(String url) {
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ResourceElement extension(String url) {
|
||||
ResourceElement res = null;
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
|
||||
if (res == null) {
|
||||
res = e;
|
||||
} else {
|
||||
throw new Error("Duplicated extension '"+url+"' @ '"+path()+"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ResourceElement extensionValue(String url) {
|
||||
ResourceElement res = null;
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
|
||||
if (res == null) {
|
||||
res = e.child("value");
|
||||
} else {
|
||||
throw new Error("Duplicated extension '"+url+"' @ '"+path()+"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ResourceElement> extensions(String url) {
|
||||
List<ResourceElement> res = new ArrayList<ResourceElement>();
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
|
||||
res.add(e);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ResourceElement> extensions() {
|
||||
List<ResourceElement> res = new ArrayList<ResourceElement>();
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType())) {
|
||||
res.add(e);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ResourceElement> extensionValues(String url) {
|
||||
List<ResourceElement> res = new ArrayList<ResourceElement>();
|
||||
loadChildren();
|
||||
for (ResourceElement e : children) {
|
||||
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
|
||||
if (e.has("value")) {
|
||||
res.add(e.child("value"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean canHaveNarrative() {
|
||||
if (!isResource()) {
|
||||
return false;
|
||||
}
|
||||
if (element != null) {
|
||||
return element instanceof DomainResource;
|
||||
} else {
|
||||
return context.isDomainResource(fhirType());
|
||||
}
|
||||
}
|
||||
|
||||
public XhtmlNode getNarrative() {
|
||||
if (!canHaveNarrative()) {
|
||||
return null;
|
||||
}
|
||||
ResourceElement text = child("text");
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
ResourceElement div = text.child("div");
|
||||
if (div == null) {
|
||||
return null;
|
||||
}
|
||||
if (div.element != null) {
|
||||
return div.element.getXhtml();
|
||||
} else {
|
||||
return div.model.getXhtml();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNarrative() {
|
||||
if (!canHaveNarrative()) {
|
||||
return false;
|
||||
}
|
||||
ResourceElement text = child("text");
|
||||
if (text == null) {
|
||||
return false;
|
||||
}
|
||||
ResourceElement div = text.child("div");
|
||||
if (div == null) {
|
||||
return false;
|
||||
}
|
||||
if (div.element != null) {
|
||||
return div.element.getXhtml() != null;
|
||||
} else {
|
||||
return div.model.getXhtml() != null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale) {
|
||||
if (element != null) {
|
||||
if (element instanceof DomainResource) {
|
||||
DomainResource r = (DomainResource) element;
|
||||
r.getText().setUserData("renderer.generated", true);
|
||||
if (!r.hasText() || !r.getText().hasDiv()) {
|
||||
r.setText(new Narrative());
|
||||
r.getText().setStatusAsString(status);
|
||||
}
|
||||
if (multiLangMode) {
|
||||
if (!r.getText().hasDiv()) {
|
||||
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
|
||||
div.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||
r.getText().setDiv(div);
|
||||
} else {
|
||||
r.getText().getDiv().getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang"));
|
||||
}
|
||||
markLanguage(x, locale);
|
||||
r.getText().getDiv().getChildNodes().add(x);
|
||||
} else {
|
||||
if (!x.hasAttribute("xmlns"))
|
||||
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||
if (r.hasLanguage()) {
|
||||
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||
x.setAttribute("lang", r.getLanguage());
|
||||
x.setAttribute("xml:lang", r.getLanguage());
|
||||
}
|
||||
r.getText().setDiv(x);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Cannot call setNarrative on a "+element.fhirType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void markLanguage(XhtmlNode x, Locale locale) {
|
||||
x.setAttribute("lang", locale.toString());
|
||||
x.setAttribute("xml:lang", locale.toString());
|
||||
x.addTag(0, "hr");
|
||||
x.addTag(0, "p").b().tx(locale.getDisplayName());
|
||||
x.addTag(0, "hr");
|
||||
}
|
||||
|
||||
|
||||
public String getId() {
|
||||
if (element != null) {
|
||||
return element.getIdBase();
|
||||
} else {
|
||||
return model.getIdBase();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + (index == -1 ? "" : "["+index+"]")+": "+fhirType()+" ("+kind+")";
|
||||
}
|
||||
|
||||
public boolean matches(ResourceElement b) {
|
||||
}
|
||||
|
||||
public String extensionString(String url) {
|
||||
ResourceElement re = extensionValue(url);
|
||||
return re == null ? null : re.primitiveValue();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
if (hasChildren()) {
|
||||
for (ResourceElement c : children) {
|
||||
if (!c.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !isPrimitive() || !hasPrimitiveValue();
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return element == null ? null : (Resource) element;
|
||||
}
|
||||
|
||||
public ResourceElement firstChild(String name) {
|
||||
List<ResourceElement> list = children(name);
|
||||
return list.size() == 0 ? null : list.get(0);
|
||||
}
|
||||
|
||||
public ContextUtilities getContextUtilities() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public boolean hasFormatComment() {
|
||||
if (element != null) {
|
||||
return element.hasFormatComment();
|
||||
} else {
|
||||
return model.hasFormatComment();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getFormatCommentsPre() {
|
||||
if (element != null) {
|
||||
return element.getFormatCommentsPre();
|
||||
} else {
|
||||
return model.getFormatCommentsPre();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package org.hl7.fhir.r5.utils;
|
|||
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Enumerations.BindingStrength;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.r5.model.PackageInformation;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
|
||||
|
@ -77,6 +78,20 @@ public class PackageHackerR5 {
|
|||
}
|
||||
}
|
||||
}
|
||||
// work around a r4 version of extension pack issue
|
||||
if (packageInfo.getId().equals("hl7.fhir.uv.extensions.r4") && r.getType().equals("StructureDefinition")) {
|
||||
StructureDefinition sd = (StructureDefinition) r.getResource();
|
||||
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
|
||||
if (ed.getType().removeIf(tr -> Utilities.existsInList(tr.getCode(), "integer64", "CodeableReference", "RatioRange", "Availability", "ExtendedContactDetail"))) {
|
||||
sd.setUserData("fixed-by-loader", true);
|
||||
}
|
||||
}
|
||||
for (ElementDefinition ed : sd.getDifferential().getElement()) {
|
||||
if (ed.getType().removeIf(tr -> Utilities.existsInList(tr.getCode(), "integer64", "CodeableReference", "RatioRange", "Availability", "ExtendedContactDetail"))) {
|
||||
sd.setUserData("fixed-by-loader", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r.hasUrl() && r.getUrl().contains("|")) {
|
||||
assert false;
|
||||
}
|
||||
|
|
|
@ -1,234 +0,0 @@
|
|||
package org.hl7.fhir.r5.test.rendering;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.r5.elementmodel.ValidatedFragment;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.ResourceElement;
|
||||
import org.hl7.fhir.r5.renderers.utils.ResourceElement.ElementKind;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ResourceElementTests {
|
||||
|
||||
@Test
|
||||
public void testDirect() throws FHIRFormatError, IOException {
|
||||
IWorkerContext worker = TestingUtilities.getSharedWorkerContext();
|
||||
Resource res = new XmlParser().parse(TestingUtilities.loadTestResource("r5", "bundle-resource-element-test.xml"));
|
||||
ResourceElement re = new ResourceElement(new ContextUtilities(worker), res);
|
||||
checkTree(re);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndirect() throws FHIRFormatError, IOException {
|
||||
IWorkerContext worker = TestingUtilities.getSharedWorkerContext();
|
||||
List<ValidatedFragment> res = Manager.parse(worker, TestingUtilities.loadTestResourceStream("r5", "bundle-resource-element-test.xml"), FhirFormat.XML);
|
||||
ResourceElement re = new ResourceElement(new ContextUtilities(worker), res.get(0).getElement());
|
||||
checkTree(re);
|
||||
}
|
||||
|
||||
private void checkTree(ResourceElement bnd) {
|
||||
Assertions.assertTrue(bnd.fhirType().equals("Bundle"));
|
||||
Assertions.assertNull(bnd.name());
|
||||
Assertions.assertNull(bnd.getId());
|
||||
Assertions.assertEquals("Bundle", bnd.path());
|
||||
Assertions.assertEquals("5.0.0", bnd.fhirVersion());
|
||||
Assertions.assertFalse(bnd.canHaveNarrative());
|
||||
Assertions.assertFalse(bnd.hasNarrative());
|
||||
Assertions.assertEquals(ElementKind.IndependentResource, bnd.kind());
|
||||
|
||||
ResourceElement type = bnd.child("type");
|
||||
Assertions.assertTrue(type.fhirType().equals("code"));
|
||||
Assertions.assertEquals("type", type.name());
|
||||
Assertions.assertEquals("Bundle.type", type.path());
|
||||
Assertions.assertTrue(type.isPrimitive());
|
||||
Assertions.assertTrue(type.hasPrimitiveValue());
|
||||
Assertions.assertEquals("collection", type.primitiveValue());
|
||||
Assertions.assertFalse(type.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, type.kind());
|
||||
|
||||
ResourceElement id = bnd.child("identifier");
|
||||
Assertions.assertEquals("Identifier", id.fhirType());
|
||||
Assertions.assertEquals("identifier", id.name());
|
||||
Assertions.assertEquals("Bundle.identifier", id.path());
|
||||
Assertions.assertFalse(id.isPrimitive());
|
||||
Assertions.assertFalse(id.hasPrimitiveValue());
|
||||
Assertions.assertTrue(id.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.DataType, id.kind());
|
||||
|
||||
ResourceElement system = id.child("system");
|
||||
Assertions.assertEquals("uri", system.fhirType());
|
||||
Assertions.assertEquals("system", system.name());
|
||||
Assertions.assertEquals("Bundle.identifier.system", system.path());
|
||||
Assertions.assertTrue(system.isPrimitive());
|
||||
Assertions.assertTrue(system.hasPrimitiveValue());
|
||||
Assertions.assertEquals("http://something1", system.primitiveValue());
|
||||
Assertions.assertFalse(system.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, system.kind());
|
||||
|
||||
ResourceElement value = id.child("value");
|
||||
Assertions.assertEquals("string", value.fhirType());
|
||||
Assertions.assertEquals("value", value.name());
|
||||
Assertions.assertEquals("Bundle.identifier.value", value.path());
|
||||
Assertions.assertTrue(value.isPrimitive());
|
||||
Assertions.assertTrue(value.hasPrimitiveValue());
|
||||
Assertions.assertEquals("something2", value.primitiveValue());
|
||||
Assertions.assertFalse(value.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, value.kind());
|
||||
|
||||
int i = 0;
|
||||
for (ResourceElement link : bnd.children("link")) {
|
||||
checkLink(i, link);
|
||||
i++;
|
||||
}
|
||||
|
||||
ResourceElement entry = bnd.child("entry");
|
||||
Assertions.assertEquals("Bundle.entry", entry.fhirType());
|
||||
Assertions.assertEquals("entry", entry.name());
|
||||
Assertions.assertEquals("Bundle.entry[0]", entry.path());
|
||||
Assertions.assertFalse(entry.isPrimitive());
|
||||
Assertions.assertFalse(entry.hasPrimitiveValue());
|
||||
Assertions.assertTrue(entry.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.BackboneElement, entry.kind());
|
||||
|
||||
ResourceElement fu = entry.child("fullUrl");
|
||||
Assertions.assertEquals("uri", fu.fhirType());
|
||||
Assertions.assertEquals("fullUrl", fu.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].fullUrl", fu.path());
|
||||
Assertions.assertTrue(fu.isPrimitive());
|
||||
Assertions.assertTrue(fu.hasPrimitiveValue());
|
||||
Assertions.assertEquals("http://something5", fu.primitiveValue());
|
||||
Assertions.assertFalse(fu.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, fu.kind());
|
||||
|
||||
ResourceElement obs = entry.child("resource");
|
||||
checkObservation(obs);
|
||||
}
|
||||
|
||||
private void checkObservation(ResourceElement obs) {
|
||||
Assertions.assertTrue(obs.fhirType().equals("Observation"));
|
||||
Assertions.assertEquals("resource", obs.name());
|
||||
Assertions.assertEquals("obs1", obs.getId());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource", obs.path());
|
||||
Assertions.assertEquals(ElementKind.BundleEntry, obs.kind());
|
||||
Assertions.assertTrue(obs.canHaveNarrative());
|
||||
Assertions.assertTrue(obs.hasNarrative());
|
||||
Assertions.assertNotNull(obs.getNarrative());
|
||||
|
||||
List<ResourceElement> children = obs.children();
|
||||
assertEquals(5, children.size());
|
||||
|
||||
checkObsCode(children.get(3));
|
||||
|
||||
assertEquals(children.get(4), obs.child("value"));
|
||||
assertEquals(children.get(4), obs.child("value[x]"));
|
||||
checkObsValue(children.get(4));
|
||||
|
||||
assertEquals(children.get(2), obs.child("contained"));
|
||||
checkContained(children.get(2));
|
||||
}
|
||||
|
||||
private void checkContained(ResourceElement cont) {
|
||||
Assertions.assertEquals("Provenance", cont.fhirType());
|
||||
Assertions.assertEquals("contained", cont.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.contained[0]", cont.path());
|
||||
Assertions.assertFalse(cont.isPrimitive());
|
||||
Assertions.assertFalse(cont.hasPrimitiveValue());
|
||||
Assertions.assertTrue(cont.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.ContainedResource, cont.kind());
|
||||
}
|
||||
|
||||
private void checkObsValue(ResourceElement obsValue) {
|
||||
Assertions.assertEquals("Quantity", obsValue.fhirType());
|
||||
Assertions.assertEquals("value[x]", obsValue.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.value[x]", obsValue.path());
|
||||
Assertions.assertFalse(obsValue.isPrimitive());
|
||||
Assertions.assertFalse(obsValue.hasPrimitiveValue());
|
||||
Assertions.assertTrue(obsValue.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.DataType, obsValue.kind());
|
||||
}
|
||||
|
||||
private void checkObsCode(ResourceElement obsCode) {
|
||||
Assertions.assertEquals("CodeableConcept", obsCode.fhirType());
|
||||
Assertions.assertEquals("code", obsCode.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.code", obsCode.path());
|
||||
Assertions.assertFalse(obsCode.isPrimitive());
|
||||
Assertions.assertFalse(obsCode.hasPrimitiveValue());
|
||||
Assertions.assertTrue(obsCode.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.DataType, obsCode.kind());
|
||||
|
||||
ResourceElement txt = obsCode.children().get(1);
|
||||
Assertions.assertEquals("string", txt.fhirType());
|
||||
Assertions.assertEquals("text", txt.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.code.text", txt.path());
|
||||
Assertions.assertTrue(txt.isPrimitive());
|
||||
Assertions.assertFalse(txt.hasPrimitiveValue());
|
||||
Assertions.assertTrue(txt.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, txt.kind());
|
||||
|
||||
ResourceElement e1 = txt.extension("http://something11");
|
||||
Assertions.assertEquals("Extension", e1.fhirType());
|
||||
Assertions.assertEquals("extension", e1.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.code.text.extension[0]", e1.path());
|
||||
Assertions.assertFalse(e1.isPrimitive());
|
||||
Assertions.assertFalse(e1.hasPrimitiveValue());
|
||||
Assertions.assertTrue(e1.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.DataType, e1.kind());
|
||||
Assertions.assertEquals("http://something11", e1.primitiveValue("url"));
|
||||
|
||||
ResourceElement ev = txt.extensionValue("http://something11");
|
||||
Assertions.assertEquals(ev, e1.child("value"));
|
||||
Assertions.assertEquals(ev, e1.child("value[x]"));
|
||||
|
||||
Assertions.assertEquals("string", ev.fhirType());
|
||||
Assertions.assertEquals("value[x]", ev.name());
|
||||
Assertions.assertEquals("Bundle.entry[0].resource.code.text.extension[0].value[x]", ev.path());
|
||||
Assertions.assertTrue(ev.isPrimitive());
|
||||
Assertions.assertTrue(ev.hasPrimitiveValue());
|
||||
Assertions.assertFalse(ev.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, ev.kind());
|
||||
Assertions.assertEquals("something12", ev.primitiveValue());
|
||||
}
|
||||
|
||||
private void checkLink(int i, ResourceElement link) {
|
||||
Assertions.assertEquals("Bundle.link", link.fhirType());
|
||||
Assertions.assertEquals("link", link.name());
|
||||
Assertions.assertEquals("Bundle.link["+i+"]", link.path());
|
||||
Assertions.assertFalse(link.isPrimitive());
|
||||
Assertions.assertFalse(link.hasPrimitiveValue());
|
||||
Assertions.assertTrue(link.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.BackboneElement, link.kind());
|
||||
|
||||
ResourceElement rel = link.child("relation");
|
||||
Assertions.assertEquals("code", rel.fhirType());
|
||||
Assertions.assertEquals("relation", rel.name());
|
||||
Assertions.assertEquals("Bundle.link["+i+"].relation", rel.path());
|
||||
Assertions.assertTrue(rel.isPrimitive());
|
||||
Assertions.assertTrue(rel.hasPrimitiveValue());
|
||||
Assertions.assertEquals(i == 0 ? "self" : "next", rel.primitiveValue());
|
||||
Assertions.assertFalse(rel.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, rel.kind());
|
||||
|
||||
ResourceElement url = link.child("url");
|
||||
Assertions.assertEquals("uri", url.fhirType());
|
||||
Assertions.assertEquals("url", url.name());
|
||||
Assertions.assertEquals("Bundle.link["+i+"].url", url.path());
|
||||
Assertions.assertTrue(url.isPrimitive());
|
||||
Assertions.assertTrue(url.hasPrimitiveValue());
|
||||
Assertions.assertEquals(i == 0 ? "http://something3" : "http://something4", url.primitiveValue());
|
||||
Assertions.assertFalse(url.hasChildren());
|
||||
Assertions.assertEquals(ElementKind.PrimitiveType, url.kind());
|
||||
}
|
||||
|
||||
}
|
|
@ -1080,4 +1080,15 @@ public class I18nConstants {
|
|||
public static final String SD_TYPE_PARAMETER_INVALID_REF = "SD_TYPE_PARAMETER_INVALID_REF";
|
||||
public static final String SD_TYPE_PARAM_NOT_SPECIFIED = "SD_TYPE_PARAM_NOT_SPECIFIED";
|
||||
public static final String SD_TYPE_PARAMETER_ABSTRACT_WARNING = "SD_TYPE_PARAMETER_ABSTRACT_WARNING";
|
||||
public static final String IG_DEPENDENCY_DIRECT = "IG_DEPENDENCY_DIRECT";
|
||||
public static final String IG_DEPENDENCY_INVALID_PACKAGEID = "IG_DEPENDENCY_INVALID_PACKAGEID";
|
||||
public static final String IG_DEPENDENCY_CLASH_PACKAGEID = "IG_DEPENDENCY_CLASH_PACKAGEID";
|
||||
public static final String IG_DEPENDENCY_CLASH_CANONICAL = "IG_DEPENDENCY_CLASH_CANONICAL";
|
||||
public static final String IG_DEPENDENCY_NO_PACKAGE = "IG_DEPENDENCY_NO_PACKAGE";
|
||||
public static final String IG_DEPENDENCY_NO_VERSION = "IG_DEPENDENCY_NO_VERSION";
|
||||
public static final String IG_DEPENDENCY_INVALID_PACKAGE_VERSION = "IG_DEPENDENCY_INVALID_PACKAGE_VERSION";
|
||||
public static final String IG_DEPENDENCY_VERSION_ERROR = "IG_DEPENDENCY_VERSION_ERROR";
|
||||
public static final String IG_DEPENDENCY_VERSION_WARNING = "IG_DEPENDENCY_VERSION_WARNING";
|
||||
public static final String IG_DEPENDENCY_EXCEPTION = "IG_DEPENDENCY_EXCEPTION";
|
||||
public static final String IG_DEPENDENCY_PACKAGE_UNKNOWN = "IG_DEPENDENCY_PACKAGE_UNKNOWN";
|
||||
}
|
||||
|
|
|
@ -1108,3 +1108,14 @@ SD_TYPE_PARAMETER_INVALID = The type definition ''{2}'' has a type parameter ''{
|
|||
SD_TYPE_PARAMETER_INVALID_REF = The type ''{0}'' is a reference to ''{1}'' which has a type parameter ''{2}'' with a base type of {3} but the type parameter provided is ''{4}'' which is not the right type
|
||||
SD_TYPE_PARAM_NOT_SPECIFIED = The type ''{0}'' at {3} is a reference to ''{1}'' which needs a type parameter ''{2}'' but a type parameter is not provided for ''{2}''
|
||||
SD_TYPE_PARAMETER_ABSTRACT_WARNING = The type ''{0}'' at {3} refers to the abstract type ''{1}'' but the context is not an abstract type - this is usually an error
|
||||
IG_DEPENDENCY_DIRECT = The URL should refer directly to the ImplementationGuide resource (e.g. include ''/ImplementationGuide/'')
|
||||
PACKAGE_REGEX = The packageId {0} is not valid
|
||||
IG_DEPENDENCY_CLASH_PACKAGEID = The canonical URL {0} points to the package {1} which is inconsistent with the stated packageId of {2}
|
||||
IG_DEPENDENCY_CLASH_CANONICAL = The packageId {0} points to the canonical {1} which is inconsistent with the stated canonical of {2}
|
||||
IG_DEPENDENCY_NO_PACKAGE = No NPM package id could be determined so the version consistency can't be checked
|
||||
IG_DEPENDENCY_NO_VERSION = No version was specified for the package so the version consistency can't be checked
|
||||
IG_DEPENDENCY_INVALID_PACKAGE_VERSION = The version {0} is not a valid NPM package version
|
||||
IG_DEPENDENCY_PACKAGE_UNKNOWN = The package {0} could not be found so the version consistency can't be checked
|
||||
IG_DEPENDENCY_VERSION_ERROR = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. Use the package {3} instead
|
||||
IG_DEPENDENCY_VERSION_WARNING = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. In general, this version mismatch should be avoided - some tools will try to make this work with variable degrees of success, but others will not even try
|
||||
IG_DEPENDENCY_EXCEPTION = Exception checking package version consistency: {0}
|
||||
|
|
|
@ -219,6 +219,7 @@ import org.hl7.fhir.validation.instance.InstanceValidator.BindingContext;
|
|||
import org.hl7.fhir.validation.instance.type.BundleValidator;
|
||||
import org.hl7.fhir.validation.instance.type.CodeSystemValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ConceptMapValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ImplementationGuideValidator;
|
||||
import org.hl7.fhir.validation.instance.type.MeasureValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ObservationValidator;
|
||||
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator;
|
||||
|
@ -5771,6 +5772,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return new StructureMapValidator(this, fpe, profileUtilities).validateStructureMap(valContext, errors, element, stack) && ok;
|
||||
} else if (element.getType().equals("ValueSet")) {
|
||||
return new ValueSetValidator(this).validateValueSet(valContext, errors, element, stack) && ok;
|
||||
} else if (element.getType().equals("ImplementationGuide")) {
|
||||
return new ImplementationGuideValidator(this.context, xverManager, debug).validateImplementationGuide(valContext, errors, element, stack) && ok;
|
||||
} else if ("http://hl7.org/fhir/uv/sql-on-fhir/StructureDefinition/ViewDefinition".equals(element.getProperty().getStructure().getUrl())) {
|
||||
if (element.getNativeObject() != null && element.getNativeObject() instanceof JsonObject) {
|
||||
JsonObject json = (JsonObject) element.getNativeObject();
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
package org.hl7.fhir.validation.instance.type;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.elementmodel.ObjectConverter;
|
||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.DateType;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.Questionnaire;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType;
|
||||
import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.TimeType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
|
||||
import org.hl7.fhir.validation.instance.utils.EnableWhenEvaluator;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
import org.hl7.fhir.validation.instance.utils.ValidationContext;
|
||||
import org.hl7.fhir.validation.instance.utils.EnableWhenEvaluator.QStack;
|
||||
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
public class ImplementationGuideValidator extends BaseValidator {
|
||||
|
||||
public ImplementationGuideValidator(IWorkerContext context, XVerExtensionManager xverManager, boolean debug) {
|
||||
super(context, xverManager, debug);
|
||||
}
|
||||
|
||||
public boolean validateImplementationGuide(ValidationContext valContext, List<ValidationMessage> errors, Element ig, NodeStack stack) {
|
||||
boolean ok = true;
|
||||
String fver = ig.getNamedChildValue("fhirVersion");
|
||||
|
||||
List<Element> dependencies = ig.getChildrenByName("dependsOn");
|
||||
int i = 0;
|
||||
for (Element dependency : dependencies) {
|
||||
ok = checkDependency(errors, ig, stack.push(dependency, i, null, null), dependency, fver) && ok;
|
||||
i++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean checkDependency(List<ValidationMessage> errors, Element ig, NodeStack stack, Element dependency, String fver) {
|
||||
boolean ok = true;
|
||||
String url = dependency.getNamedChildValue("url");
|
||||
String packageId = dependency.getNamedChildValue("packageId");
|
||||
String version = dependency.getNamedChildValue("version");
|
||||
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), url == null || url.contains("/ImplementationGuide/"), I18nConstants.IG_DEPENDENCY_DIRECT, url) && ok;
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), packageId == null || packageId.matches(FilesystemPackageCacheManager.PACKAGE_REGEX), I18nConstants.IG_DEPENDENCY_INVALID_PACKAGEID, packageId) && ok;
|
||||
|
||||
try {
|
||||
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build();
|
||||
if (url != null && packageId != null) {
|
||||
String pid = pcm.getPackageId(url);
|
||||
String canonical = pcm.getPackageUrl(packageId);
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), pid == null || pid.equals(packageId), I18nConstants.IG_DEPENDENCY_CLASH_PACKAGEID, url, pid, packageId) && ok;
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), canonical == null || canonical.equals(url), I18nConstants.IG_DEPENDENCY_CLASH_CANONICAL, packageId, canonical, url) && ok;
|
||||
}
|
||||
if (packageId == null && ok) {
|
||||
packageId = pcm.getPackageId(url);
|
||||
}
|
||||
if (ok && warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), packageId != null, I18nConstants.IG_DEPENDENCY_NO_PACKAGE) &&
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), version != null, I18nConstants.IG_DEPENDENCY_NO_VERSION)) {
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), (packageId+"#"+version).matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX), I18nConstants.IG_DEPENDENCY_INVALID_PACKAGE_VERSION, version) && ok;
|
||||
NpmPackage npm = pcm.loadPackage(packageId, version);
|
||||
if (warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), npm != null, I18nConstants.IG_DEPENDENCY_PACKAGE_UNKNOWN, packageId+"#"+version)) {
|
||||
String pver = npm.fhirVersion();
|
||||
if (!VersionUtilities.versionsMatch(pver, fver)) {
|
||||
if ("hl7.fhir.uv.extensions".equals(packageId)) {
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), false, I18nConstants.IG_DEPENDENCY_VERSION_ERROR, fver, packageId+"#"+version, pver,
|
||||
"hl7.fhir.uv.extensions."+VersionUtilities.getNameForVersion(fver).toLowerCase()) && ok;
|
||||
} else {
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), false, I18nConstants.IG_DEPENDENCY_VERSION_WARNING, fver, packageId+"#"+version, pver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), version != null, I18nConstants.IG_DEPENDENCY_EXCEPTION, e.getMessage());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue