diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 4a34f4d1b..c030469c7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -141,7 +141,7 @@ import com.google.gson.JsonObject; import javax.annotation.Nonnull; -public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext{ +public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext { private static final boolean QA_CHECK_REFERENCE_SOURCE = false; // see comments below @@ -223,6 +223,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte private CanonicalResourceManager maps = new CanonicalResourceManager(false, minimalMemory); protected CanonicalResourceManager transforms = new CanonicalResourceManager(false, minimalMemory); private CanonicalResourceManager structures = new CanonicalResourceManager(false, minimalMemory); + private TypeManager typeManager = new TypeManager(structures); private final CanonicalResourceManager measures = new CanonicalResourceManager(false, minimalMemory); private final CanonicalResourceManager libraries = new CanonicalResourceManager(false, minimalMemory); private CanonicalResourceManager guides = new CanonicalResourceManager(false, minimalMemory); @@ -279,6 +280,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte this.valueSets = valueSets; this.maps = maps; this.structures = profiles; + this.typeManager = new TypeManager(structures); this.guides = guides; clock = new TimeTracker(); } @@ -292,6 +294,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte maps.copy(other.maps); transforms.copy(other.transforms); structures.copy(other.structures); + typeManager = new TypeManager(structures); searchParameters.copy(other.searchParameters); plans.copy(other.plans); questionnaires.copy(other.questionnaires); @@ -370,6 +373,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte fixOldSD(sd); } structures.register(r, packageInfo); + typeManager.see(r); break; case "ValueSet": valueSets.register(r, packageInfo); @@ -462,6 +466,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte fixOldSD(sd); } structures.see(sd, packageInfo); + typeManager.see(sd); } else if (r instanceof ValueSet) { valueSets.see((ValueSet) m, packageInfo); } else if (r instanceof CodeSystem) { @@ -2337,6 +2342,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (fhirType.equals("StructureDefinition")) { structures.drop(id); + typeManager.reload(); } else if (fhirType.equals("ImplementationGuide")) { guides.drop(id); } else if (fhirType.equals("CapabilityStatement")) { @@ -2463,34 +2469,23 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (Utilities.isAbsoluteUrl(typeName)) { return fetchResource(StructureDefinition.class, typeName); } else { - Set types = new HashSet<>(); - types.addAll(fetchTypeDefinitions(typeName)); - types.removeIf(sd -> sd.getDerivation() == TypeDerivationRule.CONSTRAINT); - if (types.size() == 0) { - return null; // throw new FHIRException("Unresolved type "+typeName+" (0)"); - } else if (types.size() == 1) { - return types.iterator().next(); - } else { - types.removeIf(sd -> !sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/")); - if (types.size() == 0) { - return null; - } else if (types.size() != 1) { - throw new FHIRException("Ambiguous type "+typeName+" ("+types.toString()+") (contact Grahame Grieve for investigation)"); - } else { - return types.iterator().next(); - } - } + return typeManager.fetchTypeDefinition(typeName); } } @Override public List fetchTypeDefinitions(String typeName) { - List res = new ArrayList<>(); - structures.listAll(res); - res.removeIf(sd -> !sd.hasType() || !(sd.getType().equals(typeName) || sd.getTypeTail().equals(typeName))); - return res; + return typeManager.getDefinitions(typeName); } + public boolean isPrimitiveType(String type) { + return typeManager.isPrimitive(type); + } + + public boolean isDataType(String type) { + return typeManager.isDataType(type); + } + public boolean isTlogging() { return tlogging; } @@ -2627,6 +2622,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte maps.setVersion(version); transforms.setVersion(version); structures.setVersion(version); + typeManager.reload(); measures.setVersion(version); libraries.setVersion(version); guides.setVersion(version); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java index 5600403ea..f20f5d9ae 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java @@ -31,10 +31,11 @@ public class CanonicalResourceManager { private String url; private String version; private String supplements; + private String derivation; private CanonicalResource resource; private boolean hacked; - public CanonicalResourceProxy(String type, String id, String url, String version, String supplements) { + public CanonicalResourceProxy(String type, String id, String url, String version, String supplements, String derivation) { super(); this.type = type; this.id = id; @@ -75,6 +76,14 @@ public class CanonicalResourceManager { return supplements; } + public String getDerivation() { + return derivation; + } + + public void setDerivation(String derivation) { + this.derivation = derivation; + } + public CanonicalResource getResource() throws FHIRException { if (resource == null) { resource = loadResource(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java index ac7bd8b47..8c430a7cb 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java @@ -310,8 +310,7 @@ public class ContextUtilities implements ProfileKnowledgeProvider { @Override public boolean isPrimitiveType(String type) { - StructureDefinition sd = context.fetchTypeDefinition(type); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; + return context.isPrimitiveType(type); } @Override @@ -364,11 +363,6 @@ public class ContextUtilities implements ProfileKnowledgeProvider { return false; } - public boolean isPrimitiveDatatype(String type) { - StructureDefinition sd = context.fetchTypeDefinition(type); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } - public StructureDefinition fetchByJsonName(String key) { for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { ElementDefinition ed = sd.getSnapshot().getElementFirstRep(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index 36abb395f..89cc0aaea 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -938,7 +938,20 @@ public interface IWorkerContext { */ public List fetchTypeDefinitions(String n); + /** + * return whether type is primitive type. This is called a lot, and needs a high performance implementation + * @param type + * @return + */ + public boolean isPrimitiveType(String type); + /** + * return whether type is data type. This is called a lot, and needs a high performance implementation + * @param type + * @return + */ + public boolean isDataType(String type); + /** * Returns a set of keys that can be used to get binaries from this context. * The binaries come from the loaded packages (mostly the pubpack) @@ -1020,4 +1033,6 @@ public interface IWorkerContext { public boolean isForPublication(); public void setForPublication(boolean value); + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index 78a4f5d44..b542db5f3 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -99,7 +99,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon private final IContextResourceLoader loader; public PackageResourceLoader(PackageResourceInformation pri, IContextResourceLoader loader) { - super(pri.getResourceType(), pri.getId(), loader == null ? pri.getUrl() :loader.patchUrl(pri.getUrl(), pri.getResourceType()), pri.getVersion(), pri.getSupplements()); + super(pri.getResourceType(), pri.getId(), loader == null ? pri.getUrl() :loader.patchUrl(pri.getUrl(), pri.getResourceType()), pri.getVersion(), pri.getSupplements(), pri.getDerivation()); this.filename = pri.getFilename(); this.loader = loader; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TypeManager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TypeManager.java new file mode 100644 index 000000000..744436752 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TypeManager.java @@ -0,0 +1,119 @@ +package org.hl7.fhir.r5.context; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; +import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; +import org.hl7.fhir.utilities.Utilities; + +public class TypeManager { + + + private CanonicalResourceManager structures; + private Map> typeDefinitions = new HashMap<>(); + private Map> fhirTypeDefinitions = new HashMap<>(); + private Set primitiveNames = new HashSet<>(); + private Set dataTypeNames = new HashSet<>(); + + public TypeManager(CanonicalResourceManager structures) { + super(); + this.structures = structures; + reload(); + } + + public void reload() { + typeDefinitions.clear(); + primitiveNames.clear(); + dataTypeNames.clear(); + for (StructureDefinition sd : structures.getList()) { + see(sd); + } + } + + public void see(CanonicalResourceProxy r) { + if (!"constraint".equals(r.getDerivation())) { + see((StructureDefinition) r.getResource()); + } + } + + public void see(StructureDefinition sd) { + if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { + String type = sd.getType(); + List types = typeDefinitions.get(type); + if (types == null) { + types = new ArrayList<>(); + typeDefinitions.put(type, types); + } + types.add(sd); + if (sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/")) { + types = fhirTypeDefinitions.get(type); + if (types == null) { + types = new ArrayList<>(); + fhirTypeDefinitions.put(type, types); + } + types.add(sd); + } + if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) { + primitiveNames.add(sd.getType()); + } else if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) { + dataTypeNames.add(sd.getType()); + } + } + } + + + public List getDefinitions(String typeName) { + List list = new ArrayList<>(); + List defined = typeDefinitions.get(typeName); + if (defined != null) { + list.addAll(defined); + } + return list; + } + + public StructureDefinition fetchTypeDefinition(String typeName) { + List types = typeDefinitions.get(typeName); + if (types == null) { + return null; // throw new FHIRException("Unresolved type "+typeName+" (0)"); + } else if (types.size() == 1) { + return types.get(0); + } else { + types = fhirTypeDefinitions.get(typeName); + if (types == null) { + return null; + } else if (types.size() != 1) { + throw new FHIRException("Ambiguous type "+typeName+" ("+types.toString()+") (contact Grahame Grieve for investigation)"); + } else { + return types.get(0); + } + } + } + + public boolean isPrimitive(String type) { + if (primitiveNames.contains(type) || Utilities.existsInList(type, "boolean", "integer", "integer64", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "uuid", "xhtml", "url", "canonical")) { + return true; + } else { + StructureDefinition sd = structures.get(type); + return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; + } + } + + public boolean isDataType(String type) { + if (dataTypeNames.contains(type) || Utilities.existsInList(type, "Address", "Age", "Annotation", "Attachment", "CodeableConcept", "Coding", "ContactPoint", "Count", "Distance", "Duration", "HumanName", "Identifier", "Money", "Period", "Quantity", "Range", "Ratio", "Reference", "SampledData", "Signature", "Timing", + "ContactDetail", "Contributor", "DataRequirement", "Expression", "ParameterDefinition", "RelatedArtifact", "TriggerDefinition", "UsageContext")) { + return true; + } else { + StructureDefinition sd = structures.get(type); + return sd != null && sd.getKind() == StructureDefinitionKind.COMPLEXTYPE; + } + } + +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index 5eb53f44c..ae290cc29 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -556,7 +556,7 @@ public class Element extends Base { return ne; } else if (p.getDefinition().isChoice() && name.startsWith(p.getName().replace("[x]", ""))) { String type = name.substring(p.getName().length()-3); - if (new ContextUtilities(property.getContext()).isPrimitiveDatatype(Utilities.uncapitalize(type))) { + if (property.getContext().isPrimitiveType(Utilities.uncapitalize(type))) { type = Utilities.uncapitalize(type); } Element ne = new Element(name, p); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java index 73a50c6c1..dd93e379f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java @@ -45,12 +45,12 @@ public class FmlParser extends ParserBase { } @Override - public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { byte[] content = TextFile.streamToBytes(inStream); ByteArrayInputStream stream = new ByteArrayInputStream(content); String text = TextFile.streamToString(stream); - List result = new ArrayList<>(); - NamedElement ctxt = new NamedElement("focus", "fml", content); + List result = new ArrayList<>(); + ValidatedFragment ctxt = new ValidatedFragment("focus", "fml", content); ctxt.setElement(parse(ctxt.getErrors(), text)); result.add(ctxt); return result; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java index 53abb894d..5ac465113 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java @@ -52,7 +52,6 @@ import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.JsonCreator; import org.hl7.fhir.r5.formats.JsonCreatorCanonical; @@ -120,10 +119,10 @@ public class JsonParser extends ParserBase { @Override - public List parse(InputStream inStream) throws IOException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRException { // long start = System.currentTimeMillis(); byte[] content = TextFile.streamToBytes(inStream); - NamedElement ctxt = new NamedElement("focus", "json", content); + ValidatedFragment ctxt = new ValidatedFragment("focus", "json", content); ByteArrayInputStream stream = new ByteArrayInputStream(content); @@ -142,7 +141,7 @@ public class JsonParser extends ParserBase { } ctxt.setElement(parse(ctxt.getErrors(), obj)); - List res = new ArrayList<>(); + List res = new ArrayList<>(); res.add(ctxt); // long t=System.currentTimeMillis()-start; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java index 275eeb86d..16a59718b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java @@ -41,7 +41,6 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.model.StructureDefinition; @@ -106,7 +105,7 @@ public class Manager { } } - public static List parse(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException { + public static List parse(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException { return makeParser(context, inputFormat).parse(source); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java index 357b12f4e..6c9c26591 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java @@ -39,7 +39,6 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.SourcedChildDefinitions; import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.CodeableConcept; @@ -72,7 +71,7 @@ public class ObjectConverter { org.hl7.fhir.r5.formats.JsonParser jp = new org.hl7.fhir.r5.formats.JsonParser(); jp.compose(bs, ig); ByteArrayInputStream bi = new ByteArrayInputStream(bs.toByteArray()); - List list = new JsonParser(context).parse(bi); + List list = new JsonParser(context).parse(bi); if (list.size() != 1) { throw new FHIRException("Unable to convert because the source contains multieple resources"); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java index 344afc760..ab20055de 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java @@ -35,7 +35,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; -import java.util.ArrayList; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; @@ -69,54 +68,6 @@ public abstract class ParserBase { } } - public class NamedElement { - private String name; - private String extension; - private Element element; - private byte[] content; - private List errors = new ArrayList<>(); - - public NamedElement(String name, String extension, Element element, byte[] content) { - super(); - this.name = name; - this.element = element; - this.content = content; - this.extension = extension; - } - - public NamedElement(String name, String extension, byte[] content) { - super(); - this.name = name; - this.content = content; - this.extension = extension; - } - - public String getName() { - return name; - } - - public Element getElement() { - return element; - } - - public byte[] getContent() { - return content; - } - - public List getErrors() { - return errors; - } - - public void setElement(Element element) { - this.element = element; - } - - public String getFilename() { - return name+"."+extension; - } - - } - public interface ILinkResolver { String resolveType(String type); String resolveProperty(Property property); @@ -126,13 +77,7 @@ public abstract class ParserBase { public enum ValidationPolicy { NONE, QUICK, EVERYTHING } public boolean isPrimitive(String code) { - StructureDefinition sd = context.fetchTypeDefinition(code); - if (sd != null) { - return sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } - - return Utilities.existsInList(code, "boolean", "integer", "integer64", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "uuid", "xhtml", "url", "canonical"); - + return context.isPrimitiveType(code); } protected IWorkerContext context; @@ -152,20 +97,20 @@ public abstract class ParserBase { this.policy = policy; } - public abstract List parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException; + public abstract List parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException; public Element parseSingle(InputStream stream, List errors) throws IOException, FHIRFormatError, DefinitionException, FHIRException { - List res = parse(stream); + List res = parse(stream); if (res.size() != 1) { throw new FHIRException("Parsing FHIR content returned multiple elements in a context where only one element is allowed"); } var resE = res.get(0); if (resE.getElement() == null) { - throw new FHIRException("Parsing FHIR content failed: "+errorSummary(resE.errors)); + throw new FHIRException("Parsing FHIR content failed: "+errorSummary(resE.getErrors())); } else if (res.size() == 0) { - throw new FHIRException("Parsing FHIR content returned no elements in a context where one element is required because: "+errorSummary(resE.errors)); + throw new FHIRException("Parsing FHIR content returned no elements in a context where one element is required because: "+errorSummary(resE.getErrors())); } if (errors != null) { errors.addAll(resE.getErrors()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java index ab26a0537..2e5f3f941 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java @@ -249,12 +249,7 @@ public class Property { * @param E.g. "integer" */ public boolean isPrimitive(String code) { - if (Utilities.isAbsoluteUrl(code)) { - StructureDefinition sd = context.fetchTypeDefinition(code); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } else { - return TypesUtilities.isPrimitive(code); - } + return context.isPrimitiveType(code); } public boolean isPrimitive() { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ResourceParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ResourceParser.java index c214c5d52..bfbf759b0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ResourceParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ResourceParser.java @@ -27,7 +27,7 @@ public class ResourceParser extends ParserBase { } @Override - public List parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { + public List parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { throw new NotImplementedException("parse(InputStream stream)"); // doesns't make sense } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java index 11acb9ed8..9e4737e01 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java @@ -24,7 +24,6 @@ import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.elementmodel.SHCParser.SHCSignedJWT; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.utilities.TextFile; @@ -80,11 +79,11 @@ public class SHCParser extends ParserBase { jsonParser = new JsonParser(context); } - public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { byte[] content = TextFile.streamToBytes(inStream); ByteArrayInputStream stream = new ByteArrayInputStream(content); - List res = new ArrayList<>(); - NamedElement shc = new NamedElement("shc", "json", content); + List res = new ArrayList<>(); + ValidatedFragment shc = new ValidatedFragment("shc", "json", content); res.add(shc); String src = TextFile.streamToString(stream).trim(); @@ -166,7 +165,7 @@ public class SHCParser extends ParserBase { return res; } // ok. all checks passed, we can now validate the bundle - NamedElement bnd = new NamedElement(path, "json", org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(cs.getJsonObject("fhirBundle"))); + ValidatedFragment bnd = new ValidatedFragment(path, "json", org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(cs.getJsonObject("fhirBundle"))); res.add(bnd); bnd.setElement(jsonParser.parse(bnd.getErrors(), cs.getJsonObject("fhirBundle"))); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHLParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHLParser.java index 065c3553e..5682b4aa0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHLParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHLParser.java @@ -72,11 +72,11 @@ public class SHLParser extends ParserBase { super(context); } - public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { byte[] content = TextFile.streamToBytes(inStream); - List res = new ArrayList<>(); - NamedElement shl = addNamedElement(res, "shl", "txt", content); + List res = new ArrayList<>(); + ValidatedFragment shl = addNamedElement(res, "shl", "txt", content); String src = TextFile.bytesToString(content); if (src.startsWith("shlink:/")) { @@ -93,7 +93,7 @@ public class SHLParser extends ParserBase { } if (src != null) { byte[] cntin = Base64.getUrlDecoder().decode(src); - NamedElement json = addNamedElement(res, "json", "json", cntin); + ValidatedFragment json = addNamedElement(res, "json", "json", cntin); JsonObject j = null; try { j = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(cntin); @@ -145,8 +145,8 @@ public class SHLParser extends ParserBase { } - private void checkManifest(List res, HTTPResult cnt) throws IOException { - NamedElement manifest = addNamedElement(res, "manifest", "json", cnt.getContent()); + private void checkManifest(List res, HTTPResult cnt) throws IOException { + ValidatedFragment manifest = addNamedElement(res, "manifest", "json", cnt.getContent()); if (!cnt.getContentType().equals("application/json")) { logError(manifest.getErrors(), "202-08-31", 1, 1, "manifest", IssueType.STRUCTURE, "The mime type should be application/json not "+cnt.getContentType(), IssueSeverity.ERROR); @@ -188,7 +188,7 @@ public class SHLParser extends ParserBase { } } - private void processManifestEntry(List res, List errors, JsonObject j, String path, String name) throws FHIRFormatError, DefinitionException, FHIRException, IOException { + private void processManifestEntry(List res, List errors, JsonObject j, String path, String name) throws FHIRFormatError, DefinitionException, FHIRException, IOException { for (JsonProperty p : j.getProperties()) { if (!Utilities.existsInList(p.getName(), "contentType", "location", "embedded")) { logError(errors, "202-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "manifest."+p.getName(), @@ -242,8 +242,8 @@ public class SHLParser extends ParserBase { } } - private void processContent(List res, List errors, String path, String name, String jose, String ct) throws FHIRFormatError, DefinitionException, FHIRException, IOException { - NamedElement bin = addNamedElement(res, "encrypted", "jose", TextFile.stringToBytes(jose, false)); + private void processContent(List res, List errors, String path, String name, String jose, String ct) throws FHIRFormatError, DefinitionException, FHIRException, IOException { + ValidatedFragment bin = addNamedElement(res, "encrypted", "jose", TextFile.stringToBytes(jose, false)); byte[] cnt = null; JWEObject jwe; try { @@ -261,7 +261,7 @@ public class SHLParser extends ParserBase { res.addAll(shc.parse(new ByteArrayInputStream(cnt))); break; case "application/fhir+json": - NamedElement doc = addNamedElement(res, name, "json", cnt); + ValidatedFragment doc = addNamedElement(res, name, "json", cnt); // a JSON file containing any FHIR resource (e.g., an individual resource or a Bundle of resources). Generally this format may not be tamper-proof. logError(doc.getErrors(), "202-08-31", 1, 1, name, IssueType.STRUCTURE, "Processing content of type 'application/smart-api-access' is not done yet", IssueSeverity.INFORMATION); break; @@ -279,8 +279,8 @@ public class SHLParser extends ParserBase { } } - private NamedElement addNamedElement(List res, String name, String type, byte[] content) { - NamedElement result = new NamedElement(name, type, content); + private ValidatedFragment addNamedElement(List res, String name, String type, byte[] content) { + ValidatedFragment result = new ValidatedFragment(name, type, content); res.add(result); return result; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/TurtleParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/TurtleParser.java index 35e3c223f..54c7a4f19 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/TurtleParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/TurtleParser.java @@ -45,7 +45,6 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.StructureDefinition; @@ -81,9 +80,9 @@ public class TurtleParser extends ParserBase { super(context); } @Override - public List parse(InputStream inStream) throws IOException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRException { byte[] content = TextFile.streamToBytes(inStream); - NamedElement ctxt = new NamedElement("focus", "ttl", content); + ValidatedFragment ctxt = new ValidatedFragment("focus", "ttl", content); ByteArrayInputStream stream = new ByteArrayInputStream(content); Turtle src = new Turtle(); @@ -99,7 +98,7 @@ public class TurtleParser extends ParserBase { src.parse(TextFile.streamToString(stream)); ctxt.setElement(parse(ctxt.getErrors(), src)); } - List res = new ArrayList<>(); + List res = new ArrayList<>(); res.add(ctxt); return res; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ValidatedFragment.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ValidatedFragment.java new file mode 100644 index 000000000..63a78970f --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ValidatedFragment.java @@ -0,0 +1,54 @@ +package org.hl7.fhir.r5.elementmodel; + +import java.util.ArrayList; +import java.util.List; + +import org.hl7.fhir.utilities.validation.ValidationMessage; + +public class ValidatedFragment { + private String name; + private String extension; + private Element element; + private byte[] content; + private List errors = new ArrayList<>(); + + public ValidatedFragment(String name, String extension, Element element, byte[] content) { + super(); + this.name = name; + this.element = element; + this.content = content; + this.extension = extension; + } + + public ValidatedFragment(String name, String extension, byte[] content) { + super(); + this.name = name; + this.content = content; + this.extension = extension; + } + + public String getName() { + return name; + } + + public Element getElement() { + return element; + } + + public byte[] getContent() { + return content; + } + + public List getErrors() { + return errors; + } + + public void setElement(Element element) { + this.element = element; + } + + public String getFilename() { + return name+"."+extension; + } + +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/VerticalBarParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/VerticalBarParser.java index efd1022ab..53e96eea7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/VerticalBarParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/VerticalBarParser.java @@ -454,7 +454,7 @@ public class VerticalBarParser extends ParserBase { private Delimiters delimiters = new Delimiters(); @Override - public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { + public List parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/v2/StructureDefinition/Message"); Element message = new Element("Message", new Property(context, sd.getSnapshot().getElementFirstRep(), sd)); byte[] content = TextFile.streamToBytes(inStream); @@ -464,8 +464,8 @@ public class VerticalBarParser extends ParserBase { preDecode(reader); while (!reader.isFinished()) // && (getOptions().getSegmentLimit() == 0 || getOptions().getSegmentLimit() > message.getSegments().size())) readSegment(message, reader); - List res = new ArrayList<>(); - res.add(new NamedElement("focus", "hl7", message, content)); + List res = new ArrayList<>(); + res.add(new ValidatedFragment("focus", "hl7", message, content)); return res; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java index e077f9256..415cec75d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java @@ -111,10 +111,10 @@ public class XmlParser extends ParserBase { this.allowXsiLocation = allowXsiLocation; } - public List parse(InputStream inStream) throws FHIRFormatError, DefinitionException, FHIRException, IOException { + public List parse(InputStream inStream) throws FHIRFormatError, DefinitionException, FHIRException, IOException { byte[] content = TextFile.streamToBytes(inStream); - NamedElement context = new NamedElement("focus", "xml", content); + ValidatedFragment context = new ValidatedFragment("focus", "xml", content); ByteArrayInputStream stream = new ByteArrayInputStream(content); Document doc = null; @@ -177,7 +177,7 @@ public class XmlParser extends ParserBase { if (doc != null) { context.setElement(parse(context.getErrors(), doc)); } - List res = new ArrayList<>(); + List res = new ArrayList<>(); res.add(context); return res; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/profilemodel/PEBuilder.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/profilemodel/PEBuilder.java index 16317f63b..a75050191 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/profilemodel/PEBuilder.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/profilemodel/PEBuilder.java @@ -323,7 +323,7 @@ public class PEBuilder { if (passElementPropsCheck(defn) && !Utilities.existsInList(defn.getName(), omitList)) { PEDefinitionElement pe = new PEDefinitionElement(this, profile, defn, parent.path()); pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension"))); - if (cu.isPrimitiveDatatype(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) { + if (context.isPrimitiveType(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) { pe.setMustHaveValue(definition.getMustHaveValue()); } pe.setInFixedValue(definition.hasFixed() || definition.hasPattern() || parent.isInFixedValue()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index fccc14e21..b6ef03dcb 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -801,7 +801,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } } else if (hasDef && element.getType().get(0).getWorkingCode() != null && element.getType().get(0).getWorkingCode().startsWith("@")) { row.setIcon("icon_reuse.png", HierarchicalTableGenerator.TEXT_ICON_REUSE); - } else if (hasDef && isPrimitive(element.getType().get(0).getWorkingCode())) { + } else if (hasDef && context.getContext().isPrimitiveType(element.getType().get(0).getWorkingCode())) { if (keyRows.contains(element.getId())) { row.setIcon("icon-key.png", HierarchicalTableGenerator.TEXT_ICON_KEY); } else { @@ -809,7 +809,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } } else if (hasDef && element.getType().get(0).hasTarget()) { row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE); - } else if (hasDef && isDataType(element.getType().get(0).getWorkingCode())) { + } else if (hasDef && context.getContext().isDataType(element.getType().get(0).getWorkingCode())) { row.setIcon("icon_datatype.gif", HierarchicalTableGenerator.TEXT_ICON_DATATYPE); } else if (hasDef && element.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) { row.setIcon("icon-object-box.png", HierarchicalTableGenerator.TEXT_ICON_OBJECT_BOX); @@ -2122,7 +2122,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (!pattern) { c.addPiece(gen.new Piece(null, "0..0", null)); row.setIcon("icon_fixed.gif", "Fixed Value" /*HierarchicalTableGenerator.TEXT_ICON_FIXED*/); - } else if (isPrimitive(t.getTypeCode())) { + } else if (context.getContext().isPrimitiveType(t.getTypeCode())) { row.setIcon("icon_primitive.png", HierarchicalTableGenerator.TEXT_ICON_PRIMITIVE); c.addPiece(gen.new Piece(null, "0.."+(t.getMaxCardinality() == 2147483647 ? "*": Integer.toString(t.getMaxCardinality())), null)); } else if (isReference(t.getTypeCode())) { @@ -2450,28 +2450,6 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return path; } - - - - - protected boolean isPrimitive(String value) { - StructureDefinition sd = context.getWorker().fetchTypeDefinition(value); - if (sd == null) // might be running before all SDs are available - return Utilities.existsInList(value, "base64Binary", "boolean", "canonical", "code", "date", "dateTime", "decimal", "id", "instant", "integer", "integer64", "markdown", "oid", "positiveInt", "string", "time", "unsignedInt", "uri", "url", "uuid"); - else - return sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } - - - private boolean isDataType(String value) { - StructureDefinition sd = context.getWorker().fetchTypeDefinition(value); - if (sd == null) // might be running before all SDs are available - return Utilities.existsInList(value, "Address", "Age", "Annotation", "Attachment", "CodeableConcept", "Coding", "ContactPoint", "Count", "Distance", "Duration", "HumanName", "Identifier", "Money", "Period", "Quantity", "Range", "Ratio", "Reference", "SampledData", "Signature", "Timing", - "ContactDetail", "Contributor", "DataRequirement", "Expression", "ParameterDefinition", "RelatedArtifact", "TriggerDefinition", "UsageContext"); - else - return sd.getKind() == StructureDefinitionKind.COMPLEXTYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION; - } - private boolean slicesExist(List elements, ElementDefinition element) { if (elements == null) { return true; @@ -3827,7 +3805,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { private boolean hasPrimitiveTypes(ElementDefinition d) { for (TypeRefComponent tr : d.getType()) { - if (isPrimitive(tr.getCode())) { + if (context.getContext().isPrimitiveType(tr.getCode())) { return true; } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceLanguageFileBuilder.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceLanguageFileBuilder.java index 27af2116f..9d128fa20 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceLanguageFileBuilder.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceLanguageFileBuilder.java @@ -92,7 +92,7 @@ public class ResourceLanguageFileBuilder { private boolean isTranslatable(Property p, Base b, String id) { - if (new ContextUtilities(context).isPrimitiveDatatype(b.fhirType())) { // never any translations for non-primitives + if (context.isPrimitiveType(b.fhirType())) { // never any translations for non-primitives ElementDefinition ed = null; for (ElementDefinition t : profile.getSnapshot().getElement()) { if (t.getId().equals(id)) { diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTests.java index 0e9f7e991..ebae732ed 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTests.java @@ -19,7 +19,7 @@ public class CanonicalResourceManagerTests { private CanonicalResource resource; public DeferredLoadTestResource(CanonicalResource resource) { - super(resource.fhirType(), resource.getId(), resource.getUrl(), resource.getVersion(), resource instanceof CodeSystem ? ((CodeSystem) resource).getSupplements() : null); + super(resource.fhirType(), resource.getId(), resource.getUrl(), resource.getVersion(), resource instanceof CodeSystem ? ((CodeSystem) resource).getSupplements() : null, null); this.resource = resource; } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java index 3ac2574b3..028a21dac 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java @@ -13,7 +13,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; +import org.hl7.fhir.r5.elementmodel.ValidatedFragment; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.*; @@ -209,7 +209,7 @@ public class FHIRPathTests { if (node != null) { try { if ("element".equals(test.getAttribute("mode"))) { - List e = Manager.parse(fp.getWorker(), TestingUtilities.loadTestResourceStream("r5", input), input.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML); + List e = Manager.parse(fp.getWorker(), TestingUtilities.loadTestResourceStream("r5", input), input.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML); outcome = fp.evaluate(e.get(0).getElement(), node); } else { outcome = fp.evaluate(res, node); diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java index 025777c16..c0bed9a39 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java @@ -113,6 +113,7 @@ public class NpmPackage { private String filename; private String supplements; private String stype; + private String derivation; public PackageResourceInformation(String root, JsonObject fi) throws IOException { super(); @@ -123,6 +124,7 @@ public class NpmPackage { filename = Utilities.path(root, fi.asString("filename")); supplements = fi.asString("supplements"); stype = fi.asString("type"); + derivation = fi.asString("derivation"); } public String getId() { return id; @@ -148,6 +150,9 @@ public class NpmPackage { public boolean hasId() { return !Utilities.noString(id); } + public String getDerivation() { + return derivation; + } } public class IndexVersionSorter implements Comparator { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java index b4473c811..f23dc61f2 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackageIndexBuilder.java @@ -55,9 +55,11 @@ public class NpmPackageIndexBuilder { "Type nvarchar NULL,\r\n"+ "Supplements nvarchar NULL,\r\n"+ "Content nvarchar NULL,\r\n"+ + "ValueSet nvarchar NULL,\r\n"+ + "Derivation nvarchar NULL,\r\n"+ "PRIMARY KEY (FileName))\r\n"); - psql = conn.prepareStatement("Insert into ResourceList (FileName, ResourceType, Id, Url, Version, Kind, Type, Supplements, Content) values (?, ?, ?, ?, ?, ?, ?, ?, ?)"); + psql = conn.prepareStatement("Insert into ResourceList (FileName, ResourceType, Id, Url, Version, Kind, Type, Supplements, Content, ValueSet) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); } catch (Exception e) { conn = null; } @@ -95,6 +97,12 @@ public class NpmPackageIndexBuilder { if (json.hasPrimitive("content")) { fi.add("content", json.asString("content")); } + if (json.hasPrimitive("valueSet")) { + fi.add("valueSet", json.asString("valueSet")); + } + if (json.hasPrimitive("derivation")) { + fi.add("valueSet", json.asString("derivation")); + } if (psql != null) { psql.setString(1, name); // FileName); psql.setString(2, json.asString("resourceType")); // ResourceType"); @@ -105,6 +113,8 @@ public class NpmPackageIndexBuilder { psql.setString(7, json.asString("type")); // Type"); psql.setString(8, json.asString("supplements")); // Supplements"); psql.setString(9, json.asString("content")); // Content"); + psql.setString(10, json.asString("valueSet")); // ValueSet"); + psql.setString(10, json.asString("derivation")); // ValueSet"); psql.execute(); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 7412c7263..dd4fb3960 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -77,9 +77,9 @@ import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.ObjectConverter; import org.hl7.fhir.r5.elementmodel.ParserBase; -import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement; import org.hl7.fhir.r5.elementmodel.ParserBase.ValidationPolicy; import org.hl7.fhir.r5.elementmodel.ResourceParser; +import org.hl7.fhir.r5.elementmodel.ValidatedFragment; import org.hl7.fhir.r5.elementmodel.XmlParser; import org.hl7.fhir.r5.formats.FormatUtilities; import org.hl7.fhir.r5.model.Address; @@ -517,7 +517,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private Map crLookups = new HashMap<>(); private boolean logProgress; private CodingsObserver codingObserver; - public List validatedContent; + public List validatedContent; public boolean testMode; public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) { @@ -747,7 +747,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (validatedContent != null && !validatedContent.isEmpty()) { if (SAVE_INTERMEDIARIES) { int index = 0; - for (NamedElement ne : validatedContent) { + for (ValidatedFragment ne : validatedContent) { index++; saveValidatedContent(ne, index); } @@ -761,7 +761,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat profiles.add(sd); } } - for (NamedElement ne : validatedContent) { + for (ValidatedFragment ne : validatedContent) { if (ne.getElement() != null) { validate(appContext, ne.getErrors(), validatedContent.size() > 1 ? ne.getName() : null, ne.getElement(), profiles); } @@ -771,7 +771,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return (validatedContent == null || validatedContent.isEmpty()) ? null : validatedContent.get(0).getElement(); // todo: this is broken, but fixing it really complicates things elsewhere, so we do this for now } - private void saveValidatedContent(NamedElement ne, int index) { + private void saveValidatedContent(ValidatedFragment ne, int index) { String tgt = null; try { tgt = Utilities.path("[tmp]", "validator", "content"); @@ -4309,8 +4309,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } public boolean isPrimitiveType(String code) { - StructureDefinition sd = context.fetchTypeDefinition(code); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; + return context.isPrimitiveType(code); } private String getErrorMessage(String message) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java index bc882ab58..ea62e7c5e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java @@ -481,7 +481,7 @@ public class StructureDefinitionValidator extends BaseValidator { if (v != null) { ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes) && ok; hint(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "fixed"); - if (isPrimitiveType(v.fhirType())) { + if (context.isPrimitiveType(v.fhirType())) { warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "fixed"); } else { warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), false, I18nConstants.SD_VALUE_COMPLEX_FIXED, v.fhirType()); @@ -491,7 +491,7 @@ public class StructureDefinitionValidator extends BaseValidator { if (v != null) { ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes) && ok; hint(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "pattern"); - if (isPrimitiveType(v.fhirType())) { + if (context.isPrimitiveType(v.fhirType())) { warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "pattern"); } } @@ -737,10 +737,6 @@ public class StructureDefinitionValidator extends BaseValidator { return true; } - private boolean isPrimitiveType(String fhirType) { - StructureDefinition sd = context.fetchTypeDefinition(fhirType); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } private String boundType(Set typeCodes) { for (String tc : typeCodes) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/NodeStack.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/NodeStack.java index 32df6e98d..ee3cc6617 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/NodeStack.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/NodeStack.java @@ -119,7 +119,7 @@ public class NodeStack { if (en.endsWith("[x]")) { en = en.substring(0, en.length() - 3); String t = n.substring(en.length()); - if (isPrimitiveType(Utilities.uncapitalize(t))) + if (context.isPrimitiveType(Utilities.uncapitalize(t))) t = Utilities.uncapitalize(t); res.literalPath = res.literalPath.substring(0, res.literalPath.lastIndexOf(".")) + "." + en + ".ofType(" + t + ")"; } else { @@ -194,10 +194,6 @@ public class NodeStack { return path.substring(path.lastIndexOf(".") + 1); } - public boolean isPrimitiveType(String code) { - StructureDefinition sd = context.fetchTypeDefinition(code); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } public String getWorkingLang() { return workingLang;