Second pull request for fixes for issue #1048.

This commit is contained in:
Anthony Sute 2018-08-06 13:17:51 -04:00
parent 3cf3f7d5d6
commit 0fdcad0985
2 changed files with 163 additions and 51 deletions

View File

@ -1,6 +1,12 @@
package org.hl7.fhir.instance.hapi.validation; package org.hl7.fhir.instance.hapi.validation;
import ca.uhn.fhir.context.*; import static org.apache.commons.lang3.StringUtils.isBlank;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.validation.IValidationContext; import ca.uhn.fhir.validation.IValidationContext;
@ -10,6 +16,8 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
@ -20,7 +28,12 @@ import org.hl7.fhir.convertors.VersionConvertorAdvisor40;
import org.hl7.fhir.convertors.VersionConvertor_10_40; import org.hl7.fhir.convertors.VersionConvertor_10_40;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.instance.model.*; import org.hl7.fhir.instance.model.CodeableConcept;
import org.hl7.fhir.instance.model.Coding;
import org.hl7.fhir.instance.model.Questionnaire;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.StructureDefinition;
import org.hl7.fhir.instance.model.ValueSet;
import org.hl7.fhir.r4.context.IWorkerContext; import org.hl7.fhir.r4.context.IWorkerContext;
import org.hl7.fhir.r4.formats.IParser; import org.hl7.fhir.r4.formats.IParser;
import org.hl7.fhir.r4.formats.ParserType; import org.hl7.fhir.r4.formats.ParserType;
@ -40,15 +53,18 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader; import java.io.StringReader;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.StringUtils.isBlank; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule { public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
@ -128,6 +144,28 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return root.getLocalName(); return root.getLocalName();
} }
private ArrayList<String> determineIfProfilesSpecified(Document theDocument)
{
ArrayList<String> profileNames = new ArrayList<String>();
NodeList list = theDocument.getChildNodes().item(0).getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().compareToIgnoreCase("meta") == 0)
{
NodeList metaList = list.item(i).getChildNodes();
for (int j = 0; j < metaList.getLength(); j++)
{
if (metaList.item(j).getNodeName().compareToIgnoreCase("profile") == 0)
{
String[] components = metaList.item(j).getAttributes().item(0).getNodeValue().split("/");
profileNames.add(components[components.length - 1]);
}
}
break;
}
}
return profileNames;
}
private StructureDefinition findStructureDefinitionForResourceName(final FhirContext theCtx, String resourceName) { private StructureDefinition findStructureDefinitionForResourceName(final FhirContext theCtx, String resourceName) {
String sdName = "http://hl7.org/fhir/StructureDefinition/" + resourceName; String sdName = "http://hl7.org/fhir/StructureDefinition/" + resourceName;
StructureDefinition profile = myStructureDefintion != null ? myStructureDefintion : myValidationSupport.fetchResource(theCtx, StructureDefinition.class, sdName); StructureDefinition profile = myStructureDefintion != null ? myStructureDefintion : myValidationSupport.fetchResource(theCtx, StructureDefinition.class, sdName);
@ -257,27 +295,49 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return Collections.singletonList(m); return Collections.singletonList(m);
} }
String resourceName = determineResourceName(document); // Determine if meta/profiles are present...
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName); ArrayList<String> resourceNames = determineIfProfilesSpecified(document);
if (profile != null) { if (resourceNames.isEmpty())
try { {
v.validate(null, messages, document, profile.getUrl()); resourceNames.add(determineResourceName(document));
} catch (Exception e) { }
ourLog.error("Failure during validation", e);
throw new InternalErrorException("Unexpected failure while validating resource", e); for (String resourceName : resourceNames) {
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName);
if (profile != null) {
try {
v.validate(null, messages, document, profile.getUrl());
} catch (Exception e) {
ourLog.error("Failure during validation", e);
throw new InternalErrorException("Unexpected failure while validating resource", e);
}
} }
} }
} else if (theEncoding == EncodingEnum.JSON) { } else if (theEncoding == EncodingEnum.JSON) {
Gson gson = new GsonBuilder().create(); Gson gson = new GsonBuilder().create();
JsonObject json = gson.fromJson(theInput, JsonObject.class); JsonObject json = gson.fromJson(theInput, JsonObject.class);
String resourceName = json.get("resourceType").getAsString(); ArrayList<String> resourceNames = new ArrayList<String>();
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName); JsonArray profiles = null;
if (profile != null) { try {
try { profiles = json.getAsJsonObject("meta").getAsJsonArray("profile");
v.validate(null, messages, json, profile.getUrl()); for (JsonElement element : profiles)
} catch (Exception e) { {
throw new InternalErrorException("Unexpected failure while validating resource", e); String[] components = element.getAsString().split("/");
resourceNames.add(components[components.length - 1]);
}
} catch (Exception e) {
resourceNames.add(json.get("resourceType").getAsString());
}
for (String resourceName : resourceNames) {
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName);
if (profile != null) {
try {
v.validate(null, messages, json, profile.getUrl());
} catch (Exception e) {
throw new InternalErrorException("Unexpected failure while validating resource", e);
}
} }
} }
} else { } else {

View File

@ -1,15 +1,24 @@
package org.hl7.fhir.r4.hapi.validation; package org.hl7.fhir.r4.hapi.validation;
import java.io.StringReader; import ca.uhn.fhir.context.ConfigurationException;
import java.util.*; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum;
import javax.xml.parsers.DocumentBuilder; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import javax.xml.parsers.DocumentBuilderFactory; import ca.uhn.fhir.validation.IValidationContext;
import ca.uhn.fhir.validation.IValidatorModule;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r4.hapi.ctx.*; import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.model.Base;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.TypeDetails;
import org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext; import org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r4.utils.IResourceValidator.BestPracticeWarningLevel; import org.hl7.fhir.r4.utils.IResourceValidator.BestPracticeWarningLevel;
import org.hl7.fhir.r4.utils.IResourceValidator.IdStatus; import org.hl7.fhir.r4.utils.IResourceValidator.IdStatus;
@ -21,14 +30,13 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import com.google.gson.*; import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import ca.uhn.fhir.context.ConfigurationException; import javax.xml.parsers.DocumentBuilder;
import ca.uhn.fhir.context.FhirContext; import javax.xml.parsers.DocumentBuilderFactory;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.validation.IValidationContext;
import ca.uhn.fhir.validation.IValidatorModule;
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule { public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
@ -77,6 +85,28 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return root.getLocalName(); return root.getLocalName();
} }
private ArrayList<String> determineIfProfilesSpecified(Document theDocument)
{
ArrayList<String> profileNames = new ArrayList<String>();
NodeList list = theDocument.getChildNodes().item(0).getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().compareToIgnoreCase("meta") == 0)
{
NodeList metaList = list.item(i).getChildNodes();
for (int j = 0; j < metaList.getLength(); j++)
{
if (metaList.item(j).getNodeName().compareToIgnoreCase("profile") == 0)
{
String[] components = metaList.item(j).getAttributes().item(0).getNodeValue().split("/");
profileNames.add(components[components.length - 1]);
}
}
break;
}
}
return profileNames;
}
private StructureDefinition findStructureDefinitionForResourceName(final FhirContext theCtx, String resourceName) { private StructureDefinition findStructureDefinitionForResourceName(final FhirContext theCtx, String resourceName) {
String sdName = "http://hl7.org/fhir/StructureDefinition/" + resourceName; String sdName = "http://hl7.org/fhir/StructureDefinition/" + resourceName;
StructureDefinition profile = myStructureDefintion != null ? myStructureDefintion : myValidationSupport.fetchStructureDefinition(theCtx, sdName); StructureDefinition profile = myStructureDefintion != null ? myStructureDefintion : myValidationSupport.fetchStructureDefinition(theCtx, sdName);
@ -200,27 +230,49 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return Collections.singletonList(m); return Collections.singletonList(m);
} }
String resourceName = determineResourceName(document); // Determine if meta/profiles are present...
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName); ArrayList<String> resourceNames = determineIfProfilesSpecified(document);
if (profile != null) { if (resourceNames.isEmpty())
try { {
v.validate(null, messages, document, profile); resourceNames.add(determineResourceName(document));
} catch (Exception e) { }
throw new InternalErrorException("Unexpected failure while validating resource", e);
for (String resourceName : resourceNames) {
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName);
if (profile != null) {
try {
v.validate(null, messages, document, profile.getUrl());
} catch (Exception e) {
ourLog.error("Failure during validation", e);
throw new InternalErrorException("Unexpected failure while validating resource", e);
}
} }
} }
} else if (theEncoding == EncodingEnum.JSON) { } else if (theEncoding == EncodingEnum.JSON) {
Gson gson = new GsonBuilder().create(); Gson gson = new GsonBuilder().create();
JsonObject json = gson.fromJson(theInput, JsonObject.class); JsonObject json = gson.fromJson(theInput, JsonObject.class);
String resourceName = json.get("resourceType").getAsString(); ArrayList<String> resourceNames = new ArrayList<String>();
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName); JsonArray profiles = null;
if (profile != null) { try {
try { profiles = json.getAsJsonObject("meta").getAsJsonArray("profile");
v.validate(null, messages, json, profile); for (JsonElement element : profiles)
} catch (Exception e) { {
ourLog.error("Failure during validation", e); String[] components = element.getAsString().split("/");
throw new InternalErrorException("Unexpected failure while validating resource", e); resourceNames.add(components[components.length - 1]);
}
} catch (Exception e) {
resourceNames.add(json.get("resourceType").getAsString());
}
for (String resourceName : resourceNames) {
StructureDefinition profile = findStructureDefinitionForResourceName(theCtx, resourceName);
if (profile != null) {
try {
v.validate(null, messages, json, profile.getUrl());
} catch (Exception e) {
throw new InternalErrorException("Unexpected failure while validating resource", e);
}
} }
} }
} else { } else {