Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core into validator_gui

This commit is contained in:
markiantorno 2020-04-16 20:28:25 -04:00
commit d3733b3409
53 changed files with 1522 additions and 485 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -14,6 +14,13 @@
<dependencies>
<!-- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<optional>true</optional>
</dependency>
<!-- HAPI Dependencies -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>

View File

@ -0,0 +1,297 @@
package org.hl7.fhir.convertors;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.hl7.fhir.dstu2.model.ClaimResponse.ErrorsComponent;
import org.hl7.fhir.dstu2.model.Resource;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.NpmPackageIndexBuilder;
import org.hl7.fhir.utilities.cache.NpmPackage.NpmPackageFolder;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import com.google.common.base.Charsets;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
public class NpmPackageVersionConverter {
private class PR2Handler implements VersionConvertorAdvisor40 {
@Override
public boolean ignoreEntry(BundleEntryComponent src) {
return false;
}
@Override
public Resource convertR2(org.hl7.fhir.r4.model.Resource resource) throws FHIRException {
throw new Error("Not done yet");
}
@Override
public org.hl7.fhir.dstu2016may.model.Resource convertR2016May(org.hl7.fhir.r4.model.Resource resource) throws FHIRException {
throw new Error("Not done yet");
}
@Override
public org.hl7.fhir.dstu3.model.Resource convertR3(org.hl7.fhir.r4.model.Resource resource) throws FHIRException {
throw new Error("Not done yet");
}
@Override
public void handleCodeSystem(CodeSystem tgtcs, ValueSet source) throws FHIRException {
throw new Error("Not done yet");
}
@Override
public CodeSystem getCodeSystem(ValueSet src) throws FHIRException {
throw new Error("Not done yet");
}
}
private static final int BUFFER_SIZE = 1024;
private String source;
private String dest;
private String version;
private String currentVersion;
private String vCode;
private List<String> errors = new ArrayList<>();
public static void main(String[] args) throws IOException {
NpmPackageVersionConverter self = new NpmPackageVersionConverter(args[0], args[1], args[2]);
self.execute();
System.out.println("Finished");
for (String s : self.errors) {
System.out.println(s);
}
}
public NpmPackageVersionConverter(String source, String dest, String version) {
super();
this.source = source;
this.dest = dest;
this.vCode = version;
this.version = VersionUtilities.versionFromCode(version);
}
public List<String> getErrors() {
return errors;
}
public void execute() throws IOException {
GzipCompressorInputStream gzipIn;
try {
gzipIn = new GzipCompressorInputStream(new FileInputStream(source));
} catch (Exception e) {
throw new IOException("Error reading "+source+": "+e.getMessage(), e);
}
Map<String, byte[]> content = new HashMap<>();
try (TarArchiveInputStream tarIn = new TarArchiveInputStream(gzipIn)) {
TarArchiveEntry entry;
while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) {
String n = entry.getName();
if (!entry.isDirectory()) {
int count;
byte data[] = new byte[BUFFER_SIZE];
ByteArrayOutputStream fos = new ByteArrayOutputStream();
try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
while ((count = tarIn.read(data, 0, BUFFER_SIZE)) != -1) {
dest.write(data, 0, count);
}
}
fos.close();
content.put(n, fos.toByteArray());
}
}
}
Map<String, byte[]> output = new HashMap<>();
output.put("package/package.json", convertPackage(content.get("package/package.json")));
for (Entry<String, byte[]> e : content.entrySet()) {
if (!e.getKey().equals("package/package.json")) {
byte[] cnv = e.getValue();
try {
JsonObject json = JsonTrackingParser.parseJson(e.getValue());
if (json.has("resourceType")) {
cnv = convertResource(e.getKey(), e.getValue());
}
} catch (Exception ex) {
}
if (cnv != null && cnv.length > 0) {
output.put(e.getKey(), cnv);
}
}
}
TarArchiveOutputStream tar;
ByteArrayOutputStream OutputStream;
BufferedOutputStream bufferedOutputStream;
GzipCompressorOutputStream gzipOutputStream;
OutputStream = new ByteArrayOutputStream();
bufferedOutputStream = new BufferedOutputStream(OutputStream);
gzipOutputStream = new GzipCompressorOutputStream(bufferedOutputStream);
tar = new TarArchiveOutputStream(gzipOutputStream);
Map<String, NpmPackageIndexBuilder> indexers = new HashMap<>();
for (Entry<String, byte[]> e : output.entrySet()) {
String n = e.getKey().substring(0, e.getKey().lastIndexOf("/"));
String s = e.getKey().substring(n.length()+1);
byte[] b = e.getValue();
NpmPackageIndexBuilder indexer = indexers.get(n);
if (indexer == null) {
indexer = new NpmPackageIndexBuilder();
indexer.start();
indexers.put(n, indexer);
}
indexer.seeFile(s, b);
if (!s.equals(".index.json") && !s.equals("package.json")) {
TarArchiveEntry entry = new TarArchiveEntry(e.getKey());
entry.setSize(b.length);
tar.putArchiveEntry(entry);
tar.write(b);
tar.closeArchiveEntry();
}
}
for (Entry<String, NpmPackageIndexBuilder> e : indexers.entrySet()) {
byte[] cnt = e.getValue().build().getBytes(Charset.forName("UTF-8"));
TarArchiveEntry entry = new TarArchiveEntry(e.getKey()+"/.index.json");
entry.setSize(cnt.length);
tar.putArchiveEntry(entry);
tar.write(cnt);
tar.closeArchiveEntry();
}
byte[] cnt = output.get("package/package.json");
TarArchiveEntry entry = new TarArchiveEntry("package/package.json");
entry.setSize(cnt.length);
tar.putArchiveEntry(entry);
tar.write(cnt);
tar.closeArchiveEntry();
tar.finish();
tar.close();
gzipOutputStream.close();
bufferedOutputStream.close();
OutputStream.close();
byte[] b = OutputStream.toByteArray();
TextFile.bytesToFile(b, dest);
}
private byte[] convertPackage(byte[] cnt) throws IOException {
JsonObject json = JsonTrackingParser.parseJson(cnt);
currentVersion = json.getAsJsonArray("fhirVersions").get(0).getAsString();
json.remove("fhirVersions");
json.remove("dependencies");
JsonArray fv = new JsonArray();
json.add("fhirVersions", fv);
fv.add(version);
JsonObject dep = new JsonObject();
json.add("dependencies", dep);
dep.addProperty(VersionUtilities.packageForVersion(version), version);
return JsonTrackingParser.write(json).getBytes(Charsets.UTF_8);
}
private byte[] convertResource(String n, byte[] cnt) {
try {
if (VersionUtilities.isR2Ver(currentVersion)) {
org.hl7.fhir.dstu2.model.Resource res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(cnt);
if (VersionUtilities.isR2Ver(version)) {
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(res);
} else if (VersionUtilities.isR2BVer(version)) {
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertor_14_30.convertResource(VersionConvertor_10_30.convertResource(res)));
} else if (VersionUtilities.isR3Ver(version)) {
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertor_10_30.convertResource(res));
} else if (VersionUtilities.isR4Ver(version)) {
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertor_10_40.convertResource(res));
} else if (VersionUtilities.isR5Ver(version)) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertor_10_50.convertResource(res));
}
} else if (VersionUtilities.isR2BVer(currentVersion)) {
org.hl7.fhir.dstu2016may.model.Resource res = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(cnt);
if (VersionUtilities.isR2Ver(version)) {
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertor_10_30.convertResource(VersionConvertor_14_30.convertResource(res)));
} else if (VersionUtilities.isR2BVer(version)) {
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(res);
} else if (VersionUtilities.isR3Ver(version)) {
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertor_14_30.convertResource(res));
} else if (VersionUtilities.isR4Ver(version)) {
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertor_14_40.convertResource(res));
} else if (VersionUtilities.isR5Ver(version)) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertor_14_50.convertResource(res));
}
} else if (VersionUtilities.isR3Ver(currentVersion)) {
org.hl7.fhir.dstu3.model.Resource res = new org.hl7.fhir.dstu3.formats.JsonParser().parse(cnt);
if (VersionUtilities.isR2Ver(version)) {
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertor_10_30.convertResource(res));
} else if (VersionUtilities.isR2BVer(version)) {
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertor_14_30.convertResource(res));
} else if (VersionUtilities.isR3Ver(version)) {
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(res);
} else if (VersionUtilities.isR4Ver(version)) {
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertor_30_40.convertResource(res, false));
} else if (VersionUtilities.isR5Ver(version)) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertor_30_50.convertResource(res, false));
}
} else if (VersionUtilities.isR4Ver(currentVersion)) {
org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(cnt);
if (VersionUtilities.isR2Ver(version)) {
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertor_10_40.convertResource(res, new PR2Handler()));
} else if (VersionUtilities.isR2BVer(version)) {
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertor_14_40.convertResource(res));
} else if (VersionUtilities.isR3Ver(version)) {
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertor_30_40.convertResource(res, true));
} else if (VersionUtilities.isR4Ver(version)) {
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res);
} else if (VersionUtilities.isR5Ver(version)) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertor_40_50.convertResource(res));
}
} else if (VersionUtilities.isR5Ver(currentVersion)) {
org.hl7.fhir.r5.model.Resource res = new org.hl7.fhir.r5.formats.JsonParser().parse(cnt);
if (VersionUtilities.isR2Ver(version)) {
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertor_10_50.convertResource(res));
} else if (VersionUtilities.isR2BVer(version)) {
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertor_14_50.convertResource(res));
} else if (VersionUtilities.isR3Ver(version)) {
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertor_30_50.convertResource(res, true));
} else if (VersionUtilities.isR4Ver(version)) {
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertor_40_50.convertResource(res));
} else if (VersionUtilities.isR5Ver(version)) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(res);
}
}
throw new Error("Unknown version "+currentVersion+" -> "+version);
} catch (Exception ex) {
ex.printStackTrace();
errors.add("Error converting "+n+": "+ex.getMessage());
return null;
}
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -193,10 +193,15 @@ public abstract class MetadataResource extends DomainResource {
* @param value {@link #url} (An absolute URI that is used to identify this metadata resource when it is referenced in a specification, model, design or an instance. This SHALL be a URL, SHOULD be globally unique, and SHOULD be an address at which this metadata resource is (or will be) published. The URL SHOULD include the major version of the metadata resource. For more information see [Technical and Business Versions](resource.html#versions).). This is the underlying object with id, value and extensions. The accessor "getUrl" gives direct access to the value
*/
public MetadataResource setUrlElement(UriType value) {
checkCanUseUrl();
this.url = value;
return this;
}
protected void checkCanUseUrl() {
// it's fine
}
/**
* @return An absolute URI that is used to identify this metadata resource when it is referenced in a specification, model, design or an instance. This SHALL be a URL, SHOULD be globally unique, and SHOULD be an address at which this metadata resource is (or will be) published. The URL SHOULD include the major version of the metadata resource. For more information see [Technical and Business Versions](resource.html#versions).
*/
@ -211,6 +216,7 @@ public abstract class MetadataResource extends DomainResource {
if (Utilities.noString(value))
this.url = null;
else {
checkCanUseUrl();
if (this.url == null)
this.url = new UriType();
this.url.setValue(value);
@ -1049,6 +1055,7 @@ public abstract class MetadataResource extends DomainResource {
return fhirType()+"["+getUrl()+"]";
}
// end addition
}

View File

@ -2093,6 +2093,11 @@ public class NamingSystem extends MetadataResource {
*/
public static final ca.uhn.fhir.rest.gclient.TokenClientParam STATUS = new ca.uhn.fhir.rest.gclient.TokenClientParam(SP_STATUS);
@Override
protected void checkCanUseUrl() {
throw new Error("URL cannot be used on NamingSystem");
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -192,11 +192,16 @@ public abstract class MetadataResource extends DomainResource {
/**
* @param value {@link #url} (An absolute URI that is used to identify this metadata resource when it is referenced in a specification, model, design or an instance; also called its canonical identifier. This SHOULD be globally unique and SHOULD be a literal address at which at which an authoritative instance of this metadata resource is (or will be) published. This URL can be the target of a canonical reference. It SHALL remain the same when the metadata resource is stored on different servers.). This is the underlying object with id, value and extensions. The accessor "getUrl" gives direct access to the value
*/
public MetadataResource setUrlElement(UriType value) {
public MetadataResource setUrlElement(UriType value) {
checkCanUseUrl();
this.url = value;
return this;
}
protected void checkCanUseUrl() {
// it's fine
}
/**
* @return An absolute URI that is used to identify this metadata resource when it is referenced in a specification, model, design or an instance; also called its canonical identifier. This SHOULD be globally unique and SHOULD be a literal address at which at which an authoritative instance of this metadata resource is (or will be) published. This URL can be the target of a canonical reference. It SHALL remain the same when the metadata resource is stored on different servers.
*/
@ -211,6 +216,7 @@ public abstract class MetadataResource extends DomainResource {
if (Utilities.noString(value))
this.url = null;
else {
checkCanUseUrl();
if (this.url == null)
this.url = new UriType();
this.url.setValue(value);

View File

@ -2096,5 +2096,11 @@ public class NamingSystem extends MetadataResource {
public static final ca.uhn.fhir.rest.gclient.TokenClientParam STATUS = new ca.uhn.fhir.rest.gclient.TokenClientParam(SP_STATUS);
@Override
protected void checkCanUseUrl() {
throw new Error("URL cannot be used on NamingSystem");
}
}

View File

@ -51,6 +51,9 @@ package org.hl7.fhir.r4.model;
import java.net.URI;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
@DatatypeDef(name = "uuid", profileOf = UriType.class)
public class UuidType extends UriType {
private static final long serialVersionUID = 3L;

View File

@ -214,8 +214,6 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
private String getValueSetSystem() throws FHIRException {
if (valueset == null)
throw new FHIRException("Unable to resolve system - no value set");
if (valueset.getCompose().hasExclude())
throw new FHIRException("Unable to resolve system - value set has excludes");
if (valueset.getCompose().getInclude().size() == 0) {
if (!valueset.hasExpansion() || valueset.getExpansion().getContains().size() == 0)
throw new FHIRException("Unable to resolve system - value set has no includes or expansion");

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -40,6 +40,7 @@ import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory;
import org.hl7.fhir.r5.context.TerminologyCache.CacheToken;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
@ -134,7 +135,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private Object lock = new Object(); // used as a lock for the data that follows
protected String version;
private Map<String, Map<String, Resource>> allResourcesById = new HashMap<String, Map<String, Resource>>();
// all maps are to the full URI
@ -230,7 +230,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
}
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies) {
// nothing yet
}
public void cacheResource(Resource r) throws FHIRException {
cacheResourceFromPackage(r, null);
}
public void cacheResourceFromPackage(Resource r, PackageVersion packageInfo) throws FHIRException {
synchronized (lock) {
Map<String, Resource> map = allResourcesById.get(r.fhirType());
if (map == null) {
@ -254,31 +262,31 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if ("1.4.0".equals(version)) {
fixOldSD(sd);
}
structures.see(sd);
structures.see(sd, packageInfo);
} else if (r instanceof ValueSet)
valueSets.see((ValueSet) m);
valueSets.see((ValueSet) m, packageInfo);
else if (r instanceof CodeSystem)
codeSystems.see((CodeSystem) m);
codeSystems.see((CodeSystem) m, packageInfo);
else if (r instanceof ImplementationGuide)
guides.see((ImplementationGuide) m);
guides.see((ImplementationGuide) m, packageInfo);
else if (r instanceof CapabilityStatement)
capstmts.see((CapabilityStatement) m);
capstmts.see((CapabilityStatement) m, packageInfo);
else if (r instanceof Measure)
measures.see((Measure) m);
measures.see((Measure) m, packageInfo);
else if (r instanceof Library)
libraries.see((Library) m);
libraries.see((Library) m, packageInfo);
else if (r instanceof SearchParameter)
searchParameters.see((SearchParameter) m);
searchParameters.see((SearchParameter) m, packageInfo);
else if (r instanceof PlanDefinition)
plans.see((PlanDefinition) m);
plans.see((PlanDefinition) m, packageInfo);
else if (r instanceof OperationDefinition)
operations.see((OperationDefinition) m);
operations.see((OperationDefinition) m, packageInfo);
else if (r instanceof Questionnaire)
questionnaires.see((Questionnaire) m);
questionnaires.see((Questionnaire) m, packageInfo);
else if (r instanceof ConceptMap)
maps.see((ConceptMap) m);
maps.see((ConceptMap) m, packageInfo);
else if (r instanceof StructureMap)
transforms.see((StructureMap) m);
transforms.see((StructureMap) m, packageInfo);
else if (r instanceof NamingSystem)
systems.add((NamingSystem) r);
}
@ -802,9 +810,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
this.allowLoadingDuplicates = allowLoadingDuplicates;
}
@SuppressWarnings("unchecked")
@Override
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException {
return fetchResourceWithException(class_, uri, null);
}
@SuppressWarnings("unchecked")
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, CanonicalResource source) throws FHIRException {
if (uri == null) {
return null;
}
@ -822,31 +834,31 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
uri = uri.substring(0, uri.indexOf("#"));
if (class_ == Resource.class || class_ == null) {
if (structures.has(uri))
return (T) structures.get(uri);
return (T) structures.get(uri, version);
if (guides.has(uri))
return (T) guides.get(uri);
return (T) guides.get(uri, version);
if (capstmts.has(uri))
return (T) capstmts.get(uri);
return (T) capstmts.get(uri, version);
if (measures.has(uri))
return (T) measures.get(uri);
return (T) measures.get(uri, version);
if (libraries.has(uri))
return (T) libraries.get(uri);
return (T) libraries.get(uri, version);
if (valueSets.has(uri))
return (T) valueSets.get(uri);
return (T) valueSets.get(uri, version);
if (codeSystems.has(uri))
return (T) codeSystems.get(uri);
return (T) codeSystems.get(uri, version);
if (operations.has(uri))
return (T) operations.get(uri);
return (T) operations.get(uri, version);
if (searchParameters.has(uri))
return (T) searchParameters.get(uri);
return (T) searchParameters.get(uri, version);
if (plans.has(uri))
return (T) plans.get(uri);
return (T) plans.get(uri, version);
if (maps.has(uri))
return (T) maps.get(uri);
return (T) maps.get(uri, version);
if (transforms.has(uri))
return (T) transforms.get(uri);
return (T) transforms.get(uri, version);
if (questionnaires.has(uri))
return (T) questionnaires.get(uri);
return (T) questionnaires.get(uri, version);
for (Map<String, Resource> rt : allResourcesById.values()) {
for (Resource r : rt.values()) {
if (r instanceof CanonicalResource) {
@ -858,47 +870,41 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
return null;
} else if (class_ == ImplementationGuide.class) {
return (T) guides.get(uri);
return (T) guides.get(uri, version);
} else if (class_ == CapabilityStatement.class) {
return (T) capstmts.get(uri);
return (T) capstmts.get(uri, version);
} else if (class_ == Measure.class) {
return (T) measures.get(uri);
return (T) measures.get(uri, version);
} else if (class_ == Library.class) {
return (T) libraries.get(uri);
return (T) libraries.get(uri, version);
} else if (class_ == StructureDefinition.class) {
return (T) structures.get(uri);
return (T) structures.get(uri, version);
} else if (class_ == StructureMap.class) {
return (T) transforms.get(uri);
return (T) transforms.get(uri, version);
} else if (class_ == ValueSet.class) {
if (valueSets.has(uri, version))
return (T) valueSets.get(uri, version);
else
return (T) valueSets.get(uri);
return (T) valueSets.get(uri, version);
} else if (class_ == CodeSystem.class) {
if (codeSystems.has(uri, version))
return (T) codeSystems.get(uri, version);
else
return (T) codeSystems.get(uri);
} else if (class_ == ConceptMap.class) {
return (T) maps.get(uri);
return (T) maps.get(uri, version);
} else if (class_ == PlanDefinition.class) {
return (T) plans.get(uri);
return (T) plans.get(uri, version);
} else if (class_ == OperationDefinition.class) {
OperationDefinition od = operations.get(uri);
OperationDefinition od = operations.get(uri, version);
return (T) od;
} else if (class_ == Questionnaire.class) {
return (T) questionnaires.get(uri);
return (T) questionnaires.get(uri, version);
} else if (class_ == SearchParameter.class) {
SearchParameter res = searchParameters.get(uri);
SearchParameter res = searchParameters.get(uri, version);
return (T) res;
}
if (class_ == CodeSystem.class && codeSystems.has(uri))
return (T) codeSystems.get(uri);
return (T) codeSystems.get(uri, version);
if (class_ == ValueSet.class && valueSets.has(uri))
return (T) valueSets.get(uri);
return (T) valueSets.get(uri, version);
if (class_ == Questionnaire.class)
return (T) questionnaires.get(uri);
return (T) questionnaires.get(uri, version);
if (class_ == null) {
if (uri.matches(Constants.URI_REGEX) && !uri.contains("ValueSet"))
return null;
@ -966,9 +972,17 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
}
public <T extends Resource> T fetchResource(Class<T> class_, String uri, CanonicalResource source) {
try {
return fetchResourceWithException(class_, uri, source);
} catch (FHIRException e) {
throw new Error(e);
}
}
public <T extends Resource> T fetchResource(Class<T> class_, String uri) {
try {
return fetchResourceWithException(class_, uri);
return fetchResourceWithException(class_, uri, null);
} catch (FHIRException e) {
throw new Error(e);
}

View File

@ -11,6 +11,7 @@ import java.util.UUID;
import org.hl7.fhir.r5.context.BaseWorkerContext.MetadataResourceVersionComparator;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalListSorter;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.utilities.VersionUtilities;
@ -35,11 +36,39 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
}
public class MetadataResourceVersionComparator<T extends CanonicalResource> implements Comparator<T> {
private class CachedCanonicalResource<T1 extends CanonicalResource> {
private T1 resource;
private PackageVersion packageInfo;
public CachedCanonicalResource(T1 resource, PackageVersion packageInfo) {
super();
this.resource = resource;
this.packageInfo = packageInfo;
}
public T1 getResource() {
return resource;
}
public PackageVersion getPackageInfo() {
return packageInfo;
}
public String getUrl() {
return resource.getUrl();
}
public String getId() {
return resource.getId();
}
public String getVersion() {
return resource.getVersion();
}
public boolean hasVersion() {
return resource.hasVersion();
}
}
public class MetadataResourceVersionComparator<T1 extends CachedCanonicalResource<T>> implements Comparator<T1> {
@Override
public int compare(T arg1, T arg2) {
String v1 = arg1.getVersion();
String v2 = arg2.getVersion();
public int compare(T1 arg1, T1 arg2) {
String v1 = arg1.getResource().getVersion();
String v2 = arg2.getResource().getVersion();
if (v1 == null && v2 == null) {
return Integer.compare(list.indexOf(arg1), list.indexOf(arg2)); // retain original order
} else if (v1 == null) {
@ -58,9 +87,8 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
}
private boolean enforceUniqueId;
private List<T> list = new ArrayList<>();
private List<CachedCanonicalResource<T>> list = new ArrayList<>();
private Map<String, T> map = new HashMap<>();
@ -76,14 +104,26 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
map.putAll(source.map);
}
public void see(T r) {
public void see(T r, PackageVersion packgeInfo) {
if (!r.hasId()) {
r.setId(UUID.randomUUID().toString());
}
if (enforceUniqueId && map.containsKey(r.getId())) {
drop(r.getId());
}
list.add(r);
// special case logic for UTG support prior to version 5
if (packgeInfo != null && packgeInfo.getId().startsWith("hl7.terminology")) {
List<CachedCanonicalResource<T>> toDrop = new ArrayList<>();
for (CachedCanonicalResource<T> n : list) {
if (n.getResource().getUrl().equals(r.getUrl()) && isBasePackage(n.getPackageInfo())) {
toDrop.add(n);
}
}
for (CachedCanonicalResource<T> n : toDrop) {
drop(n.getId());
}
}
list.add(new CachedCanonicalResource<T>(r, packgeInfo));
map.put(r.getId(), r); // we do this so we can drop by id
if (r.hasUrl()) {
@ -95,30 +135,34 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
}
private boolean isBasePackage(PackageVersion packageInfo) {
return packageInfo == null ? false : VersionUtilities.isCorePackage(packageInfo.getId());
}
private void updateList(String url, String version) {
List<T> rl = new ArrayList<T>();
for (T t : list) {
List<CachedCanonicalResource<T>> rl = new ArrayList<>();
for (CachedCanonicalResource<T> t : list) {
if (url.equals(t.getUrl()) && !rl.contains(t)) {
rl.add(t);
}
}
if (rl.size() > 0) {
// sort by version as much as we are able
Collections.sort(rl, new MetadataResourceVersionComparator<T>());
Collections.sort(rl, new MetadataResourceVersionComparator<CachedCanonicalResource<T>>());
// the current is the latest
map.put(url, rl.get(rl.size()-1));
map.put(url, rl.get(rl.size()-1).getResource());
// now, also, the latest for major/minor
if (version != null) {
T latest = null;
for (T t : rl) {
if (VersionUtilities.versionsCompatible(t.getVersion(), version)) {
latest = t;
for (CachedCanonicalResource<T> t : rl) {
if (VersionUtilities.versionsCompatible(t.getResource().getVersion(), version)) {
latest = t.getResource();
}
}
if (latest != null) { // might be null if it's not using semver
String lv = VersionUtilities.getMajMin(latest.getVersion());
if (lv != null && !lv.equals(version))
map.put(url+"|"+lv, rl.get(rl.size()-1));
map.put(url+"|"+lv, rl.get(rl.size()-1).getResource());
}
}
}
@ -134,13 +178,17 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
public T get(String system, String version) {
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version);
String mm = VersionUtilities.getMajMin(version);
if (mm != null)
return map.get(system+"|"+mm);
else
return null;
if (version == null) {
return get(system);
} else {
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version);
String mm = VersionUtilities.getMajMin(version);
if (mm != null)
return map.get(system+"|"+mm);
else
return null;
}
}
public boolean has(String system, String version) {
@ -158,10 +206,10 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
public void drop(String id) {
T res = null;
CachedCanonicalResource<T> res = null;
do {
res = null;
for (T t : list) {
for (CachedCanonicalResource<T> t : list) {
if (t.getId().equals(id)) {
res = t;
}
@ -184,11 +232,15 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
public void listAll(List<T> result) {
result.addAll(list);
for (CachedCanonicalResource<T> t : list) {
result.add(t.getResource());
}
}
public void listAllM(List<CanonicalResource> result) {
result.addAll(list);
for (CachedCanonicalResource<T> t : list) {
result.add(t.getResource());
}
}
public void clear() {
@ -199,21 +251,16 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
public List<T> getList() {
List<T> res = new ArrayList<>();
for (T t : list) {
if (!res.contains(t)) {
res.add(t);
for (CachedCanonicalResource<T> t : list) {
if (!res.contains(t.getResource())) {
res.add(t.getResource());
}
}
return res;
}
public List<T> getSortedList() {
List<T> res = new ArrayList<>();
for (T t : list) {
if (!res.contains(t)) {
res.add(t);
}
}
List<T> res = getList();
Collections.sort(res, new CanonicalListSorter());
return res;
}

View File

@ -32,6 +32,7 @@ import org.fhir.ucum.UcumService;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.ParserType;
import org.hl7.fhir.r5.model.CodeSystem;
@ -77,6 +78,33 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
*/
public interface IWorkerContext {
public class PackageVersion {
private String id;
private String version;
public PackageVersion(String source) {
if (source == null) {
throw new Error("Source cannot be null");
}
if (!source.contains("#")) {
throw new FHIRException("Source ");
}
id = source.substring(0, source.indexOf("#"));
version = source.substring(source.indexOf("#")+1);
}
public PackageVersion(String id, String version) {
super();
this.id = id;
this.version = version;
}
public String getId() {
return id;
}
public String getVersion() {
return version;
}
}
/**
* Get the versions of the definitions loaded in context
* @return
@ -172,6 +200,17 @@ public interface IWorkerContext {
public <T extends Resource> T fetchResource(Class<T> class_, String uri);
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
/** has the same functionality as fetchResource, but passes in information about the source of the
* reference (this may affect resolution of version)
*
* @param <T>
* @param class_
* @param uri
* @param canonicalForSource
* @return
*/
public <T extends Resource> T fetchResource(Class<T> class_, String uri, CanonicalResource canonicalForSource);
/**
* Variation of fetchResource when you have a string type, and don't need the right class
*
@ -204,12 +243,37 @@ public interface IWorkerContext {
* cache a resource for later retrieval using fetchResource.
*
* Note that various context implementations will have their own ways of loading
* rseources, and not all need implement cacheResource
* rseources, and not all need implement cacheResource.
*
* If the resource is loaded out of a package, call cacheResourceFromPackage instead
* @param res
* @throws FHIRException
*/
public void cacheResource(Resource res) throws FHIRException;
/**
* cache a resource for later retrieval using fetchResource.
*
* The package information is used to help manage the cache internally, and to
* help with reference resolution. Packages should be define using cachePackage (but don't have to be)
*
* Note that various context implementations will have their own ways of loading
* rseources, and not all need implement cacheResource
*
* @param res
* @throws FHIRException
*/
public void cacheResourceFromPackage(Resource res, PackageVersion packageDetails) throws FHIRException;
/**
* Inform the cache about package dependencies. This can be used to help resolve references
*
* Note that the cache doesn't load dependencies
*
* @param packageInfo
*/
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies);
// -- profile services ---------------------------------------------------------
/**

View File

@ -208,19 +208,19 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return res;
}
public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source) throws IOException, FHIRException {
SimpleWorkerContext res = new SimpleWorkerContext();
for (String name : source.keySet()) {
res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), null, null);
}
return res;
}
// public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source) throws IOException, FHIRException {
// SimpleWorkerContext res = new SimpleWorkerContext();
// for (String name : source.keySet()) {
// res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), null, null);
// }
// return res;
// }
public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException {
public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source, IContextResourceLoader loader, PackageVersion pi) throws FileNotFoundException, IOException, FHIRException {
SimpleWorkerContext res = new SimpleWorkerContext();
for (String name : source.keySet()) {
try {
res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), loader, null);
res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), loader, null, pi);
} catch (Exception e) {
System.out.println("Error loading "+name+": "+e.getMessage());
throw new FHIRException("Error loading "+name+": "+e.getMessage(), e);
@ -229,11 +229,11 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return res;
}
private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter) throws IOException, FHIRException {
private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException {
if (name.endsWith(".xml"))
loadFromFile(stream, name, loader, filter);
else if (name.endsWith(".json"))
loadFromFileJson(stream, name, loader, filter);
loadFromFileJson(stream, name, loader, filter, pi);
else if (name.equals("version.info"))
readVersionInfo(stream);
else
@ -291,7 +291,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
private void loadFromFileJson(InputStream stream, String name, IContextResourceLoader loader, ILoadFilter filter) throws IOException, FHIRException {
private void loadFromFileJson(InputStream stream, String name, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException {
Bundle f = null;
try {
if (loader != null)
@ -302,7 +302,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
if (r instanceof Bundle)
f = (Bundle) r;
else if (filter == null || filter.isOkToLoad(f)) {
cacheResource(r);
cacheResourceFromPackage(r, pi);
}
}
} catch (FHIRFormatError e1) {
@ -311,7 +311,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
if (f != null)
for (BundleEntryComponent e : f.getEntry()) {
if (filter == null || filter.isOkToLoad(e.getResource())) {
cacheResource(e.getResource());
cacheResourceFromPackage(e.getResource(), pi);
}
}
}
@ -326,7 +326,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
for (String s : pi.listResources(loader.getTypes())) {
try {
loadDefinitionItem(s, pi.load("package", s), loader, filter);
loadDefinitionItem(s, pi.load("package", s), loader, filter, new PackageVersion(pi.id(), pi.version()));
} catch (FHIRException | IOException e) {
throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, s, pi.name(), pi.version(), e.getMessage()), e);
}
@ -344,9 +344,9 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
System.out.println("Load Package "+pi.name()+"#"+pi.version());
}
if (types.length == 0)
types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"};
types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem" };
for (String s : pi.listResources(types)) {
loadDefinitionItem(s, pi.load("package", s), loader, null);
loadDefinitionItem(s, pi.load("package", s), loader, null, new PackageVersion(pi.id(), pi.version()));
}
for (String s : pi.list("other")) {
binaries.put(s, TextFile.streamToBytes(pi.load("other", s)));
@ -357,14 +357,14 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
public void loadFromFile(String file, IContextResourceLoader loader) throws IOException, FHIRException {
loadDefinitionItem(file, new CSFileInputStream(file), loader, null);
loadDefinitionItem(file, new CSFileInputStream(file), loader, null, null);
}
private void loadFromStream(InputStream stream, IContextResourceLoader loader) throws IOException, FHIRException {
ZipInputStream zip = new ZipInputStream(stream);
ZipEntry ze;
while ((ze = zip.getNextEntry()) != null) {
loadDefinitionItem(ze.getName(), zip, loader, null);
loadDefinitionItem(ze.getName(), zip, loader, null, null);
zip.closeEntry();
}
zip.close();

View File

@ -364,8 +364,8 @@ public class Element extends Base {
if (p.getName().equals(e.getName()))
t = c;
}
if (t > i)
i = t;
if (t >= i)
i = t+1;
if (p.getName().equals(name) || p.getName().equals(name+"[x]")) {
Element ne = new Element(name, p);
children.add(i, ne);

View File

@ -24,6 +24,7 @@ package org.hl7.fhir.r5.elementmodel;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
@ -37,34 +38,40 @@ import org.hl7.fhir.r5.model.StructureDefinition;
public class Manager {
//TODO use EnumMap
public enum FhirFormat {
XML("xml"),
JSON("json"),
TURTLE("ttl"),
TEXT("txt"),
VBAR("hl7");
final String extension;
FhirFormat(String extension) {
this.extension = extension;
}
public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR;
public String getExtension() {
return this.extension;
}
private static final Map<String, FhirFormat> lookup = new HashMap<>();
static {
for(FhirFormat ff : FhirFormat.values()) {
lookup.put(ff.getExtension(), ff);
switch (this) {
case JSON:
return "json";
case TURTLE:
return "ttl";
case XML:
return "xml";
case TEXT:
return "txt";
case VBAR:
return "hl7";
}
return null;
}
public static FhirFormat get(String extension) {
return lookup.get(extension);
public static FhirFormat getFhirFormat(String code) {
switch (code) {
case "json":
return JSON;
case "ttl":
return TURTLE;
case "xml":
return XML;
case "txt":
return TEXT;
case "hl7":
return VBAR;
}
return null;
}
}
public static Element parse(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException {

View File

@ -159,12 +159,12 @@ public class XmlParser extends ParserBase {
private int line(Node node) {
XmlLocationData loc = (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : loc.getStartLine();
}
private int col(Node node) {
XmlLocationData loc = (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : loc.getStartColumn();
}
@ -253,22 +253,38 @@ public class XmlParser extends ParserBase {
List<Property> properties = element.getProperty().getChildProperties(element.getName(), XMLUtil.getXsiType(node));
String text = XMLUtil.getDirectText(node).trim();
int line = line(node);
int col = col(node);
if (!Utilities.noString(text)) {
Property property = getTextProp(properties);
if (property != null) {
if ("ED.data[x]".equals(property.getDefinition().getId()) || (property.getDefinition()!=null && property.getDefinition().getBase()!=null && "ED.data[x]".equals(property.getDefinition().getBase().getPath()))) {
if ("B64".equals(node.getAttribute("representation"))) {
element.getChildren().add(new Element("dataBase64Binary", property, "base64Binary", text).markLocation(line(node), col(node)));
element.getChildren().add(new Element("dataBase64Binary", property, "base64Binary", text).markLocation(line, col));
} else {
element.getChildren().add(new Element("dataString", property, "string", text).markLocation(line(node), col(node)));
element.getChildren().add(new Element("dataString", property, "string", text).markLocation(line, col));
}
} else {
element.getChildren().add(
new Element(property.getName(), property, property.getType(), text).markLocation(line(node), col(node)));
new Element(property.getName(), property, property.getType(), text).markLocation(line, col));
}
}
else {
logError(line(node), col(node), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT), IssueSeverity.ERROR);
Node n = node.getFirstChild();
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE && !Utilities.noString(n.getTextContent().trim())) {
while (n.getNextSibling() != null && n.getNodeType() != Node.ELEMENT_NODE) {
n = n.getNextSibling();
}
while (n.getPreviousSibling() != null && n.getNodeType() != Node.ELEMENT_NODE) {
n = n.getPreviousSibling();
}
line = line(n);
col = col(n);
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, text), IssueSeverity.ERROR);
}
n = n.getNextSibling();
}
}
}
@ -276,7 +292,7 @@ public class XmlParser extends ParserBase {
Node attr = node.getAttributes().item(i);
String value = attr.getNodeValue();
if (!validAttrValue(value)) {
logError(line(node), col(node), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR);
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR);
}
if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) {
Property property = getAttrProp(properties, attr.getNodeName());
@ -287,7 +303,7 @@ public class XmlParser extends ParserBase {
if (property.getName().equals("value") && element.isPrimitive())
element.setValue(av);
else
element.getChildren().add(new Element(property.getName(), property, property.getType(), av).markLocation(line(node), col(node)));
element.getChildren().add(new Element(property.getName(), property, property.getType(), av).markLocation(line, col));
} else {
boolean ok = false;
if (FormatUtilities.FHIR_NS.equals(node.getNamespaceURI())) {
@ -298,7 +314,7 @@ public class XmlParser extends ParserBase {
ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content
ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so
if (!ok)
logError(line(node), col(node), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
}
}
}

View File

@ -235,8 +235,6 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
private String getValueSetSystem() throws FHIRException {
if (valueset == null)
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__NO_VALUE_SET));
if (valueset.getCompose().hasExclude())
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_EXCLUDES));
if (valueset.getCompose().getInclude().size() == 0) {
if (!valueset.hasExpansion() || valueset.getExpansion().getContains().size() == 0)
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_NO_INCLUDES_OR_EXPANSION));

View File

@ -68,6 +68,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.NoTerminologyServiceException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
@ -319,7 +320,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
}
if (source.hasCompose())
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), expParams, source.getUrl(), focus.getExpansion().getExtension());
handleCompose(source.getCompose(), focus.getExpansion(), expParams, source.getUrl(), focus.getExpansion().getExtension());
if (canBeHeirarchy) {
for (ValueSetExpansionContainsComponent c : roots) {
@ -372,12 +373,12 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
return null;
}
private void handleCompose(ValueSetComposeComponent compose, List<ValueSetExpansionParameterComponent> params, Parameters expParams, String ctxt, List<Extension> extensions)
private void handleCompose(ValueSetComposeComponent compose, ValueSetExpansionComponent exp, Parameters expParams, String ctxt, List<Extension> extensions)
throws ETooCostly, FileNotFoundException, IOException, FHIRException {
compose.checkNoModifiers("ValueSet.compose", "expanding");
// Exclude comes first because we build up a map of things to exclude
for (ConceptSetComponent inc : compose.getExclude())
excludeCodes(inc, params, ctxt);
excludeCodes(inc, exp.getParameter(), ctxt);
canBeHeirarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty();
boolean first = true;
for (ConceptSetComponent inc : compose.getInclude()) {
@ -385,12 +386,12 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
first = false;
else
canBeHeirarchy = false;
includeCodes(inc, params, expParams, canBeHeirarchy, extensions);
includeCodes(inc, exp, expParams, canBeHeirarchy, extensions);
}
}
private ValueSet importValueSet(String value, List<ValueSetExpansionParameterComponent> params, Parameters expParams) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
private ValueSet importValueSet(String value, ValueSetExpansionComponent exp, Parameters expParams) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
if (value == null)
throw new TerminologyServiceException("unable to find value set with no identity");
ValueSet vs = context.fetchResource(ValueSet.class, value);
@ -400,11 +401,20 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (vso.getError() != null)
throw new TerminologyServiceException("Unable to expand imported value set: " + vso.getError());
if (vs.hasVersion())
if (!existsInParams(params, "version", new UriType(vs.getUrl() + "|" + vs.getVersion())))
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
if (!existsInParams(exp.getParameter(), "version", new UriType(vs.getUrl() + "|" + vs.getVersion())))
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
for (Extension ex : vso.getValueset().getExpansion().getExtension()) {
if (ex.getUrl().equals("http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
if (ex.getValue() instanceof BooleanType) {
exp.getExtension().add(new Extension("http://hl7.org/fhir/StructureDefinition/valueset-toocostly").setValue(new UriType(value)));
} else {
exp.getExtension().add(ex);
}
}
}
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
if (!existsInParams(params, p.getName(), p.getValue()))
params.add(p);
if (!existsInParams(exp.getParameter(), p.getName(), p.getValue()))
exp.getParameter().add(p);
}
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
return vso.getValueset();
@ -418,11 +428,11 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
}
}
private void includeCodes(ConceptSetComponent inc, List<ValueSetExpansionParameterComponent> params, Parameters expParams, boolean heirarchical, List<Extension> extensions) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
private void includeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, boolean heirarchical, List<Extension> extensions) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
inc.checkNoModifiers("Compose.include", "expanding");
List<ValueSet> imports = new ArrayList<ValueSet>();
for (UriType imp : inc.getValueSet()) {
imports.add(importValueSet(imp.getValue(), params, expParams));
imports.add(importValueSet(imp.getValue(), exp, expParams));
}
if (!inc.hasSystem()) {
@ -435,27 +445,27 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
} else {
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE)) {
doServerIncludeCodes(inc, heirarchical, params, imports, expParams, extensions);
doServerIncludeCodes(inc, heirarchical, exp, imports, expParams, extensions);
} else {
doInternalIncludeCodes(inc, params, expParams, imports, cs);
doInternalIncludeCodes(inc, exp, expParams, imports, cs);
}
}
}
private void doServerIncludeCodes(ConceptSetComponent inc, boolean heirarchical, List<ValueSetExpansionParameterComponent> params, List<ValueSet> imports, Parameters expParams, List<Extension> extensions) throws FHIRException {
private void doServerIncludeCodes(ConceptSetComponent inc, boolean heirarchical, ValueSetExpansionComponent exp, List<ValueSet> imports, Parameters expParams, List<Extension> extensions) throws FHIRException {
ValueSetExpansionOutcome vso = context.expandVS(inc, heirarchical);
if (vso.getError() != null) {
throw new TerminologyServiceException("Unable to expand imported value set: " + vso.getError());
}
ValueSet vs = vso.getValueset();
if (vs.hasVersion()) {
if (!existsInParams(params, "version", new UriType(vs.getUrl() + "|" + vs.getVersion()))) {
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
if (!existsInParams(exp.getParameter(), "version", new UriType(vs.getUrl() + "|" + vs.getVersion()))) {
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
}
}
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
if (!existsInParams(params, p.getName(), p.getValue())) {
params.add(p);
if (!existsInParams(exp.getParameter(), p.getName(), p.getValue())) {
exp.getParameter().add(p);
}
}
for (Extension ex : vs.getExpansion().getExtension()) {
@ -479,7 +489,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
return false;
}
public void doInternalIncludeCodes(ConceptSetComponent inc, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> imports,
public void doInternalIncludeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, List<ValueSet> imports,
CodeSystem cs) throws NoTerminologyServiceException, TerminologyServiceException, FHIRException {
if (cs == null) {
if (context.isNoTerminologyServer())
@ -491,8 +501,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (cs.getContent() != CodeSystemContentMode.COMPLETE)
throw new TerminologyServiceException("Code system " + inc.getSystem().toString() + " is incomplete");
if (cs.hasVersion())
if (!existsInParams(params, "version", new UriType(cs.getUrl() + "|" + cs.getVersion())))
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl() + "|" + cs.getVersion())));
if (!existsInParams(exp.getParameter(), "version", new UriType(cs.getUrl() + "|" + cs.getVersion())))
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl() + "|" + cs.getVersion())));
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
// special case - add all the code system

View File

@ -146,7 +146,7 @@ public class ToolsHelper {
String address = args[1];
String definitions = args[3];
SimpleWorkerContext context = SimpleWorkerContext.fromDefinitions(getDefinitions(definitions));
// SimpleWorkerContext context = SimpleWorkerContext.fromDefinitions(getDefinitions(definitions));
// if (address.startsWith("http:") || address.startsWith("http:")) {
// // this is on a restful interface

View File

@ -185,6 +185,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
@ -422,7 +423,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
throw new FHIRException("Error in template: Root element is not 'div'");
} catch (FHIRException | IOException e) {
x = new XhtmlNode(NodeType.Element, "div");
x.para().b().setAttribute("style", "color: maroon").tx("Exception generating Narrative: "+e.getMessage());
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
}
inject(r, x, NarrativeStatus.GENERATED);
return true;
@ -769,7 +770,13 @@ public class NarrativeGenerator implements INarrativeGenerator {
@Override
public void display(XhtmlNode x) {
throw new Error("Not done yet");
if (wrapped.hasChild("title") && wrapped.getChildValue("title") != null) {
x.tx(wrapped.getChildValue("title"));
} else if (wrapped.hasChild("name") && wrapped.getChildValue("name") != null) {
x.tx(wrapped.getChildValue("name"));
} else {
x.tx("??");
}
}
}
@ -1109,6 +1116,8 @@ public class NarrativeGenerator implements INarrativeGenerator {
private String basePath;
private String tooCostlyNoteEmpty;
private String tooCostlyNoteNotEmpty;
private String tooCostlyNoteEmptyDependent;
private String tooCostlyNoteNotEmptyDependent;
private IReferenceResolver resolver;
private int headerLevelContext;
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
@ -1118,6 +1127,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
private boolean noSlowLookup;
private List<String> codeSystemPropList = new ArrayList<>();
private ProfileUtilities profileUtilities;
private XVerExtensionManager xverManager;
public NarrativeGenerator(String prefix, String basePath, IWorkerContext context) {
super();
@ -1190,6 +1200,22 @@ public class NarrativeGenerator implements INarrativeGenerator {
}
public String getTooCostlyNoteEmptyDependent() {
return tooCostlyNoteEmptyDependent;
}
public void setTooCostlyNoteEmptyDependent(String tooCostlyNoteEmptyDependent) {
this.tooCostlyNoteEmptyDependent = tooCostlyNoteEmptyDependent;
}
public String getTooCostlyNoteNotEmptyDependent() {
return tooCostlyNoteNotEmptyDependent;
}
public void setTooCostlyNoteNotEmptyDependent(String tooCostlyNoteNotEmptyDependent) {
this.tooCostlyNoteNotEmptyDependent = tooCostlyNoteNotEmptyDependent;
}
// dom based version, for build program
public String generate(Element doc) throws IOException, org.hl7.fhir.exceptions.FHIRException {
return generate(null, doc);
@ -1225,7 +1251,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
} catch (Exception e) {
e.printStackTrace();
x.para().b().setAttribute("style", "color: maroon").tx("Exception generating Narrative: "+e.getMessage());
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
}
}
inject(er, x, NarrativeStatus.GENERATED);
@ -1239,7 +1265,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
generateByProfile(rc.resourceResource, profile, rc.resourceResource, profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), rc.resourceResource.getResourceType().toString()), x, rc.resourceResource.getResourceType().toString(), showCodeDetails, rc);
} catch (Exception e) {
e.printStackTrace();
x.para().b().setAttribute("style", "color: maroon").tx("Exception generating Narrative: "+e.getMessage());
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
}
inject(rc.resourceResource, x, NarrativeStatus.GENERATED);
return true;
@ -1252,7 +1278,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
generateByProfile(er, profile, er, profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), er.getLocalName()), x, er.getLocalName(), showCodeDetails);
} catch (Exception e) {
e.printStackTrace();
x.para().b().setAttribute("style", "color: maroon").tx("Exception generating Narrative: "+e.getMessage());
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
}
inject(er, x, NarrativeStatus.GENERATED);
String b = new XhtmlComposer(XhtmlComposer.XML, pretty).compose(x);
@ -1372,6 +1398,16 @@ public class NarrativeGenerator implements INarrativeGenerator {
Extension ex = (Extension) v.getBase();
String url = ex.getUrl();
StructureDefinition ed = context.fetchResource(StructureDefinition.class, url);
if (ed == null) {
if (xverManager == null) {
xverManager = new XVerExtensionManager(context);
}
if (xverManager.matchingUrl(url) && xverManager.status(url) == XVerExtensionStatus.Valid) {
ed = xverManager.makeDefinition(url);
context.generateSnapshot(ed);
context.cacheResource(ed);
}
}
if (p.getName().equals("modifierExtension") && ed == null)
throw new DefinitionException("Unknown modifier extension "+url);
PropertyWrapper pe = map.get(p.getName()+"["+url+"]");
@ -2521,22 +2557,23 @@ public class NarrativeGenerator implements INarrativeGenerator {
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
XhtmlNode td;
tr.td().colspan(Integer.toString(sources.size())).b().tx("Source Concept Details");
tr.td().colspan(Integer.toString(1+sources.size())).b().tx("Source Concept Details");
tr.td().b().tx("Relationship");
tr.td().colspan(Integer.toString(targets.size())).b().tx("Destination Concept Details");
if (comment)
tr.td().colspan(Integer.toString(1+targets.size())).b().tx("Destination Concept Details");
if (comment) {
tr.td().b().tx("Comment");
}
tr = tbl.tr();
if (sources.get("code").size() == 1) {
String url = sources.get("code").iterator().next();
renderCSDetailsLink(tr, url);
renderCSDetailsLink(tr, url, true);
} else
tr.td().b().tx("Code");
for (String s : sources.keySet()) {
if (!s.equals("code")) {
if (sources.get(s).size() == 1) {
String url = sources.get(s).iterator().next();
renderCSDetailsLink(tr, url);
renderCSDetailsLink(tr, url, false);
} else
tr.td().b().addText(getDescForConcept(s));
}
@ -2544,14 +2581,14 @@ public class NarrativeGenerator implements INarrativeGenerator {
tr.td();
if (targets.get("code").size() == 1) {
String url = targets.get("code").iterator().next();
renderCSDetailsLink(tr, url);
renderCSDetailsLink(tr, url, true);
} else
tr.td().b().tx("Code");
for (String s : targets.keySet()) {
if (!s.equals("code")) {
if (targets.get(s).size() == 1) {
String url = targets.get(s).iterator().next();
renderCSDetailsLink(tr, url);
renderCSDetailsLink(tr, url, false);
} else
tr.td().b().addText(getDescForConcept(s));
}
@ -2563,68 +2600,83 @@ public class NarrativeGenerator implements INarrativeGenerator {
SourceElementComponent ccl = grp.getElement().get(si);
boolean slast = si == grp.getElement().size()-1;
boolean first = true;
for (int ti = 0; ti < ccl.getTarget().size(); ti++) {
TargetElementComponent ccm = ccl.getTarget().get(ti);
boolean last = ti == ccl.getTarget().size()-1;
if (ccl.hasNoMap() && ccl.getNoMap()) {
tr = tbl.tr();
td = tr.td();
if (!first && !last)
td.setAttribute("style", "border-top-style: none; border-bottom-style: none");
else if (!first)
td.setAttribute("style", "border-top-style: none");
else if (!last)
td.setAttribute("style", "border-bottom-style: none");
if (first) {
if (sources.get("code").size() == 1)
td.addText(ccl.getCode());
td = tr.td().style("border-right-width: 0px");
if (!first)
td.style("border-top-style: none");
else
td.style("border-bottom-style: none");
if (sources.get("code").size() == 1)
td.addText(ccl.getCode());
else
td.addText(grp.getSource()+" / "+ccl.getCode());
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
tr.td().colspan("4").style("background-color: #efefef").tx("(not mapped)");
} else {
for (int ti = 0; ti < ccl.getTarget().size(); ti++) {
TargetElementComponent ccm = ccl.getTarget().get(ti);
boolean last = ti == ccl.getTarget().size()-1;
tr = tbl.tr();
td = tr.td().style("border-right-width: 0px");
if (!first && !last)
td.style("border-top-style: none; border-bottom-style: none");
else if (!first)
td.style("border-top-style: none");
else if (!last)
td.style("border-bottom-style: none");
if (first) {
if (sources.get("code").size() == 1)
td.addText(ccl.getCode());
else
td.addText(grp.getSource()+" / "+ccl.getCode());
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
}
for (String s : sources.keySet()) {
if (!s.equals("code")) {
td = tr.td();
if (first) {
td.addText(getValue(ccm.getDependsOn(), s, sources.get(s).size() != 1));
display = getDisplay(ccm.getDependsOn(), s);
if (display != null)
td.tx(" ("+display+")");
}
}
}
first = false;
if (!ccm.hasRelationship())
tr.td().tx(":"+"("+ConceptMapRelationship.EQUIVALENT.toCode()+")");
else {
if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
tr.td().ah(eqpath+"#"+code).tx(presentEquivalenceCode(code));
} else {
tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode()));
}
}
td = tr.td().style("border-right-width: 0px");
if (targets.get("code").size() == 1)
td.addText(ccm.getCode());
else
td.addText(grp.getSource()+" / "+ccl.getCode());
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
if (display != null)
td.tx(" ("+display+")");
}
for (String s : sources.keySet()) {
if (!s.equals("code")) {
td = tr.td();
if (first) {
td.addText(getValue(ccm.getDependsOn(), s, sources.get(s).size() != 1));
display = getDisplay(ccm.getDependsOn(), s);
td.addText(grp.getTarget()+" / "+ccm.getCode());
display = getDisplayForConcept(grp.getTarget(), ccm.getCode());
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
for (String s : targets.keySet()) {
if (!s.equals("code")) {
td = tr.td();
td.addText(getValue(ccm.getProduct(), s, targets.get(s).size() != 1));
display = getDisplay(ccm.getProduct(), s);
if (display != null)
td.tx(" ("+display+")");
}
}
if (comment)
tr.td().addText(ccm.getComment());
}
first = false;
if (!ccm.hasRelationship())
tr.td().tx(":"+"("+ConceptMapRelationship.EQUIVALENT.toCode()+")");
else {
if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
tr.td().ah(eqpath+"#"+code).tx(presentEquivalenceCode(code));
} else {
tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode()));
}
}
td = tr.td();
if (targets.get("code").size() == 1)
td.addText(ccm.getCode());
else
td.addText(grp.getTarget()+" / "+ccm.getCode());
display = getDisplayForConcept(grp.getTarget(), ccm.getCode());
if (display != null)
td.tx(" ("+display+")");
for (String s : targets.keySet()) {
if (!s.equals("code")) {
td = tr.td();
td.addText(getValue(ccm.getProduct(), s, targets.get(s).size() != 1));
display = getDisplay(ccm.getProduct(), s);
if (display != null)
td.tx(" ("+display+")");
}
}
if (comment)
tr.td().addText(ccm.getComment());
}
addUnmapped(tbl, grp);
}
@ -2684,11 +2736,14 @@ public class NarrativeGenerator implements INarrativeGenerator {
}
}
public void renderCSDetailsLink(XhtmlNode tr, String url) {
public void renderCSDetailsLink(XhtmlNode tr, String url, boolean span2) {
CodeSystem cs;
XhtmlNode td;
cs = context.fetchCodeSystem(url);
td = tr.td();
if (span2) {
td.colspan("2");
}
td.b().tx("Code");
td.tx(" from ");
if (cs == null)
@ -3221,9 +3276,18 @@ public class NarrativeGenerator implements INarrativeGenerator {
if (vs.hasCopyright())
generateCopyright(x, vs);
}
if (ToolingExtensions.hasExtension(vs.getExpansion(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly"))
x.para().setAttribute("style", "border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? tooCostlyNoteEmpty : tooCostlyNoteNotEmpty );
else {
if (ToolingExtensions.hasExtension(vs.getExpansion(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
List<Extension> exl = vs.getExpansion().getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-toocostly");
boolean other = false;
for (Extension ex : exl) {
if (ex.getValue() instanceof BooleanType) {
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? tooCostlyNoteEmpty : tooCostlyNoteNotEmpty );
} else if (!other) {
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? tooCostlyNoteEmptyDependent : tooCostlyNoteNotEmptyDependent );
other = true;
}
}
} else {
Integer count = countMembership(vs);
if (count == null)
x.para().tx("This value set does not contain a fixed number of concepts");
@ -3294,48 +3358,117 @@ public class NarrativeGenerator implements INarrativeGenerator {
@SuppressWarnings("rawtypes")
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion) {
Map<String, String> versions = new HashMap<String, String>();
boolean firstVersion = true;
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
if (p.getName().equals("version")) {
String[] parts = ((PrimitiveType) p.getValue()).asStringValue().split("\\|");
if (parts.length == 2)
versions.put(parts[0], parts[1]);
if (!versions.isEmpty()) {
StringBuilder b = new StringBuilder();
if (firstVersion) {
// the first version
// set the <p> tag and style attribute
x.para().setAttribute("style", "border: black 1px dotted; background-color: #EEEEEE; padding: 8px");
firstVersion = false;
} else {
// the second (or greater) version
x.br(); // add line break before the version text
}
b.append("Expansion based on ");
boolean firstPart = true;
for (String s : versions.keySet()) {
if (firstPart)
firstPart = false;
else
b.append(", ");
if (!s.equals("http://snomed.info/sct"))
b.append(describeSystem(s)+" version "+versions.get(s));
else {
parts = versions.get(s).split("\\/");
if (parts.length >= 5) {
String m = describeModule(parts[4]);
if (parts.length == 7)
b.append("SNOMED CT "+m+" edition "+formatSCTDate(parts[6]));
else
b.append("SNOMED CT "+m+" edition");
} else
b.append(describeSystem(s)+" version "+versions.get(s));
}
}
x.addText(b.toString()); // add the version text
}
}
}
if (versions.size() > 1) {
XhtmlNode div = x.div().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
div.para().tx("Expansion based on: ");
XhtmlNode ul = div.ul();
for (String s : versions.keySet()) { // though there'll only be one
expRef(ul.li(), s, versions.get(s));
}
} else if (versions.size() == 1) {
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
p.tx("Expansion based on ");
for (String s : versions.keySet()) { // though there'll only be one
expRef(p, s, versions.get(s));
}
}
}
private void expRef(XhtmlNode x, String u, String v) {
// TODO Auto-generated method stub
if (u.equals("http://snomed.info/sct")) {
String[] parts = v.split("\\/");
if (parts.length >= 5) {
String m = describeModule(parts[4]);
if (parts.length == 7) {
x.tx("SNOMED CT "+m+" edition "+formatSCTDate(parts[6]));
} else {
x.tx("SNOMED CT "+m+" edition");
}
} else {
x.tx(describeSystem(u)+" version "+v);
}
} else if (u.equals("http://loinc.org")) {
String vd = describeLoincVer(v);
if (vd != null) {
x.tx("Loinc v"+v+" ("+vd+")");
} else {
x.tx("Loinc v"+v);
}
} else {
CanonicalResource cr = (CanonicalResource) context.fetchResource(Resource.class, u+"|"+v);
if (cr != null) {
if (cr.hasUserData("path")) {
x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")");
} else {
x.tx(describeSystem(u)+" v"+v+" ("+cr.fhirType()+")");
}
} else {
x.tx(describeSystem(u)+" version "+v);
}
}
}
private String describeLoincVer(String v) {
if ("2.67".equals(v)) return "Dec 2019";
if ("2.66".equals(v)) return "Jun 2019";
if ("2.65".equals(v)) return "Dec 2018";
if ("2.64".equals(v)) return "Jun 2018";
if ("2.63".equals(v)) return "Dec 2017";
if ("2.61".equals(v)) return "Jun 2017";
if ("2.59".equals(v)) return "Feb 2017";
if ("2.58".equals(v)) return "Dec 2016";
if ("2.56".equals(v)) return "Jun 2016";
if ("2.54".equals(v)) return "Dec 2015";
if ("2.52".equals(v)) return "Jun 2015";
if ("2.50".equals(v)) return "Dec 2014";
if ("2.48".equals(v)) return "Jun 2014";
if ("2.46".equals(v)) return "Dec 2013";
if ("2.44".equals(v)) return "Jun 2013";
if ("2.42".equals(v)) return "Dec 2012";
if ("2.40".equals(v)) return "Jun 2012";
if ("2.38".equals(v)) return "Dec 2011";
if ("2.36".equals(v)) return "Jun 2011";
if ("2.34".equals(v)) return "Dec 2010";
if ("2.32".equals(v)) return "Jun 2010";
if ("2.30".equals(v)) return "Feb 2010";
if ("2.29".equals(v)) return "Dec 2009";
if ("2.27".equals(v)) return "Jul 2009";
if ("2.26".equals(v)) return "Jan 2009";
if ("2.24".equals(v)) return "Jul 2008";
if ("2.22".equals(v)) return "Dec 2007";
if ("2.21".equals(v)) return "Jun 2007";
if ("2.19".equals(v)) return "Dec 2006";
if ("2.17".equals(v)) return "Jun 2006";
if ("2.16".equals(v)) return "Dec 2005";
if ("2.15".equals(v)) return "Jun 2005";
if ("2.14".equals(v)) return "Dec 2004";
if ("2.13".equals(v)) return "Aug 2004";
if ("2.12".equals(v)) return "Feb 2004";
if ("2.10".equals(v)) return "Oct 2003";
if ("2.09".equals(v)) return "May 2003";
if ("2.08 ".equals(v)) return "Sep 2002";
if ("2.07".equals(v)) return "Aug 2002";
if ("2.05".equals(v)) return "Feb 2002";
if ("2.04".equals(v)) return "Jan 2002";
if ("2.03".equals(v)) return "Jul 2001";
if ("2.02".equals(v)) return "May 2001";
if ("2.01".equals(v)) return "Jan 2001";
if ("2.00".equals(v)) return "Jan 2001";
if ("1.0n".equals(v)) return "Feb 2000";
if ("1.0ma".equals(v)) return "Aug 1999";
if ("1.0m".equals(v)) return "Jul 1999";
if ("1.0l".equals(v)) return "Jan 1998";
if ("1.0ja".equals(v)) return "Oct 1997";
return null;
}
private String formatSCTDate(String ds) {
@ -4582,30 +4715,33 @@ public class NarrativeGenerator implements INarrativeGenerator {
}
XhtmlNode t = x.table("clstu");
XhtmlNode tr = t.tr();
XhtmlNode td = tr.td();
if (list.has("date")) {
tr.td().tx("Date: "+list.get("date").dateTimeValue().toHumanDisplay());
td.tx("Date: "+list.get("date").dateTimeValue().toHumanDisplay());
}
if (list.has("mode")) {
tr.td().tx("Mode: "+list.get("mode").primitiveValue());
td.tx("Mode: "+list.get("mode").primitiveValue());
}
if (list.has("status")) {
tr.td().tx("Status: "+list.get("status").primitiveValue());
td.tx("Status: "+list.get("status").primitiveValue());
}
if (list.has("code")) {
tr.td().tx("Code: "+genCC(list.get("code")));
td.tx("Code: "+genCC(list.get("code")));
}
tr = t.tr();
if (list.has("subject")) {
shortForRef(tr.td().tx("Subject: "), list.get("subject"));
td.tx("Subject: ");
shortForRef(td, list.get("subject"));
}
if (list.has("encounter")) {
shortForRef(tr.td().tx("Encounter: "), list.get("encounter"));
shortForRef(td.tx("Encounter: "), list.get("encounter"));
}
if (list.has("source")) {
shortForRef(tr.td().tx("Source: "), list.get("encounter"));
td.tx("Source: ");
shortForRef(td, list.get("encounter"));
}
if (list.has("orderedBy")) {
tr.td().tx("Order: "+genCC(list.get("orderedBy")));
td.tx("Order: "+genCC(list.get("orderedBy")));
}
// for (Annotation a : list.getNote()) {
// renderAnnotation(a, x);
@ -4620,27 +4756,27 @@ public class NarrativeGenerator implements INarrativeGenerator {
}
t = x.table("grid");
tr = t.tr().style("backgound-color: #eeeeee");
tr.td().b().tx("Items");
td.b().tx("Items");
if (date) {
tr.td().tx("Date");
td.tx("Date");
}
if (flag) {
tr.td().tx("Flag");
td.tx("Flag");
}
if (deleted) {
tr.td().tx("Deleted");
td.tx("Deleted");
}
for (BaseWrapper e : list.children("entry")) {
tr = t.tr();
shortForRef(tr.td(), e.get("item"));
shortForRef(td, e.get("item"));
if (date) {
tr.td().tx(e.has("date") ? e.get("date").dateTimeValue().toHumanDisplay() : "");
td.tx(e.has("date") ? e.get("date").dateTimeValue().toHumanDisplay() : "");
}
if (flag) {
tr.td().tx(e.has("flag") ? genCC(e.get("flag")) : "");
td.tx(e.has("flag") ? genCC(e.get("flag")) : "");
}
if (deleted) {
tr.td().tx(e.has("deleted") ? e.get("deleted").primitiveValue() : "");
td.tx(e.has("deleted") ? e.get("deleted").primitiveValue() : "");
}
}
return false;
@ -4666,24 +4802,29 @@ public class NarrativeGenerator implements INarrativeGenerator {
}
}
private void shortForRef(XhtmlNode x, Base ref) {
String disp = ref.getChildByName("display").hasValues() ? ref.getChildByName("display").getValues().get(0).primitiveValue() : null;
if (ref.getChildByName("reference").hasValues()) {
String url = ref.getChildByName("reference").getValues().get(0).primitiveValue();
ResourceWithReference r = resolver.resolve(url);
if (r == null) {
if (disp == null) {
disp = url;
}
x.tx(disp);
} else {
r.resource.display(x.ah(r.reference));
}
} else if (disp != null) {
x.tx(disp);
private XhtmlNode shortForRef(XhtmlNode x, Base ref) {
if (ref == null) {
x.tx("(null)");
} else {
x.tx("??");
}
String disp = ref.getChildByName("display") != null && ref.getChildByName("display").hasValues() ? ref.getChildByName("display").getValues().get(0).primitiveValue() : null;
if (ref.getChildByName("reference").hasValues()) {
String url = ref.getChildByName("reference").getValues().get(0).primitiveValue();
ResourceWithReference r = resolver.resolve(url);
if (r == null) {
if (disp == null) {
disp = url;
}
x.tx(disp);
} else {
r.resource.display(x.ah(r.reference));
}
} else if (disp != null) {
x.tx(disp);
} else {
x.tx("??");
}
}
return x;
}
public boolean generate(ResourceContext rcontext, ImplementationGuide ig) throws EOperationOutcome, FHIRException, IOException {

View File

@ -1,4 +1,4 @@
package org.hl7.fhir.validation;
package org.hl7.fhir.r5.utils;
import java.io.IOException;
import java.util.Date;
@ -7,6 +7,7 @@ import java.util.Map;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
@ -38,6 +39,9 @@ public class XVerExtensionManager {
public XVerExtensionStatus status(String url) throws FHIRException {
String v = url.substring(20, 23);
if ("5.0".equals(v)) {
v = Constants.VERSION_MM;
}
String e = url.substring(54);
if (!lists.containsKey(v)) {
if (context.getBinaries().containsKey("xver-paths-"+v+".json")) {
@ -68,6 +72,9 @@ public class XVerExtensionManager {
public StructureDefinition makeDefinition(String url) {
String verSource = url.substring(20, 23);
if ("5.0".equals(verSource)) {
verSource = Constants.VERSION_MM;
}
String verTarget = VersionUtilities.getMajMin(context.getVersion());
String e = url.substring(54);
JsonObject root = lists.get(verSource);

View File

@ -22,7 +22,7 @@ import org.junit.runners.Suite.SuiteClasses;
ShexGeneratorTests.class,
BaseDateTimeTypeTest.class,
OpenApiGeneratorTest.class,
MetadataResourceManagerTester.class,
CanonicalResourceManagerTester.class,
MetaTest.class,
UtilitiesTests.class,
SnapShotGenerationTests.class})

View File

@ -3,12 +3,13 @@ package org.hl7.fhir.r5.test;
import static org.junit.Assert.*;
import org.hl7.fhir.r5.context.CanonicalResourceManager;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.ValueSet;
import org.junit.Assert;
import org.junit.Test;
public class MetadataResourceManagerTester {
public class CanonicalResourceManagerTester {
@Test
@ -20,13 +21,13 @@ public class MetadataResourceManagerTester {
// no version
mrm.clear();
mrm.see(vs);
mrm.see(vs, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("http://url/ValueSet/234"));
Assert.assertNotNull(mrm.get("2345"));
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0"));
mrm.see(vs);
mrm.see(vs, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("http://url/ValueSet/234"));
Assert.assertNotNull(mrm.get("2345"));
@ -54,7 +55,7 @@ public class MetadataResourceManagerTester {
vs.setVersion("4.0.1");
mrm.clear();
mrm.see(vs);
mrm.see(vs, null);
Assert.assertNotNull(mrm.get("2345"));
Assert.assertNotNull(mrm.get("http://url/ValueSet/234"));
@ -74,7 +75,7 @@ public class MetadataResourceManagerTester {
vs.setVersion("20140403");
mrm.clear();
mrm.see(vs);
mrm.see(vs, null);
Assert.assertNotNull(mrm.get("2345"));
Assert.assertNotNull(mrm.get("http://url/ValueSet/234"));
@ -99,7 +100,7 @@ public class MetadataResourceManagerTester {
vs2.setName("2");
mrm.clear();
mrm.see(vs1);
mrm.see(vs1, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("2345"));
@ -116,7 +117,7 @@ public class MetadataResourceManagerTester {
Assert.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1");
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
mrm.see(vs2);
mrm.see(vs2, null);
Assert.assertEquals(mrm.size(), 2);
Assert.assertNotNull(mrm.get("2345"));
@ -180,7 +181,7 @@ public class MetadataResourceManagerTester {
vs2.setName("2");
mrm.clear();
mrm.see(vs1);
mrm.see(vs1, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("2345"));
@ -197,7 +198,7 @@ public class MetadataResourceManagerTester {
Assert.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1");
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
mrm.see(vs2);
mrm.see(vs2, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("2345"));
@ -243,7 +244,7 @@ public class MetadataResourceManagerTester {
vs2.setName("2");
mrm.clear();
mrm.see(vs1);
mrm.see(vs1, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("2345"));
@ -260,7 +261,7 @@ public class MetadataResourceManagerTester {
Assert.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1");
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
mrm.see(vs2);
mrm.see(vs2, null);
Assert.assertEquals(mrm.size(), 2);
Assert.assertNotNull(mrm.get("2345"));
@ -315,7 +316,7 @@ public class MetadataResourceManagerTester {
vs2.setName("2");
mrm.clear();
mrm.see(vs1);
mrm.see(vs1, null);
Assert.assertEquals(mrm.size(), 1);
Assert.assertNotNull(mrm.get("2345"));
@ -332,7 +333,7 @@ public class MetadataResourceManagerTester {
Assert.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1");
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
mrm.see(vs2);
mrm.see(vs2, null);
Assert.assertEquals(mrm.size(), 2);
Assert.assertNotNull(mrm.get("2345"));
@ -371,4 +372,58 @@ public class MetadataResourceManagerTester {
Assert.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
}
@Test
public void testUTG1() {
CanonicalResourceManager<ValueSet> mrm = new CanonicalResourceManager<>(false);
ValueSet vs1 = new ValueSet();
vs1.setId("234");
vs1.setUrl("http://terminology.hl7.org/ValueSet/234");
vs1.setVersion("2.0.0");
vs1.setName("1");
ValueSet vs2 = new ValueSet();
vs2.setId("234");
vs2.setUrl("http://terminology.hl7.org/ValueSet/234");
vs2.setVersion("2000.0.0");
vs2.setName("2");
mrm.see(vs1, null);
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0"));
Assert.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("1"));
mrm.see(vs2, null);
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assert.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("2"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2000.0.0"));
}
@Test
public void testUTG2() {
CanonicalResourceManager<ValueSet> mrm = new CanonicalResourceManager<>(false);
ValueSet vs1 = new ValueSet();
vs1.setId("234");
vs1.setUrl("http://terminology.hl7.org/ValueSet/234");
vs1.setVersion("2.0.0");
vs1.setName("1");
ValueSet vs2 = new ValueSet();
vs2.setId("234");
vs2.setUrl("http://terminology.hl7.org/ValueSet/234");
vs2.setVersion("2000.0.0");
vs2.setName("2");
mrm.see(vs1, new PackageVersion("hl7.fhir.r4.core", "4.0.1"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0"));
Assert.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("1"));
mrm.see(vs2, new PackageVersion("hl7.terminology.r4", "4.0.1"));
Assert.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assert.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("2"));
Assert.assertNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0")); // this will get dropped completely because of UTG rules
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -93,7 +93,11 @@ public class CSVReader extends InputStreamReader {
}
public boolean has(String name) {
return cell(name) != null;
for (int i = 0; i < cols.length; i++) {
if (name.equals(cols[i].trim()))
return cell(name) != null;
}
return false;
}
public String cell(String name) {
@ -103,11 +107,15 @@ public class CSVReader extends InputStreamReader {
index = i;
}
if (index == -1)
throw new Error("no cell "+name);
throw new FHIRException("no cell "+name);
String s = cells.length >= index ? cells[index] : null;
if (Utilities.noString(s))
return null;
return s;
if (s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length()-2);
} else {
return s;
}
}
protected boolean parseBoolean(String column) {
@ -149,7 +157,7 @@ public class CSVReader extends InputStreamReader {
StringBuilder b = new StringBuilder();
boolean inQuote = false;
while (inQuote || (peek() != '\r' && peek() != '\n')) {
while (ready() && (inQuote || (peek() != '\r' && peek() != '\n'))) {
char c = peek();
next();
if (c == '"') {

View File

@ -834,6 +834,15 @@ public class Utilities {
return ch >= a && ch <= z;
}
public static boolean existsInList(String value, List<String> array) {
if (value == null)
return false;
for (String s : array)
if (value.equals(s))
return true;
return false;
}
public static boolean existsInList(String value, String... array) {
if (value == null)
return false;

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.utilities;
import org.hl7.fhir.exceptions.FHIRException;
/*-
* #%L
* org.hl7.fhir.r5
@ -194,4 +196,23 @@ public class VersionUtilities {
return i;
}
public static String versionFromCode(String version) {
if ("r2".equals(version)) {
return "1.0.2";
}
if ("r2b".equals(version)) {
return "1.4.0";
}
if ("r3".equals(version)) {
return "3.0.2";
}
if ("r4".equals(version)) {
return "4.0.1";
}
if ("r5".equals(version)) {
return CURRENT_FULL_VERSION;
}
throw new FHIRException("Unknown version "+version);
}
}

View File

@ -33,6 +33,7 @@ import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -53,6 +54,7 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage.IndexVersionSorter;
import org.hl7.fhir.utilities.cache.PackageCacheManager.PackageEntry;
import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType;
import org.hl7.fhir.utilities.json.JSONUtil;
@ -76,6 +78,16 @@ import com.google.gson.JsonObject;
*/
public class NpmPackage {
public class IndexVersionSorter implements Comparator<JsonObject> {
@Override
public int compare(JsonObject o0, JsonObject o1) {
String v0 = JSONUtil.str(o0, "version");
String v1 = JSONUtil.str(o1, "version");
return v0.compareTo(v1);
}
}
public static boolean isValidName(String pid) {
return pid.matches("^[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9\\-]*)+$");
}
@ -452,6 +464,86 @@ public class NpmPackage {
return new ByteArrayInputStream(folder.fetchFile(file));
}
/**
* get a stream that contains the contents of a resource in the base folder, by it's canonical URL
*
* @param url - the canonical URL of the resource (exact match only)
* @return null if it is not found
* @throws IOException
*/
public InputStream loadByCanonical(String canonical) throws IOException {
return loadByCanonicalVersion("package", canonical, null);
}
/**
* get a stream that contains the contents of a resource in the nominated folder, by it's canonical URL
*
* @param folder - one of the folders in the package (main folder is "package")
* @param url - the canonical URL of the resource (exact match only)
* @return null if it is not found
* @throws IOException
*/
public InputStream loadByCanonical(String folder, String canonical) throws IOException {
return loadByCanonicalVersion(folder, canonical, null);
}
/**
* get a stream that contains the contents of a resource in the base folder, by it's canonical URL
*
* @param url - the canonical URL of the resource (exact match only)
* @param version - the specified version (or null if the most recent)
*
* @return null if it is not found
* @throws IOException
*/
public InputStream loadByCanonicalVersion(String canonical, String version) throws IOException {
return loadByCanonicalVersion("package", canonical, version);
}
/**
* get a stream that contains the contents of a resource in the nominated folder, by it's canonical URL
*
* @param folder - one of the folders in the package (main folder is "package")
* @param url - the canonical URL of the resource (exact match only)
* @param version - the specified version (or null if the most recent)
*
* @return null if it is not found
* @throws IOException
*/
public InputStream loadByCanonicalVersion(String folder, String canonical, String version) throws IOException {
NpmPackageFolder f = folders.get(folder);
List<JsonObject> matches = new ArrayList<>();
for (JsonElement e : f.index.getAsJsonArray("files")) {
JsonObject file = (JsonObject) e;
if (canonical.equals(JSONUtil.str(file, "url"))) {
if (version != null && version.equals(JSONUtil.str(file, "version"))) {
return load("package", JSONUtil.str(file, "filename"));
} else if (version == null) {
matches.add(file);
}
}
if (matches.size() > 0) {
if (matches.size() == 1) {
return load("package", JSONUtil.str(matches.get(0), "filename"));
} else {
Collections.sort(matches, new IndexVersionSorter());
return load("package", JSONUtil.str(matches.get(matches.size()-1), "filename"));
}
}
}
return null;
}
/**
* get a stream that contains the contents of one of the files in the base package
*
* @param file
* @return
* @throws IOException
*/
public InputStream load(String file) throws IOException {
return load("package", file);
}
/**
* get a stream that contains the contents of one of the files in a folder
*
@ -495,6 +587,14 @@ public class NpmPackage {
return JSONUtil.str(npm, "name");
}
/**
* convenience method for getting the package id (which in NPM language is the same as the name)
* @return
*/
public String id() {
return JSONUtil.str(npm, "name");
}
public String date() {
return JSONUtil.str(npm, "date");
}

View File

@ -470,4 +470,36 @@ public class I18nConstants {
public static final String MEASURE_MR_SCORE_VALUE_INVALID_01 = "MEASURE_MR_SCORE_VALUE_INVALID_01";
public static final String MEASURE_MR_SCORE_FIXED = "MEASURE_MR_SCORE_FIXED";
public static final String MEASURE_MR_SCORE_UNIT_REQUIRED = "MEASURE_MR_SCORE_UNIT_REQUIRED";
public static final String MEASURE_M_CRITERIA_UNKNOWN = "MEASURE_M_CRITERIA_UNKNOWN";
public static final String MEASURE_M_CQL_NOT_FOUND = "MEASURE_M_CQL_NOT_FOUND";
public static final String MEASURE_M_CRITERIA_CQL_ERROR = "MEASURE_M_CRITERIA_CQL_ERROR";
public static final String MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB = "MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB";
public static final String MEASURE_M_CRITERIA_CQL_NO_LIB = "MEASURE_M_CRITERIA_CQL_NO_LIB";
public static final String MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND = "MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND";
public static final String MEASURE_M_CRITERIA_CQL_LIB_DUPL = "MEASURE_M_CRITERIA_CQL_LIB_DUPL";
public static final String MEASURE_M_CRITERIA_CQL_NO_ELM = "MEASURE_M_CRITERIA_CQL_NO_ELM";
public static final String MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID = "MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID";
public static final String MEASURE_M_CRITERIA_CQL_NOT_FOUND = "MEASURE_M_CRITERIA_CQL_NOT_FOUND";
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
//public static final String
}

View File

@ -483,6 +483,7 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
private int col;
private String location; // fhirPath
private String message;
private String messageId; // source, for grouping
private IssueType type;
private IssueSeverity level;
private String html;
@ -766,5 +767,14 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
this.sliceHtml = sliceHtml;
}
public String getMessageId() {
return messageId;
}
public ValidationMessage setMessageId(String messageId) {
this.messageId = messageId;
return this;
}
}

View File

@ -50,6 +50,7 @@ package org.hl7.fhir.utilities.xhtml;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -67,7 +68,8 @@ public class XhtmlNode implements IBaseXhtml {
private static final long serialVersionUID = -4362547161441436492L;
public static class Location {
public static class Location implements Serializable {
private static final long serialVersionUID = -4079302502900219721L;
private int line;
private int column;
public Location(int line, int column) {
@ -156,7 +158,7 @@ public class XhtmlNode implements IBaseXhtml {
{
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document))
throw new Error("Wrong node type. is "+nodeType.toString());
throw new Error("Wrong node type - node is "+nodeType.toString()+" ('"+getName()+"/"+getContent()+"')");
XhtmlNode node = new XhtmlNode(NodeType.Element);
node.setName(name);
childNodes.add(node);
@ -288,6 +290,9 @@ public class XhtmlNode implements IBaseXhtml {
}
public XhtmlNode setAttribute(String name, String value) {
if (nodeType != NodeType.Element) {
throw new Error("Attempt to set an attribute on something that is not an element");
}
getAttributes().put(name, value);
return this;
}
@ -523,6 +528,10 @@ public class XhtmlNode implements IBaseXhtml {
return setAttribute("colspan", n);
}
public XhtmlNode div() {
return addTag("div");
}
public XhtmlNode para() {
return addTag("p");
}
@ -636,7 +645,11 @@ public class XhtmlNode implements IBaseXhtml {
public XhtmlNode style(String style) {
setAttribute("style", style);
if (hasAttribute("style")) {
setAttribute("style", getAttribute("style")+"; "+style);
} else {
setAttribute("style", style);
}
return this;
}

View File

@ -458,6 +458,20 @@ public class XMLUtil {
return builder.parse(new ByteArrayInputStream(content.getBytes()));
}
public static Document parseToDom(byte[] content) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content));
}
public static Document parseToDom(byte[] content, boolean ns) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(ns);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content));
}
public static Document parseFileToDom(String filename) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);

View File

@ -142,23 +142,23 @@ Terminology_TX_Error_CodeableConcept = Error {0} validating CodeableConcept
Terminology_TX_Error_CodeableConcept_Max = Error {0} validating CodeableConcept using maxValueSet
Terminology_TX_Error_Coding1 = Error {0} validating Coding
Terminology_TX_Error_Coding2 = Error {0} validating Coding: {1}
Terminology_TX_NoValid_1 = None of the codes provided are in the value set {0} ({1}, and a code from this value set is required) (codes = {2})
Terminology_TX_NoValid_10 = The code provided is not in the maximum value set {0} ({1}, and a code from this value set is required) (code = {2}#{3})
Terminology_TX_NoValid_11 = The code provided is not in the maximum value set {0} ({1}{2}
Terminology_TX_NoValid_1 = None of the codes provided are in the value set {0} ({1}), and a code from this value set is required) (codes = {2})
Terminology_TX_NoValid_10 = The code provided is not in the maximum value set {0} ({1}), and a code from this value set is required) (code = {2}#{3})
Terminology_TX_NoValid_11 = The code provided is not in the maximum value set {0} ({1}{2})
Terminology_TX_NoValid_12 = The Coding provided is not in the value set {0}, and a code is required from this value set. {1}
Terminology_TX_NoValid_13 = The Coding provided is not in the value set {0}, and a code should come from this value set unless it has no suitable code. {1}
Terminology_TX_NoValid_14 = The Coding provided is not in the value set {0}, and a code is recommended to come from this value set. {1}
Terminology_TX_NoValid_15 = The value provided ("{0}") could not be validated in the absence of a terminology server
Terminology_TX_NoValid_16 = The value provided ("{0}") is not in the value set {1} ({2}, and a code is required from this value set){3}
Terminology_TX_NoValid_17 = The value provided ("{0}") is not in the value set {1} ({2}, and a code should come from this value set unless it has no suitable code){3}
Terminology_TX_NoValid_18 = The value provided ("{0}") is not in the value set {1} ({2}, and a code is recommended to come from this value set){3}
Terminology_TX_NoValid_2 = None of the codes provided are in the value set {0} ({1}, and a code should come from this value set unless it has no suitable code) (codes = {2})
Terminology_TX_NoValid_3 = None of the codes provided are in the value set {0} ({1}, and a code is recommended to come from this value set) (codes = {2})
Terminology_TX_NoValid_16 = The value provided ("{0}") is not in the value set {1} ({2}), and a code is required from this value set){3}
Terminology_TX_NoValid_17 = The value provided ("{0}") is not in the value set {1} ({2}), and a code should come from this value set unless it has no suitable code){3}
Terminology_TX_NoValid_18 = The value provided ("{0}") is not in the value set {1} ({2}), and a code is recommended to come from this value set){3}
Terminology_TX_NoValid_2 = None of the codes provided are in the value set {0} ({1}), and a code should come from this value set unless it has no suitable code) (codes = {2})
Terminology_TX_NoValid_3 = None of the codes provided are in the value set {0} ({1}), and a code is recommended to come from this value set) (codes = {2})
Terminology_TX_NoValid_4 = The Coding provided is not in the value set {0}, and a code is required from this value set{1}
Terminology_TX_NoValid_5 = The Coding provided is not in the value set {0}, and a code should come from this value set unless it has no suitable code{1}
Terminology_TX_NoValid_6 = The Coding provided is not in the value set {0}, and a code is recommended to come from this value set{1}
Terminology_TX_NoValid_7 = None of the codes provided could be validated against the maximum value set {0} ({1}), (error = {2})
Terminology_TX_NoValid_8 = None of the codes provided are in the maximum value set {0} ({1}, and a code from this value set is required) (codes = {2})
Terminology_TX_NoValid_8 = None of the codes provided are in the maximum value set {0} ({1}), and a code from this value set is required) (codes = {2})
Terminology_TX_NoValid_9 = The code provided could not be validated against the maximum value set {0} ({1}), (error = {2})
Terminology_TX_System_Invalid = Invalid System URI: {0}
Terminology_TX_System_NotKnown = Code System URI "{0}" is unknown so the code cannot be validated
@ -372,7 +372,7 @@ Node_type__is_not_allowed = Node type {0} is not allowed
CDATA_is_not_allowed = CDATA is not allowed
Undefined_element_ = Undefined element ''{0}''
Undefined_attribute__on__for_type__properties__ = Undefined attribute ''@{0}'' on {1} for type {2} (properties = {3})
Text_should_not_be_present = Text should not be present
Text_should_not_be_present = Text should not be present (''{0}'')
Wrong_namespace__expected_ = Wrong namespace - expected ''{0}''
Element_must_have_some_content = Element must have some content
No_processing_instructions_allowed_in_resources = No processing instructions allowed in resources
@ -469,4 +469,15 @@ MEASURE_MR_SCORE_UNIT_PROHIBITED = A measureScore for this Measure Scoring ({0})
MEASURE_MR_SCORE_VALUE_REQUIRED = A value is required when the Measure.scoring={0}
MEASURE_MR_SCORE_VALUE_INVALID_01 = The value is invalid - it must be between 0 and 1
MEASURE_MR_SCORE_FIXED = This value is fixed by the Measure to ''{0]''
MEASURE_MR_SCORE_UNIT_REQUIRED = A unit should be present when the scoring type is {0}
MEASURE_MR_SCORE_UNIT_REQUIRED = A unit should be present when the scoring type is {0}
MEASURE_M_CRITERIA_UNKNOWN = The expression language {0} is not supported, so can''t be validated
MEASURE_M_CQL_NOT_FOUND = None of the include CQL Libraries define a function {0}
MEASURE_M_CRITERIA_CQL_NO_LIB = No CQL Libraries found on this Measure
MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB = If the CQL expression does not include a namespace, there can only be one Library for the measure
MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND = No matching Library found for the namespace {0}
MEASURE_M_CRITERIA_CQL_LIB_DUPL = Multiple matching libraies found for the namespace {0}
MEASURE_M_CRITERIA_CQL_ERROR = Error in {0}: ''{1}''
MEASURE_M_CRITERIA_CQL_NO_ELM = Error in {0}: No compiled version of CQL found
MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID = = Error in {0}: Compiled version of CQL is not valid
MEASURE_M_CRITERIA_CQL_NOT_FOUND = The function {1} does not exist in the library {0}

View File

@ -1,5 +1,8 @@
package org.hl7.fhir.utilities.tests;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.Test;
import org.slf4j.Logger;
@ -71,4 +74,13 @@ public class XhtmlNodeTest {
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\"><img src=\"http://pbs.twimg.com/profile_images/544507893991485440/r_vo3uj2_bigger.png\" alt=\"Twitter Avatar\"/>@fhirabend</div>", output);
}
@Test
public void testSerializable() throws IOException {
XhtmlNode node = new XhtmlNode();
node.setValueAsString("<?xml version=\"1.0\" encoding=\"UTF-8\"?><div xmlns=\"http://www.w3.org/1999/xhtml\">Test</div>");
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.writeObject(node);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -103,6 +103,46 @@
<version>1.0.2</version>
</dependency>
<!-- CQL-to-ELM -->
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>cql</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>model</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>elm</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>cql-to-elm</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>quick</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>qdm</artifactId>
<version>1.4.9-SNAPSHOT</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.hl7.fhir.testcases</groupId>
<artifactId>fhir-test-cases</artifactId>
<version>${validator_test_case_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>

View File

@ -50,7 +50,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
*/
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r5.context.IWorkerContext;
@ -85,15 +85,15 @@ public class BaseValidator {
@Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL);
}
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL, null);
}
return thePass;
}
protected boolean fail(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String msg = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL);
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL, theMessage);
}
return thePass;
}
@ -109,11 +109,11 @@ public class BaseValidator {
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass) {
String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
*
@ -125,8 +125,8 @@ public class BaseValidator {
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, context.formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL);
}
addValidationMessage(errors, type, -1, -1, path, context.formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL, theMessage);
}
return thePass;
}
@ -140,8 +140,8 @@ public class BaseValidator {
@Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
}
return thePass;
}
//TODO: i18n
@ -159,8 +159,8 @@ public class BaseValidator {
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass) {
String message = context.formatMessage(msg);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, msg);
}
return thePass;
}
@ -174,11 +174,11 @@ public class BaseValidator {
//FIXME: formatMessage should be done here
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html) {
if (!thePass) {
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true).setSliceHtml(html);
}
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html);
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
@ -189,15 +189,15 @@ public class BaseValidator {
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage);
}
return thePass;
}
protected boolean txHint(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine).setTxLink(txLink);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine, theMessage).setTxLink(txLink);
}
return thePass;
}
@ -213,8 +213,8 @@ public class BaseValidator {
if (!thePass) {
String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
}
return thePass;
}
@ -227,8 +227,8 @@ public class BaseValidator {
*/
protected boolean hint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null);
}
return thePass;
}
@ -242,8 +242,8 @@ public class BaseValidator {
protected boolean rule(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.ERROR);
}
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.ERROR, theMessage);
}
return thePass;
}
@ -265,8 +265,8 @@ public class BaseValidator {
protected boolean rule(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass) {
String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, null);
}
return thePass;
}
@ -281,11 +281,11 @@ public class BaseValidator {
if (!thePass) {
String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR);
}
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
}
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
*
@ -297,23 +297,23 @@ public class BaseValidator {
//todo: delete this when finished i18n
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, null);
}
return thePass;
}
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
}
return thePass;
}
public boolean rule(List<ValidationMessage> errors, Source source, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, source);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, source, null);
}
return thePass;
}
@ -328,8 +328,8 @@ public class BaseValidator {
if (!thePass) {
msg = context.formatMessage(msg, null);
html = context.formatMessage(html, null);
addValidationMessage(errors, type, path, msg, html, IssueSeverity.ERROR);
}
addValidationMessage(errors, type, path, msg, html, IssueSeverity.ERROR, null);
}
return thePass;
}
@ -370,26 +370,26 @@ public class BaseValidator {
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
IssueSeverity severity = IssueSeverity.WARNING;
addValidationMessage(errors, type, line, col, path, msg, severity);
}
String nmsg = context.formatMessage(msg, theMessageArguments);
IssueSeverity severity = IssueSeverity.WARNING;
addValidationMessage(errors, type, line, col, path, nmsg, severity, msg);
}
return thePass;
}
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity) {
Source source = this.source;
return addValidationMessage(errors, type, line, col, path, msg, theSeverity, source);
}
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, String id) {
Source source = this.source;
return addValidationMessage(errors, type, line, col, path, msg, theSeverity, source, id);
}
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource) {
ValidationMessage validationMessage = new ValidationMessage(theSource, type, line, col, path, msg, theSeverity);
errors.add(validationMessage);
return validationMessage;
}
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource, String id) {
ValidationMessage validationMessage = new ValidationMessage(theSource, type, line, col, path, msg, theSeverity).setMessageId(id);
errors.add(validationMessage);
return validationMessage;
}
/**
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
@ -398,8 +398,8 @@ public class BaseValidator {
*/
protected boolean txWarning(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(Source.TerminologyEngine, type, line, col, path, msg, IssueSeverity.WARNING).setTxLink(txLink));
String nmsg = context.formatMessage(msg, theMessageArguments);
errors.add(new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg));
}
return thePass;
@ -407,9 +407,9 @@ public class BaseValidator {
protected boolean warningOrError(boolean isError, List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, line, col, path, msg, isError ? IssueSeverity.ERROR : IssueSeverity.WARNING);
}
String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, line, col, path, nmsg, isError ? IssueSeverity.ERROR : IssueSeverity.WARNING, msg);
}
return thePass;
}
@ -425,8 +425,8 @@ public class BaseValidator {
if (!thePass) {
String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.WARNING);
}
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.WARNING, theMessage);
}
return thePass;
}
@ -439,8 +439,8 @@ public class BaseValidator {
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.WARNING);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.WARNING, null);
}
return thePass;
}
@ -453,8 +453,8 @@ public class BaseValidator {
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass) {
addValidationMessage(errors, type, path, msg, html, IssueSeverity.WARNING);
}
addValidationMessage(errors, type, path, msg, html, IssueSeverity.WARNING, null);
}
return thePass;
}
@ -467,9 +467,9 @@ public class BaseValidator {
*/
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, msg, html, IssueSeverity.WARNING);
}
String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, nmsg, html, IssueSeverity.WARNING, msg);
}
return thePass;
}
@ -483,9 +483,9 @@ public class BaseValidator {
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION);
}
String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, line, col, path, nmsg, IssueSeverity.INFORMATION, msg);
}
return thePass;
}
@ -501,8 +501,8 @@ public class BaseValidator {
if (!thePass) {
String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
}
return thePass;
}
@ -515,8 +515,8 @@ public class BaseValidator {
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
if (!thePass) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION);
}
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null);
}
return thePass;
}
@ -529,17 +529,17 @@ public class BaseValidator {
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass) {
IssueSeverity severity = IssueSeverity.INFORMATION;
addValidationMessage(errors, type, path, msg, html, severity);
}
IssueSeverity severity = IssueSeverity.INFORMATION;
addValidationMessage(errors, type, path, msg, html, severity, null);
}
return thePass;
}
protected void addValidationMessage(List<ValidationMessage> errors, IssueType type, String path, String msg, String html, IssueSeverity theSeverity) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity));
}
protected void addValidationMessage(List<ValidationMessage> errors, IssueType type, String path, String msg, String html, IssueSeverity theSeverity, String id) {
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity).setMessageId(id));
}
/**
/**
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
*
* @param thePass
@ -548,13 +548,13 @@ public class BaseValidator {
*/
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass) {
msg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, msg, html, IssueSeverity.INFORMATION);
}
String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, nmsg, html, IssueSeverity.INFORMATION, msg);
}
return thePass;
}
protected ValueSet resolveBindingReference(DomainResource ctxt, String reference, String uri) {
if (reference != null) {
if (reference.startsWith("#")) {

View File

@ -86,6 +86,7 @@ The interface is optimised for JNI.
*
*/
public class NativeHostServices {
private class NH_10_50_Advisor implements VersionConvertorAdvisor50 {
@Override

View File

@ -5,6 +5,7 @@ import org.hl7.fhir.convertors.*;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.context.SimpleWorkerContext.IContextResourceLoader;
import org.hl7.fhir.r5.elementmodel.Element;
@ -284,11 +285,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
public ValidationEngine() throws IOException {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
}
public void loadInitialDefinitions(String src) throws Exception {
loadDefinitions(src, false);
}
public void setTerminologyServer(String src, String log, FhirPublication version) throws Exception {
connectToTSServer(src, log, version);
}
@ -311,7 +308,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws Exception {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
loadInitialDefinitions(src);
loadCoreDefinitions(src, false);
context.setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
setTerminologyServer(txsrvr, txLog, version);
this.version = vString;
@ -319,13 +316,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws Exception {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
loadInitialDefinitions(src);
loadCoreDefinitions(src, false);
setTerminologyServer(txsrvr, txLog, version);
this.version = vString;
}
public ValidationEngine(String src) throws Exception {
loadDefinitions(src, false);
loadCoreDefinitions(src, false);
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
}
@ -337,14 +334,14 @@ public class ValidationEngine implements IValidatorResourceFetcher {
this.language = language;
}
private void loadDefinitions(String src, boolean recursive) throws Exception {
private void loadCoreDefinitions(String src, boolean recursive) throws Exception {
Map<String, byte[]> source = loadIgSource(src, recursive, true);
if (version == null)
version = getVersionFromPack(source);
context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion());
context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion(), new PackageVersion(src));
context.setAllowLoadingDuplicates(true); // because of Forge
context.setExpansionProfile(makeExpProfile());
NpmPackage npm = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.2");
NpmPackage npm = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.3");
context.loadFromPackage(npm, null);
grabNatives(source, "http://hl7.org/fhir");
}

View File

@ -38,7 +38,7 @@ public class FileInfo {
@JsonProperty("fileType")
public Manager.FhirFormat getFileType() {
return Manager.FhirFormat.get(fileType);
return Manager.FhirFormat.JSON;
}
@JsonProperty("fileType")

View File

@ -171,9 +171,11 @@ public class Params {
throw new Error("Specified " + args[i] + " without indicating ig file");
else {
String s = args[++i];
cliContext.setSv(Common.getVersionFromIGName(null, s));
if (cliContext.getSv() == null) {
String version = Common.getVersionFromIGName(null, s);
if (version == null) {
cliContext.addIg(s);
} else {
cliContext.setSv(version);
}
}
} else if (args[i].equals(MAP)) {

View File

@ -134,13 +134,13 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.IResourceValidator;
import org.hl7.fhir.r5.utils.NarrativeGenerator;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.TimeTracker;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator.QStack;
import org.hl7.fhir.validation.instance.type.MeasureValidator;
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator;
import org.hl7.fhir.validation.XVerExtensionManager;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.Utilities.DecimalStatus;
@ -695,10 +695,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
long t = System.nanoTime();
if (profiles == null || profiles.isEmpty()) {
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, new NodeStack(context, element, validationLanguage));
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, new NodeStack(context, element, validationLanguage).resetIds());
} else {
for (StructureDefinition defn : profiles) {
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, new NodeStack(context, element, validationLanguage));
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, new NodeStack(context, element, validationLanguage).resetIds());
}
}
if (hintAboutNonMustSupport) {
@ -2827,6 +2827,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rr.setFocus(res.getMatch());
rr.setExternal(false);
rr.setStack(stack.push(res.getMatch(), res.getIndex(), res.getMatch().getProperty().getDefinition(), res.getMatch().getProperty().getDefinition()));
rr.getStack().qualifyPath(".ofType("+stack.getElement().fhirType()+")");
return rr;
}
}
@ -2861,6 +2862,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rr.setStack(stack.push(res.getEntry(), res.getIndex(), res.getEntry().getProperty().getDefinition(),
res.getEntry().getProperty().getDefinition()).push(res.getMatch(), -1,
res.getMatch().getProperty().getDefinition(), res.getMatch().getProperty().getDefinition()));
rr.getStack().qualifyPath(".ofType("+rr.getResource().fhirType()+")");
return rr;
}
}
@ -2882,6 +2884,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rr.setStack(new NodeStack(context, hostContext, validationLanguage).push(res.getEntry(), res.getIndex(), res.getEntry().getProperty().getDefinition(),
res.getEntry().getProperty().getDefinition()).push(res.getMatch(), -1,
res.getMatch().getProperty().getDefinition(), res.getMatch().getProperty().getDefinition()));
rr.getStack().qualifyPath(".ofType("+rr.getResource().fhirType()+")");
return rr;
}
}
@ -3832,6 +3835,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
break;
}
}
stack.qualifyPath(".ofType("+resourceName+")");
if (trr == null) {
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName);
} else if (isValidResourceType(resourceName, trr)) {
@ -3949,7 +3953,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (stack.getIds().containsKey(id) && stack.getIds().get(id) != element) {
rule(errors, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.DUPLICATE_ID, id);
}
stack.getIds().put(id, element);
if (!stack.isResetPoint()) {
stack.getIds().put(id, element);
}
}
if (definition.getPath().equals("StructureDefinition.snapshot")) {
// work around a known issue in the spec, that idsa are duplicated in snapshot and differential

View File

@ -1,17 +1,24 @@
package org.hl7.fhir.validation.instance.type;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Attachment;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Library;
import org.hl7.fhir.r5.model.Measure;
import org.hl7.fhir.r5.model.Measure.MeasureGroupComponent;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.xml.sax.SAXException;
public class MeasureContext {
public static final String USER_DATA_ELM = "validator.ELM";
private List<Library> libs = new ArrayList<>();
private Measure measure;
private Element report;
@ -26,6 +33,15 @@ public class MeasureContext {
public void seeLibrary(Library l) {
libs.add(l);
for (Attachment att : l.getContent()) {
if ("application/elm+xml".equals(att.getContentType())) {
try {
l.setUserData(USER_DATA_ELM, XMLUtil.parseToDom(att.getData(), true));
} catch (Exception e) {
l.setUserData(USER_DATA_ELM, e.getMessage());
}
}
}
}
public List<MeasureGroupComponent> groups() {
@ -42,5 +58,8 @@ public class MeasureContext {
public String scoring() {
return measure.getScoring().getCodingFirstRep().getCode();
}
public List<Library> libraries() {
return libs;
}
}

View File

@ -32,10 +32,12 @@ import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.hl7.fhir.validation.instance.utils.NodeStack;
import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.TimeTracker;
import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
import org.w3c.dom.Document;
import net.sf.saxon.tree.tiny.LargeStringBuffer;
@ -104,12 +106,70 @@ public class MeasureValidator extends BaseValidator {
}
private void validateMeasureCriteria(ValidatorHostContext hostContext, List<ValidationMessage> errors, MeasureContext mctxt, Element crit, NodeStack nsc) {
// TODO Auto-generated method stub
String mimeType = crit.getChildValue("language");
if (!Utilities.noString(mimeType)) { // that would be an error elsewhere
if ("text/cql".equals(mimeType)) {
String cqlRef = crit.getChildValue("expression");
Library lib = null;
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size()> 0, I18nConstants.MEASURE_M_CRITERIA_CQL_NO_LIB)) {
if (cqlRef.contains(".")) {
String name = cqlRef.substring(0, cqlRef.indexOf("."));
cqlRef = cqlRef.substring(cqlRef.indexOf(".")+1);
for (Library l : mctxt.libraries()) {
if (l.getName().equals(name)) {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib == null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_DUPL)) {
lib = l;
}
}
}
rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib != null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND, name);
} else {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size() == 1, I18nConstants.MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB)) {
lib = mctxt.libraries().get(0);
}
}
}
if (lib != null) {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib.hasUserData(MeasureContext.USER_DATA_ELM), I18nConstants.MEASURE_M_CRITERIA_CQL_NO_ELM, lib.getUrl())) {
if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof String) {
rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_CQL_ERROR, lib.getUrl(), lib.getUserString(MeasureContext.USER_DATA_ELM));
} else if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof Document) {
org.w3c.dom.Element elm = ((Document)lib.getUserData(MeasureContext.USER_DATA_ELM)).getDocumentElement();
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), isValidElm(elm), I18nConstants.MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID, lib.getUrl(), cqlRef)) {
rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), hasCqlTarget(elm, cqlRef), I18nConstants.MEASURE_M_CRITERIA_CQL_NOT_FOUND, lib.getUrl(), cqlRef);
}
}
}
}
} else if ("text/fhirpath".equals(mimeType)) {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
} else if ("application/x-fhir-query".equals(mimeType)) {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
} else {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
}
}
}
private boolean isValidElm(org.w3c.dom.Element elm) {
return elm != null && "library".equals(elm.getNodeName()) && "urn:hl7-org:elm:r1".equals(elm.getNamespaceURI());
}
private boolean hasCqlTarget(org.w3c.dom.Element element, String cqlRef) {
org.w3c.dom.Element stmts = XMLUtil.getNamedChild(element, "statements");
if (stmts != null) {
for (org.w3c.dom.Element def : XMLUtil.getNamedChildren(stmts, "def")) {
if (cqlRef.equals(def.getAttribute("name"))) {
return true;
}
}
}
return false;
}
// ---------------------------------------------------------------------------------------------------------------------------------------------------------
public void validateMeasureReport(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack) throws FHIRException {
Element m = element.getNamedChild("measure");
String measure = null;
@ -339,7 +399,7 @@ public class MeasureValidator extends BaseValidator {
i++;
}
for (MeasureGroupPopulationComponent mgp : mg.getPopulation()) {
if (!pops.contains(mgp)) {
if (!pops.contains(mgp) && !mgp.getCode().hasCoding("http://terminology.hl7.org/CodeSystem/measure-population", "measure-observation")) {
rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), stack.getLiteralPath(), pops.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, gen.gen(mgp.getCode()));
}
}

View File

@ -515,7 +515,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (!res.isOk()) {
txRule(errors, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode());
} else if (res.getSeverity() != null) {
super.addValidationMessage(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine);
super.addValidationMessage(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null);
}
} catch (Exception e) {
warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODING, e.getMessage());

View File

@ -26,6 +26,7 @@ public class NodeStack {
private ElementDefinition type;
private String workingLang;
private Map<String, Element> ids;
private boolean resetPoint = false;
public NodeStack(IWorkerContext context) {
this.context = context;
@ -147,6 +148,7 @@ public class NodeStack {
public NodeStack resetIds() {
ids = new HashMap<>();
resetPoint = true;
return this;
}
public Map<String, Element> getIds() {
@ -173,5 +175,14 @@ public class NodeStack {
return parent;
}
public void qualifyPath(String qualifier) {
literalPath = literalPath + qualifier;
}
public boolean isResetPoint() {
return resetPoint;
}
}

View File

@ -146,35 +146,12 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
vCurr.loadIg(e.getAsString(), true);
}
}
if (content.has("questionnaire")) {
String filename = content.get("questionnaire").getAsString();
String contents = TestingUtilities.loadTestResource("validator", filename);
vCurr.getContext().cacheResource(loadResource(filename, contents));
}
if (content.has("measure")) {
String filename = content.get("measure").getAsString();
String contents = TestingUtilities.loadTestResource("validator", filename);
vCurr.getContext().cacheResource(loadResource(filename, contents));
}
if (content.has("library")) {
String filename = content.get("library").getAsString();
String contents = TestingUtilities.loadTestResource("validator", filename);
vCurr.getContext().cacheResource(loadResource(filename, contents));
}
if (content.has("codesystems")) {
for (JsonElement je : content.getAsJsonArray("codesystems")) {
String filename = je.getAsString();
if (content.has("supporting")) {
for (JsonElement e : content.getAsJsonArray("supporting")) {
String filename = e.getAsString();
String contents = TestingUtilities.loadTestResource("validator", filename);
CodeSystem sd = (CodeSystem) loadResource(filename, contents);
val.getContext().cacheResource(sd);
}
}
if (content.has("valuesets")) {
for (JsonElement je : content.getAsJsonArray("valuesets")) {
String filename = je.getAsString();
String contents = TestingUtilities.loadTestResource("validator", filename);
ValueSet vs = (ValueSet) loadResource(filename, contents);
val.getContext().cacheResource(vs);
CanonicalResource mr = (CanonicalResource) loadResource(filename, contents);
val.getContext().cacheResource(mr);
}
}
if (content.has("profiles")) {

View File

@ -13,11 +13,11 @@
each other. It is fine to bump the point version of this POM without affecting
HAPI FHIR.
-->
<version>4.2.13-SNAPSHOT</version>
<version>4.2.17-SNAPSHOT</version>
<properties>
<hapi_fhir_version>4.2.0</hapi_fhir_version>
<validator_test_case_version>1.1.4-SNAPSHOT</validator_test_case_version>
<validator_test_case_version>1.1.6-SNAPSHOT</validator_test_case_version>
</properties>
<artifactId>org.hl7.fhir.core</artifactId>
@ -53,6 +53,11 @@
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>sonatype-public</id>
<name>Sonatype Public</name>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>

View File

@ -1,7 +1,7 @@
@echo off
set oldver=4.2.12
set newver=4.2.13
set oldver=4.2.16
set newver=4.2.17
echo ..
echo =========================================================================
@ -12,6 +12,7 @@ echo ..
call mvn versions:set -DnewVersion=%newver%-SNAPSHOT
call git commit -t v%newver% -a -m "Release new version %newver%"
call git tag v%newver%
call git push origin master
call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\build" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 8