Clean up exception handling in server, and add QuestionnaireAnswers validation for JPA server
This commit is contained in:
parent
3bba0c0425
commit
2fc0d4c7a2
|
@ -244,10 +244,10 @@ class ModelScanner {
|
||||||
* annotations if the HL7.org ones are found instead.
|
* annotations if the HL7.org ones are found instead.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T extends Annotation> T pullAnnotation(AnnotatedElement theTarget, Class<T> theAnnotationType) {
|
private <T extends Annotation> T pullAnnotation(Class<?> theContainer, AnnotatedElement theTarget, Class<T> theAnnotationType) {
|
||||||
|
|
||||||
T retVal = theTarget.getAnnotation(theAnnotationType);
|
T retVal = theTarget.getAnnotation(theAnnotationType);
|
||||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG) == false) {
|
if (myContext.getVersion().getVersion() != FhirVersionEnum.DSTU2_HL7ORG) {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ class ModelScanner {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDef resourceDefinition = pullAnnotation(theClass, ResourceDef.class);
|
ResourceDef resourceDefinition = pullAnnotation(theClass, theClass, ResourceDef.class);
|
||||||
if (resourceDefinition != null) {
|
if (resourceDefinition != null) {
|
||||||
if (!IBaseResource.class.isAssignableFrom(theClass)) {
|
if (!IBaseResource.class.isAssignableFrom(theClass)) {
|
||||||
throw new ConfigurationException("Resource type contains a @" + ResourceDef.class.getSimpleName() + " annotation but does not implement " + IResource.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
throw new ConfigurationException("Resource type contains a @" + ResourceDef.class.getSimpleName() + " annotation but does not implement " + IResource.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
||||||
|
@ -317,7 +317,7 @@ class ModelScanner {
|
||||||
scanResource(resClass, resourceDefinition);
|
scanResource(resClass, resourceDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
DatatypeDef datatypeDefinition = pullAnnotation(theClass, DatatypeDef.class);
|
DatatypeDef datatypeDefinition = pullAnnotation(theClass, theClass, DatatypeDef.class);
|
||||||
if (datatypeDefinition != null) {
|
if (datatypeDefinition != null) {
|
||||||
if (ICompositeType.class.isAssignableFrom(theClass)) {
|
if (ICompositeType.class.isAssignableFrom(theClass)) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -332,7 +332,7 @@ class ModelScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Block blockDefinition = pullAnnotation(theClass, Block.class);
|
Block blockDefinition = pullAnnotation(theClass, theClass, Block.class);
|
||||||
|
|
||||||
if (blockDefinition != null) {
|
if (blockDefinition != null) {
|
||||||
if (IResourceBlock.class.isAssignableFrom(theClass) || IBaseBackboneElement.class.isAssignableFrom(theClass) || IBaseDatatypeElement.class.isAssignableFrom(theClass)) {
|
if (IResourceBlock.class.isAssignableFrom(theClass) || IBaseBackboneElement.class.isAssignableFrom(theClass) || IBaseDatatypeElement.class.isAssignableFrom(theClass)) {
|
||||||
|
@ -440,16 +440,16 @@ class ModelScanner {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Child childAnnotation = pullAnnotation(next, Child.class);
|
Child childAnnotation = pullAnnotation(theClass, next, Child.class);
|
||||||
if (childAnnotation == null) {
|
if (childAnnotation == null) {
|
||||||
ourLog.trace("Ignoring non @Child field {} on target type {}", next.getName(), theClass);
|
ourLog.trace("Ignoring non @Child field {} on target type {}", next.getName(), theClass);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Description descriptionAnnotation = pullAnnotation(next, Description.class);
|
Description descriptionAnnotation = pullAnnotation(theClass, next, Description.class);
|
||||||
|
|
||||||
TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> orderMap = theOrderToElementDef;
|
TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> orderMap = theOrderToElementDef;
|
||||||
Extension extensionAttr = pullAnnotation(next, Extension.class);
|
Extension extensionAttr = pullAnnotation(theClass, next, Extension.class);
|
||||||
if (extensionAttr != null) {
|
if (extensionAttr != null) {
|
||||||
orderMap = theOrderToExtensionDef;
|
orderMap = theOrderToExtensionDef;
|
||||||
}
|
}
|
||||||
|
@ -649,7 +649,7 @@ class ModelScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeableConceptElement concept = pullAnnotation(next, CodeableConceptElement.class);
|
CodeableConceptElement concept = pullAnnotation(theClass, next, CodeableConceptElement.class);
|
||||||
if (concept != null) {
|
if (concept != null) {
|
||||||
if (!ICodedDatatype.class.isAssignableFrom(nextDatatype)) {
|
if (!ICodedDatatype.class.isAssignableFrom(nextDatatype)) {
|
||||||
throw new ConfigurationException("Field '" + elementName + "' in type '" + theClass.getCanonicalName() + "' is marked as @" + CodeableConceptElement.class.getCanonicalName() + " but type is not a subtype of " + ICodedDatatype.class.getName());
|
throw new ConfigurationException("Field '" + elementName + "' in type '" + theClass.getCanonicalName() + "' is marked as @" + CodeableConceptElement.class.getCanonicalName() + " but type is not a subtype of " + ICodedDatatype.class.getName());
|
||||||
|
@ -709,7 +709,7 @@ class ModelScanner {
|
||||||
Class<?> parent = theClass.getSuperclass();
|
Class<?> parent = theClass.getSuperclass();
|
||||||
primaryNameProvider = false;
|
primaryNameProvider = false;
|
||||||
while (parent.equals(Object.class) == false && isBlank(resourceName)) {
|
while (parent.equals(Object.class) == false && isBlank(resourceName)) {
|
||||||
ResourceDef nextDef = pullAnnotation(parent, ResourceDef.class);
|
ResourceDef nextDef = pullAnnotation(theClass, parent, ResourceDef.class);
|
||||||
if (nextDef != null) {
|
if (nextDef != null) {
|
||||||
resourceName = nextDef.name();
|
resourceName = nextDef.name();
|
||||||
}
|
}
|
||||||
|
@ -749,7 +749,7 @@ class ModelScanner {
|
||||||
Map<Field, SearchParamDefinition> compositeFields = new LinkedHashMap<Field, SearchParamDefinition>();
|
Map<Field, SearchParamDefinition> compositeFields = new LinkedHashMap<Field, SearchParamDefinition>();
|
||||||
|
|
||||||
for (Field nextField : theClass.getFields()) {
|
for (Field nextField : theClass.getFields()) {
|
||||||
SearchParamDefinition searchParam = pullAnnotation(nextField, SearchParamDefinition.class);
|
SearchParamDefinition searchParam = pullAnnotation(theClass, nextField, SearchParamDefinition.class);
|
||||||
if (searchParam != null) {
|
if (searchParam != null) {
|
||||||
RestSearchParameterTypeEnum paramType = RestSearchParameterTypeEnum.valueOf(searchParam.type().toUpperCase());
|
RestSearchParameterTypeEnum paramType = RestSearchParameterTypeEnum.valueOf(searchParam.type().toUpperCase());
|
||||||
if (paramType == null) {
|
if (paramType == null) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -54,7 +54,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> myAdditionalMessages = null;
|
private List<String> myAdditionalMessages = null;
|
||||||
private BaseOperationOutcome myBaseOperationOutcome;
|
private IBaseOperationOutcome myBaseOperationOutcome;
|
||||||
private String myResponseBody;
|
private String myResponseBody;
|
||||||
private String myResponseMimeType;
|
private String myResponseMimeType;
|
||||||
private int myStatusCode;
|
private int myStatusCode;
|
||||||
|
@ -100,7 +100,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
* @param theBaseOperationOutcome
|
* @param theBaseOperationOutcome
|
||||||
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
||||||
*/
|
*/
|
||||||
public BaseServerResponseException(int theStatusCode, String theMessage, BaseOperationOutcome theBaseOperationOutcome) {
|
public BaseServerResponseException(int theStatusCode, String theMessage, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||||
super(theMessage);
|
super(theMessage);
|
||||||
myStatusCode = theStatusCode;
|
myStatusCode = theStatusCode;
|
||||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||||
|
@ -134,7 +134,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
* @param theBaseOperationOutcome
|
* @param theBaseOperationOutcome
|
||||||
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
||||||
*/
|
*/
|
||||||
public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause, BaseOperationOutcome theBaseOperationOutcome) {
|
public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||||
super(theMessage, theCause);
|
super(theMessage, theCause);
|
||||||
myStatusCode = theStatusCode;
|
myStatusCode = theStatusCode;
|
||||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||||
|
@ -164,7 +164,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
* @param theBaseOperationOutcome
|
* @param theBaseOperationOutcome
|
||||||
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
* An BaseOperationOutcome resource to return to the calling client (in a server) or the BaseOperationOutcome that was returned from the server (in a client)
|
||||||
*/
|
*/
|
||||||
public BaseServerResponseException(int theStatusCode, Throwable theCause, BaseOperationOutcome theBaseOperationOutcome) {
|
public BaseServerResponseException(int theStatusCode, Throwable theCause, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||||
super(theCause.toString(), theCause);
|
super(theCause.toString(), theCause);
|
||||||
myStatusCode = theStatusCode;
|
myStatusCode = theStatusCode;
|
||||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||||
|
@ -182,9 +182,9 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link BaseOperationOutcome} resource if any which was supplied in the response, or <code>null</code>
|
* Returns the {@link IBaseOperationOutcome} resource if any which was supplied in the response, or <code>null</code>
|
||||||
*/
|
*/
|
||||||
public BaseOperationOutcome getOperationOutcome() {
|
public IBaseOperationOutcome getOperationOutcome() {
|
||||||
return myBaseOperationOutcome;
|
return myBaseOperationOutcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
* The BaseOperationOutcome resource Sets the BaseOperationOutcome resource associated with this exception. In server implementations, this is the OperartionOutcome resource to include
|
* The BaseOperationOutcome resource Sets the BaseOperationOutcome resource associated with this exception. In server implementations, this is the OperartionOutcome resource to include
|
||||||
* with the HTTP response. In client implementations you should not call this method.
|
* with the HTTP response. In client implementations you should not call this method.
|
||||||
*/
|
*/
|
||||||
public void setOperationOutcome(BaseOperationOutcome theBaseOperationOutcome) {
|
public void setOperationOutcome(IBaseOperationOutcome theBaseOperationOutcome) {
|
||||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -54,7 +56,7 @@ public class ForbiddenOperationException extends BaseServerResponseException {
|
||||||
* @param theOperationOutcome
|
* @param theOperationOutcome
|
||||||
* The OperationOutcome resource to return to the client
|
* The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ForbiddenOperationException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ForbiddenOperationException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -54,7 +56,7 @@ public class InternalErrorException extends BaseServerResponseException {
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public InternalErrorException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public InternalErrorException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -54,7 +56,7 @@ public class InvalidRequestException extends BaseServerResponseException {
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public InvalidRequestException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public InvalidRequestException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
|
||||||
* @param theAllowedMethods
|
* @param theAllowedMethods
|
||||||
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
|
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
|
||||||
*/
|
*/
|
||||||
public MethodNotAllowedException(String theMessage, BaseOperationOutcome theOperationOutcome, RequestTypeEnum... theAllowedMethods) {
|
public MethodNotAllowedException(String theMessage, IBaseOperationOutcome theOperationOutcome, RequestTypeEnum... theAllowedMethods) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
setAllowedMethods(theAllowedMethods);
|
setAllowedMethods(theAllowedMethods);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
|
||||||
* @param theOperationOutcome
|
* @param theOperationOutcome
|
||||||
* The OperationOutcome resource to return to the client
|
* The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public MethodNotAllowedException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public MethodNotAllowedException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -51,7 +53,7 @@ public class NotImplementedOperationException extends BaseServerResponseExceptio
|
||||||
* @param theOperationOutcome
|
* @param theOperationOutcome
|
||||||
* The OperationOutcome resource to return to the client
|
* The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public NotImplementedOperationException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public NotImplementedOperationException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -52,7 +54,7 @@ public class NotModifiedException extends BaseServerResponseException {
|
||||||
* @param theOperationOutcome
|
* @param theOperationOutcome
|
||||||
* The OperationOutcome resource to return to the client
|
* The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public NotModifiedException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public NotModifiedException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
import ca.uhn.fhir.rest.annotation.Update;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ public class PreconditionFailedException extends ResourceVersionNotSpecifiedExce
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public PreconditionFailedException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public PreconditionFailedException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,11 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
|
@ -55,7 +57,7 @@ public class ResourceGoneException extends BaseServerResponseException {
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ResourceGoneException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ResourceGoneException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,11 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
||||||
super(STATUS_CODE, createErrorMessage(theClass, theId));
|
super(STATUS_CODE, createErrorMessage(theClass, theId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceNotFoundException(Class<? extends IResource> theClass, IdDt theId, BaseOperationOutcome theOperationOutcome) {
|
public ResourceNotFoundException(Class<? extends IResource> theClass, IdDt theId, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, createErrorMessage(theClass, theId), theOperationOutcome);
|
super(STATUS_CODE, createErrorMessage(theClass, theId), theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
||||||
super(STATUS_CODE, createErrorMessage(theClass, theId));
|
super(STATUS_CODE, createErrorMessage(theClass, theId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceNotFoundException(Class<? extends IResource> theClass, IIdType theId, BaseOperationOutcome theOperationOutcome) {
|
public ResourceNotFoundException(Class<? extends IResource> theClass, IIdType theId, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, createErrorMessage(theClass, theId), theOperationOutcome);
|
super(STATUS_CODE, createErrorMessage(theClass, theId), theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ResourceNotFoundException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ResourceNotFoundException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
||||||
super(STATUS_CODE, createErrorMessage(theId));
|
super(STATUS_CODE, createErrorMessage(theId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceNotFoundException(IdDt theId, BaseOperationOutcome theOperationOutcome) {
|
public ResourceNotFoundException(IdDt theId, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, createErrorMessage(theId), theOperationOutcome);
|
super(STATUS_CODE, createErrorMessage(theId), theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
import ca.uhn.fhir.rest.annotation.Delete;
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
import ca.uhn.fhir.rest.annotation.Update;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
@ -47,7 +49,7 @@ public class ResourceVersionConflictException extends BaseServerResponseExceptio
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ResourceVersionConflictException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ResourceVersionConflictException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +47,7 @@ public class ResourceVersionNotSpecifiedException extends BaseServerResponseExce
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ResourceVersionNotSpecifiedException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ResourceVersionNotSpecifiedException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ public class ResourceVersionNotSpecifiedException extends BaseServerResponseExce
|
||||||
* The message
|
* The message
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public ResourceVersionNotSpecifiedException(int theStatusCode, String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public ResourceVersionNotSpecifiedException(int theStatusCode, String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(theStatusCode, theMessage, theOperationOutcome);
|
super(theStatusCode, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -51,7 +52,7 @@ public class UnclassifiedServerFailureException extends BaseServerResponseExcept
|
||||||
* The message to add to the status line
|
* The message to add to the status line
|
||||||
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
* @param theOperationOutcome The OperationOutcome resource to return to the client
|
||||||
*/
|
*/
|
||||||
public UnclassifiedServerFailureException(int theStatusCode, String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public UnclassifiedServerFailureException(int theStatusCode, String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(theStatusCode, theMessage, theOperationOutcome);
|
super(theStatusCode, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,16 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.sourceforge.cobertura.CoverageIgnore;
|
import net.sourceforge.cobertura.CoverageIgnore;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an <b>HTTP 422 Unprocessable Entity</b> response, which means that a resource was rejected by the server because it "violated applicable FHIR profiles or server business rules".
|
* Represents an <b>HTTP 422 Unprocessable Entity</b> response, which means that a resource was rejected by the server because it "violated applicable FHIR profiles or server business rules".
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This exception will generally contain an {@link BaseOperationOutcome} instance which details the failure.
|
* This exception will generally contain an {@link IBaseOperationOutcome} instance which details the failure.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see InvalidRequestException Which corresponds to an <b>HTTP 400 Bad Request</b> failure
|
* @see InvalidRequestException Which corresponds to an <b>HTTP 400 Bad Request</b> failure
|
||||||
|
@ -45,29 +47,29 @@ public class UnprocessableEntityException extends BaseServerResponseException {
|
||||||
*
|
*
|
||||||
* @param theMessage
|
* @param theMessage
|
||||||
* The message to add to the status line
|
* The message to add to the status line
|
||||||
* @param theOperationOutcome The BaseOperationOutcome resource to return to the client
|
* @param theOperationOutcome The {@link IBaseOperationOutcome} resource to return to the client
|
||||||
*/
|
*/
|
||||||
public UnprocessableEntityException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
public UnprocessableEntityException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor which accepts an {@link BaseOperationOutcome} resource which will be supplied in the response
|
* Constructor which accepts an {@link IBaseOperationOutcome} resource which will be supplied in the response
|
||||||
*/
|
*/
|
||||||
public UnprocessableEntityException(BaseOperationOutcome theOperationOutcome) {
|
public UnprocessableEntityException(IBaseOperationOutcome theOperationOutcome) {
|
||||||
super(STATUS_CODE, DEFAULT_MESSAGE, theOperationOutcome);
|
super(STATUS_CODE, DEFAULT_MESSAGE, theOperationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor which accepts a String describing the issue. This string will be translated into an {@link BaseOperationOutcome} resource which will be supplied in the response.
|
* Constructor which accepts a String describing the issue. This string will be translated into an {@link IBaseOperationOutcome} resource which will be supplied in the response.
|
||||||
*/
|
*/
|
||||||
public UnprocessableEntityException(String theMessage) {
|
public UnprocessableEntityException(String theMessage) {
|
||||||
super(STATUS_CODE, theMessage);
|
super(STATUS_CODE, theMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor which accepts an array of Strings describing the issue. This strings will be translated into an {@link BaseOperationOutcome} resource which will be supplied in the response.
|
* Constructor which accepts an array of Strings describing the issue. This strings will be translated into an {@link IBaseOperationOutcome} resource which will be supplied in the response.
|
||||||
*/
|
*/
|
||||||
public UnprocessableEntityException(String... theMessage) {
|
public UnprocessableEntityException(String... theMessage) {
|
||||||
super(STATUS_CODE, theMessage);
|
super(STATUS_CODE, theMessage);
|
||||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@ -33,11 +34,18 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer.NarrativeModeEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interceptor detects when a request is coming from a browser, and automatically
|
||||||
|
* returns a response with syntax highlighted (coloured) HTML for the response instead
|
||||||
|
* of just returning raw XML/JSON.
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
||||||
|
|
||||||
private String format(String theResultBody, EncodingEnum theEncodingEnum) {
|
private String format(String theResultBody, EncodingEnum theEncodingEnum) {
|
||||||
|
@ -178,12 +186,15 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
||||||
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
|
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
streamResponse(theRequestDetails, theServletRequest, theServletResponse, theResponseObject);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void streamResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse, IBaseResource resource) {
|
||||||
// Pretty print
|
// Pretty print
|
||||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
|
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
|
||||||
|
|
||||||
// Narrative mode
|
|
||||||
NarrativeModeEnum narrativeMode = RestfulServerUtils.determineNarrativeMode(theRequestDetails);
|
|
||||||
|
|
||||||
// Determine response encoding
|
// Determine response encoding
|
||||||
EncodingEnum responseEncoding = null;
|
EncodingEnum responseEncoding = null;
|
||||||
if (theRequestDetails.getParameters().containsKey(Constants.PARAM_FORMAT)) {
|
if (theRequestDetails.getParameters().containsKey(Constants.PARAM_FORMAT)) {
|
||||||
|
@ -198,7 +209,7 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
||||||
IParser p = responseEncoding.newParser(theRequestDetails.getServer().getFhirContext());
|
IParser p = responseEncoding.newParser(theRequestDetails.getServer().getFhirContext());
|
||||||
p.setPrettyPrint(prettyPrint);
|
p.setPrettyPrint(prettyPrint);
|
||||||
|
|
||||||
String encoded = p.encodeResourceToString(theResponseObject);
|
String encoded = p.encodeResourceToString(resource);
|
||||||
|
|
||||||
theServletResponse.setContentType(Constants.CT_HTML_WITH_UTF8);
|
theServletResponse.setContentType(Constants.CT_HTML_WITH_UTF8);
|
||||||
|
|
||||||
|
@ -239,6 +250,43 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new InternalErrorException(e);
|
throw new InternalErrorException(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws ServletException, IOException {
|
||||||
|
/*
|
||||||
|
* It's not a browser...
|
||||||
|
*/
|
||||||
|
String accept = theServletRequest.getHeader(Constants.HEADER_ACCEPT);
|
||||||
|
if (accept == null || !accept.toLowerCase().contains("html")) {
|
||||||
|
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's an AJAX request, so no HTML
|
||||||
|
*/
|
||||||
|
String requestedWith = theServletRequest.getHeader("X-Requested-With");
|
||||||
|
if (requestedWith != null) {
|
||||||
|
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not a GET
|
||||||
|
*/
|
||||||
|
if (theRequestDetails.getRequestType() != RequestTypeEnum.GET) {
|
||||||
|
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(theException instanceof BaseServerResponseException)) {
|
||||||
|
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseServerResponseException bsre = (BaseServerResponseException)theException;
|
||||||
|
if (bsre.getOperationOutcome() == null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
streamResponse(theRequestDetails, theServletRequest, theServletResponse, bsre.getOperationOutcome());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class FhirValidator {
|
||||||
|
|
||||||
private static volatile Boolean ourPhlocPresentOnClasspath;
|
private static volatile Boolean ourPhlocPresentOnClasspath;
|
||||||
private final FhirContext myContext;
|
private final FhirContext myContext;
|
||||||
private volatile List<IValidator> myValidators = new ArrayList<IValidator>();
|
private volatile List<IValidatorModule> myValidators = new ArrayList<IValidatorModule>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor (this should not be called directly, but rather {@link FhirContext#newValidator()} should be called to obtain an instance of {@link FhirValidator})
|
* Constructor (this should not be called directly, but rather {@link FhirContext#newValidator()} should be called to obtain an instance of {@link FhirValidator})
|
||||||
|
@ -78,25 +78,25 @@ public class FhirValidator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addOrRemoveValidator(boolean theValidateAgainstStandardSchema, Class<? extends IValidator> type, IValidator theInstance) {
|
private void addOrRemoveValidator(boolean theValidateAgainstStandardSchema, Class<? extends IValidatorModule> type, IValidatorModule theInstance) {
|
||||||
if (theValidateAgainstStandardSchema) {
|
if (theValidateAgainstStandardSchema) {
|
||||||
boolean found = haveValidatorOfType(type);
|
boolean found = haveValidatorOfType(type);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
registerValidator(theInstance);
|
registerValidatorModule(theInstance);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Iterator<IValidator> iter = myValidators.iterator(); iter.hasNext();) {
|
for (Iterator<IValidatorModule> iter = myValidators.iterator(); iter.hasNext();) {
|
||||||
IValidator next = iter.next();
|
IValidatorModule next = iter.next();
|
||||||
if (next.getClass().equals(type)) {
|
if (next.getClass().equals(type)) {
|
||||||
unregisterValidator(next);
|
unregisterValidatorModule(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean haveValidatorOfType(Class<? extends IValidator> type) {
|
private boolean haveValidatorOfType(Class<? extends IValidatorModule> type) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (IValidator next : myValidators) {
|
for (IValidatorModule next : myValidators) {
|
||||||
if (next.getClass().equals(type)) {
|
if (next.getClass().equals(type)) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
@ -124,9 +124,9 @@ public class FhirValidator {
|
||||||
* @param theValidator
|
* @param theValidator
|
||||||
* The validator module. Must not be null.
|
* The validator module. Must not be null.
|
||||||
*/
|
*/
|
||||||
public synchronized void registerValidator(IValidator theValidator) {
|
public synchronized void registerValidatorModule(IValidatorModule theValidator) {
|
||||||
Validate.notNull(theValidator, "theValidator must not be null");
|
Validate.notNull(theValidator, "theValidator must not be null");
|
||||||
ArrayList<IValidator> newValidators = new ArrayList<IValidator>(myValidators.size() + 1);
|
ArrayList<IValidatorModule> newValidators = new ArrayList<IValidatorModule>(myValidators.size() + 1);
|
||||||
newValidators.addAll(myValidators);
|
newValidators.addAll(myValidators);
|
||||||
newValidators.add(theValidator);
|
newValidators.add(theValidator);
|
||||||
|
|
||||||
|
@ -162,9 +162,9 @@ public class FhirValidator {
|
||||||
* @param theValidator
|
* @param theValidator
|
||||||
* The validator module. Must not be null.
|
* The validator module. Must not be null.
|
||||||
*/
|
*/
|
||||||
public synchronized void unregisterValidator(IValidator theValidator) {
|
public synchronized void unregisterValidatorModule(IValidatorModule theValidator) {
|
||||||
Validate.notNull(theValidator, "theValidator must not be null");
|
Validate.notNull(theValidator, "theValidator must not be null");
|
||||||
ArrayList<IValidator> newValidators = new ArrayList<IValidator>(myValidators.size() + 1);
|
ArrayList<IValidatorModule> newValidators = new ArrayList<IValidatorModule>(myValidators.size() + 1);
|
||||||
newValidators.addAll(myValidators);
|
newValidators.addAll(myValidators);
|
||||||
newValidators.remove(theValidator);
|
newValidators.remove(theValidator);
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ public class FhirValidator {
|
||||||
|
|
||||||
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
||||||
|
|
||||||
for (IValidator next : myValidators) {
|
for (IValidatorModule next : myValidators) {
|
||||||
next.validateBundle(ctx);
|
next.validateBundle(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ public class FhirValidator {
|
||||||
|
|
||||||
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
||||||
|
|
||||||
for (IValidator next : myValidators) {
|
for (IValidatorModule next : myValidators) {
|
||||||
next.validateBundle(ctx);
|
next.validateBundle(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ public class FhirValidator {
|
||||||
|
|
||||||
IValidationContext<IBaseResource> ctx = ValidationContext.forResource(myContext, theResource);
|
IValidationContext<IBaseResource> ctx = ValidationContext.forResource(myContext, theResource);
|
||||||
|
|
||||||
for (IValidator next : myValidators) {
|
for (IValidatorModule next : myValidators) {
|
||||||
next.validateResource(ctx);
|
next.validateResource(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ public class FhirValidator {
|
||||||
|
|
||||||
IValidationContext<IBaseResource> ctx = ValidationContext.forText(myContext, theResource);
|
IValidationContext<IBaseResource> ctx = ValidationContext.forText(myContext, theResource);
|
||||||
|
|
||||||
for (IValidator next : myValidators) {
|
for (IValidatorModule next : myValidators) {
|
||||||
next.validateResource(ctx);
|
next.validateResource(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
||||||
/**
|
/**
|
||||||
* Registers
|
* Registers
|
||||||
*/
|
*/
|
||||||
public interface IValidator {
|
public interface IValidatorModule {
|
||||||
|
|
||||||
void validateResource(IValidationContext<IBaseResource> theCtx);
|
void validateResource(IValidationContext<IBaseResource> theCtx);
|
||||||
|
|
|
@ -52,7 +52,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
|
||||||
class SchemaBaseValidator implements IValidator {
|
class SchemaBaseValidator implements IValidatorModule {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaBaseValidator.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaBaseValidator.class);
|
||||||
private static final Set<String> SCHEMA_NAMES;
|
private static final Set<String> SCHEMA_NAMES;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import com.phloc.schematron.ISchematronResource;
|
||||||
import com.phloc.schematron.SchematronHelper;
|
import com.phloc.schematron.SchematronHelper;
|
||||||
import com.phloc.schematron.xslt.SchematronResourceSCH;
|
import com.phloc.schematron.xslt.SchematronResourceSCH;
|
||||||
|
|
||||||
public class SchematronBaseValidator implements IValidator {
|
public class SchematronBaseValidator implements IValidatorModule {
|
||||||
|
|
||||||
private Map<Class<? extends IBaseResource>, ISchematronResource> myClassToSchematron = new HashMap<Class<? extends IBaseResource>, ISchematronResource>();
|
private Map<Class<? extends IBaseResource>, ISchematronResource> myClassToSchematron = new HashMap<Class<? extends IBaseResource>, ISchematronResource>();
|
||||||
private FhirContext myCtx;
|
private FhirContext myCtx;
|
||||||
|
|
|
@ -80,7 +80,9 @@ public class ValidationResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link #toOperationOutcome()} instead since this method returns a view
|
* @deprecated Use {@link #toOperationOutcome()} instead since this method returns a view.
|
||||||
|
* {@link #toOperationOutcome()} is identical to this method, but has a more suitable name so this method
|
||||||
|
* will be removed at some point.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public IBaseOperationOutcome getOperationOutcome() {
|
public IBaseOperationOutcome getOperationOutcome() {
|
||||||
|
|
|
@ -276,7 +276,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
values.addAll(t.getValues(theResource, nextPathTrimmed));
|
values.addAll(t.getValues(theResource, nextPathTrimmed));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", new Object[] { nextPathTrimmed, def.getName(), e.toString() } );
|
ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", new Object[] { nextPathTrimmed, def.getName(), e.toString() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
|
@ -325,7 +325,8 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IFhirResourceDao<? extends IResource> getDao(Class<? extends IBaseResource> theType) {
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T extends IBaseResource> IFhirResourceDao<T> getDao(Class<T> theType) {
|
||||||
if (myResourceTypeToDao == null) {
|
if (myResourceTypeToDao == null) {
|
||||||
myResourceTypeToDao = new HashMap<Class<? extends IBaseResource>, IFhirResourceDao<?>>();
|
myResourceTypeToDao = new HashMap<Class<? extends IBaseResource>, IFhirResourceDao<?>>();
|
||||||
for (IFhirResourceDao<?> next : myResourceDaos) {
|
for (IFhirResourceDao<?> next : myResourceDaos) {
|
||||||
|
@ -339,7 +340,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return myResourceTypeToDao.get(theType);
|
return (IFhirResourceDao<T>) myResourceTypeToDao.get(theType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TagDefinition getTag(TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
protected TagDefinition getTag(TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||||
|
@ -625,12 +626,12 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
protected <T extends IResource> Set<Long> processMatchUrl(String theMatchUrl, Class<T> theResourceType) {
|
||||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||||
|
|
||||||
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
||||||
|
|
||||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
IFhirResourceDao<T> dao = getDao(theResourceType);
|
||||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
|
@ -1019,8 +1020,10 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true);
|
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
|
||||||
boolean theUpdateVersion) {
|
|
||||||
|
validateResourceForStorage(theResource);
|
||||||
|
|
||||||
if (entity.getPublished() == null) {
|
if (entity.getPublished() == null) {
|
||||||
entity.setPublished(new Date());
|
entity.setPublished(new Date());
|
||||||
}
|
}
|
||||||
|
@ -1028,8 +1031,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
if (theResource != null) {
|
if (theResource != null) {
|
||||||
String resourceType = myContext.getResourceDefinition(theResource).getName();
|
String resourceType = myContext.getResourceDefinition(theResource).getName();
|
||||||
if (isNotBlank(entity.getResourceType()) && !entity.getResourceType().equals(resourceType)) {
|
if (isNotBlank(entity.getResourceType()) && !entity.getResourceType().equals(resourceType)) {
|
||||||
throw new UnprocessableEntityException("Existing resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + entity.getResourceType() + "] - Cannot update with ["
|
throw new UnprocessableEntityException("Existing resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + entity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
|
||||||
+ resourceType + "]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1195,6 +1197,16 @@ public abstract class BaseHapiFhirDao implements IDao {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses may override to provide specific behaviour
|
||||||
|
*
|
||||||
|
* @param theResource
|
||||||
|
* The resource that is about to be persisted
|
||||||
|
*/
|
||||||
|
protected void validateResourceForStorage(IResource theResource) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
protected static String normalizeString(String theString) {
|
protected static String normalizeString(String theString) {
|
||||||
char[] out = new char[theString.length()];
|
char[] out = new char[theString.length()];
|
||||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||||
|
|
|
@ -56,8 +56,10 @@ import javax.persistence.criteria.Subquery;
|
||||||
|
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.omg.PortableInterceptor.InterceptorOperations;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Required;
|
import org.springframework.beans.factory.annotation.Required;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
@ -857,16 +859,24 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
||||||
if (isNotBlank(theResource.getId().getIdPart())) {
|
if (isNotBlank(theResource.getId().getIdPart())) {
|
||||||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||||
if (theResource.getId().isIdPartValidLong()) {
|
if (theResource.getId().isIdPartValidLong()) {
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart());
|
||||||
|
throw new InvalidRequestException(message, createErrorOperationOutcome(message));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getId().getIdPart()));
|
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getId().getIdPart());
|
||||||
|
throw new InvalidRequestException(message, createErrorOperationOutcome(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
|
||||||
|
return createOperationOutcome("error", theMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage);
|
||||||
|
|
||||||
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
||||||
Predicate retVal = null;
|
Predicate retVal = null;
|
||||||
switch (left.getParamType()) {
|
switch (left.getParamType()) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.model.primitive.UriDt;
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
|
||||||
public class FhirBundleResourceDaoDstu2 extends FhirResourceDaoDstu2<Bundle> {
|
public class FhirResourceDaoBundleDstu2 extends FhirResourceDaoDstu2<Bundle> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void preProcessResourceForStorage(Bundle theResource) {
|
protected void preProcessResourceForStorage(Bundle theResource) {
|
|
@ -24,12 +24,18 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
||||||
|
@ -47,5 +53,18 @@ public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResou
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodOutcome validate(T theResource, IdDt theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
|
||||||
|
OperationOutcome oo = new OperationOutcome();
|
||||||
|
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
|
||||||
|
oo.getIssueFirstRep().getDetailsElement().setValue(theMessage);
|
||||||
|
return oo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,11 @@ package ca.uhn.fhir.jpa.dao;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
@ -31,7 +32,20 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome.Issue;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import ca.uhn.fhir.parser.IParserErrorHandler;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
||||||
|
|
||||||
|
@ -52,5 +66,48 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
|
||||||
|
OperationOutcome oo = new OperationOutcome();
|
||||||
|
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
|
||||||
|
oo.getIssueFirstRep().getDetailsElement().setValue(theMessage);
|
||||||
|
return oo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodOutcome validate(T theResource, IdDt theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
|
||||||
|
final OperationOutcome oo = new OperationOutcome();
|
||||||
|
|
||||||
|
IParser parser = theEncoding.newParser(getContext());
|
||||||
|
parser.setParserErrorHandler(new IParserErrorHandler() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unknownAttribute(IParseLocation theLocation, String theAttributeName) {
|
||||||
|
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown attribute found: " + theAttributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unknownElement(IParseLocation theLocation, String theElementName) {
|
||||||
|
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown element found: " + theElementName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
FhirValidator validator = getContext().newValidator();
|
||||||
|
validator.setValidateAgainstStandardSchema(true);
|
||||||
|
validator.setValidateAgainstStandardSchematron(true);
|
||||||
|
ValidationResult result = validator.validateWithResult(theResource);
|
||||||
|
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
|
||||||
|
for (BaseIssue next : operationOutcome.getIssue()) {
|
||||||
|
oo.getIssue().add((Issue) next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method returns a MethodOutcome object
|
||||||
|
MethodOutcome retVal = new MethodOutcome();
|
||||||
|
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Validation succeeded");
|
||||||
|
retVal.setOperationOutcome(oo);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireAnswers;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
import ca.uhn.fhir.validation.FhirQuestionnaireAnswersValidator;
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
import ca.uhn.fhir.validation.IResourceLoader;
|
||||||
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
|
|
||||||
|
public class FhirResourceDaoQuestionnaireAnswersDstu2 extends FhirResourceDaoDstu2<QuestionnaireAnswers> {
|
||||||
|
|
||||||
|
private FhirContext myRefImplCtx = FhirContext.forDstu2Hl7Org();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateResourceForStorage(IResource theResource) {
|
||||||
|
super.validateResourceForStorage(theResource);
|
||||||
|
|
||||||
|
QuestionnaireAnswers qa = (QuestionnaireAnswers) theResource;
|
||||||
|
if (qa.getQuestionnaire().getReference().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FhirValidator val = myRefImplCtx.newValidator();
|
||||||
|
val.setValidateAgainstStandardSchema(false);
|
||||||
|
val.setValidateAgainstStandardSchematron(false);
|
||||||
|
|
||||||
|
FhirQuestionnaireAnswersValidator module = new FhirQuestionnaireAnswersValidator();
|
||||||
|
module.setResourceLoader(new JpaResourceLoader());
|
||||||
|
val.registerValidatorModule(module);
|
||||||
|
|
||||||
|
ValidationResult result = val.validateWithResult(myRefImplCtx.newJsonParser().parseResource(getContext().newJsonParser().encodeResourceToString(qa)));
|
||||||
|
if (!result.isSuccessful()) {
|
||||||
|
IBaseOperationOutcome oo = getContext().newJsonParser().parseResource(OperationOutcome.class, myRefImplCtx.newJsonParser().encodeResourceToString(result.toOperationOutcome()));
|
||||||
|
throw new UnprocessableEntityException(oo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JpaResourceLoader implements IResourceLoader {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IBaseResource> T load(Class<T> theType, IIdType theId) throws ResourceNotFoundException {
|
||||||
|
/*
|
||||||
|
* The QuestionnaireAnswers validator uses RI structures, so for now we need
|
||||||
|
* to convert between that and HAPI structures. This is a bit hackish, but
|
||||||
|
* hopefully it will go away at some point.
|
||||||
|
*/
|
||||||
|
if ("ValueSet".equals(theType.getSimpleName())) {
|
||||||
|
IFhirResourceDao<ValueSet> dao = getDao(ValueSet.class);
|
||||||
|
ValueSet vs = dao.read(theId);
|
||||||
|
return myRefImplCtx.newJsonParser().parseResource(theType, getContext().newJsonParser().encodeResourceToString(vs));
|
||||||
|
} else if ("Questionnaire".equals(theType.getSimpleName())) {
|
||||||
|
IFhirResourceDao<Questionnaire> dao = getDao(Questionnaire.class);
|
||||||
|
Questionnaire vs = dao.read(theId);
|
||||||
|
return myRefImplCtx.newJsonParser().parseResource(theType, getContext().newJsonParser().encodeResourceToString(vs));
|
||||||
|
} else {
|
||||||
|
// Should not happen, validator will only ask for these two
|
||||||
|
throw new IllegalStateException("Unexpected request to load resource of type " + theType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -132,7 +132,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
||||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||||
throw new InvalidRequestException(msg);
|
throw new InvalidRequestException(msg);
|
||||||
}
|
}
|
||||||
IFhirResourceDao<? extends IResource> dao = null;
|
IFhirResourceDao<? extends IBaseResource> dao = null;
|
||||||
if (resType != null) {
|
if (resType != null) {
|
||||||
dao = getDao(resType.getImplementingClass());
|
dao = getDao(resType.getImplementingClass());
|
||||||
}
|
}
|
||||||
|
@ -268,9 +268,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
||||||
if (isNotBlank(ifNoneMatch)) {
|
if (isNotBlank(ifNoneMatch)) {
|
||||||
throw new InvalidRequestException("Unable to perform vread on '" + url + "' with ifNoneMatch also set. Do not include a version in the URL to perform a conditional read.");
|
throw new InvalidRequestException("Unable to perform vread on '" + url + "' with ifNoneMatch also set. Do not include a version in the URL to perform a conditional read.");
|
||||||
}
|
}
|
||||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
found = (IResource) resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||||
} else {
|
} else {
|
||||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
found = (IResource) resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||||
if (isNotBlank(ifNoneMatch) && ifNoneMatch.equals(found.getId().getVersionIdPart())) {
|
if (isNotBlank(ifNoneMatch) && ifNoneMatch.equals(found.getId().getVersionIdPart())) {
|
||||||
notChanged = true;
|
notChanged = true;
|
||||||
}
|
}
|
||||||
|
@ -392,13 +392,13 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class UrlParts {
|
private static class UrlParts {
|
||||||
private IFhirResourceDao<? extends IResource> myDao;
|
private IFhirResourceDao<? extends IBaseResource> myDao;
|
||||||
private String myParams;
|
private String myParams;
|
||||||
private String myResourceId;
|
private String myResourceId;
|
||||||
private String myResourceType;
|
private String myResourceType;
|
||||||
private String myVersionId;
|
private String myVersionId;
|
||||||
|
|
||||||
public IFhirResourceDao<? extends IResource> getDao() {
|
public IFhirResourceDao<? extends IBaseResource> getDao() {
|
||||||
return myDao;
|
return myDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
||||||
return myVersionId;
|
return myVersionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDao(IFhirResourceDao<? extends IResource> theDao) {
|
public void setDao(IFhirResourceDao<? extends IBaseResource> theDao) {
|
||||||
myDao = theDao;
|
myDao = theDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,22 @@ import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
|
||||||
public interface IFhirResourceDao<T extends IResource> extends IDao {
|
public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
|
||||||
|
|
||||||
void addTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel);
|
void addTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel);
|
||||||
|
|
||||||
|
@ -44,8 +48,9 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
||||||
DaoMethodOutcome create(T theResource, String theIfNoneExist);
|
DaoMethodOutcome create(T theResource, String theIfNoneExist);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param thePerformIndexing Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
* @param thePerformIndexing
|
||||||
* won't be indexed and searches won't work.
|
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||||
|
* won't be indexed and searches won't work.
|
||||||
*/
|
*/
|
||||||
DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing);
|
DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing);
|
||||||
|
|
||||||
|
@ -65,20 +70,41 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
||||||
|
|
||||||
IBundleProvider history(Long theId, Date theSince);
|
IBundleProvider history(Long theId, Date theSince);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported in DSTU1!
|
||||||
|
*/
|
||||||
|
MetaDt metaAddOperation(IIdType theId1, MetaDt theMetaAdd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported in DSTU1!
|
||||||
|
*/
|
||||||
|
MetaDt metaDeleteOperation(IIdType theId1, MetaDt theMetaDel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported in DSTU1!
|
||||||
|
*/
|
||||||
|
MetaDt metaGetOperation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported in DSTU1!
|
||||||
|
*/
|
||||||
|
MetaDt metaGetOperation(IIdType theId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param theId
|
* @param theId
|
||||||
* @return
|
* @return
|
||||||
* @throws ResourceNotFoundException
|
* @throws ResourceNotFoundException
|
||||||
* If the ID is not known to the server
|
* If the ID is not known to the server
|
||||||
*/
|
*/
|
||||||
T read(IIdType theId);
|
T read(IIdType theId);
|
||||||
|
|
||||||
BaseHasResource readEntity(IIdType theId);
|
BaseHasResource readEntity(IIdType theId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param theCheckForForcedId If true, this method should fail if the requested ID contains a numeric PID which exists, but is
|
* @param theCheckForForcedId
|
||||||
* obscured by a "forced ID" so should not exist as far as the outside world is concerned.
|
* If true, this method should fail if the requested ID contains a numeric PID which exists, but is
|
||||||
|
* obscured by a "forced ID" so should not exist as far as the outside world is concerned.
|
||||||
*/
|
*/
|
||||||
BaseHasResource readEntity(IIdType theId, boolean theCheckForForcedId);
|
BaseHasResource readEntity(IIdType theId, boolean theCheckForForcedId);
|
||||||
|
|
||||||
|
@ -102,28 +128,14 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param thePerformIndexing
|
* @param thePerformIndexing
|
||||||
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||||
* won't be indexed and searches won't work.
|
* won't be indexed and searches won't work.
|
||||||
*/
|
*/
|
||||||
DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing);
|
DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not supported in DSTU1!
|
* Not supported in DSTU1!
|
||||||
*/
|
*/
|
||||||
MetaDt metaGetOperation();
|
MethodOutcome validate(T theResource, IdDt theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile);
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported in DSTU1!
|
|
||||||
*/
|
|
||||||
MetaDt metaGetOperation(IIdType theId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported in DSTU1!
|
|
||||||
*/
|
|
||||||
MetaDt metaDeleteOperation(IIdType theId1, MetaDt theMetaDel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported in DSTU1!
|
|
||||||
*/
|
|
||||||
MetaDt metaAddOperation(IIdType theId1, MetaDt theMetaAdd);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,38 +165,7 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
||||||
@Validate
|
@Validate
|
||||||
public MethodOutcome validate(@ResourceParam T theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
|
public MethodOutcome validate(@ResourceParam T theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
|
||||||
@Validate.Profile String theProfile) {
|
@Validate.Profile String theProfile) {
|
||||||
|
return getDao().validate(theResource, theId, theRawResource, theEncoding, theMode, theProfile);
|
||||||
final OperationOutcome oo = new OperationOutcome();
|
|
||||||
|
|
||||||
IParser parser = theEncoding.newParser(getContext());
|
|
||||||
parser.setParserErrorHandler(new IParserErrorHandler() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unknownAttribute(IParseLocation theLocation, String theAttributeName) {
|
|
||||||
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown attribute found: " + theAttributeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unknownElement(IParseLocation theLocation, String theElementName) {
|
|
||||||
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown element found: " + theElementName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
FhirValidator validator = getContext().newValidator();
|
|
||||||
validator.setValidateAgainstStandardSchema(true);
|
|
||||||
validator.setValidateAgainstStandardSchematron(true);
|
|
||||||
ValidationResult result = validator.validateWithResult(theResource);
|
|
||||||
OperationOutcome operationOutcome = (OperationOutcome) result.getOperationOutcome();
|
|
||||||
for (BaseIssue next : operationOutcome.getIssue()) {
|
|
||||||
oo.getIssue().add((Issue) next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method returns a MethodOutcome object
|
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
|
||||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Validation succeeded");
|
|
||||||
retVal.setOperationOutcome(oo);
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Device;
|
import ca.uhn.fhir.model.dstu.resource.Device;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Practitioner;
|
import ca.uhn.fhir.model.dstu.resource.Practitioner;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||||
|
@ -65,7 +66,10 @@ import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireAnswers;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||||
|
@ -188,27 +192,26 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
@Test
|
@Test
|
||||||
public void testMetaOperations() throws Exception {
|
public void testMetaOperations() throws Exception {
|
||||||
String methodName = "testMetaOperations";
|
String methodName = "testMetaOperations";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
pt.addName().addFamily(methodName);
|
pt.addName().addFamily(methodName);
|
||||||
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
|
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
|
||||||
assertEquals(0, meta.getTag().size());
|
assertEquals(0, meta.getTag().size());
|
||||||
|
|
||||||
MetaDt inMeta = new MetaDt();
|
MetaDt inMeta = new MetaDt();
|
||||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||||
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
|
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
|
||||||
assertEquals(1, meta.getTag().size());
|
assertEquals(1, meta.getTag().size());
|
||||||
|
|
||||||
inMeta = new MetaDt();
|
inMeta = new MetaDt();
|
||||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||||
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
|
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
|
||||||
assertEquals(0, meta.getTag().size());
|
assertEquals(0, meta.getTag().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResourceConditional() throws IOException {
|
public void testCreateResourceConditional() throws IOException {
|
||||||
String methodName = "testCreateResourceConditional";
|
String methodName = "testCreateResourceConditional";
|
||||||
|
@ -245,6 +248,40 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateQuestionnaireAnswersWithValidation() throws IOException {
|
||||||
|
String methodName = "testCreateQuestionnaireAnswersWithValidation";
|
||||||
|
|
||||||
|
ValueSet options = new ValueSet();
|
||||||
|
options.getDefine().setSystem("urn:system").addConcept().setCode("code0");
|
||||||
|
IIdType optId = ourClient.create().resource(options).execute().getId();
|
||||||
|
|
||||||
|
Questionnaire q = new Questionnaire();
|
||||||
|
q.getGroup().addQuestion().setLinkId("link0").setRequired(false).setType(AnswerFormatEnum.CHOICE).setOptions(new ResourceReferenceDt(optId));
|
||||||
|
IIdType qId = ourClient.create().resource(q).execute().getId();
|
||||||
|
|
||||||
|
QuestionnaireAnswers qa;
|
||||||
|
|
||||||
|
// Good code
|
||||||
|
|
||||||
|
qa = new QuestionnaireAnswers();
|
||||||
|
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
|
||||||
|
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code0"));
|
||||||
|
ourClient.create().resource(qa).execute();
|
||||||
|
|
||||||
|
// Bad code
|
||||||
|
|
||||||
|
qa = new QuestionnaireAnswers();
|
||||||
|
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
|
||||||
|
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code1"));
|
||||||
|
try {
|
||||||
|
ourClient.create().resource(qa).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Question with linkId[link0]"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResourceWithNumericId() throws IOException {
|
public void testCreateResourceWithNumericId() throws IOException {
|
||||||
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||||
|
@ -255,7 +292,10 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||||
try {
|
try {
|
||||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||||
|
String respString = IOUtils.toString(response.getEntity().getContent());
|
||||||
|
ourLog.info(respString);
|
||||||
} finally {
|
} finally {
|
||||||
|
response.getEntity().getContent().close();
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +405,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to make sure that works too..
|
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to
|
||||||
|
* make sure that works too..
|
||||||
*/
|
*/
|
||||||
Socket sock = new Socket();
|
Socket sock = new Socket();
|
||||||
sock.setSoTimeout(3000);
|
sock.setSoTimeout(3000);
|
||||||
|
@ -739,8 +780,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
|
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
|
||||||
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
|
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
|
||||||
|
|
||||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint()
|
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint().execute();
|
||||||
.execute();
|
|
||||||
assertEquals(1, actual.size());
|
assertEquals(1, actual.size());
|
||||||
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
||||||
|
|
||||||
|
@ -1166,8 +1206,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
||||||
|
|
||||||
assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history"));
|
assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history"));
|
||||||
|
|
||||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2"))
|
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2")).encodedJson().prettyPrint().execute();
|
||||||
.encodedJson().prettyPrint().execute();
|
|
||||||
assertEquals(1, actual.size());
|
assertEquals(1, actual.size());
|
||||||
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
@ -122,7 +123,6 @@ public class ExceptionHandlingTest {
|
||||||
assertThat(e.getResponseBody(), StringContains.containsString("value=\"foo\""));
|
assertThat(e.getResponseBody(), StringContains.containsString("value=\"foo\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -146,7 +146,7 @@ public class ExceptionHandlingTest {
|
||||||
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
||||||
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
||||||
assertNotNull(e.getOperationOutcome());
|
assertNotNull(e.getOperationOutcome());
|
||||||
assertEquals("Help I'm a bug",e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue());
|
assertEquals("Help I'm a bug", ((BaseOperationOutcome) e.getOperationOutcome()).getIssueFirstRep().getDetailsElement().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ public class ExceptionHandlingTest {
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", contentType + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", contentType + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
IMyClient client = ourCtx.newRestfulClient(IMyClient.class,"http://example.com/fhir");
|
IMyClient client = ourCtx.newRestfulClient(IMyClient.class, "http://example.com/fhir");
|
||||||
try {
|
try {
|
||||||
client.read(new IdDt("Patient/1234"));
|
client.read(new IdDt("Patient/1234"));
|
||||||
fail();
|
fail();
|
||||||
|
@ -172,15 +172,14 @@ public class ExceptionHandlingTest {
|
||||||
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
||||||
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
||||||
assertNotNull(e.getOperationOutcome());
|
assertNotNull(e.getOperationOutcome());
|
||||||
assertEquals("Help I'm a bug",e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue());
|
assertEquals("Help I'm a bug", ((BaseOperationOutcome) e.getOperationOutcome()).getIssueFirstRep().getDetailsElement().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IMyClient extends IRestfulClient
|
public interface IMyClient extends IRestfulClient {
|
||||||
{
|
|
||||||
@Read
|
@Read
|
||||||
Patient read(@IdParam IdDt theId);
|
Patient read(@IdParam IdDt theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package ca.uhn.fhir.rest.server.exceptions;
|
package ca.uhn.fhir.rest.server.exceptions;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.reflect.ClassPath;
|
import com.google.common.reflect.ClassPath;
|
||||||
import com.google.common.reflect.ClassPath.ClassInfo;
|
import com.google.common.reflect.ClassPath.ClassInfo;
|
||||||
|
@ -48,9 +45,9 @@ public class ExceptionPropertiesTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
next.getConstructor(String.class, BaseOperationOutcome.class);
|
next.getConstructor(String.class, IBaseOperationOutcome.class);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
fail(classInfo.getName() + " has no constructor with params: (String, OperationOutcome)");
|
fail(classInfo.getName() + " has no constructor with params: (String, IBaseOperationOutcome)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class FhirDstu2 implements IFhirVersion {
|
||||||
str = FhirDstu2.class.getResourceAsStream("ca/uhn/fhir/model/dstu2/fhirversion.properties");
|
str = FhirDstu2.class.getResourceAsStream("ca/uhn/fhir/model/dstu2/fhirversion.properties");
|
||||||
}
|
}
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
throw new ConfigurationException("Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dstu2/model.properties");
|
throw new ConfigurationException("Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dstu2/fhirversion.properties");
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,87 @@
|
||||||
package ca.uhn.fhir.rest.server.interceptor;
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome.Issue;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
|
||||||
public class ResponseHighlightingInterceptorTest {
|
public class ResponseHighlightingInterceptorTest {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseHighlightingInterceptorTest.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHighlight() {
|
public void testHighlightNormalResponse() throws Exception {
|
||||||
ResponseHighlighterInterceptor ic = new ResponseHighlighterInterceptor();
|
ResponseHighlighterInterceptor ic = new ResponseHighlighterInterceptor();
|
||||||
|
|
||||||
|
HttpServletRequest req = mock(HttpServletRequest.class);
|
||||||
|
when(req.getHeader(Constants.HEADER_ACCEPT)).thenReturn("text/html");
|
||||||
|
|
||||||
|
HttpServletResponse resp = mock(HttpServletResponse.class);
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
when(resp.getWriter()).thenReturn(new PrintWriter(sw));
|
||||||
|
|
||||||
|
Patient resource = new Patient();
|
||||||
|
resource.addName().addFamily("FAMILY");
|
||||||
|
|
||||||
|
RequestDetails reqDetails = new RequestDetails();
|
||||||
|
reqDetails.setRequestType(RequestTypeEnum.GET);
|
||||||
|
reqDetails.setParameters(new HashMap<String, String[]>());
|
||||||
|
reqDetails.setServer(new RestfulServer());
|
||||||
|
reqDetails.setServletRequest(req);
|
||||||
|
|
||||||
|
assertFalse(ic.outgoingResponse(reqDetails, resource, req, resp));
|
||||||
|
|
||||||
|
String output = sw.getBuffer().toString();
|
||||||
|
ourLog.info(output);
|
||||||
|
assertThat(output, containsString("<span class='hlTagName'>Patient</span>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHighlightException() throws Exception {
|
||||||
|
ResponseHighlighterInterceptor ic = new ResponseHighlighterInterceptor();
|
||||||
|
|
||||||
|
HttpServletRequest req = mock(HttpServletRequest.class);
|
||||||
|
when(req.getHeader(Constants.HEADER_ACCEPT)).thenReturn("text/html");
|
||||||
|
|
||||||
|
HttpServletResponse resp = mock(HttpServletResponse.class);
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
when(resp.getWriter()).thenReturn(new PrintWriter(sw));
|
||||||
|
|
||||||
|
Patient resource = new Patient();
|
||||||
|
resource.addName().addFamily("FAMILY");
|
||||||
|
|
||||||
|
RequestDetails reqDetails = new RequestDetails();
|
||||||
|
reqDetails.setRequestType(RequestTypeEnum.GET);
|
||||||
|
reqDetails.setParameters(new HashMap<String, String[]>());
|
||||||
|
reqDetails.setServer(new RestfulServer());
|
||||||
|
reqDetails.setServletRequest(req);
|
||||||
|
|
||||||
|
ResourceNotFoundException exception = new ResourceNotFoundException("Not found");
|
||||||
|
exception.setOperationOutcome(new OperationOutcome().addIssue(new Issue().setDetails("Hello")));
|
||||||
|
|
||||||
|
assertFalse(ic.handleException(reqDetails, exception, req, resp));
|
||||||
|
|
||||||
|
String output = sw.getBuffer().toString();
|
||||||
|
ourLog.info(output);
|
||||||
|
assertThat(output, containsString("<span class='hlTagName'>OperationOutcome</span>"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
||||||
/**
|
/**
|
||||||
* Base class for a bridge between the RI validation tools and HAPI
|
* Base class for a bridge between the RI validation tools and HAPI
|
||||||
*/
|
*/
|
||||||
abstract class BaseValidatorBridge implements IValidator {
|
abstract class BaseValidatorBridge implements IValidatorModule {
|
||||||
|
|
||||||
public BaseValidatorBridge() {
|
public BaseValidatorBridge() {
|
||||||
super();
|
super();
|
||||||
|
|
|
@ -30,7 +30,7 @@ import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidator {
|
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
|
||||||
|
|
||||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidator.class);
|
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidator.class);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class FhirInstanceValidatorTest {
|
||||||
val = ourCtx.newValidator();
|
val = ourCtx.newValidator();
|
||||||
val.setValidateAgainstStandardSchema(false);
|
val.setValidateAgainstStandardSchema(false);
|
||||||
val.setValidateAgainstStandardSchematron(false);
|
val.setValidateAgainstStandardSchematron(false);
|
||||||
val.registerValidator(new FhirInstanceValidator());
|
val.registerValidatorModule(new FhirInstanceValidator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
||||||
myVal = ourCtx.newValidator();
|
myVal = ourCtx.newValidator();
|
||||||
myVal.setValidateAgainstStandardSchema(false);
|
myVal.setValidateAgainstStandardSchema(false);
|
||||||
myVal.setValidateAgainstStandardSchematron(false);
|
myVal.setValidateAgainstStandardSchematron(false);
|
||||||
myVal.registerValidator(qaVal);
|
myVal.registerValidatorModule(qaVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -73,7 +73,7 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
||||||
Questionnaire q = new Questionnaire();
|
Questionnaire q = new Questionnaire();
|
||||||
q.getGroup().addQuestion().setLinkId("link0").setRequired(false).setType(AnswerFormat.CHOICE).setOptions(new Reference("http://somevalueset/ValueSet/123"));
|
q.getGroup().addQuestion().setLinkId("link0").setRequired(false).setType(AnswerFormat.CHOICE).setOptions(new Reference("http://somevalueset/ValueSet/123"));
|
||||||
when(myResourceLoaderMock.load(Mockito.eq(Questionnaire.class), Mockito.eq(new IdType("http://example.com/Questionnaire/q1")))).thenReturn(q);
|
when(myResourceLoaderMock.load(Mockito.eq(Questionnaire.class), Mockito.eq(new IdType("http://example.com/Questionnaire/q1")))).thenReturn(q);
|
||||||
|
|
||||||
ValueSet options = new ValueSet();
|
ValueSet options = new ValueSet();
|
||||||
options.getDefine().setSystem("urn:system").addConcept().setCode("code0");
|
options.getDefine().setSystem("urn:system").addConcept().setCode("code0");
|
||||||
when(myResourceLoaderMock.load(Mockito.eq(ValueSet.class), Mockito.eq(new IdType("http://somevalueset/ValueSet/123")))).thenReturn(options);
|
when(myResourceLoaderMock.load(Mockito.eq(ValueSet.class), Mockito.eq(new IdType("http://somevalueset/ValueSet/123")))).thenReturn(options);
|
||||||
|
@ -97,6 +97,8 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
||||||
ourLog.info(result.getMessages().toString());
|
ourLog.info(result.getMessages().toString());
|
||||||
assertThat(result.getMessages().toString(), containsString("myLocationString=QuestionnaireAnswers.group(0).question(0).answer(0)"));
|
assertThat(result.getMessages().toString(), containsString("myLocationString=QuestionnaireAnswers.group(0).question(0).answer(0)"));
|
||||||
assertThat(result.getMessages().toString(), containsString("myMessage=Question with linkId[link0] has answer with system[urn:system] and code[code1] but this is not a valid answer for ValueSet[http://somevalueset/ValueSet/123]"));
|
assertThat(result.getMessages().toString(), containsString("myMessage=Question with linkId[link0] has answer with system[urn:system] and code[code1] but this is not a valid answer for ValueSet[http://somevalueset/ValueSet/123]"));
|
||||||
|
|
||||||
|
result.toOperationOutcome();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
|
|
||||||
#foreach ( $res in $resources )
|
#foreach ( $res in $resources )
|
||||||
<bean id="my${res.name}Dao${versionCapitalized}"
|
<bean id="my${res.name}Dao${versionCapitalized}"
|
||||||
#if ( ${res.name} == 'Bundle' )
|
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'QuestionnaireAnswers' ))
|
||||||
class="ca.uhn.fhir.jpa.dao.Fhir${res.name}ResourceDao${versionCapitalized}">
|
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${res.name}${versionCapitalized}">
|
||||||
#else
|
#else
|
||||||
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">
|
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">
|
||||||
#end
|
#end
|
||||||
|
|
|
@ -6,6 +6,15 @@
|
||||||
<title>HAPI FHIR Changelog</title>
|
<title>HAPI FHIR Changelog</title>
|
||||||
</properties>
|
</properties>
|
||||||
<body>
|
<body>
|
||||||
|
<release version="1.2" date="2015-07-13">
|
||||||
|
<action type="add">
|
||||||
|
JPA server now validates QuestionnaireAnswers for conformance to their respective Questionnaire
|
||||||
|
if one is declared.
|
||||||
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
SyntaxHighlightingInterceptor now also highlights OperationOutcome responses for errors/exceptions.
|
||||||
|
</action>
|
||||||
|
</release>
|
||||||
<release version="1.1" date="2015-07-13">
|
<release version="1.1" date="2015-07-13">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
Add support for reference implementation structures.
|
Add support for reference implementation structures.
|
||||||
|
|
Loading…
Reference in New Issue