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.
|
||||
*/
|
||||
@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);
|
||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG) == false) {
|
||||
if (myContext.getVersion().getVersion() != FhirVersionEnum.DSTU2_HL7ORG) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ class ModelScanner {
|
|||
return;
|
||||
}
|
||||
|
||||
ResourceDef resourceDefinition = pullAnnotation(theClass, ResourceDef.class);
|
||||
ResourceDef resourceDefinition = pullAnnotation(theClass, theClass, ResourceDef.class);
|
||||
if (resourceDefinition != null) {
|
||||
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());
|
||||
|
@ -317,7 +317,7 @@ class ModelScanner {
|
|||
scanResource(resClass, resourceDefinition);
|
||||
}
|
||||
|
||||
DatatypeDef datatypeDefinition = pullAnnotation(theClass, DatatypeDef.class);
|
||||
DatatypeDef datatypeDefinition = pullAnnotation(theClass, theClass, DatatypeDef.class);
|
||||
if (datatypeDefinition != null) {
|
||||
if (ICompositeType.class.isAssignableFrom(theClass)) {
|
||||
@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 (IResourceBlock.class.isAssignableFrom(theClass) || IBaseBackboneElement.class.isAssignableFrom(theClass) || IBaseDatatypeElement.class.isAssignableFrom(theClass)) {
|
||||
|
@ -440,16 +440,16 @@ class ModelScanner {
|
|||
continue;
|
||||
}
|
||||
|
||||
Child childAnnotation = pullAnnotation(next, Child.class);
|
||||
Child childAnnotation = pullAnnotation(theClass, next, Child.class);
|
||||
if (childAnnotation == null) {
|
||||
ourLog.trace("Ignoring non @Child field {} on target type {}", next.getName(), theClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
Description descriptionAnnotation = pullAnnotation(next, Description.class);
|
||||
Description descriptionAnnotation = pullAnnotation(theClass, next, Description.class);
|
||||
|
||||
TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> orderMap = theOrderToElementDef;
|
||||
Extension extensionAttr = pullAnnotation(next, Extension.class);
|
||||
Extension extensionAttr = pullAnnotation(theClass, next, Extension.class);
|
||||
if (extensionAttr != null) {
|
||||
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 (!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());
|
||||
|
@ -709,7 +709,7 @@ class ModelScanner {
|
|||
Class<?> parent = theClass.getSuperclass();
|
||||
primaryNameProvider = false;
|
||||
while (parent.equals(Object.class) == false && isBlank(resourceName)) {
|
||||
ResourceDef nextDef = pullAnnotation(parent, ResourceDef.class);
|
||||
ResourceDef nextDef = pullAnnotation(theClass, parent, ResourceDef.class);
|
||||
if (nextDef != null) {
|
||||
resourceName = nextDef.name();
|
||||
}
|
||||
|
@ -749,7 +749,7 @@ class ModelScanner {
|
|||
Map<Field, SearchParamDefinition> compositeFields = new LinkedHashMap<Field, SearchParamDefinition>();
|
||||
|
||||
for (Field nextField : theClass.getFields()) {
|
||||
SearchParamDefinition searchParam = pullAnnotation(nextField, SearchParamDefinition.class);
|
||||
SearchParamDefinition searchParam = pullAnnotation(theClass, nextField, SearchParamDefinition.class);
|
||||
if (searchParam != null) {
|
||||
RestSearchParameterTypeEnum paramType = RestSearchParameterTypeEnum.valueOf(searchParam.type().toUpperCase());
|
||||
if (paramType == null) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -54,7 +54,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
}
|
||||
|
||||
private List<String> myAdditionalMessages = null;
|
||||
private BaseOperationOutcome myBaseOperationOutcome;
|
||||
private IBaseOperationOutcome myBaseOperationOutcome;
|
||||
private String myResponseBody;
|
||||
private String myResponseMimeType;
|
||||
private int myStatusCode;
|
||||
|
@ -100,7 +100,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
* @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)
|
||||
*/
|
||||
public BaseServerResponseException(int theStatusCode, String theMessage, BaseOperationOutcome theBaseOperationOutcome) {
|
||||
public BaseServerResponseException(int theStatusCode, String theMessage, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||
super(theMessage);
|
||||
myStatusCode = theStatusCode;
|
||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||
|
@ -134,7 +134,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
* @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)
|
||||
*/
|
||||
public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause, BaseOperationOutcome theBaseOperationOutcome) {
|
||||
public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||
super(theMessage, theCause);
|
||||
myStatusCode = theStatusCode;
|
||||
myBaseOperationOutcome = theBaseOperationOutcome;
|
||||
|
@ -164,7 +164,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
* @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)
|
||||
*/
|
||||
public BaseServerResponseException(int theStatusCode, Throwable theCause, BaseOperationOutcome theBaseOperationOutcome) {
|
||||
public BaseServerResponseException(int theStatusCode, Throwable theCause, IBaseOperationOutcome theBaseOperationOutcome) {
|
||||
super(theCause.toString(), theCause);
|
||||
myStatusCode = theStatusCode;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -54,7 +56,7 @@ public class ForbiddenOperationException extends BaseServerResponseException {
|
|||
* @param theOperationOutcome
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -54,7 +56,7 @@ public class InternalErrorException extends BaseServerResponseException {
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -54,7 +56,7 @@ public class InvalidRequestException extends BaseServerResponseException {
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import java.util.LinkedHashSet;
|
|||
import java.util.Map;
|
||||
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.server.Constants;
|
||||
|
||||
|
@ -53,7 +54,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
|
|||
* @param theAllowedMethods
|
||||
* 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);
|
||||
setAllowedMethods(theAllowedMethods);
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
|
|||
* @param theOperationOutcome
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -51,7 +53,7 @@ public class NotImplementedOperationException extends BaseServerResponseExceptio
|
|||
* @param theOperationOutcome
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -52,7 +54,7 @@ public class NotModifiedException extends BaseServerResponseException {
|
|||
* @param theOperationOutcome
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
*/
|
||||
|
||||
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.server.Constants;
|
||||
|
||||
|
@ -48,7 +50,7 @@ public class PreconditionFailedException extends ResourceVersionNotSpecifiedExce
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,11 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
*/
|
||||
|
||||
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.base.composite.BaseIdentifierDt;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
|
@ -55,7 +57,7 @@ public class ResourceGoneException extends BaseServerResponseException {
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
|
||||
import net.sourceforge.cobertura.CoverageIgnore;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
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.rest.server.Constants;
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class ResourceNotFoundException extends BaseServerResponseException {
|
|||
super(STATUS_CODE, createErrorMessage(theId));
|
||||
}
|
||||
|
||||
public ResourceNotFoundException(IdDt theId, BaseOperationOutcome theOperationOutcome) {
|
||||
public ResourceNotFoundException(IdDt theId, IBaseOperationOutcome theOperationOutcome) {
|
||||
super(STATUS_CODE, createErrorMessage(theId), theOperationOutcome);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
*/
|
||||
|
||||
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.Update;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
@ -47,7 +49,7 @@ public class ResourceVersionConflictException extends BaseServerResponseExceptio
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +47,7 @@ public class ResourceVersionNotSpecifiedException extends BaseServerResponseExce
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,7 @@ public class ResourceVersionNotSpecifiedException extends BaseServerResponseExce
|
|||
* The message
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
import net.sourceforge.cobertura.CoverageIgnore;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -51,7 +52,7 @@ public class UnclassifiedServerFailureException extends BaseServerResponseExcept
|
|||
* The message to add to the status line
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,16 @@ package ca.uhn.fhir.rest.server.exceptions;
|
|||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* 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>
|
||||
*
|
||||
* @see InvalidRequestException Which corresponds to an <b>HTTP 400 Bad Request</b> failure
|
||||
|
@ -45,29 +47,29 @@ public class UnprocessableEntityException extends BaseServerResponseException {
|
|||
*
|
||||
* @param theMessage
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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) {
|
||||
super(STATUS_CODE, theMessage);
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.server.interceptor;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
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.server.Constants;
|
||||
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.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
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 {
|
||||
|
||||
private String format(String theResultBody, EncodingEnum theEncodingEnum) {
|
||||
|
@ -178,12 +186,15 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||
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
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
|
||||
|
||||
// Narrative mode
|
||||
NarrativeModeEnum narrativeMode = RestfulServerUtils.determineNarrativeMode(theRequestDetails);
|
||||
|
||||
// Determine response encoding
|
||||
EncodingEnum responseEncoding = null;
|
||||
if (theRequestDetails.getParameters().containsKey(Constants.PARAM_FORMAT)) {
|
||||
|
@ -198,7 +209,7 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||
IParser p = responseEncoding.newParser(theRequestDetails.getServer().getFhirContext());
|
||||
p.setPrettyPrint(prettyPrint);
|
||||
|
||||
String encoded = p.encodeResourceToString(theResponseObject);
|
||||
String encoded = p.encodeResourceToString(resource);
|
||||
|
||||
theServletResponse.setContentType(Constants.CT_HTML_WITH_UTF8);
|
||||
|
||||
|
@ -239,6 +250,43 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||
} catch (IOException 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;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class FhirValidator {
|
|||
|
||||
private static volatile Boolean ourPhlocPresentOnClasspath;
|
||||
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})
|
||||
|
@ -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) {
|
||||
boolean found = haveValidatorOfType(type);
|
||||
if (!found) {
|
||||
registerValidator(theInstance);
|
||||
registerValidatorModule(theInstance);
|
||||
}
|
||||
} else {
|
||||
for (Iterator<IValidator> iter = myValidators.iterator(); iter.hasNext();) {
|
||||
IValidator next = iter.next();
|
||||
for (Iterator<IValidatorModule> iter = myValidators.iterator(); iter.hasNext();) {
|
||||
IValidatorModule next = iter.next();
|
||||
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;
|
||||
for (IValidator next : myValidators) {
|
||||
for (IValidatorModule next : myValidators) {
|
||||
if (next.getClass().equals(type)) {
|
||||
found = true;
|
||||
}
|
||||
|
@ -124,9 +124,9 @@ public class FhirValidator {
|
|||
* @param theValidator
|
||||
* 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");
|
||||
ArrayList<IValidator> newValidators = new ArrayList<IValidator>(myValidators.size() + 1);
|
||||
ArrayList<IValidatorModule> newValidators = new ArrayList<IValidatorModule>(myValidators.size() + 1);
|
||||
newValidators.addAll(myValidators);
|
||||
newValidators.add(theValidator);
|
||||
|
||||
|
@ -162,9 +162,9 @@ public class FhirValidator {
|
|||
* @param theValidator
|
||||
* 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");
|
||||
ArrayList<IValidator> newValidators = new ArrayList<IValidator>(myValidators.size() + 1);
|
||||
ArrayList<IValidatorModule> newValidators = new ArrayList<IValidatorModule>(myValidators.size() + 1);
|
||||
newValidators.addAll(myValidators);
|
||||
newValidators.remove(theValidator);
|
||||
|
||||
|
@ -186,7 +186,7 @@ public class FhirValidator {
|
|||
|
||||
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
||||
|
||||
for (IValidator next : myValidators) {
|
||||
for (IValidatorModule next : myValidators) {
|
||||
next.validateBundle(ctx);
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ public class FhirValidator {
|
|||
|
||||
IValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
|
||||
|
||||
for (IValidator next : myValidators) {
|
||||
for (IValidatorModule next : myValidators) {
|
||||
next.validateBundle(ctx);
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ public class FhirValidator {
|
|||
|
||||
IValidationContext<IBaseResource> ctx = ValidationContext.forResource(myContext, theResource);
|
||||
|
||||
for (IValidator next : myValidators) {
|
||||
for (IValidatorModule next : myValidators) {
|
||||
next.validateResource(ctx);
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ public class FhirValidator {
|
|||
|
||||
IValidationContext<IBaseResource> ctx = ValidationContext.forText(myContext, theResource);
|
||||
|
||||
for (IValidator next : myValidators) {
|
||||
for (IValidatorModule next : myValidators) {
|
||||
next.validateResource(ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
/**
|
||||
* Registers
|
||||
*/
|
||||
public interface IValidator {
|
||||
public interface IValidatorModule {
|
||||
|
||||
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.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 Set<String> SCHEMA_NAMES;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ import com.phloc.schematron.ISchematronResource;
|
|||
import com.phloc.schematron.SchematronHelper;
|
||||
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 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
|
||||
public IBaseOperationOutcome getOperationOutcome() {
|
||||
|
|
|
@ -276,7 +276,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
values.addAll(t.getValues(theResource, nextPathTrimmed));
|
||||
} catch (Exception e) {
|
||||
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;
|
||||
|
@ -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) {
|
||||
myResourceTypeToDao = new HashMap<Class<? extends IBaseResource>, IFhirResourceDao<?>>();
|
||||
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) {
|
||||
|
@ -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);
|
||||
|
||||
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
IFhirResourceDao<T> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
|
@ -1019,8 +1020,10 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true);
|
||||
}
|
||||
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion) {
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
|
||||
|
||||
validateResourceForStorage(theResource);
|
||||
|
||||
if (entity.getPublished() == null) {
|
||||
entity.setPublished(new Date());
|
||||
}
|
||||
|
@ -1028,8 +1031,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
if (theResource != null) {
|
||||
String resourceType = myContext.getResourceDefinition(theResource).getName();
|
||||
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 ["
|
||||
+ resourceType + "]");
|
||||
throw new UnprocessableEntityException("Existing resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + entity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1195,6 +1197,16 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
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) {
|
||||
char[] out = new char[theString.length()];
|
||||
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.StringUtils;
|
||||
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 org.omg.PortableInterceptor.InterceptorOperations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -857,16 +859,24 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
if (isNotBlank(theResource.getId().getIdPart())) {
|
||||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
Predicate retVal = null;
|
||||
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.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
||||
public class FhirBundleResourceDaoDstu2 extends FhirResourceDaoDstu2<Bundle> {
|
||||
public class FhirResourceDaoBundleDstu2 extends FhirResourceDaoDstu2<Bundle> {
|
||||
|
||||
@Override
|
||||
protected void preProcessResourceForStorage(Bundle theResource) {
|
|
@ -24,12 +24,18 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
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;
|
||||
|
||||
public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
||||
|
@ -47,5 +53,18 @@ public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResou
|
|||
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%
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
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 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.Include;
|
||||
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.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResourceDao<T> {
|
||||
|
||||
|
@ -52,5 +66,48 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
|
|||
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);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
IFhirResourceDao<? extends IResource> dao = null;
|
||||
IFhirResourceDao<? extends IBaseResource> dao = null;
|
||||
if (resType != null) {
|
||||
dao = getDao(resType.getImplementingClass());
|
||||
}
|
||||
|
@ -268,9 +268,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
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.");
|
||||
}
|
||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||
found = (IResource) resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||
} 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())) {
|
||||
notChanged = true;
|
||||
}
|
||||
|
@ -392,13 +392,13 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
}
|
||||
|
||||
private static class UrlParts {
|
||||
private IFhirResourceDao<? extends IResource> myDao;
|
||||
private IFhirResourceDao<? extends IBaseResource> myDao;
|
||||
private String myParams;
|
||||
private String myResourceId;
|
||||
private String myResourceType;
|
||||
private String myVersionId;
|
||||
|
||||
public IFhirResourceDao<? extends IResource> getDao() {
|
||||
public IFhirResourceDao<? extends IBaseResource> getDao() {
|
||||
return myDao;
|
||||
}
|
||||
|
||||
|
@ -418,7 +418,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
return myVersionId;
|
||||
}
|
||||
|
||||
public void setDao(IFhirResourceDao<? extends IResource> theDao) {
|
||||
public void setDao(IFhirResourceDao<? extends IBaseResource> theDao) {
|
||||
myDao = theDao;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,18 +24,22 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
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.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.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);
|
||||
|
||||
|
@ -44,8 +48,9 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
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
|
||||
* won't be indexed and searches won't work.
|
||||
* @param thePerformIndexing
|
||||
* 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);
|
||||
|
||||
|
@ -65,20 +70,41 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
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
|
||||
* @return
|
||||
* @throws ResourceNotFoundException
|
||||
* If the ID is not known to the server
|
||||
* If the ID is not known to the server
|
||||
*/
|
||||
T read(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
|
||||
* obscured by a "forced ID" so should not exist as far as the outside world is concerned.
|
||||
* @param theCheckForForcedId
|
||||
* 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);
|
||||
|
||||
|
@ -102,28 +128,14 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
/**
|
||||
* @param thePerformIndexing
|
||||
* 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.
|
||||
* 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 update(T theResource, String theMatchUrl, boolean thePerformIndexing);
|
||||
|
||||
/**
|
||||
* 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
|
||||
public MethodOutcome validate(@ResourceParam T theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
|
||||
@Validate.Profile 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.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;
|
||||
return getDao().validate(theResource, theId, theRawResource, theEncoding, theMode, theProfile);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
|||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.Device;
|
||||
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.PeriodDt;
|
||||
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.Parameters;
|
||||
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.valueset.AnswerFormatEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
|
@ -188,27 +192,26 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
@Test
|
||||
public void testMetaOperations() throws Exception {
|
||||
String methodName = "testMetaOperations";
|
||||
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
|
||||
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
|
||||
assertEquals(0, meta.getTag().size());
|
||||
|
||||
|
||||
MetaDt inMeta = new MetaDt();
|
||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
|
||||
assertEquals(1, meta.getTag().size());
|
||||
|
||||
|
||||
inMeta = new MetaDt();
|
||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
|
||||
assertEquals(0, meta.getTag().size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateResourceConditional() throws IOException {
|
||||
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
|
||||
public void testCreateResourceWithNumericId() throws IOException {
|
||||
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||
|
@ -255,7 +292,10 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
String respString = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(respString);
|
||||
} finally {
|
||||
response.getEntity().getContent().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();
|
||||
sock.setSoTimeout(3000);
|
||||
|
@ -739,8 +780,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
|
||||
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()
|
||||
.execute();
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint().execute();
|
||||
assertEquals(1, actual.size());
|
||||
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"));
|
||||
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2"))
|
||||
.encodedJson().prettyPrint().execute();
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2")).encodedJson().prettyPrint().execute();
|
||||
assertEquals(1, actual.size());
|
||||
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 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.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -122,7 +123,6 @@ public class ExceptionHandlingTest {
|
|||
assertThat(e.getResponseBody(), StringContains.containsString("value=\"foo\""));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -146,7 +146,7 @@ public class ExceptionHandlingTest {
|
|||
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
||||
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
||||
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().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 {
|
||||
client.read(new IdDt("Patient/1234"));
|
||||
fail();
|
||||
|
@ -172,15 +172,14 @@ public class ExceptionHandlingTest {
|
|||
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
|
||||
assertThat(e.getMessage(), StringContains.containsString("Help I'm a bug"));
|
||||
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
|
||||
Patient read(@IdParam IdDt theId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import com.google.common.reflect.ClassPath.ClassInfo;
|
||||
|
@ -48,9 +45,9 @@ public class ExceptionPropertiesTest {
|
|||
}
|
||||
|
||||
try {
|
||||
next.getConstructor(String.class, BaseOperationOutcome.class);
|
||||
next.getConstructor(String.class, IBaseOperationOutcome.class);
|
||||
} 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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,87 @@
|
|||
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 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 {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseHighlightingInterceptorTest.class);
|
||||
|
||||
@Test
|
||||
public void testHighlight() {
|
||||
public void testHighlightNormalResponse() 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);
|
||||
|
||||
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
|
||||
*/
|
||||
abstract class BaseValidatorBridge implements IValidator {
|
||||
abstract class BaseValidatorBridge implements IValidatorModule {
|
||||
|
||||
public BaseValidatorBridge() {
|
||||
super();
|
||||
|
|
|
@ -30,7 +30,7 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.GsonBuilder;
|
||||
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);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ public class FhirInstanceValidatorTest {
|
|||
val = ourCtx.newValidator();
|
||||
val.setValidateAgainstStandardSchema(false);
|
||||
val.setValidateAgainstStandardSchematron(false);
|
||||
val.registerValidator(new FhirInstanceValidator());
|
||||
val.registerValidatorModule(new FhirInstanceValidator());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -47,7 +47,7 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
|||
myVal = ourCtx.newValidator();
|
||||
myVal.setValidateAgainstStandardSchema(false);
|
||||
myVal.setValidateAgainstStandardSchematron(false);
|
||||
myVal.registerValidator(qaVal);
|
||||
myVal.registerValidatorModule(qaVal);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -73,7 +73,7 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
|||
Questionnaire q = new Questionnaire();
|
||||
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);
|
||||
|
||||
|
||||
ValueSet options = new ValueSet();
|
||||
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);
|
||||
|
@ -97,6 +97,8 @@ public class QuestionnaireAnswersValidatorIntegrationTest {
|
|||
ourLog.info(result.getMessages().toString());
|
||||
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]"));
|
||||
|
||||
result.toOperationOutcome();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
#foreach ( $res in $resources )
|
||||
<bean id="my${res.name}Dao${versionCapitalized}"
|
||||
#if ( ${res.name} == 'Bundle' )
|
||||
class="ca.uhn.fhir.jpa.dao.Fhir${res.name}ResourceDao${versionCapitalized}">
|
||||
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'QuestionnaireAnswers' ))
|
||||
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${res.name}${versionCapitalized}">
|
||||
#else
|
||||
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">
|
||||
#end
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
<title>HAPI FHIR Changelog</title>
|
||||
</properties>
|
||||
<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">
|
||||
<action type="add">
|
||||
Add support for reference implementation structures.
|
||||
|
|
Loading…
Reference in New Issue