mirror of
https://github.com/hapifhir/org.hl7.fhir.core.git
synced 2025-02-08 05:48:12 +00:00
Merge pull request #1850 from hapifhir/2024-12-gg-many-fixes
2024 12 gg many fixes
This commit is contained in:
commit
17dfc5c285
@ -1,5 +1,8 @@
|
||||
## Validator Changes
|
||||
|
||||
* Add support for valueset-version
|
||||
* Add support for terminology extraction
|
||||
* Add support for expansion parameters when validating
|
||||
* fix NPE in validator around Extension context
|
||||
* Handle secondary terminology server errors properly
|
||||
* Fix questionnaire response status checking
|
||||
@ -7,6 +10,12 @@
|
||||
* hide API-Key from appearing on the tx log
|
||||
* Add supplements for used systems as well as for value set systems when validating on server
|
||||
* fix missing port from server when doing tx-registry redirections
|
||||
* Fix problem not finding current version of extensions pack for non-R5 versions
|
||||
* Fix validation of displays when language is unknown
|
||||
* fix issue missing idrefs validating IPS documents
|
||||
* Update FHIRPath validation to handle rootResource type properly
|
||||
* Fix obscure error on contentReference in profiles in FHIRPath engine
|
||||
* Fix version conversion issue for validating derived questionnaires
|
||||
|
||||
## Other code changes
|
||||
|
||||
@ -25,3 +34,9 @@
|
||||
* Fix version issues in snapshot generation tests
|
||||
* Eliminate id from snapshot generation test case comparison
|
||||
* Change rules around stripping extensions when generating snapshots
|
||||
* fix bug using wrong reference on uri in liquid renderer
|
||||
* add translations for expansion errors
|
||||
* fix issue with comparison template missing
|
||||
* Apply null pointer check to all switch(Enumeration) statements in version conversion code
|
||||
* Remove mysql dependency
|
||||
* Fix bug in DecimalType on null Bigdecimal ()] all versions)
|
@ -1,6 +1,7 @@
|
||||
package org.hl7.fhir.convertors;
|
||||
|
||||
import org.hl7.fhir.r5.renderers.QuestionnaireRenderer;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
@ -43,7 +44,7 @@ public class VersionConvertorConstants {
|
||||
public final static String IG_CONFORMANCE_MESSAGE_EVENT = "http://hl7.org/fhir/1.0/StructureDefinition/extension-Conformance.messaging.event";
|
||||
public static final String EXT_OLD_CONCEPTMAP_EQUIVALENCE = "http://hl7.org/fhir/1.0/StructureDefinition/extension-ConceptMap.element.target.equivalence";
|
||||
public static final String EXT_ACTUAL_RESOURCE_NAME = "http://hl7.org/fhir/tools/StructureDefinition/original-resource-name";
|
||||
public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = QuestionnaireRenderer.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL;
|
||||
public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL;
|
||||
public static final String EXT_NAMINGSYSTEM_TITLE = "http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.title";
|
||||
public static final String EXT_NAMINGSYSTEM_URL = "http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.url";
|
||||
public static final String EXT_NAMINGSYSTEM_VERSION = "http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.version";
|
||||
|
@ -187,6 +187,13 @@ public class FHIRPathEngine {
|
||||
// the application can implement them by providing a constant resolver
|
||||
public interface IEvaluationContext {
|
||||
|
||||
public abstract class FunctionDefinition {
|
||||
public abstract String name();
|
||||
public abstract FunctionDetails details();
|
||||
public abstract TypeDetails check(FHIRPathEngine engine, Object appContext, TypeDetails focus, List<TypeDetails> parameters);
|
||||
public abstract List<Base> execute(FHIRPathEngine engine, Object appContext, List<Base> focus, List<List<Base>> parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* A constant reference - e.g. a reference to a name that must be resolved in context.
|
||||
* The % will be removed from the constant name before this is invoked.
|
||||
@ -476,8 +483,8 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, resourceType, context, expr, null);
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, rootResourceType, resourceType, context, expr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -492,7 +499,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types;
|
||||
@ -533,7 +540,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -548,7 +555,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, List<String> typeList, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, List<String> typeList, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
@ -598,14 +605,21 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings, boolean canBeNone) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, canBeNone, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
@ -621,7 +635,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, List<String> resourceTypes, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, List<String> resourceTypes, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types = null;
|
||||
@ -633,7 +647,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
}
|
||||
|
||||
private FHIRException makeExceptionPlural(Integer num, ExpressionNode holder, String constName, Object... args) {
|
||||
@ -660,7 +674,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, StructureDefinition sd, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, StructureDefinition sd, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types;
|
||||
if (!context.contains(".")) {
|
||||
@ -686,17 +700,17 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, sd.getUrl(), types, types), types, expr, null, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, sd.getUrl(), types, types), types, expr, null, true, false, expr);
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, StructureDefinition sd, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, StructureDefinition sd, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types = null; // this is a special case; the first path reference will have to resolve to something in the context
|
||||
return executeType(new ExecutionTypeContext(appContext, sd == null ? null : sd.getUrl(), null, types), types, expr, null, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, sd == null ? null : sd.getUrl(), null, types), types, expr, null, true, false, expr);
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, String expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, resourceType, context, parse(expr));
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, String expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, rootResourceType, resourceType, context, parse(expr));
|
||||
}
|
||||
|
||||
private Integer compareDateTimeElements(Base theL, Base theR, boolean theEquivalenceTest) {
|
||||
@ -1093,10 +1107,12 @@ public class FHIRPathEngine {
|
||||
private TypeDetails thisItem;
|
||||
private TypeDetails total;
|
||||
private Map<String, TypeDetails> definedVariables;
|
||||
private String rootResource;
|
||||
|
||||
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
public ExecutionTypeContext(Object appInfo, String rootResource, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
super();
|
||||
this.appInfo = appInfo;
|
||||
this.rootResource = rootResource;
|
||||
this.resource = resource;
|
||||
this.context = context;
|
||||
this.thisItem = thisItem;
|
||||
@ -3208,10 +3224,10 @@ public class FHIRPathEngine {
|
||||
}
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
|
||||
} else if (s.equals("%rootResource")) {
|
||||
if (context.resource == null) {
|
||||
if (context.rootResource == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus rootResource");
|
||||
}
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.rootResource);
|
||||
} else if (s.equals("%context")) {
|
||||
return context.context;
|
||||
} else if (s.equals("%map-codes")) {
|
||||
@ -3847,6 +3863,18 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private boolean typeCastIsImpossible(TypeDetails focus, String tn) {
|
||||
for (ProfiledType pt : focus.getProfiledTypes()) {
|
||||
if (!pt.hasProfiles()) { // get back to this later
|
||||
String purl = tn;
|
||||
while (purl != null && !purl.equals(pt.getUri())) {
|
||||
StructureDefinition sd = worker.fetchResource(StructureDefinition.class, purl);
|
||||
purl = sd == null ? null : sd.getBaseDefinition();
|
||||
}
|
||||
if (purl != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !focus.hasType(tn);
|
||||
}
|
||||
|
||||
@ -4790,7 +4818,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.rootResource, context.resource, context.context, newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
@ -4801,7 +4829,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.rootResource, context.resource, context.context, context.thisItem);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
@ -6298,6 +6326,12 @@ public class FHIRPathEngine {
|
||||
if (ed.getPath().startsWith(path)) {
|
||||
if (ed.hasContentReference()) {
|
||||
String cpath = ed.getContentReference();
|
||||
if (!cpath.startsWith("#")) {
|
||||
if (!cpath.contains("#")) {
|
||||
throw new Error("ContentReference doesn't contain a #: "+cpath);
|
||||
}
|
||||
cpath = cpath.substring(cpath.indexOf("#"));
|
||||
}
|
||||
String tn = sdi.getType()+cpath;
|
||||
if (!result.hasType(worker, tn)) {
|
||||
if (elementDependencies != null) {
|
||||
@ -6513,15 +6547,15 @@ public class FHIRPathEngine {
|
||||
}
|
||||
if (ed.hasContentReference() && path.startsWith(ed.getPath()+".")) {
|
||||
ElementDefinitionMatch m = getElementDefinitionById(sd, ed.getContentReference());
|
||||
List<ElementDefinitionMatch> res = getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
|
||||
if (res.size() == 0) {
|
||||
throw new Error("Unable to find "+ed.getContentReference());
|
||||
if (m == null) {
|
||||
throw new Error("Unable to find path "+path+" with a content reference of "+ed.getContentReference());
|
||||
} else {
|
||||
List<ElementDefinitionMatch> res = getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
|
||||
for (ElementDefinitionMatch item : res) {
|
||||
item.sourceDefinition = ed;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return ml(null);
|
||||
@ -6563,8 +6597,13 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private ElementDefinitionMatch getElementDefinitionById(StructureDefinition sd, String ref) {
|
||||
if (ref.startsWith(sd.getUrl()+"#")) {
|
||||
ref = ref.replace(sd.getUrl()+"#", "#");
|
||||
StructureDefinition sdt = sd;
|
||||
while (sdt != null) {
|
||||
if (ref.startsWith(sdt.getUrl()+"#")) {
|
||||
ref = ref.replace(sdt.getUrl()+"#", "#");
|
||||
break;
|
||||
}
|
||||
sdt = worker.fetchResource(StructureDefinition.class, sdt.getBaseDefinition());
|
||||
}
|
||||
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
|
||||
if (ref.equals("#"+ed.getId())) {
|
||||
|
@ -2904,7 +2904,7 @@ public class StructureMapUtilities {
|
||||
expr = fpe.parse(getParamString(vars, tgt.getParameter().get(tgt.getParameter().size() - 1)));
|
||||
tgt.setUserData(MAP_WHERE_EXPRESSION, expr);
|
||||
}
|
||||
return fpe.check(vars, null, expr);
|
||||
return fpe.check(vars, "Resource", null, expr);
|
||||
|
||||
////case TRUNCATE :
|
||||
//// String src = getParamString(vars, tgt.getParameter().get(0));
|
||||
|
@ -289,7 +289,7 @@ public class Validator {
|
||||
try {
|
||||
node = fpe.parse(expr);
|
||||
column.setUserData("path", node);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, node, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, node, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -471,7 +471,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
focus.setUserData("forEach", n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -496,7 +496,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
focus.setUserData("forEachOrNull", n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -607,7 +607,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
where.setUserData("path", n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, types, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, types, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, where.get("path"), e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
|
@ -224,9 +224,9 @@ public class FHIRPathTests {
|
||||
|
||||
try {
|
||||
if (Utilities.noString(input)) {
|
||||
fp.check(null, null, node);
|
||||
fp.check(null, null, null, node);
|
||||
} else {
|
||||
fp.check(res, res.getResourceType().toString(), res.getResourceType().toString(), node);
|
||||
fp.check(res, "Resource", res.getResourceType().toString(), res.getResourceType().toString(), node);
|
||||
}
|
||||
Assertions.assertTrue(fail != TestResultType.SEMANTICS,
|
||||
String.format("Expected exception didn't occur checking %s", expression));
|
||||
|
@ -363,4 +363,19 @@ public class ComparisonRenderer implements IEvaluationContext {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void loadTemplates(IWorkerContext context) {
|
||||
getTemplates().put("CapabilityStatement", new String(context.getBinaryForKey("template-comparison-CapabilityStatement.html")));
|
||||
getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html")));
|
||||
getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html")));
|
||||
getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html")));
|
||||
getTemplates().put("Index", new String(context.getBinaryForKey("template-comparison-index.html")));
|
||||
getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html")));
|
||||
getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html")));
|
||||
getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html")));
|
||||
getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html")));
|
||||
getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html")));
|
||||
getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html")));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.r5.model.NamingSystem.NamingSystemIdentifierType;
|
||||
import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
||||
import org.hl7.fhir.r5.model.StructureMap;
|
||||
@ -30,6 +31,7 @@ import org.hl7.fhir.r5.utils.UserDataNames;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.model.Identifier;
|
||||
import org.hl7.fhir.r5.model.NamingSystem;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.OIDUtils;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
@ -479,5 +481,24 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String pinValueSet(String valueSet) {
|
||||
return pinValueSet(valueSet, context.getExpansionParameters());
|
||||
}
|
||||
|
||||
public String pinValueSet(String value, Parameters expParams) {
|
||||
if (value.contains("|")) {
|
||||
return value;
|
||||
}
|
||||
for (ParametersParameterComponent p : expParams.getParameter()) {
|
||||
if ("valueset-version".equals(p.getName())) {
|
||||
String s = p.getValue().primitiveValue();
|
||||
if (s.startsWith(value+"|")) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,14 @@ public class Manager {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FhirFormat fromCode(String code) {
|
||||
FhirFormat fmt = getFhirFormat(code);
|
||||
if (fmt == null) {
|
||||
fmt = readFromMimeType(code);
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ValidatedFragment> parse(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException {
|
||||
|
@ -485,8 +485,8 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, resourceType, context, expr, null);
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, rootResourceType, resourceType, context, expr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,7 +501,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types;
|
||||
@ -542,7 +542,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -557,7 +557,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, List<String> typeList, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, List<String> typeList, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
@ -607,21 +607,21 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings, boolean canBeNone) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String rootResourceType, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings, boolean canBeNone) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, canBeNone, expr);
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, null, true, canBeNone, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
@ -637,7 +637,7 @@ public class FHIRPathEngine {
|
||||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails check(Object appContext, String resourceType, List<String> resourceTypes, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, List<String> resourceTypes, ExpressionNode expr, Set<ElementDefinition> elementDependencies) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types = null;
|
||||
@ -649,7 +649,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, resourceType, types, types), types, expr, elementDependencies, true, false, expr);
|
||||
}
|
||||
|
||||
private FHIRException makeExceptionPlural(Integer num, ExpressionNode holder, String constName, Object... args) {
|
||||
@ -676,7 +676,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, StructureDefinition sd, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, StructureDefinition sd, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types;
|
||||
if (!context.contains(".")) {
|
||||
@ -702,17 +702,17 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
return executeType(new ExecutionTypeContext(appContext, sd.getUrl(), types, types), types, expr, null, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, sd.getUrl(), types, types), types, expr, null, true, false, expr);
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, StructureDefinition sd, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails check(Object appContext, String rootResourceType, StructureDefinition sd, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
TypeDetails types = null; // this is a special case; the first path reference will have to resolve to something in the context
|
||||
return executeType(new ExecutionTypeContext(appContext, sd == null ? null : sd.getUrl(), null, types), types, expr, null, true, false, expr);
|
||||
return executeType(new ExecutionTypeContext(appContext, rootResourceType, sd == null ? null : sd.getUrl(), null, types), types, expr, null, true, false, expr);
|
||||
}
|
||||
|
||||
public TypeDetails check(Object appContext, String resourceType, String context, String expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, resourceType, context, parse(expr));
|
||||
public TypeDetails check(Object appContext, String rootResourceType, String resourceType, String context, String expr) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
return check(appContext, rootResourceType, resourceType, context, parse(expr));
|
||||
}
|
||||
|
||||
private Integer compareDateTimeElements(Base theL, Base theR, boolean theEquivalenceTest) {
|
||||
@ -1109,10 +1109,12 @@ public class FHIRPathEngine {
|
||||
private TypeDetails thisItem;
|
||||
private TypeDetails total;
|
||||
private Map<String, TypeDetails> definedVariables;
|
||||
private String rootResource;
|
||||
|
||||
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
public ExecutionTypeContext(Object appInfo, String rootResource, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
super();
|
||||
this.appInfo = appInfo;
|
||||
this.rootResource = rootResource;
|
||||
this.resource = resource;
|
||||
this.context = context;
|
||||
this.thisItem = thisItem;
|
||||
@ -3224,10 +3226,10 @@ public class FHIRPathEngine {
|
||||
}
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
|
||||
} else if (s.equals("%rootResource")) {
|
||||
if (context.resource == null) {
|
||||
if (context.rootResource == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus rootResource");
|
||||
}
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, context.rootResource);
|
||||
} else if (s.equals("%context")) {
|
||||
return context.context;
|
||||
} else if (s.equals("%map-codes")) {
|
||||
@ -3863,6 +3865,18 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private boolean typeCastIsImpossible(TypeDetails focus, String tn) {
|
||||
for (ProfiledType pt : focus.getProfiledTypes()) {
|
||||
if (!pt.hasProfiles()) { // get back to this later
|
||||
String purl = tn;
|
||||
while (purl != null && !purl.equals(pt.getUri())) {
|
||||
StructureDefinition sd = worker.fetchResource(StructureDefinition.class, purl);
|
||||
purl = sd == null ? null : sd.getBaseDefinition();
|
||||
}
|
||||
if (purl != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !focus.hasType(tn);
|
||||
}
|
||||
|
||||
@ -4806,7 +4820,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.rootResource, context.resource, context.context, newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
@ -4817,7 +4831,7 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.rootResource, context.resource, context.context, context.thisItem);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
@ -6314,6 +6328,12 @@ public class FHIRPathEngine {
|
||||
if (ed.getPath().startsWith(path)) {
|
||||
if (ed.hasContentReference()) {
|
||||
String cpath = ed.getContentReference();
|
||||
if (!cpath.startsWith("#")) {
|
||||
if (!cpath.contains("#")) {
|
||||
throw new Error("ContentReference doesn't contain a #: "+cpath);
|
||||
}
|
||||
cpath = cpath.substring(cpath.indexOf("#"));
|
||||
}
|
||||
String tn = sdi.getType()+cpath;
|
||||
if (!result.hasType(worker, tn)) {
|
||||
if (elementDependencies != null) {
|
||||
|
@ -0,0 +1,64 @@
|
||||
package org.hl7.fhir.r5.profilemodel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ResourceFactory;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TestInstanceGenerator {
|
||||
|
||||
private IWorkerContext context;
|
||||
private Map<String, String> data;
|
||||
|
||||
protected TestInstanceGenerator(IWorkerContext context) {
|
||||
super();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Resource generate(StructureDefinition profile) {
|
||||
PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.NONE, true);
|
||||
PEDefinition definition = builder.buildPEDefinition(profile);
|
||||
Resource res = ResourceFactory.createResource(definition.types().get(0).getType());
|
||||
populateByProfile(res, definition);
|
||||
|
||||
res.getMeta().addProfile(definition.profile.getVersionedUrl());
|
||||
return res;
|
||||
}
|
||||
|
||||
protected void populateByProfile(Base base, PEDefinition definition) {
|
||||
if (definition.types().size() == 1) {
|
||||
for (PEDefinition pe : definition.directChildren(true)) {
|
||||
if (pe.hasFixedValue()) {
|
||||
if (pe.definition().hasPattern()) {
|
||||
base.setProperty(pe.schemaName(), pe.definition().getPattern());
|
||||
} else {
|
||||
base.setProperty(pe.schemaName(), pe.definition().getFixed());
|
||||
}
|
||||
} else if (!pe.isSlicer() && pe.max() == 1) {
|
||||
for (int i = 0; i < pe.min(); i++) {
|
||||
Base b = null;
|
||||
if (pe.schemaName().endsWith("[x]")) {
|
||||
if (pe.types().size() == 1) {
|
||||
b = base.addChild(pe.schemaName().replace("[x]", Utilities.capitalize(pe.types().get(0).getType())));
|
||||
}
|
||||
} else if (!pe.isBaseList()) {
|
||||
b = base.makeProperty(pe.schemaName().hashCode(), pe.schemaName());
|
||||
} else {
|
||||
b = base.addChild(pe.schemaName());
|
||||
}
|
||||
if (b != null) {
|
||||
populateByProfile(b, pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -41,7 +41,6 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||
import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||
|
@ -3,14 +3,12 @@ package org.hl7.fhir.r5.renderers;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
@ -20,7 +18,6 @@ import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.SourcedElementDefinition;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.NamedResourceWrapperList;
|
||||
|
@ -33,7 +33,6 @@ import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class QuestionnaireRenderer extends TerminologyRenderer {
|
||||
public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = "http://hl7.org/fhir/4.0/StructureDefinition/extension-questionnaire.item.type";
|
||||
|
||||
public QuestionnaireRenderer(RenderingContext context) {
|
||||
super(context);
|
||||
@ -289,9 +288,9 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
||||
String txt = (i.has("prefix") ? i.primitiveValue("prefix") + ". " : "") + i.primitiveValue("text");
|
||||
r.getCells().add(gen.new Cell(null, null, txt, null, null));
|
||||
r.getCells().add(gen.new Cell(null, null, ("true".equals(i.primitiveValue("required")) ? "1" : "0")+".."+("true".equals(i.primitiveValue("repeats")) ? "*" : "1"), null, null));
|
||||
if (i.child("type").hasExtension(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) {
|
||||
if (i.child("type").hasExtension(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) {
|
||||
status.setExtensions(true);
|
||||
String t = i.child("type").extensionString(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL);
|
||||
String t = i.child("type").extensionString(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL);
|
||||
r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+t, t, null, null));
|
||||
} else {
|
||||
r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+type, type, null, null));
|
||||
|
@ -26,7 +26,6 @@ import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceReferenceKind;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
|
||||
@ -603,6 +602,10 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||
if (v.startsWith("mailto:")) {
|
||||
x.ah(v).addText(v.substring(7));
|
||||
} else {
|
||||
String link = getLinkForCode(v, null, null);
|
||||
if (link != null) {
|
||||
x.ah(context.prefixLocalHref(link)).addText(v);
|
||||
} else {
|
||||
ResourceWithReference rr = local ? resolveReference(uri.resource(), v, true) : resolveReference(uri);
|
||||
if (rr != null) {
|
||||
if (rr.getResource() == null) {
|
||||
@ -628,6 +631,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,10 @@ import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.LanguageUtils;
|
||||
import org.hl7.fhir.r5.extensions.ExtensionConstants;
|
||||
import org.hl7.fhir.r5.extensions.Extensions;
|
||||
import org.hl7.fhir.r5.extensions.ExtensionsUtils;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||
@ -93,6 +92,7 @@ import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.DecimalType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.Factory;
|
||||
@ -103,7 +103,6 @@ import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||
@ -117,7 +116,6 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpander.Token;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext;
|
||||
@ -132,7 +130,6 @@ import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.AcceptLanguageHeader;
|
||||
import org.hl7.fhir.utilities.i18n.AcceptLanguageHeader.LanguagePreference;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
|
||||
public class ValueSetExpander extends ValueSetProcessBase {
|
||||
|
||||
@ -160,6 +157,8 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
}
|
||||
|
||||
private static final boolean REPORT_VERSION_ANYWAY = true;
|
||||
|
||||
private static final String VS_EXP_IMPORT_ERROR_TOO_COSTLY = null;
|
||||
|
||||
private ValueSet focus;
|
||||
private List<String> allErrors = new ArrayList<>();
|
||||
@ -864,13 +863,16 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
|
||||
private ValueSet importValueSet(WorkingContext wc, String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
|
||||
if (value == null)
|
||||
throw fail("unable to find value set with no identity");
|
||||
ValueSet vs = context.findTxResource(ValueSet.class, value, valueSet);
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_NULL, true);
|
||||
String url = getCu().pinValueSet(value, expParams);
|
||||
ValueSet vs = context.findTxResource(ValueSet.class, url, valueSet);
|
||||
if (vs == null) {
|
||||
if (context.fetchResource(CodeSystem.class, value, valueSet) != null) {
|
||||
throw fail("Cannot include value set "+value+" because it's actually a code system");
|
||||
} else {
|
||||
throw fail("Unable to find imported value set " + value);
|
||||
boolean pinned = !url.equals(value);
|
||||
String ver = pinned ? url.substring(value.length()+1) : null;
|
||||
if (context.fetchResource(CodeSystem.class, url, valueSet) != null) {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_CS_PINNED : I18nConstants.VS_EXP_IMPORT_CS, true, value, ver);
|
||||
} else {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_UNK_PINNED : I18nConstants.VS_EXP_IMPORT_UNK, true, value, ver);
|
||||
}
|
||||
}
|
||||
checkCanonical(exp, vs, focus);
|
||||
@ -881,9 +883,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpander(context, opContext.copy(), allErrors).expand(vs, expParams);
|
||||
if (vso.getError() != null) {
|
||||
addErrors(vso.getAllErrors());
|
||||
throw fail("Unable to expand imported value set "+vs.getUrl()+": " + vso.getError());
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR, true, vs.getUrl(), vso.getError());
|
||||
} else if (vso.getValueset() == null) {
|
||||
throw fail("Unable to expand imported value set "+vs.getUrl()+" but no error");
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_FAIL, true, vs.getUrl());
|
||||
}
|
||||
if (vs.hasVersion() || REPORT_VERSION_ANYWAY) {
|
||||
UriType u = new UriType(vs.getUrl() + (vs.hasVersion() ? "|"+vs.getVersion() : ""));
|
||||
@ -916,15 +918,19 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ValueSet importValueSetForExclude(WorkingContext wc, String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
|
||||
if (value == null)
|
||||
throw fail("unable to find value set with no identity");
|
||||
ValueSet vs = context.findTxResource(ValueSet.class, value, valueSet);
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_NULL_X, true);
|
||||
String url = getCu().pinValueSet(value, expParams);
|
||||
ValueSet vs = context.findTxResource(ValueSet.class, url, valueSet);
|
||||
if (vs == null) {
|
||||
if (context.fetchResource(CodeSystem.class, value, valueSet) != null) {
|
||||
throw fail("Cannot include value set "+value+" because it's actually a code system");
|
||||
} else {
|
||||
throw fail("Unable to find imported value set " + value);
|
||||
boolean pinned = !url.equals(value);
|
||||
String ver = pinned ? url.substring(value.length()+1) : null;
|
||||
if (context.fetchResource(CodeSystem.class, url, valueSet) != null) {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_CS_PINNED_X : I18nConstants.VS_EXP_IMPORT_CS_X, true, value, ver);
|
||||
} else {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_UNK_PINNED_X : I18nConstants.VS_EXP_IMPORT_UNK_X, true, value, ver);
|
||||
}
|
||||
}
|
||||
checkCanonical(exp, vs, focus);
|
||||
@ -935,8 +941,11 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpander(context, opContext.copy(), allErrors).expand(vs, expParams);
|
||||
if (vso.getError() != null) {
|
||||
addErrors(vso.getAllErrors());
|
||||
throw fail("Unable to expand imported value set "+vs.getUrl()+": " + vso.getError());
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR_X, true, vs.getUrl(), vso.getError());
|
||||
} else if (vso.getValueset() == null) {
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_FAIL_X, true, vs.getUrl());
|
||||
}
|
||||
|
||||
if (vs.hasVersion() || REPORT_VERSION_ANYWAY) {
|
||||
UriType u = new UriType(vs.getUrl() + (vs.hasVersion() ? "|"+vs.getVersion() : ""));
|
||||
if (!existsInParams(exp.getParameter(), "used-valueset", u))
|
||||
@ -944,7 +953,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
}
|
||||
for (Extension ex : vso.getValueset().getExpansion().getExtension()) {
|
||||
if (ex.getUrl().equals(ToolingExtensions.EXT_EXP_TOOCOSTLY)) {
|
||||
throw fail("Unable to expand imported value set "+vs.getUrl()+" for exclude: too costly");
|
||||
throw fail(VS_EXP_IMPORT_ERROR_TOO_COSTLY, true, vs.getUrl());
|
||||
}
|
||||
}
|
||||
return vso.getValueset();
|
||||
@ -1252,7 +1261,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw fail("Filter by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
||||
throw fail(I18nConstants.VS_EXP_FILTER_UNK, true, focus.getVersionedUrl(), fc.getProperty(), fc.getOp());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1313,7 +1322,8 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
||||
return key(c.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
private FHIRException fail(String msg) {
|
||||
private FHIRException fail(String msgId, boolean check, Object... params) {
|
||||
String msg = context.formatMessage(msgId, params);
|
||||
allErrors.add(msg);
|
||||
return new FHIRException(msg);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ public class ValidationResult {
|
||||
private boolean inactive;
|
||||
private String status;
|
||||
private String server;
|
||||
private boolean errorIsDisplayIssue;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -110,7 +111,7 @@ public class ValidationResult {
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING;
|
||||
return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING || errorIsDisplayIssue;
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
@ -408,4 +409,15 @@ public class ValidationResult {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isErrorIsDisplayIssue() {
|
||||
return errorIsDisplayIssue;
|
||||
}
|
||||
|
||||
public ValidationResult setErrorIsDisplayIssue(boolean errorIsDisplayIssue) {
|
||||
this.errorIsDisplayIssue = errorIsDisplayIssue;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ package org.hl7.fhir.r5.terminologies.utilities;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
@ -48,6 +49,7 @@ public class ValueSetProcessBase {
|
||||
}
|
||||
}
|
||||
protected IWorkerContext context;
|
||||
private ContextUtilities cu;
|
||||
protected TerminologyOperationContext opContext;
|
||||
protected List<String> requiredSupplements = new ArrayList<>();
|
||||
|
||||
@ -236,6 +238,14 @@ public class ValueSetProcessBase {
|
||||
}
|
||||
|
||||
|
||||
public ContextUtilities getCu() {
|
||||
if (cu == null) {
|
||||
cu = new ContextUtilities(context);
|
||||
}
|
||||
return cu;
|
||||
}
|
||||
|
||||
|
||||
protected AlternateCodesProcessingRules altCodeParams = new AlternateCodesProcessingRules(false);
|
||||
protected AlternateCodesProcessingRules allAltCodes = new AlternateCodesProcessingRules(true);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
private ValidationOptions options;
|
||||
private ValidationContextCarrier localContext;
|
||||
private List<CodeSystem> localSystems = new ArrayList<>();
|
||||
protected Parameters expansionProfile;
|
||||
protected Parameters expansionParameters;
|
||||
private TerminologyClientManager tcm;
|
||||
private Set<String> unknownSystems;
|
||||
private Set<String> unknownValueSets = new HashSet<>();
|
||||
@ -143,7 +143,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
super(context, opContext);
|
||||
this.valueset = source;
|
||||
this.options = options;
|
||||
this.expansionProfile = expansionProfile;
|
||||
this.expansionParameters = expansionProfile;
|
||||
this.tcm = tcm;
|
||||
analyseValueSet();
|
||||
}
|
||||
@ -154,7 +154,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
this.options = options.copy();
|
||||
this.options.setEnglishOk(true);
|
||||
this.localContext = ctxt;
|
||||
this.expansionProfile = expansionProfile;
|
||||
this.expansionParameters = expansionProfile;
|
||||
this.tcm = tcm;
|
||||
analyseValueSet();
|
||||
}
|
||||
@ -200,7 +200,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
opContext.note("vs = null");
|
||||
}
|
||||
|
||||
altCodeParams.seeParameters(expansionProfile);
|
||||
altCodeParams.seeParameters(expansionParameters);
|
||||
altCodeParams.seeValueSet(valueset);
|
||||
if (localContext != null) {
|
||||
if (valueset != null) {
|
||||
@ -456,7 +456,8 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
private int checkValueSetLoad(ConceptSetComponent inc, ValidationProcessInfo info) {
|
||||
int serverCount = 0;
|
||||
for (UriType uri : inc.getValueSet()) {
|
||||
ValueSetValidator vsv = getVs(uri.getValue(), info);
|
||||
String url = getCu().pinValueSet(uri.getValue(), expansionParameters);
|
||||
ValueSetValidator vsv = getVs(url, info);
|
||||
serverCount += vsv.getServerLoad(info);
|
||||
}
|
||||
CodeSystem cs = resolveCodeSystem(inc.getSystem(), inc.getVersion());
|
||||
@ -1005,6 +1006,9 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
String msg = context.formatMessagePlural(options.getLanguages().getLangs().size(), none ? I18nConstants.NO_VALID_DISPLAY_FOUND_LANG_NONE : I18nConstants.NO_VALID_DISPLAY_FOUND_LANG_SOME, code.getSystem(), code.getCode(), code.getDisplay(), options.langSummary(), code.getDisplay());
|
||||
String n = null;
|
||||
return new ValidationResult(IssueSeverity.INFORMATION, n, code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs), makeIssue(IssueSeverity.INFORMATION, IssueType.INVALID, path+".display", msg, OpIssueCode.DisplayComment, null)).setStatus(inactive, status);
|
||||
} else if (!code.getDisplay().equals(vc.getDisplay())) {
|
||||
String msg = context.formatMessage(I18nConstants.NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR, code.getDisplay(), code.getSystem(), code.getCode(), options.langSummary(), vc.getDisplay());
|
||||
return new ValidationResult(IssueSeverity.ERROR, msg, code.getSystem(), cs.getVersion(), cc, cc.getDisplay(), makeIssue(IssueSeverity.ERROR, IssueType.INVALID, path+".display", msg, OpIssueCode.Display, null)).setStatus(inactive, status).setErrorIsDisplayIssue(true);
|
||||
} else {
|
||||
String msg = context.formatMessagePlural(options.getLanguages().getLangs().size(), I18nConstants.NO_VALID_DISPLAY_FOUND, code.getSystem(), code.getCode(), code.getDisplay(), options.langSummary());
|
||||
return new ValidationResult(IssueSeverity.WARNING, msg, code.getSystem(), cs.getVersion(), cc, cc.getDisplay(), makeIssue(IssueSeverity.WARNING, IssueType.INVALID, path+".display", msg, OpIssueCode.Display, null)).setStatus(inactive, status);
|
||||
@ -1108,7 +1112,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
}
|
||||
}
|
||||
for (CanonicalType url : inc.getValueSet()) {
|
||||
ConceptReferencePair cc = getVs(url.asStringValue(), null).findValueSetRef(system, code);
|
||||
ConceptReferencePair cc = getVs(getCu().pinValueSet(url.asStringValue(), expansionParameters), null).findValueSetRef(system, code);
|
||||
if (cc != null) {
|
||||
return cc;
|
||||
}
|
||||
@ -1221,7 +1225,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
private boolean scanForCodeInValueSetInclude(String code, Set<String> sys, List<StringWithCode> problems, int i, ConceptSetComponent vsi) {
|
||||
if (vsi.hasValueSet()) {
|
||||
for (CanonicalType u : vsi.getValueSet()) {
|
||||
if (!checkForCodeInValueSet(code, u.getValue(), sys, problems)) {
|
||||
if (!checkForCodeInValueSet(code, getCu().pinValueSet(u.getValue(), expansionParameters), sys, problems)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1379,19 +1383,19 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
if (isValueSetUnionImports()) {
|
||||
ok = false;
|
||||
for (UriType uri : vsi.getValueSet()) {
|
||||
if (inImport(path, uri.getValue(), system, version, code, info)) {
|
||||
if (inImport(path, getCu().pinValueSet(uri.getValue(), expansionParameters), system, version, code, info)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Boolean bok = inImport(path, vsi.getValueSet().get(0).getValue(), system, version, code, info);
|
||||
Boolean bok = inImport(path, getCu().pinValueSet(vsi.getValueSet().get(0).getValue(), expansionParameters), system, version, code, info);
|
||||
if (bok == null) {
|
||||
return bok;
|
||||
}
|
||||
ok = bok;
|
||||
for (int i = 1; i < vsi.getValueSet().size(); i++) {
|
||||
UriType uri = vsi.getValueSet().get(i);
|
||||
ok = ok && inImport(path, uri.getValue(), system, version, code, info);
|
||||
ok = ok && inImport(path, getCu().pinValueSet(uri.getValue(), expansionParameters), system, version, code, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1662,7 +1666,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
||||
unknownValueSets.add(url);
|
||||
info.addIssue(makeIssue(IssueSeverity.ERROR, IssueType.NOTFOUND, null, context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, url), OpIssueCode.NotFound, null));
|
||||
}
|
||||
ValueSetValidator vsc = new ValueSetValidator(context, opContext.copy(), options, vs, localContext, expansionProfile, tcm);
|
||||
ValueSetValidator vsc = new ValueSetValidator(context, opContext.copy(), options, vs, localContext, expansionParameters, tcm);
|
||||
vsc.setThrowToServer(throwToServer);
|
||||
inner.put(url, vsc);
|
||||
return vsc;
|
||||
|
@ -63,8 +63,8 @@ public class VersionInfo {
|
||||
}
|
||||
|
||||
private String getVersionParameter(String name, String system) {
|
||||
if (this.valueSetCheckerSimple.expansionProfile != null) {
|
||||
for (ParametersParameterComponent pc : this.valueSetCheckerSimple.expansionProfile.getParameter()) {
|
||||
if (this.valueSetCheckerSimple.expansionParameters != null) {
|
||||
for (ParametersParameterComponent pc : this.valueSetCheckerSimple.expansionParameters.getParameter()) {
|
||||
if (name.equals(pc.getName()) && pc.hasValue()) {
|
||||
String v = pc.getValue().primitiveValue();
|
||||
if (v != null && v.startsWith(system+"|")) {
|
||||
|
@ -237,6 +237,7 @@ public class ToolingExtensions {
|
||||
public static final String EXT_JSON_PRIMITIVE_CHOICE = "http://hl7.org/fhir/tools/StructureDefinition/json-primitive-choice";
|
||||
public static final String EXT_SUMMARY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-summary";
|
||||
public static final String EXT_BINDING_DEFINITION = "http://hl7.org/fhir/tools/StructureDefinition/binding-definition";
|
||||
public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = "http://hl7.org/fhir/4.0/StructureDefinition/extension-questionnaire.item.type";
|
||||
|
||||
|
||||
// unregistered? - don't know what these are used for
|
||||
|
@ -291,7 +291,7 @@ public class Validator {
|
||||
try {
|
||||
node = fpe.parse(expr);
|
||||
column.setUserData(UserDataNames.db_path, node);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, node, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, node, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -473,7 +473,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
focus.setUserData(UserDataNames.db_forEach, n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -498,7 +498,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
focus.setUserData(UserDataNames.db_forEachOrNull, n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
@ -611,7 +611,7 @@ public class Validator {
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
where.setUserData(UserDataNames.db_path, n);
|
||||
td = fpe.checkOnTypes(vd, resourceName, types, n, warnings);
|
||||
td = fpe.checkOnTypes(vd, "Resource", resourceName, types, n, warnings);
|
||||
} catch (Exception e) {
|
||||
error(path, where.get("path"), e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
|
@ -2531,7 +2531,7 @@ public class StructureMapUtilities {
|
||||
if (expr == null) {
|
||||
expr = fpe.parse(getParamString(vars, tgt.getParameter().get(tgt.getParameter().size() - 1)));
|
||||
}
|
||||
return fpe.check(vars, null, expr);
|
||||
return fpe.check(vars, null, null, expr);
|
||||
case TRANSLATE:
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, "CodeableConcept");
|
||||
case CC:
|
||||
|
@ -219,9 +219,9 @@ public class FHIRPathTests {
|
||||
if (!skipStaticCheck) {
|
||||
try {
|
||||
if (Utilities.noString(input)) {
|
||||
fp.check(null, null, node);
|
||||
fp.check(null, null, null, node);
|
||||
} else {
|
||||
fp.check(res, res.fhirType(), res.fhirType(), node);
|
||||
fp.check(res, res.fhirType(), res.fhirType(), res.fhirType(), node);
|
||||
}
|
||||
Assertions.assertTrue(fail != TestResultType.SEMANTICS, String.format("Expected exception didn't occur checking %s", expression));
|
||||
} catch (Exception e) {
|
||||
|
@ -1147,4 +1147,20 @@ public class I18nConstants {
|
||||
public static final String HTA_SCT_MESSAGE = "HTA_SCT_MESSAGE";
|
||||
public static final String HTA_LOINC_DESC = "HTA_LOINC_DESC";
|
||||
public static final String HTA_LOINC_MESSAGE = "HTA_LOINC_MESSAGE";
|
||||
public static final String VS_EXP_IMPORT_CS_PINNED = "VS_EXP_IMPORT_CS_PINNED";
|
||||
public static final String VS_EXP_IMPORT_CS = "VS_EXP_IMPORT_CS";
|
||||
public static final String VS_EXP_IMPORT_UNK_PINNED = "VS_EXP_IMPORT_UNK_PINNED";
|
||||
public static final String VS_EXP_IMPORT_UNK = "VS_EXP_IMPORT_UNK";
|
||||
public static final String VS_EXP_IMPORT_NULL = "VS_EXP_IMPORT_NULL";
|
||||
public static final String VS_EXP_IMPORT_ERROR = "VS_EXP_IMPORT_ERROR";
|
||||
public static final String VS_EXP_IMPORT_FAIL = "VS_EXP_IMPORT_FAIL";
|
||||
public static final String VS_EXP_IMPORT_NULL_X = "VS_EXP_IMPORT_NULL_X";
|
||||
public static final String VS_EXP_IMPORT_CS_PINNED_X = "VS_EXP_IMPORT_CS_PINNED_X";
|
||||
public static final String VS_EXP_IMPORT_CS_X = "VS_EXP_IMPORT_CS_X";
|
||||
public static final String VS_EXP_IMPORT_UNK_PINNED_X = "VS_EXP_IMPORT_UNK_PINNED_X";
|
||||
public static final String VS_EXP_IMPORT_UNK_X = "VS_EXP_IMPORT_UNK_X";
|
||||
public static final String VS_EXP_IMPORT_ERROR_X = "VS_EXP_IMPORT_ERROR_X";
|
||||
public static final String VS_EXP_IMPORT_FAIL_X = "VS_EXP_IMPORT_FAIL_X";
|
||||
public static final String VS_EXP_FILTER_UNK = "VS_EXP_FILTER_UNK";
|
||||
public static final String NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR = "NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR";
|
||||
}
|
||||
|
@ -758,6 +758,9 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
||||
} else if (id.startsWith("hl7.fhir.r6")) {
|
||||
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL("https://build.fhir.org", id + ".tgz"), false);
|
||||
return new InputStreamWithSrc(stream, Utilities.pathURL("https://build.fhir.org", id + ".tgz"), "current");
|
||||
} else if (id.startsWith("hl7.fhir.uv.extensions.")) {
|
||||
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL("https://build.fhir.org/ig/HL7/fhir-extensions/", id + ".tgz"), false);
|
||||
return new InputStreamWithSrc(stream, Utilities.pathURL("https://build.fhir.org/ig/HL7/fhir-extensions/", id + ".tgz"), "current");
|
||||
} else {
|
||||
throw new FHIRException("The package '" + id + "' has no entry on the current build server (" + ciList + ")");
|
||||
}
|
||||
|
@ -1180,3 +1180,20 @@ HTA_SCT_MESSAGE = This material contains content that is copyright of SNOMED Int
|
||||
HTA_LOINC_DESC = LOINC
|
||||
HTA_LOINC_MESSAGE = This material contains content from <a href=\"http://loinc.org\">LOINC</a>. LOINC is copyright © 1995-2020, Regenstrief Institute, Inc. and the Logical Observation Identifiers Names and Codes (LOINC) Committee and is available at no cost under the <a href=\"http://loinc.org/license\">license</a>. LOINC® is a registered United States trademark of Regenstrief Institute, Inc.
|
||||
SD_PATH_NO_SLICING = Slicing is not allowed at ''{0}''
|
||||
VS_EXP_IMPORT_CS = Cannot include value set ''{0}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_CS_PINNED = Cannot include value set ''{0}'' version ''{1}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_UNK = Unable to find included value set ''{0}''
|
||||
VS_EXP_IMPORT_UNK_PINNED = Unable to find included value set ''{0}'' version ''{1}''
|
||||
VS_EXP_IMPORT_NULL = Unable to find included value set with no identity
|
||||
VS_EXP_IMPORT_ERROR = Unable to expand included value set ''{0}'': {1}
|
||||
VS_EXP_IMPORT_ERROR = Unable to expand included value set ''{0}'', but no error
|
||||
VS_EXP_IMPORT_CS_X = Cannot exclude value set ''{0}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_CS_PINNED_X = Cannot exclude value set ''{0}'' version ''{1}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_UNK_X = Unable to find excluded value set ''{0}''
|
||||
VS_EXP_IMPORT_UNK_PINNED_X = Unable to find excluded value set ''{0}'' version ''{1}''
|
||||
VS_EXP_IMPORT_NUL_XL = Unable to find excluded value set with no identity
|
||||
VS_EXP_IMPORT_ERROR_X = Unable to expand excluded value set ''{0}'': {1}
|
||||
VS_EXP_IMPORT_ERROR_X = Unable to expand excluded value set ''{0}'', but no error
|
||||
VS_EXP_IMPORT_ERROR_TOO_COSTLY = Unable to expand excluded value set ''{0}'': too costly
|
||||
VS_EXP_FILTER_UNK = ValueSet ''{0}'' Filter by property ''{1}'' and op ''{2}'' is not supported yet
|
||||
|
@ -195,10 +195,12 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
||||
protected BestPracticeWarningLevel bpWarnings = BestPracticeWarningLevel.Warning; // @configuration
|
||||
protected List<UsageContext> usageContexts = new ArrayList<UsageContext>(); // @configuration
|
||||
protected ValidationOptions baseOptions = new ValidationOptions(FhirPublication.R5); // @configuration
|
||||
protected ContextUtilities cu;
|
||||
|
||||
public BaseValidator(IWorkerContext context, XVerExtensionManager xverManager, boolean debug, ValidatorSession session) {
|
||||
super();
|
||||
this.context = context;
|
||||
cu = new ContextUtilities(context);
|
||||
this.session = session;
|
||||
if (this.session == null) {
|
||||
this.session = new ValidatorSession();
|
||||
@ -217,6 +219,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
||||
this.parent = parent;
|
||||
this.session = parent.session;
|
||||
this.context = parent.context;
|
||||
this.cu = parent.cu;
|
||||
this.xverManager = parent.xverManager;
|
||||
this.debug = parent.debug;
|
||||
this.source = parent.source;
|
||||
@ -955,6 +958,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
reference = cu.pinValueSet(reference);
|
||||
long t = System.nanoTime();
|
||||
ValueSet fr = context.findTxResource(ValueSet.class, reference, src);
|
||||
if (fr == null) {
|
||||
@ -1160,9 +1164,11 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
||||
if (bnd != null) {
|
||||
// in this case, we look into the parent - if there is one - and if it's a bundle, we look at the entries (but not in them)
|
||||
for (Element be : bnd.getChildrenByName("entry")) {
|
||||
String id = be.getIdBase();
|
||||
if (fragment.equals(id)) {
|
||||
count++;
|
||||
if (be.hasChild("resource")) {
|
||||
String id = be.getNamedChild("resource").getIdBase();
|
||||
if (fragment.equals(id)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package org.hl7.fhir.validation;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -1295,4 +1296,24 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
||||
return ReferenceValidationPolicy.IGNORE;
|
||||
}
|
||||
|
||||
public void loadExpansionParameters(String expansionParameters) {
|
||||
System.out.println("Load Expansion Parameters: "+expansionParameters);
|
||||
Parameters p = null;
|
||||
try {
|
||||
p = (Parameters) new XmlParser().parse(new FileInputStream(expansionParameters));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (p == null) {
|
||||
try {
|
||||
p = (Parameters) new JsonParser().parse(new FileInputStream(expansionParameters));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unable to load expansion parameters '"+expansionParameters+"' as either xml or json: "+e.getMessage());
|
||||
throw new FHIRException("Unable to load expansion parameters '"+expansionParameters+"' as either xml or json: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
context.setExpansionParameters(p);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ public class ValidatorCli {
|
||||
new TransformTask(),
|
||||
new VersionTask(),
|
||||
new CodeGenTask(),
|
||||
new TxPackTask(),
|
||||
defaultCliTask);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -8,6 +9,11 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
||||
@ -322,6 +328,16 @@ public class CliContext {
|
||||
private
|
||||
String advisorFile;
|
||||
|
||||
@JsonProperty("expansionParameters")
|
||||
@SerializedName("expansionParameters")
|
||||
private
|
||||
String expansionParameters;
|
||||
|
||||
@JsonProperty("format")
|
||||
@SerializedName("format")
|
||||
private
|
||||
FhirFormat format;
|
||||
|
||||
@SerializedName("baseEngine")
|
||||
@JsonProperty("baseEngine")
|
||||
public String getBaseEngine() {
|
||||
@ -1146,6 +1162,8 @@ public class CliContext {
|
||||
Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) &&
|
||||
Objects.equals(noExperimentalContent, that.noExperimentalContent) &&
|
||||
Objects.equals(advisorFile, that.advisorFile) &&
|
||||
Objects.equals(expansionParameters, that.expansionParameters) &&
|
||||
Objects.equals(format, that.format) &&
|
||||
Objects.equals(watchSettleTime, that.watchSettleTime);
|
||||
}
|
||||
|
||||
@ -1154,7 +1172,7 @@ public class CliContext {
|
||||
return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
|
||||
noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT,
|
||||
targetVer, packageName, igs, questionnaireMode, level, profiles, options, sources, inputs, mode, locale, locations, crumbTrails, showMessageIds, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars,
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, advisorFile, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, advisorFile, expansionParameters, format, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1219,6 +1237,8 @@ public class CliContext {
|
||||
", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
|
||||
", noExperimentalContent=" + noExperimentalContent +
|
||||
", advisorFile=" + advisorFile +
|
||||
", expansionParameters=" + expansionParameters +
|
||||
", format=" + format +
|
||||
'}';
|
||||
}
|
||||
|
||||
@ -1325,5 +1345,28 @@ public class CliContext {
|
||||
this.advisorFile = advisorFile;
|
||||
}
|
||||
|
||||
@SerializedName("expansionParameters")
|
||||
@JsonProperty("expansionParameters")
|
||||
public String getExpansionParameters() {
|
||||
return expansionParameters;
|
||||
}
|
||||
|
||||
@SerializedName("expansionParameters")
|
||||
@JsonProperty("expansionParameters")
|
||||
public void setExpansionParameters(String expansionParameters) {
|
||||
this.expansionParameters = expansionParameters;
|
||||
}
|
||||
|
||||
@SerializedName("format")
|
||||
@JsonProperty("format")
|
||||
public FhirFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@SerializedName("format")
|
||||
@JsonProperty("format")
|
||||
public void setFormat(FhirFormat format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package org.hl7.fhir.validation.cli.tasks;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
import org.hl7.fhir.validation.cli.utils.Display;
|
||||
import org.hl7.fhir.validation.cli.utils.EngineMode;
|
||||
import org.hl7.fhir.validation.special.ExpansionPackageGenerator;
|
||||
import org.hl7.fhir.validation.special.ExpansionPackageGenerator.ExpansionPackageGeneratorOutputType;
|
||||
import org.hl7.fhir.validation.special.ExpansionPackageGenerator.ExpansionPackageGeneratorScope;
|
||||
|
||||
public class TxPackTask extends ValidationEngineTask {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "tx-pack";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Generate a terminology pack";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExecuteTask(CliContext cliContext, String[] args) {
|
||||
return cliContext.getMode() == EngineMode.TX_PACK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelp(PrintStream out) {
|
||||
Display.displayHelpDetails(out,"help/tx-pack.txt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeTask(ValidationService validationService, ValidationEngine validationEngine, CliContext cliContext, String[] args, TimeTracker tt, TimeTracker.Session tts) throws Exception {
|
||||
String pid = cliContext.getPackageName();
|
||||
boolean json = cliContext.getFormat() != FhirFormat.XML;
|
||||
String output = cliContext.getOutput();
|
||||
File f = new File(output);
|
||||
ExpansionPackageGeneratorOutputType t = ExpansionPackageGeneratorOutputType.FOLDER;
|
||||
if (f.exists() && f.isDirectory()) {
|
||||
t = ExpansionPackageGeneratorOutputType.FOLDER;
|
||||
} else if (output.endsWith(".zip")) {
|
||||
t = ExpansionPackageGeneratorOutputType.ZIP;
|
||||
} else if (output.endsWith(".tgz")) {
|
||||
t = ExpansionPackageGeneratorOutputType.TGZ;
|
||||
}
|
||||
ExpansionPackageGeneratorScope scope = ExpansionPackageGeneratorScope.IG_ONLY;
|
||||
int c = -1;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if ("-scope".equals(args[i])) {
|
||||
c = i;
|
||||
}
|
||||
}
|
||||
if (c < args.length - 1) {
|
||||
switch (args[c+1].toLowerCase()) {
|
||||
case "ig" : scope = ExpansionPackageGeneratorScope.IG_ONLY;
|
||||
case "igs" : scope = ExpansionPackageGeneratorScope.ALL_IGS;
|
||||
case "core" : scope = ExpansionPackageGeneratorScope.EVERYTHING;
|
||||
default:
|
||||
System.out.println("Unknown scope "+args[c+1]);
|
||||
}
|
||||
}
|
||||
IWorkerContext ctxt = validationEngine.getContext();
|
||||
ExpansionPackageGenerator ep = new ExpansionPackageGenerator().setContext(ctxt).setPackageId(pid).setScope(scope);
|
||||
if (cliContext.getExpansionParameters() != null) {
|
||||
validationEngine.loadExpansionParameters(cliContext.getExpansionParameters());
|
||||
}
|
||||
ep.setOutput(output).setOutputType(t);
|
||||
ep.generateExpansionPackage();
|
||||
}
|
||||
}
|
@ -51,6 +51,10 @@ public class ValidateTask extends ValidationEngineTask {
|
||||
|
||||
@Override
|
||||
public void executeTask(ValidationService validationService, ValidationEngine validationEngine, CliContext cliContext, String[] args, TimeTracker tt, TimeTracker.Session tts) throws Exception {
|
||||
if (cliContext.getExpansionParameters() != null) {
|
||||
validationEngine.loadExpansionParameters(cliContext.getExpansionParameters());
|
||||
}
|
||||
|
||||
for (String s : cliContext.getProfiles()) {
|
||||
if (!validationEngine.getContext().hasResource(StructureDefinition.class, s) && !validationEngine.getContext().hasResource(ImplementationGuide.class, s)) {
|
||||
System.out.println(" Fetch Profile from " + s);
|
||||
|
@ -14,5 +14,6 @@ public enum EngineMode {
|
||||
VERSION,
|
||||
RUN_TESTS,
|
||||
INSTALL,
|
||||
CODEGEN
|
||||
CODEGEN,
|
||||
TX_PACK
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
||||
@ -45,13 +46,16 @@ public class Params {
|
||||
public static final String EXTENSION = "-extension";
|
||||
public static final String HINT_ABOUT_NON_MUST_SUPPORT = "-hintAboutNonMustSupport";
|
||||
public static final String TO_VERSION = "-to-version";
|
||||
public static final String TX_PACK = "-tx-pack";
|
||||
public static final String PACKAGE_NAME = "-package-name";
|
||||
public static final String DO_NATIVE = "-do-native";
|
||||
public static final String NO_NATIVE = "-no-native";
|
||||
public static final String COMPILE = "-compile";
|
||||
public static final String CODEGEN = "-codegen";
|
||||
public static final String TRANSFORM = "-transform";
|
||||
public static final String FORMAT = "-format";
|
||||
public static final String LANG_TRANSFORM = "-lang-transform";
|
||||
public static final String EXP_PARAMS = "-expansion-parameters";
|
||||
public static final String NARRATIVE = "-narrative";
|
||||
public static final String SNAPSHOT = "-snapshot";
|
||||
public static final String INSTALL = "-install";
|
||||
@ -330,6 +334,9 @@ public class Params {
|
||||
} else if (args[i].equals(PACKAGE_NAME)) {
|
||||
cliContext.setPackageName(args[++i]);
|
||||
cliContext.setMode(EngineMode.CODEGEN);
|
||||
} else if (args[i].equals(TX_PACK)) {
|
||||
cliContext.setPackageName(args[++i]);
|
||||
cliContext.setMode(EngineMode.TX_PACK);
|
||||
} else if (args[i].equals(DO_NATIVE)) {
|
||||
cliContext.setCanDoNative(true);
|
||||
} else if (args[i].equals(NO_NATIVE)) {
|
||||
@ -337,9 +344,13 @@ public class Params {
|
||||
} else if (args[i].equals(TRANSFORM)) {
|
||||
cliContext.setMap(args[++i]);
|
||||
cliContext.setMode(EngineMode.TRANSFORM);
|
||||
} else if (args[i].equals(FORMAT)) {
|
||||
cliContext.setFormat(FhirFormat.fromCode(args[++i]));
|
||||
} else if (args[i].equals(LANG_TRANSFORM)) {
|
||||
cliContext.setLangTransform(args[++i]);
|
||||
cliContext.setMode(EngineMode.LANG_TRANSFORM);
|
||||
} else if (args[i].equals(EXP_PARAMS)) {
|
||||
cliContext.setExpansionParameters(args[++i]);
|
||||
} else if (args[i].equals(COMPILE)) {
|
||||
cliContext.setMap(args[++i]);
|
||||
cliContext.setMode(EngineMode.COMPILE);
|
||||
|
@ -532,7 +532,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return context.findTxResource(ValueSet.class, url);
|
||||
return context.findTxResource(ValueSet.class, cu.pinValueSet(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -602,7 +602,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
public boolean testMode;
|
||||
private boolean example ;
|
||||
private IDigitalSignatureServices signatureServices;
|
||||
private ContextUtilities cu;
|
||||
private boolean unknownCodeSystemsCauseErrors;
|
||||
private boolean noExperimentalContent;
|
||||
|
||||
@ -611,7 +610,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
start = System.currentTimeMillis();
|
||||
this.externalHostServices = hostServices;
|
||||
this.profileUtilities = new ProfileUtilities(theContext, null, null);
|
||||
cu = new ContextUtilities(theContext);
|
||||
fpe = new FHIRPathEngine(context);
|
||||
validatorServices = new ValidatorHostServices();
|
||||
fpe.setHostServices(validatorServices);
|
||||
@ -7739,7 +7737,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
n = fpe.parse(FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey(), context.getVersion()));
|
||||
inv.setUserData(UserDataNames.validator_expression_cache, n);
|
||||
}
|
||||
fpe.check(null, sd.getKind() == StructureDefinitionKind.RESOURCE ? sd.getType() : "DomainResource", ed.getPath(), n);
|
||||
fpe.check(null, "Resource", sd.getKind() == StructureDefinitionKind.RESOURCE ? sd.getType() : "DomainResource", ed.getPath(), n);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error processing structure [" + sd.getId() + "] path " + ed.getPath() + ":" + inv.getKey() + " ('" + inv.getExpression() + "'): " + e.getMessage());
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ 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.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
@ -241,7 +242,11 @@ public class QuestionnaireValidator extends BaseValidator {
|
||||
Element e = item.getNamedChild("type", false);
|
||||
if (e != null) {
|
||||
NodeStack ne = ns.push(e, -1, e.getProperty().getDefinition(), e.getProperty().getDefinition());
|
||||
ok = rule(errors, "2023-06-15", IssueType.BUSINESSRULE, ne, qi.getType().toCode().equals(e.primitiveValue()), I18nConstants.QUESTIONNAIRE_Q_ITEM_DERIVED_NC_TYPE, derivation.questionnaire.getUrl(), linkId, qi.getType().toCode(), e.primitiveValue()) && ok;
|
||||
String myType = qi.getType().toCode();
|
||||
if (qi.getTypeElement().hasExtension(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) {
|
||||
myType = qi.getTypeElement().getExtensionString(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL);
|
||||
}
|
||||
ok = rule(errors, "2023-06-15", IssueType.BUSINESSRULE, ne, myType.equals(e.primitiveValue()), I18nConstants.QUESTIONNAIRE_Q_ITEM_DERIVED_NC_TYPE, derivation.questionnaire.getUrl(), linkId, qi.getType().toCode(), e.primitiveValue()) && ok;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class SearchParameterValidator extends BaseValidator {
|
||||
boolean ok = true;
|
||||
try {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
fpe.checkOnTypes(null, bases.size() == 1 ? bases.get(0) : "Resource", bases, fpe.parse(expression), warnings);
|
||||
fpe.checkOnTypes(null, "Resource", bases.size() == 1 ? bases.get(0) : "Resource", bases, fpe.parse(expression), warnings);
|
||||
for (IssueMessage m : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, m.getId(), false, m.getMessage());
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||
if (!td.isEmpty()) {
|
||||
List<IssueMessage> warnings = new ArrayList<IssueMessage>();
|
||||
try {
|
||||
TypeDetails eval = fpe.checkOnTypes(this, tn, td, fpe.parse(pathExp), warnings, true);
|
||||
TypeDetails eval = fpe.checkOnTypes(this, "Resource", tn, td, fpe.parse(pathExp), warnings, true);
|
||||
if (eval.isEmpty()) {
|
||||
ok = rule(errors, "2024-11-06", IssueType.INVALID, dStack, false, I18nConstants.SD_PATH_NOT_VALID, pathExp, path) && ok;
|
||||
}
|
||||
@ -744,16 +744,16 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
ValidationContext vc = new ValidationContext(invariant);
|
||||
if (Utilities.existsInList(rootPath, context.getResourceNames())) {
|
||||
fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings);
|
||||
fpe.checkOnTypes(vc, "Resource", rootPath, types, fpe.parse(exp), warnings);
|
||||
} else {
|
||||
StructureDefinition sd = context.fetchTypeDefinition(rootPath);
|
||||
if (sd != null && sd.getKind() == StructureDefinitionKind.RESOURCE) {
|
||||
fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings);
|
||||
fpe.checkOnTypes(vc, "Resource", rootPath, types, fpe.parse(exp), warnings);
|
||||
} else if (sd != null && sd.getKind() == StructureDefinitionKind.LOGICAL) {
|
||||
String tn = ToolingExtensions.readStringExtension(sd, ToolingExtensions.EXT_LOGICAL_CONTAINER);
|
||||
fpe.checkOnTypes(vc, tn == null ? rootPath : tn, types, fpe.parse(exp), warnings);
|
||||
fpe.checkOnTypes(vc, "Resource", tn == null ? rootPath : tn, types, fpe.parse(exp), warnings);
|
||||
} else {
|
||||
fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings);
|
||||
fpe.checkOnTypes(vc, "Resource", "DomainResource", types, fpe.parse(exp), warnings);
|
||||
}
|
||||
}
|
||||
for (IssueMessage s : warnings) {
|
||||
@ -790,7 +790,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||
try {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
ValidationContext vc = new ValidationContext(invariant);
|
||||
fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings);
|
||||
fpe.checkOnTypes(vc, "Resource", "DomainResource", types, fpe.parse(exp), warnings);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, s.getId(), false, s.getMessage());
|
||||
}
|
||||
|
@ -863,7 +863,7 @@ public class StructureMapValidator extends BaseValidator {
|
||||
String exp = params.get(0).getChildValue("value");
|
||||
if (rule(errors, "2023-03-01", IssueType.INVALID, params.get(0).line(), params.get(0).col(), stack.getLiteralPath(), exp != null, I18nConstants.SM_TARGET_TRANSFORM_PARAM_UNPROCESSIBLE, "0", params.size())) {
|
||||
try {
|
||||
TypeDetails td = fpe.check(variables, v.getSd().getUrl(), v.getEd().getPath(), fpe.parse(exp));
|
||||
TypeDetails td = fpe.check(variables, null, v.getSd().getUrl(), v.getEd().getPath(), fpe.parse(exp));
|
||||
if (td.getTypes().size() == 1) {
|
||||
type = td.getType();
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ public class ViewDefinitionValidator extends BaseValidator {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
td = vec.fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = vec.fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
rule(errors, "2024-11-14", IssueType.EXCEPTION, stack, false, I18nConstants.VIEWDEFINITION_PATH_ERROR, e.getMessage(), vdesc);
|
||||
ok = false;
|
||||
@ -422,7 +422,7 @@ public class ViewDefinitionValidator extends BaseValidator {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
td = vec.fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = vec.fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
rule(errors, "2024-11-14", IssueType.EXCEPTION, stack, false, I18nConstants.VIEWDEFINITION_PATH_ERROR, e.getMessage(), vdesc);
|
||||
return null;
|
||||
@ -448,7 +448,7 @@ public class ViewDefinitionValidator extends BaseValidator {
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
td = vec.fpe.checkOnTypes(vd, resourceName, t, n, warnings);
|
||||
td = vec.fpe.checkOnTypes(vd, "Resource", resourceName, t, n, warnings);
|
||||
} catch (Exception e) {
|
||||
rule(errors, "2024-11-14", IssueType.EXCEPTION, stack, false, I18nConstants.VIEWDEFINITION_PATH_ERROR, e.getMessage(), vdesc);
|
||||
return null;
|
||||
@ -482,7 +482,7 @@ public class ViewDefinitionValidator extends BaseValidator {
|
||||
types.add(resourceName);
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
td = vec.fpe.checkOnTypes(vd, resourceName, types, n, warnings);}
|
||||
td = vec.fpe.checkOnTypes(vd, "Resource", resourceName, types, n, warnings);}
|
||||
catch (Exception e) {
|
||||
rule(errors, "2024-11-14", IssueType.EXCEPTION, stack, false, I18nConstants.VIEWDEFINITION_PATH_ERROR, e.getMessage(), vdesc);
|
||||
ok = false;
|
||||
|
@ -0,0 +1,409 @@
|
||||
package org.hl7.fhir.validation.special;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.NPMPackageGenerator;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.ZipGenerator;
|
||||
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.validation.IgLoader;
|
||||
import org.hl7.fhir.validation.special.ExpansionPackageGenerator.TerminologyResourceEntry;
|
||||
|
||||
/**
|
||||
* Given a package id, and an expansion parameters,
|
||||
* get a list of all the value sets in the package, optionally with expansions.
|
||||
* Parameters:
|
||||
*
|
||||
* - scope: this ig | all igs | all igs + core
|
||||
* - expansions: true | false
|
||||
* - output type: folder | zip | tgz
|
||||
*/
|
||||
|
||||
public class ExpansionPackageGenerator {
|
||||
|
||||
public static class TerminologyResourceEntry {
|
||||
public ValueSet valueSet;
|
||||
public Set<String> sources = new HashSet<>();
|
||||
public String error;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new ExpansionPackageGenerator()
|
||||
.setPackageId("hl7.fhir.us.davinci-alerts")
|
||||
.setJson(true)
|
||||
.setOutputType(ExpansionPackageGeneratorOutputType.TGZ)
|
||||
.setOutput("/Users/grahamegrieve/temp/vs-output.tgz")
|
||||
.generateExpansionPackage();
|
||||
}
|
||||
public enum ExpansionPackageGeneratorOutputType {
|
||||
FOLDER, ZIP, TGZ
|
||||
}
|
||||
|
||||
public enum ExpansionPackageGeneratorScope {
|
||||
IG_ONLY, ALL_IGS, EVERYTHING
|
||||
}
|
||||
|
||||
private String packageId;
|
||||
private Parameters expansionParameters = new Parameters();
|
||||
private ExpansionPackageGeneratorScope scope = ExpansionPackageGeneratorScope.EVERYTHING;
|
||||
private boolean expansions;
|
||||
private String output;
|
||||
private ExpansionPackageGeneratorOutputType outputType;
|
||||
private boolean hierarchical;
|
||||
private boolean json;
|
||||
private IWorkerContext context;
|
||||
|
||||
|
||||
public String getPackageId() {
|
||||
return packageId;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setPackageId(String packageId) {
|
||||
this.packageId = packageId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Parameters getExpansionParameters() {
|
||||
return expansionParameters;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setExpansionParameters(Parameters expansionParameters) {
|
||||
this.expansionParameters = expansionParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpansionPackageGeneratorScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setScope(ExpansionPackageGeneratorScope scope) {
|
||||
this.scope = scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isExpansions() {
|
||||
return expansions;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setExpansions(boolean expansions) {
|
||||
this.expansions = expansions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setOutput(String output) {
|
||||
this.output = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpansionPackageGeneratorOutputType getOutputType() {
|
||||
return outputType;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setOutputType(ExpansionPackageGeneratorOutputType outputType) {
|
||||
this.outputType = outputType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isHierarchical() {
|
||||
return hierarchical;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setHierarchical(boolean hierarchical) {
|
||||
this.hierarchical = hierarchical;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isJson() {
|
||||
return json;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setJson(boolean json) {
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public IWorkerContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public ExpansionPackageGenerator setContext(IWorkerContext context) {
|
||||
this.context = context;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private ContextUtilities cu;
|
||||
|
||||
private Map<String, TerminologyResourceEntry> entries = new HashMap<>();
|
||||
|
||||
public void generateExpansionPackage() throws IOException {
|
||||
if (output == null) {
|
||||
throw new Error("No output");
|
||||
}
|
||||
|
||||
|
||||
var npm = load();
|
||||
System.out.println("Finding ValueSets");
|
||||
for (String res : npm.listResources("StructureDefinition")) {
|
||||
StructureDefinition sd = (StructureDefinition) new JsonParser().parse(npm.loadResource(res));
|
||||
processSD(sd, npm.id());
|
||||
|
||||
}
|
||||
System.out.println("Generating Expansions");
|
||||
for (String n : Utilities.sorted(entries.keySet())) {
|
||||
TerminologyResourceEntry e = entries.get(n);
|
||||
try {
|
||||
System.out.print("Generate Expansion for "+n+" ... ");
|
||||
ValueSetExpansionOutcome exp = context.expandVS(e.valueSet, true, hierarchical);
|
||||
if (exp.isOk()) {
|
||||
e.valueSet.setExpansion(exp.getValueset().getExpansion());
|
||||
System.out.println("OK");
|
||||
} else {
|
||||
e.valueSet.setExpansion(null);
|
||||
e.error = exp.getError();
|
||||
System.out.println(exp.getError());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error= "+ex.getMessage());
|
||||
e.error = ex.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Producing Output");
|
||||
switch (outputType) {
|
||||
case FOLDER:
|
||||
produceFolder();
|
||||
break;
|
||||
case TGZ:
|
||||
producePackage(npm);
|
||||
break;
|
||||
case ZIP:
|
||||
produceZip();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
System.out.println("Done");
|
||||
}
|
||||
|
||||
private void produceZip() throws IOException {
|
||||
ZipGenerator zip = new ZipGenerator(output);
|
||||
Set<String> names = new HashSet<>();
|
||||
names.add("manifest");
|
||||
if (json) {
|
||||
zip.addBytes("manifest.json", new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(expansionParameters), false);
|
||||
} else {
|
||||
zip.addBytes("manifest.xml", new XmlParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(expansionParameters), false);
|
||||
}
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (String n : Utilities.sorted(entries.keySet())) {
|
||||
TerminologyResourceEntry e = entries.get(n);
|
||||
String name = e.valueSet.getIdBase();
|
||||
int i = 0;
|
||||
while (names.contains(name)) {
|
||||
i++;
|
||||
name = e.valueSet.getIdBase()+i;
|
||||
}
|
||||
names.add(name);
|
||||
if (e.error == null) {
|
||||
b.append(name+","+n+", , "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
} else {
|
||||
b.append(name+","+n+", \""+Utilities.escapeCSV(e.error)+"\", "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
}
|
||||
if (json) {
|
||||
zip.addBytes(name+".json", new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(e.valueSet), false);
|
||||
} else {
|
||||
zip.addBytes(name+".xml", new XmlParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(e.valueSet), false);
|
||||
}
|
||||
}
|
||||
zip.addBytes("valuesets.csv", b.toString().getBytes(StandardCharsets.UTF_8), false);
|
||||
zip.close();
|
||||
}
|
||||
|
||||
private void producePackage(NpmPackage npm) throws FHIRException, IOException {
|
||||
JsonObject j = new JsonObject();
|
||||
j.add("name", npm.id()+".custom.extensions");
|
||||
j.add("version", npm.version());
|
||||
j.add("tools-version", 3);
|
||||
j.add("type", "Conformance");
|
||||
j.forceArray("fhirVersions").add(npm.fhirVersion());
|
||||
j.forceObject("dependencies").add(VersionUtilities.packageForVersion(npm.fhirVersion()), npm.fhirVersion());
|
||||
|
||||
NPMPackageGenerator gen = new NPMPackageGenerator(output, j, new Date(), true);
|
||||
|
||||
Set<String> names = new HashSet<>();
|
||||
names.add("manifest");
|
||||
if (json) {
|
||||
gen.addFile("package", "manifest.json", new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(expansionParameters));
|
||||
} else {
|
||||
gen.addFile("package", "manifest.xml", new XmlParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(expansionParameters));
|
||||
}
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (String n : Utilities.sorted(entries.keySet())) {
|
||||
TerminologyResourceEntry e = entries.get(n);
|
||||
String name = e.valueSet.getIdBase();
|
||||
int i = 0;
|
||||
while (names.contains(name)) {
|
||||
i++;
|
||||
name = e.valueSet.getIdBase()+i;
|
||||
}
|
||||
names.add(name);
|
||||
if (e.error == null) {
|
||||
b.append(name+","+n+", , "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
} else {
|
||||
b.append(name+","+n+", \""+Utilities.escapeCSV(e.error)+"\", "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
}
|
||||
if (json) {
|
||||
gen.addFile("package",name+".json", new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(e.valueSet));
|
||||
} else {
|
||||
gen.addFile("package",name+".xml", new XmlParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(e.valueSet));
|
||||
}
|
||||
}
|
||||
gen.addFile("other","valuesets.csv", b.toString().getBytes(StandardCharsets.UTF_8));
|
||||
gen.finish();
|
||||
}
|
||||
|
||||
private void produceFolder() throws IOException {
|
||||
Utilities.createDirectory(output);
|
||||
Utilities.clearDirectory(output);
|
||||
Set<String> names = new HashSet<>();
|
||||
names.add("manifest");
|
||||
if (json) {
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(output, "manifest.json")), expansionParameters);
|
||||
} else {
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(output, "manifest.xml")), expansionParameters);
|
||||
}
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (String n : Utilities.sorted(entries.keySet())) {
|
||||
TerminologyResourceEntry e = entries.get(n);
|
||||
String name = e.valueSet.getIdBase();
|
||||
int i = 0;
|
||||
while (names.contains(name)) {
|
||||
i++;
|
||||
name = e.valueSet.getIdBase()+i;
|
||||
}
|
||||
names.add(name);
|
||||
if (e.error == null) {
|
||||
b.append(name+","+n+", , "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
} else {
|
||||
b.append(name+","+n+", \""+Utilities.escapeCSV(e.error)+"\", "+CommaSeparatedStringBuilder.join(";",e.sources)+"\r\n");
|
||||
}
|
||||
if (json) {
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(output, name+".json")), e.valueSet);
|
||||
} else {
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(output, name+".xml")), e.valueSet);
|
||||
}
|
||||
}
|
||||
TextFile.stringToFile(b.toString(), Utilities.path(output, "valuesets.csv"));
|
||||
}
|
||||
|
||||
private void processSD(StructureDefinition sd, String packageId) {
|
||||
// System.out.println("Found Structure: "+sd.getVersionedUrl());
|
||||
for (ElementDefinition ed : sd.getDifferential().getElement()) {
|
||||
if (ed.hasBinding() && ed.getBinding().hasValueSet()) {
|
||||
// TerminologyResourceEntry e = new TerminologyResourceEntry();
|
||||
processValueSet(ed.getBinding().getValueSet(), packageId+":"+sd.getVersionedUrl()+"#"+ed.getId());
|
||||
}
|
||||
}
|
||||
if (scope != ExpansionPackageGeneratorScope.IG_ONLY && sd.getBaseDefinition() != null) {
|
||||
StructureDefinition bsd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
if (!bsd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition") || scope == ExpansionPackageGeneratorScope.EVERYTHING) {
|
||||
processSD(bsd, bsd.getSourcePackage().getVID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processValueSet(String valueSet, String source) {
|
||||
String url = cu.pinValueSet(valueSet);
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, url);
|
||||
if (vs != null) {
|
||||
TerminologyResourceEntry e = entries.get(vs.getVersionedUrl());
|
||||
if (e == null) {
|
||||
e = new TerminologyResourceEntry();
|
||||
e.sources.add(source);
|
||||
e.valueSet = vs;
|
||||
entries.put(vs.getVersionedUrl(), e);
|
||||
source = vs.getSourcePackage().getVID()+":"+vs.getVersionedUrl();
|
||||
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
||||
for (CanonicalType v : inc.getValueSet()) {
|
||||
if (v.hasValue()) {
|
||||
processValueSet(v.primitiveValue(), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
|
||||
for (CanonicalType v : inc.getValueSet()) {
|
||||
if (v.hasValue()) {
|
||||
processValueSet(v.primitiveValue(), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
e.sources.add(source);
|
||||
}
|
||||
|
||||
} else {
|
||||
System.out.println("Unable to resolve value set "+valueSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private NpmPackage load() throws IOException {
|
||||
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build();
|
||||
NpmPackage npm = pcm.loadPackage(packageId);
|
||||
if (context == null) {
|
||||
String v = npm.fhirVersion();
|
||||
NpmPackage core = pcm.loadPackage(VersionUtilities.packageForVersion(v));
|
||||
NpmPackage tho = pcm.loadPackage("hl7.terminology");
|
||||
System.out.println("Load FHIR from "+core.name()+"#"+core.version());
|
||||
SimpleWorkerContext ctxt = new SimpleWorkerContext.SimpleWorkerContextBuilder().withAllowLoadingDuplicates(true).fromPackage(core);
|
||||
TerminologyClientFactory factory = new TerminologyClientFactory(ctxt.getVersion());
|
||||
ctxt.connectToTSServer(factory, "http://tx.fhir.org", ctxt.getUserAgent(), null, true);
|
||||
var loader = new IgLoader(pcm, ctxt, ctxt.getVersion());
|
||||
loader.loadPackage(tho, true);
|
||||
loader.loadPackage(npm, true);
|
||||
context = ctxt;
|
||||
} else {
|
||||
var loader = new IgLoader(pcm, (SimpleWorkerContext) context, context.getVersion());
|
||||
loader.loadPackage(npm, true);
|
||||
}
|
||||
context.setExpansionParameters(expansionParameters);
|
||||
cu = new ContextUtilities(context);
|
||||
return npm;
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.formats.IParser;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
||||
@ -66,6 +67,11 @@ public class TxServiceTestHelper {
|
||||
if (p.hasParameter("activeOnly") && "true".equals(p.getParameterString("activeOnly"))) {
|
||||
options = options.setActiveOnly(true);
|
||||
}
|
||||
for (ParametersParameterComponent pp : p.getParameter()) {
|
||||
if (Utilities.existsInList(pp.getName(), "valueset-version", "system-version", "force-system-version", "default-system-version")) {
|
||||
context.getExpansionParameters().getParameter().add(pp);
|
||||
}
|
||||
}
|
||||
context.getExpansionParameters().clearParameters("includeAlternateCodes");
|
||||
for (Parameters.ParametersParameterComponent pp : p.getParameter()) {
|
||||
if ("includeAlternateCodes".equals(pp.getName())) {
|
||||
|
11
org.hl7.fhir.validation/src/main/resources/help/tx-pack.txt
Normal file
11
org.hl7.fhir.validation/src/main/resources/help/tx-pack.txt
Normal file
@ -0,0 +1,11 @@
|
||||
You can use the validator to generate a package containing all the terminology resources for
|
||||
an Implementation Guide. To do this, you must provide a specific parameter:
|
||||
|
||||
-tx-pack {package-id}
|
||||
|
||||
-tx-pack requires the parameter -output. All parameters:
|
||||
|
||||
- output {file|folder}: a named file or folder. If it's a file, it must end with .tgz or .zip
|
||||
- format xml may be used to specify xml instead of json.
|
||||
- scope ig|igs|all - which to include value sets etc from dependent IGs or core as well
|
||||
- expansion-parameters {file} - specifies the expansion parameters to use - this can supply fixed versions for code systems and value sets
|
@ -86,6 +86,9 @@ public class ValidatorCliTests {
|
||||
@Spy
|
||||
CodeGenTask codeGenTask;
|
||||
|
||||
@Spy
|
||||
TxPackTask txPackTask;
|
||||
|
||||
@Spy
|
||||
ScanTask scanTask = new ScanTask() {
|
||||
@Override
|
||||
@ -122,6 +125,7 @@ public class ValidatorCliTests {
|
||||
transformTask,
|
||||
versionTask,
|
||||
codeGenTask,
|
||||
txPackTask,
|
||||
//validate is the default
|
||||
validateTask
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user