Merge branch 'master' into jaxrs-client
This commit is contained in:
commit
69450c7dab
|
@ -70,6 +70,8 @@ import ca.uhn.fhir.model.api.IResourceBlock;
|
|||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
import ca.uhn.fhir.model.api.annotation.Block;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Compartment;
|
||||
import ca.uhn.fhir.model.api.annotation.Compartments;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||
|
@ -87,7 +89,6 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
|||
class ModelScanner {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ModelScanner.class);
|
||||
|
||||
private final Map<Class<? extends Annotation>, Class<? extends Annotation>> myAnnotationForwards = new HashMap<Class<? extends Annotation>, Class<? extends Annotation>>();
|
||||
private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinitions = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
|
||||
private FhirContext myContext;
|
||||
private Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = new HashMap<String, RuntimeResourceDefinition>();
|
||||
|
@ -101,7 +102,8 @@ class ModelScanner {
|
|||
|
||||
private Set<Class<? extends IBase>> myVersionTypes;
|
||||
|
||||
ModelScanner(FhirContext theContext, FhirVersionEnum theVersion, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theExistingDefinitions, Collection<Class<? extends IElement>> theResourceTypes) throws ConfigurationException {
|
||||
ModelScanner(FhirContext theContext, FhirVersionEnum theVersion, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theExistingDefinitions,
|
||||
Collection<Class<? extends IElement>> theResourceTypes) throws ConfigurationException {
|
||||
myContext = theContext;
|
||||
myVersion = theVersion;
|
||||
Set<Class<? extends IBase>> toScan;
|
||||
|
@ -189,7 +191,7 @@ class ModelScanner {
|
|||
Map<String, Class<? extends IBaseResource>> resourceTypes = myNameToResourceType;
|
||||
|
||||
myVersionTypes = scanVersionPropertyFile(theDatatypes, resourceTypes, myVersion);
|
||||
|
||||
|
||||
// toScan.add(DateDt.class);
|
||||
// toScan.add(CodeDt.class);
|
||||
// toScan.add(DecimalDt.class);
|
||||
|
@ -233,68 +235,13 @@ class ModelScanner {
|
|||
}
|
||||
|
||||
/**
|
||||
* There are two implementations of all of the annotations (e.g. {@link Child} and
|
||||
* {@link org.hl7.fhir.instance.model.annotations.Child}) since the HL7.org ones will eventually replace the HAPI
|
||||
* ones. Annotations can't extend each other or implement interfaces or anything like that, so rather than duplicate
|
||||
* all of the annotation processing code this method just creates an interface Proxy to simulate the HAPI
|
||||
* annotations if the HL7.org ones are found instead.
|
||||
* There are two implementations of all of the annotations (e.g. {@link Child} and {@link org.hl7.fhir.instance.model.annotations.Child}) since the HL7.org ones will eventually replace the HAPI
|
||||
* ones. Annotations can't extend each other or implement interfaces or anything like that, so rather than duplicate all of the annotation processing code this method just creates an interface
|
||||
* Proxy to simulate the HAPI annotations if the HL7.org ones are found instead.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Annotation> T pullAnnotation(Class<?> theContainer, AnnotatedElement theTarget, Class<T> theAnnotationType) {
|
||||
|
||||
private <T extends Annotation> T pullAnnotation(AnnotatedElement theTarget, Class<T> theAnnotationType) {
|
||||
T retVal = theTarget.getAnnotation(theAnnotationType);
|
||||
// if (myContext.getVersion().getVersion() != FhirVersionEnum.DSTU2_HL7ORG) {
|
||||
return retVal;
|
||||
// }
|
||||
//
|
||||
// if (retVal == null) {
|
||||
// final Class<? extends Annotation> altAnnotationClass;
|
||||
// /*
|
||||
// * Use a cache to minimize Class.forName calls, since they are slow and expensive..
|
||||
// */
|
||||
// if (myAnnotationForwards.containsKey(theAnnotationType) == false) {
|
||||
// String sourceClassName = theAnnotationType.getName();
|
||||
// String candidateAltClassName = sourceClassName.replace("ca.uhn.fhir.model.api.annotation", "org.hl7.fhir.instance.model.annotations");
|
||||
// if (!sourceClassName.equals(candidateAltClassName)) {
|
||||
// Class<?> forName;
|
||||
// try {
|
||||
// forName = Class.forName(candidateAltClassName);
|
||||
// ourLog.debug("Forwarding annotation request for [{}] to class [{}]", theAnnotationType, forName);
|
||||
// } catch (ClassNotFoundException e) {
|
||||
// forName = null;
|
||||
// }
|
||||
// altAnnotationClass = (Class<? extends Annotation>) forName;
|
||||
// } else {
|
||||
// altAnnotationClass = null;
|
||||
// }
|
||||
// myAnnotationForwards.put(theAnnotationType, altAnnotationClass);
|
||||
// } else {
|
||||
// altAnnotationClass = myAnnotationForwards.get(theAnnotationType);
|
||||
// }
|
||||
//
|
||||
// if (altAnnotationClass == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// final Annotation altAnnotation;
|
||||
// altAnnotation = theTarget.getAnnotation(altAnnotationClass);
|
||||
// if (altAnnotation == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// InvocationHandler h = new InvocationHandler() {
|
||||
//
|
||||
// @Override
|
||||
// public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable {
|
||||
// Method altMethod = altAnnotationClass.getMethod(theMethod.getName(), theMethod.getParameterTypes());
|
||||
// return altMethod.invoke(altAnnotation, theArgs);
|
||||
// }
|
||||
// };
|
||||
// retVal = (T) Proxy.newProxyInstance(theAnnotationType.getClassLoader(), new Class<?>[] { theAnnotationType }, h);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// return retVal;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void scan(Class<? extends IBase> theClass) throws ConfigurationException {
|
||||
|
@ -303,17 +250,18 @@ class ModelScanner {
|
|||
return;
|
||||
}
|
||||
|
||||
ResourceDef resourceDefinition = pullAnnotation(theClass, theClass, ResourceDef.class);
|
||||
ResourceDef resourceDefinition = pullAnnotation(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());
|
||||
throw new ConfigurationException(
|
||||
"Resource type contains a @" + ResourceDef.class.getSimpleName() + " annotation but does not implement " + IResource.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends IBaseResource> resClass = (Class<? extends IBaseResource>) theClass;
|
||||
scanResource(resClass, resourceDefinition);
|
||||
}
|
||||
|
||||
DatatypeDef datatypeDefinition = pullAnnotation(theClass, theClass, DatatypeDef.class);
|
||||
DatatypeDef datatypeDefinition = pullAnnotation(theClass, DatatypeDef.class);
|
||||
if (datatypeDefinition != null) {
|
||||
if (ICompositeType.class.isAssignableFrom(theClass)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -325,17 +273,19 @@ class ModelScanner {
|
|||
scanPrimitiveDatatype(resClass, datatypeDefinition);
|
||||
} else {
|
||||
return;
|
||||
// throw new ConfigurationException("Resource type contains a @" + DatatypeDef.class.getSimpleName() + " annotation but does not implement " + IDatatype.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
||||
// throw new ConfigurationException("Resource type contains a @" + DatatypeDef.class.getSimpleName() + " annotation but does not implement " + IDatatype.class.getCanonicalName() + ": " +
|
||||
// theClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
Block blockDefinition = pullAnnotation(theClass, theClass, Block.class);
|
||||
Block blockDefinition = pullAnnotation(theClass, Block.class);
|
||||
|
||||
if (blockDefinition != null) {
|
||||
if (IResourceBlock.class.isAssignableFrom(theClass) || IBaseBackboneElement.class.isAssignableFrom(theClass) || IBaseDatatypeElement.class.isAssignableFrom(theClass)) {
|
||||
scanBlock(theClass);
|
||||
} else {
|
||||
throw new ConfigurationException("Type contains a @" + Block.class.getSimpleName() + " annotation but does not implement " + IResourceBlock.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
||||
throw new ConfigurationException(
|
||||
"Type contains a @" + Block.class.getSimpleName() + " annotation but does not implement " + IResourceBlock.class.getCanonicalName() + ": " + theClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,8 +314,8 @@ class ModelScanner {
|
|||
RuntimeCompositeDatatypeDefinition resourceDef;
|
||||
if (theClass.equals(ExtensionDt.class)) {
|
||||
resourceDef = new RuntimeExtensionDtDefinition(theDatatypeDefinition, theClass, true);
|
||||
// } else if (IBaseMetaType.class.isAssignableFrom(theClass)) {
|
||||
// resourceDef = new RuntimeMetaDefinition(theDatatypeDefinition, theClass, isStandardType(theClass));
|
||||
// } else if (IBaseMetaType.class.isAssignableFrom(theClass)) {
|
||||
// resourceDef = new RuntimeMetaDefinition(theDatatypeDefinition, theClass, isStandardType(theClass));
|
||||
} else {
|
||||
resourceDef = new RuntimeCompositeDatatypeDefinition(theDatatypeDefinition, theClass, isStandardType(theClass));
|
||||
}
|
||||
|
@ -429,7 +379,8 @@ class ModelScanner {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void scanCompositeElementForChildren(Class<? extends IBase> theClass, Set<String> elementNames, TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> theOrderToElementDef, TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> theOrderToExtensionDef) {
|
||||
private void scanCompositeElementForChildren(Class<? extends IBase> theClass, Set<String> elementNames, TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> theOrderToElementDef,
|
||||
TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> theOrderToExtensionDef) {
|
||||
int baseElementOrder = theOrderToElementDef.isEmpty() ? 0 : theOrderToElementDef.lastEntry().getKey() + 1;
|
||||
|
||||
for (Field next : theClass.getDeclaredFields()) {
|
||||
|
@ -439,16 +390,16 @@ class ModelScanner {
|
|||
continue;
|
||||
}
|
||||
|
||||
Child childAnnotation = pullAnnotation(theClass, next, Child.class);
|
||||
Child childAnnotation = pullAnnotation(next, Child.class);
|
||||
if (childAnnotation == null) {
|
||||
ourLog.trace("Ignoring non @Child field {} on target type {}", next.getName(), theClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
Description descriptionAnnotation = pullAnnotation(theClass, next, Description.class);
|
||||
Description descriptionAnnotation = pullAnnotation(next, Description.class);
|
||||
|
||||
TreeMap<Integer, BaseRuntimeDeclaredChildDefinition> orderMap = theOrderToElementDef;
|
||||
Extension extensionAttr = pullAnnotation(theClass, next, Extension.class);
|
||||
Extension extensionAttr = pullAnnotation(next, Extension.class);
|
||||
if (extensionAttr != null) {
|
||||
orderMap = theOrderToExtensionDef;
|
||||
}
|
||||
|
@ -471,8 +422,8 @@ class ModelScanner {
|
|||
}
|
||||
}
|
||||
if (order == Child.REPLACE_PARENT) {
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT + ") but no parent element with extension URL " + extensionAttr.url() + " could be found on type "
|
||||
+ next.getDeclaringClass().getSimpleName());
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT
|
||||
+ ") but no parent element with extension URL " + extensionAttr.url() + " could be found on type " + next.getDeclaringClass().getSimpleName());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -487,8 +438,8 @@ class ModelScanner {
|
|||
}
|
||||
}
|
||||
if (order == Child.REPLACE_PARENT) {
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT + ") but no parent element with name " + elementName + " could be found on type "
|
||||
+ next.getDeclaringClass().getSimpleName());
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT
|
||||
+ ") but no parent element with name " + elementName + " could be found on type " + next.getDeclaringClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -504,8 +455,7 @@ class ModelScanner {
|
|||
// int max = childAnnotation.max();
|
||||
|
||||
/*
|
||||
* Anything that's marked as unknown is given a new ID that is <0 so that it doesn't conflict with any given
|
||||
* IDs and can be figured out later
|
||||
* Anything that's marked as unknown is given a new ID that is <0 so that it doesn't conflict with any given IDs and can be figured out later
|
||||
*/
|
||||
if (order == Child.ORDER_UNKNOWN) {
|
||||
order = Integer.MIN_VALUE;
|
||||
|
@ -572,7 +522,8 @@ class ModelScanner {
|
|||
binder = getBoundCodeBinder(next);
|
||||
}
|
||||
|
||||
RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et, binder);
|
||||
RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et,
|
||||
binder);
|
||||
|
||||
if (IBaseEnumeration.class.isAssignableFrom(nextElementType)) {
|
||||
def.setEnumerationType(ReflectionUtil.getGenericCollectionTypeOfFieldWithSecondOrderForList(next));
|
||||
|
@ -600,10 +551,10 @@ class ModelScanner {
|
|||
RuntimeChildResourceDefinition def = new RuntimeChildResourceDefinition(next, elementName, childAnnotation, descriptionAnnotation, refTypesList);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (IResourceBlock.class.isAssignableFrom(nextElementType) || IBaseBackboneElement.class.isAssignableFrom(nextElementType) || IBaseDatatypeElement.class.isAssignableFrom(nextElementType)) {
|
||||
} else if (IResourceBlock.class.isAssignableFrom(nextElementType) || IBaseBackboneElement.class.isAssignableFrom(nextElementType)
|
||||
|| IBaseDatatypeElement.class.isAssignableFrom(nextElementType)) {
|
||||
/*
|
||||
* Child is a resource block (i.e. a sub-tag within a resource) TODO: do these have a better name
|
||||
* according to HL7?
|
||||
* Child is a resource block (i.e. a sub-tag within a resource) TODO: do these have a better name according to HL7?
|
||||
*/
|
||||
|
||||
Class<? extends IBase> blockDef = (Class<? extends IBase>) nextElementType;
|
||||
|
@ -611,13 +562,14 @@ class ModelScanner {
|
|||
RuntimeChildResourceBlockDefinition def = new RuntimeChildResourceBlockDefinition(next, childAnnotation, descriptionAnnotation, elementName, blockDef);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "Type".equals(nextElementType.getSimpleName()) || IBaseDatatype.class.equals(nextElementType)) {
|
||||
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "Type".equals(nextElementType.getSimpleName())
|
||||
|| IBaseDatatype.class.equals(nextElementType)) {
|
||||
|
||||
RuntimeChildAny def = new RuntimeChildAny(next, elementName, childAnnotation, descriptionAnnotation);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (IDatatype.class.isAssignableFrom(nextElementType) || IPrimitiveType.class.isAssignableFrom(nextElementType) || ICompositeType.class.isAssignableFrom(nextElementType) || IBaseDatatype.class.isAssignableFrom(nextElementType)
|
||||
|| IBaseExtension.class.isAssignableFrom(nextElementType)) {
|
||||
} else if (IDatatype.class.isAssignableFrom(nextElementType) || IPrimitiveType.class.isAssignableFrom(nextElementType) || ICompositeType.class.isAssignableFrom(nextElementType)
|
||||
|| IBaseDatatype.class.isAssignableFrom(nextElementType) || IBaseExtension.class.isAssignableFrom(nextElementType)) {
|
||||
Class<? extends IBase> nextDatatype = (Class<? extends IBase>) nextElementType;
|
||||
|
||||
addScanAlso(nextDatatype);
|
||||
|
@ -645,10 +597,11 @@ class ModelScanner {
|
|||
}
|
||||
}
|
||||
|
||||
CodeableConceptElement concept = pullAnnotation(theClass, next, CodeableConceptElement.class);
|
||||
CodeableConceptElement concept = pullAnnotation(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());
|
||||
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());
|
||||
} else {
|
||||
Class<? extends ICodeEnum> type = concept.type();
|
||||
myScanAlsoCodeTable.add(type);
|
||||
|
@ -711,21 +664,23 @@ class ModelScanner {
|
|||
Class<?> parent = theClass.getSuperclass();
|
||||
primaryNameProvider = false;
|
||||
while (parent.equals(Object.class) == false && isBlank(resourceName)) {
|
||||
ResourceDef nextDef = pullAnnotation(theClass, parent, ResourceDef.class);
|
||||
ResourceDef nextDef = pullAnnotation(parent, ResourceDef.class);
|
||||
if (nextDef != null) {
|
||||
resourceName = nextDef.name();
|
||||
}
|
||||
parent = parent.getSuperclass();
|
||||
}
|
||||
if (isBlank(resourceName)) {
|
||||
throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name(): " + theClass.getCanonicalName() + " - This is only allowed for types that extend other resource types ");
|
||||
throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name(): " + theClass.getCanonicalName()
|
||||
+ " - This is only allowed for types that extend other resource types ");
|
||||
}
|
||||
}
|
||||
|
||||
String resourceId = resourceDefinition.id();
|
||||
if (!isBlank(resourceId)) {
|
||||
if (myIdToResourceDefinition.containsKey(resourceId)) {
|
||||
throw new ConfigurationException("The following resource types have the same ID of '" + resourceId + "' - " + theClass.getCanonicalName() + " and " + myIdToResourceDefinition.get(resourceId).getImplementingClass().getCanonicalName());
|
||||
throw new ConfigurationException("The following resource types have the same ID of '" + resourceId + "' - " + theClass.getCanonicalName() + " and "
|
||||
+ myIdToResourceDefinition.get(resourceId).getImplementingClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,7 +706,7 @@ class ModelScanner {
|
|||
Map<Field, SearchParamDefinition> compositeFields = new LinkedHashMap<Field, SearchParamDefinition>();
|
||||
|
||||
for (Field nextField : theClass.getFields()) {
|
||||
SearchParamDefinition searchParam = pullAnnotation(theClass, nextField, SearchParamDefinition.class);
|
||||
SearchParamDefinition searchParam = pullAnnotation(nextField, SearchParamDefinition.class);
|
||||
if (searchParam != null) {
|
||||
RestSearchParameterTypeEnum paramType = RestSearchParameterTypeEnum.valueOf(searchParam.type().toUpperCase());
|
||||
if (paramType == null) {
|
||||
|
@ -761,7 +716,17 @@ class ModelScanner {
|
|||
compositeFields.put(nextField, searchParam);
|
||||
continue;
|
||||
}
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), paramType);
|
||||
|
||||
Set<String> providesMembershipInCompartments = null;
|
||||
Compartments compartmentsAnnotation = pullAnnotation(nextField, Compartments.class);
|
||||
if (compartmentsAnnotation != null) {
|
||||
providesMembershipInCompartments = new HashSet<String>();
|
||||
for (Compartment next : compartmentsAnnotation.providesMembershipIn()) {
|
||||
providesMembershipInCompartments.add(next.name());
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments);
|
||||
theResourceDef.addSearchParam(param);
|
||||
nameToParam.put(param.getName(), param);
|
||||
}
|
||||
|
@ -774,13 +739,14 @@ class ModelScanner {
|
|||
for (String nextName : searchParam.compositeOf()) {
|
||||
RuntimeSearchParam param = nameToParam.get(nextName);
|
||||
if (param == null) {
|
||||
ourLog.warn("Search parameter {}.{} declares that it is a composite with compositeOf value '{}' but that is not a valid parametr name itself. Valid values are: {}", new Object[] { theResourceDef.getName(), searchParam.name(), nextName, nameToParam.keySet() });
|
||||
ourLog.warn("Search parameter {}.{} declares that it is a composite with compositeOf value '{}' but that is not a valid parametr name itself. Valid values are: {}",
|
||||
new Object[] { theResourceDef.getName(), searchParam.name(), nextName, nameToParam.keySet() });
|
||||
continue;
|
||||
}
|
||||
compositeOf.add(param);
|
||||
}
|
||||
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), RestSearchParameterTypeEnum.COMPOSITE, compositeOf);
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), RestSearchParameterTypeEnum.COMPOSITE, compositeOf, null);
|
||||
theResourceDef.addSearchParam(param);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.context;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
|
||||
|
@ -29,23 +30,30 @@ import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
|
|||
|
||||
public class RuntimeSearchParam {
|
||||
|
||||
private List<RuntimeSearchParam> myCompositeOf;
|
||||
private String myDescription;
|
||||
private String myName;
|
||||
private RestSearchParameterTypeEnum myParamType;
|
||||
private String myPath;
|
||||
private List<RuntimeSearchParam> myCompositeOf;
|
||||
private Set<String> myProvidesMembershipInCompartments;
|
||||
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType) {
|
||||
this(theName, theDescription, thePath, theParamType, null);
|
||||
}
|
||||
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf) {
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
|
||||
Set<String> theProvidesMembershipInCompartments) {
|
||||
super();
|
||||
myName = theName;
|
||||
myDescription = theDescription;
|
||||
myPath = thePath;
|
||||
myParamType = theParamType;
|
||||
myCompositeOf = theCompositeOf;
|
||||
if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) {
|
||||
myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments);
|
||||
} else {
|
||||
myProvidesMembershipInCompartments = null;
|
||||
}
|
||||
}
|
||||
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments) {
|
||||
this(theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments);
|
||||
}
|
||||
|
||||
public List<RuntimeSearchParam> getCompositeOf() {
|
||||
|
@ -70,10 +78,10 @@ public class RuntimeSearchParam {
|
|||
|
||||
public List<String> getPathsSplit() {
|
||||
String path = getPath();
|
||||
if (path.indexOf('|')==-1) {
|
||||
if (path.indexOf('|') == -1) {
|
||||
return Collections.singletonList(path);
|
||||
}
|
||||
|
||||
|
||||
List<String> retVal = new ArrayList<String>();
|
||||
StringTokenizer tok = new StringTokenizer(path, "|");
|
||||
while (tok.hasMoreElements()) {
|
||||
|
@ -83,4 +91,11 @@ public class RuntimeSearchParam {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can return null
|
||||
*/
|
||||
public Set<String> getProvidesMembershipInCompartments() {
|
||||
return myProvidesMembershipInCompartments;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package ca.uhn.fhir.model.api.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {})
|
||||
public @interface Compartment {
|
||||
|
||||
/**
|
||||
* This may only be populated on a reference field. On such a field, places the containing
|
||||
* resource in a compartment with the name(s) specified by the given strings, where the compartment
|
||||
* belongs to the target resource. For example, this field could be populated with <code>Patient</code> on
|
||||
* the <code>Observation.subject</code> field.
|
||||
*/
|
||||
String name();
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package ca.uhn.fhir.model.api.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.FIELD})
|
||||
public @interface Compartments {
|
||||
|
||||
Compartment[] providesMembershipIn();
|
||||
|
||||
}
|
|
@ -25,6 +25,29 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
/**
|
||||
* Denotes a parameter for a REST method which will contain the resource actually
|
||||
* being created/updated/etc in an operation which contains a resource in the HTTP request.
|
||||
* <p>
|
||||
* For example, in a {@link Create} operation the method parameter annotated with this
|
||||
* annotation will contain the actual resource being created.
|
||||
* </p>
|
||||
* <p>
|
||||
* Parameters with this annotation should typically be of the type of resource being
|
||||
* operated on (see below for an exception when raw data is required). For example, in a
|
||||
* {@link IResourceProvider} for Patient resources, the parameter annotated with this
|
||||
* annotation should be of type Patient.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that in servers it is also acceptable to have parameters with this annotation
|
||||
* which are of type {@link String} or of type <code>byte[]</code>. Parameters of
|
||||
* these types will contain the raw/unparsed HTTP request body. It is fine to
|
||||
* have multiple parameters with this annotation, so you can have one parameter
|
||||
* which accepts the parsed resource, and another which accepts the raw request.
|
||||
* </p>
|
||||
*/
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ResourceParam {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -46,6 +49,7 @@ import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
|||
* @author Doug Martin (Regenstrief Center for Biomedical Informatics)
|
||||
*/
|
||||
abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvocation {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHttpClientInvocationWithContents.class);
|
||||
|
||||
private final Bundle myBundle;
|
||||
private final BundleTypeEnum myBundleType;
|
||||
|
|
|
@ -117,7 +117,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
|||
|
||||
@Override
|
||||
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
IResource resource = (IResource) theArgs[myResourceParameterIndex];
|
||||
IResource resource = (IResource) theArgs[myResourceParameterIndex]; // TODO: use IBaseResource
|
||||
if (resource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
|
|
@ -451,10 +451,20 @@ public class MethodUtil {
|
|||
mode = Mode.RESOURCE;
|
||||
} else if (String.class.equals(parameterType)) {
|
||||
mode = ResourceParameter.Mode.BODY;
|
||||
} else if (byte[].class.equals(parameterType)) {
|
||||
mode = ResourceParameter.Mode.BODY_BYTE_ARRAY;
|
||||
} else if (EncodingEnum.class.equals(parameterType)) {
|
||||
mode = Mode.ENCODING;
|
||||
} else {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName() + " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("Method '");
|
||||
b.append(theMethod.getName());
|
||||
b.append("' is annotated with @");
|
||||
b.append(ResourceParam.class.getSimpleName());
|
||||
b.append(" but has a type that is not an implemtation of ");
|
||||
b.append(IBaseResource.class.getCanonicalName());
|
||||
b.append(" or String or byte[]");
|
||||
throw new ConfigurationException(b.toString());
|
||||
}
|
||||
param = new ResourceParameter((Class<? extends IResource>) parameterType, theProvider, mode);
|
||||
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
||||
|
|
|
@ -105,8 +105,10 @@ public class ResourceParameter implements IParameter {
|
|||
return IOUtils.toString(createRequestReader(theRequest));
|
||||
} catch (IOException e) {
|
||||
// Shouldn't happen since we're reading from a byte array
|
||||
throw new InternalErrorException("Failed to load request");
|
||||
throw new InternalErrorException("Failed to load request", e);
|
||||
}
|
||||
case BODY_BYTE_ARRAY:
|
||||
return theRequest.loadRequestContents();
|
||||
case ENCODING:
|
||||
return RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
case RESOURCE:
|
||||
|
@ -201,23 +203,27 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
public static IBaseResource parseResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||
IBaseResource retVal;
|
||||
IBaseResource retVal = null;
|
||||
|
||||
if (IBaseBinary.class.isAssignableFrom(theResourceType)) {
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
String ct = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
if (EncodingEnum.forContentTypeStrict(ct) == null) {
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
IBaseBinary binary = (IBaseBinary) ctx.getResourceDefinition("Binary").newInstance();
|
||||
binary.setContentType(ct);
|
||||
binary.setContent(theRequest.loadRequestContents());
|
||||
|
||||
retVal = binary;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal == null) {
|
||||
retVal = loadResourceFromRequest(theRequest, theMethodBinding, theResourceType);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
BODY, ENCODING, RESOURCE
|
||||
BODY, BODY_BYTE_ARRAY, ENCODING, RESOURCE
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class Constants {
|
|||
public static final String FORMAT_XML = "xml";
|
||||
public static final String HEADER_ACCEPT = "Accept";
|
||||
public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
|
||||
public static final String HEADER_ACCEPT_VALUE_ALL = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0";
|
||||
public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0";
|
||||
public static final String HEADER_ALLOW = "Allow";
|
||||
public static final String HEADER_AUTHORIZATION = "Authorization";
|
||||
public static final String HEADER_AUTHORIZATION_VALPREFIX_BASIC = "Basic ";
|
||||
|
|
|
@ -44,6 +44,7 @@ public enum EncodingEnum {
|
|||
;
|
||||
|
||||
private static HashMap<String, EncodingEnum> ourContentTypeToEncoding;
|
||||
private static HashMap<String, EncodingEnum> ourContentTypeToEncodingStrict;
|
||||
|
||||
static {
|
||||
ourContentTypeToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
@ -51,6 +52,9 @@ public enum EncodingEnum {
|
|||
ourContentTypeToEncoding.put(next.getBundleContentType(), next);
|
||||
ourContentTypeToEncoding.put(next.getResourceContentType(), next);
|
||||
}
|
||||
|
||||
// Add before we add the lenient ones
|
||||
ourContentTypeToEncodingStrict = new HashMap<String, EncodingEnum>(ourContentTypeToEncoding);
|
||||
|
||||
/*
|
||||
* These are wrong, but we add them just to be tolerant of other
|
||||
|
@ -88,10 +92,30 @@ public enum EncodingEnum {
|
|||
return myResourceContentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoding for a given content type, or <code>null</code> if no encoding
|
||||
* is found.
|
||||
* <p>
|
||||
* <b>This method is lenient!</b> Things like "application/xml" will return {@link EncodingEnum#XML}
|
||||
* even if the "+fhir" part is missing from the expected content type.
|
||||
* </p>
|
||||
*/
|
||||
public static EncodingEnum forContentType(String theContentType) {
|
||||
return ourContentTypeToEncoding.get(theContentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoding for a given content type, or <code>null</code> if no encoding
|
||||
* is found.
|
||||
* <p>
|
||||
* <b>This method is NOT lenient!</b> Things like "application/xml" will return <code>null</code>
|
||||
* </p>
|
||||
* @see #forContentType(String)
|
||||
*/
|
||||
public static EncodingEnum forContentTypeStrict(String theContentType) {
|
||||
return ourContentTypeToEncodingStrict.get(theContentType);
|
||||
}
|
||||
|
||||
public String getFormatContentType() {
|
||||
return myFormatContentType;
|
||||
}
|
||||
|
|
|
@ -517,7 +517,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
|
||||
protected void handleRequest(RequestTypeEnum theRequestType, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
||||
String fhirServerBase = null;
|
||||
boolean requestIsBrowser = requestIsBrowser(theRequest);
|
||||
ServletRequestDetails requestDetails = new ServletRequestDetails();
|
||||
requestDetails.setServer(this);
|
||||
requestDetails.setRequestType(theRequestType);
|
||||
|
@ -651,10 +650,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
}
|
||||
}
|
||||
|
||||
if (requestIsBrowser) {
|
||||
// if request is coming from a browser, prompt the user to enter login credentials
|
||||
theResponse.setHeader("WWW-Authenticate", "BASIC realm=\"FHIR\"");
|
||||
}
|
||||
writeExceptionToResponse(theResponse, e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
@ -1399,9 +1394,4 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
return nextString.length() > 0 && (nextString.charAt(0) == '_' || nextString.charAt(0) == '$' || nextString.equals(Constants.URL_TOKEN_METADATA));
|
||||
}
|
||||
|
||||
public static boolean requestIsBrowser(HttpServletRequest theRequest) {
|
||||
String userAgent = theRequest.getHeader("User-Agent");
|
||||
return userAgent != null && userAgent.contains("Mozilla");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ ca.uhn.fhir.validation.ValidationResult.noIssuesDetected=No issues detected duri
|
|||
# JPA Messages
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlInvalidResourceType=Invalid match URL "{0}" - Unknown resource type: "{1}"
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlNoMatches=Invalid match URL "{0}" - No resources match this search
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlMultipleMatches=Invalid match URL "{0}" - Multiple resources match this search
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,32 +34,39 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||
|
||||
public class DaoConfig {
|
||||
|
||||
private boolean myAllowMultipleDelete;
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private boolean myAllowInlineMatchUrlReferences = false;
|
||||
|
||||
private boolean myAllowMultipleDelete;
|
||||
private int myHardSearchLimit = 1000;
|
||||
private int myHardTagListLimit = 1000;
|
||||
private int myIncludeLimit = 2000;
|
||||
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private boolean myIndexContainedResources = true;
|
||||
|
||||
private List<IServerInterceptor> myInterceptors;
|
||||
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
||||
private boolean mySchedulingDisabled;
|
||||
private boolean mySubscriptionEnabled;
|
||||
private long mySubscriptionPollDelay = 1000;
|
||||
private Long mySubscriptionPurgeInactiveAfterMillis;
|
||||
|
||||
/**
|
||||
* See {@link #setIncludeLimit(int)}
|
||||
*/
|
||||
public int getHardSearchLimit() {
|
||||
return myHardSearchLimit;
|
||||
}
|
||||
|
||||
public int getHardTagListLimit() {
|
||||
return myHardTagListLimit;
|
||||
}
|
||||
|
||||
public int getIncludeLimit() {
|
||||
return myIncludeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interceptors which will be notified of operations.
|
||||
*
|
||||
|
@ -84,10 +91,25 @@ public class DaoConfig {
|
|||
return mySubscriptionPurgeInactiveAfterMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setAllowInlineMatchUrlReferences(boolean)
|
||||
*/
|
||||
public boolean isAllowInlineMatchUrlReferences() {
|
||||
return myAllowInlineMatchUrlReferences;
|
||||
}
|
||||
|
||||
public boolean isAllowMultipleDelete() {
|
||||
return myAllowMultipleDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
||||
* <code>true</code>)
|
||||
*/
|
||||
public boolean isIndexContainedResources() {
|
||||
return myIndexContainedResources;
|
||||
}
|
||||
|
||||
public boolean isSchedulingDisabled() {
|
||||
return mySchedulingDisabled;
|
||||
}
|
||||
|
@ -99,6 +121,20 @@ public class DaoConfig {
|
|||
return mySubscriptionEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should references containing match URLs be resolved and replaced in create and update operations. For
|
||||
* example, if this property is set to true and a resource is created containing a reference
|
||||
* to "Patient?identifier=12345", this is reference match URL will be resolved and replaced according
|
||||
* to the usual match URL rules.
|
||||
* <p>
|
||||
* Default is false for now, as this is an experimental feature.
|
||||
* </p>
|
||||
* @since 1.5
|
||||
*/
|
||||
public void setAllowInlineMatchUrlReferences(boolean theAllowInlineMatchUrlReferences) {
|
||||
myAllowInlineMatchUrlReferences = theAllowInlineMatchUrlReferences;
|
||||
}
|
||||
|
||||
public void setAllowMultipleDelete(boolean theAllowMultipleDelete) {
|
||||
myAllowMultipleDelete = theAllowMultipleDelete;
|
||||
}
|
||||
|
@ -120,6 +156,14 @@ public class DaoConfig {
|
|||
myIncludeLimit = theIncludeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
||||
* <code>true</code>)
|
||||
*/
|
||||
public void setIndexContainedResources(boolean theIndexContainedResources) {
|
||||
myIndexContainedResources = theIndexContainedResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* This may be used to optionally register server interceptors directly against the DAOs.
|
||||
* <p>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ForcedId;
|
||||
|
||||
public interface IForcedIdDao extends JpaRepository<ForcedId, Long> {
|
||||
|
||||
@Query("SELECT f FROM ForcedId f WHERE f.myResourcePid = :resource_pid")
|
||||
public ForcedId findByResourcePid(@Param("resource_pid") Long theResourcePid);
|
||||
|
||||
}
|
|
@ -462,7 +462,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
FhirTerser terser = getContext().newTerser();
|
||||
for (DaoMethodOutcome nextOutcome : idToPersistedOutcome.values()) {
|
||||
IBaseResource nextResource = (IBaseResource) nextOutcome.getResource();
|
||||
IBaseResource nextResource = nextOutcome.getResource();
|
||||
if (nextResource == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ import javax.persistence.UniqueConstraint;
|
|||
//@formatter:off
|
||||
@Entity()
|
||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "IDX_FORCEDID", columnNames = {"FORCED_ID"})
|
||||
@UniqueConstraint(name = "IDX_FORCEDID", columnNames = {"FORCED_ID"}),
|
||||
@UniqueConstraint(name = "IDX_FORCEDID_RESID", columnNames = {"RESOURCE_PID"})
|
||||
})
|
||||
@NamedQueries(value = {
|
||||
@NamedQuery(name = "Q_GET_FORCED_ID", query = "SELECT f FROM ForcedId f WHERE myForcedId = :ID")
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.entity;
|
|||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
|
@ -34,9 +35,8 @@ import org.hibernate.search.annotations.Field;
|
|||
//@formatter:off
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_COORDS" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_COORDS", indexes = {
|
||||
@org.hibernate.annotations.Index(name = "IDX_SP_COORDS", columnNames = { "RES_TYPE", "SP_NAME", "SP_LATITUDE" })
|
||||
@Table(name = "HFJ_SPIDX_COORDS", indexes = {
|
||||
@Index(name = "IDX_SP_COORDS", columnList = "RES_TYPE,SP_NAME,SP_LATITUDE,SP_LONGITUDE")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchParam {
|
||||
|
|
|
@ -144,6 +144,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
//@formatter:on
|
||||
private String myContentText;
|
||||
|
||||
@Column(name = "HAS_CONTAINED", nullable = true)
|
||||
private boolean myHasContainedResource;
|
||||
|
||||
@Column(name = "SP_HAS_LINKS")
|
||||
private boolean myHasLinks;
|
||||
|
||||
|
@ -158,6 +161,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
@Column(name = "SP_INDEX_STATUS", nullable = true)
|
||||
private Long myIndexStatus;
|
||||
|
||||
@Column(name = "IS_CONTAINED", nullable = true)
|
||||
private boolean myIsContainedResource;
|
||||
|
||||
@Column(name = "RES_LANGUAGE", length = MAX_LANGUAGE_LENGTH, nullable = true)
|
||||
private String myLanguage;
|
||||
|
||||
|
@ -173,13 +179,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
|
||||
@Column(name = "SP_COORDS_PRESENT")
|
||||
private boolean myParamsCoordsPopulated;
|
||||
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamDate> myParamsDate;
|
||||
|
||||
@Column(name = "SP_DATE_PRESENT")
|
||||
private boolean myParamsDatePopulated;
|
||||
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamNumber> myParamsNumber;
|
||||
|
||||
|
@ -340,10 +346,18 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isHasContainedResource() {
|
||||
return myHasContainedResource;
|
||||
}
|
||||
|
||||
public boolean isHasLinks() {
|
||||
return myHasLinks;
|
||||
}
|
||||
|
||||
public boolean isIsContainedResource() {
|
||||
return myIsContainedResource;
|
||||
}
|
||||
|
||||
public boolean isParamsCoordsPopulated() {
|
||||
return myParamsCoordsPopulated;
|
||||
}
|
||||
|
@ -376,6 +390,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
myContentText = theContentText;
|
||||
}
|
||||
|
||||
public void setHasContainedResource(boolean theHasContainedResource) {
|
||||
myHasContainedResource = theHasContainedResource;
|
||||
}
|
||||
|
||||
public void setHasLinks(boolean theHasLinks) {
|
||||
myHasLinks = theHasLinks;
|
||||
}
|
||||
|
@ -388,6 +406,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
myIndexStatus = theIndexStatus;
|
||||
}
|
||||
|
||||
public void setIsContainedResource(boolean theIsContainedResource) {
|
||||
myIsContainedResource = theIsContainedResource;
|
||||
}
|
||||
|
||||
public void setLanguage(String theLanguage) {
|
||||
if (defaultString(theLanguage).length() > MAX_LANGUAGE_LENGTH) {
|
||||
throw new UnprocessableEntityException("Language exceeds maximum length of " + MAX_LANGUAGE_LENGTH + " chars: " + theLanguage);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -12,21 +13,29 @@ import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
|
||||
public class BaseJpaTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaTest.class);
|
||||
protected ServletRequestDetails mySrd;
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
protected List toList(IBundleProvider theSearch) {
|
||||
return theSearch.getResources(0, theSearch.size());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeCreateSrd() {
|
||||
mySrd = mock(ServletRequestDetails.class);
|
||||
}
|
||||
|
||||
protected List<IIdType> toUnqualifiedVersionlessIds(Bundle theFound) {
|
||||
List<IIdType> retVal = new ArrayList<IIdType>();
|
||||
for (Entry next : theFound.getEntry()) {
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.springframework.context.ApplicationContext;
|
|||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
|
@ -239,14 +240,14 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
|||
|
||||
public TransactionTemplate newTxTemplate() {
|
||||
TransactionTemplate retVal = new TransactionTemplate(myTxManager);
|
||||
retVal.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
retVal.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
retVal.afterPropertiesSet();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(theTxManager);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
@Override
|
||||
public Void doInTransaction(TransactionStatus theStatus) {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
|
||||
public class FhirResourceDaoDstu3ContainedTest extends BaseJpaDstu3Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3ContainedTest.class);
|
||||
|
||||
@Test
|
||||
public void before() {
|
||||
myDaoConfig.setIndexContainedResources(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexContained() {
|
||||
Patient p = new Patient();
|
||||
p.setId("#some_patient");
|
||||
p.addName().addFamily("MYFAMILY").addGiven("MYGIVEN");
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.getCode().setText("Some Observation");
|
||||
o1.setSubject(new Reference(p));
|
||||
IIdType oid1 = myObservationDao.create(o1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.getCode().setText("Some Observation");
|
||||
o2.setSubject(new Reference(p));
|
||||
IIdType oid2 = myObservationDao.create(o2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addName().addFamily("MYFAMILY").addGiven("MYGIVEN");
|
||||
IIdType pid2 = myPatientDao.create(p2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(o2));
|
||||
|
||||
|
||||
SearchParameterMap map;
|
||||
|
||||
// map = new SearchParameterMap();
|
||||
// map.add(Observation.SP_CODE, new TokenParam(null, "some observation").setModifier(TokenParamModifier.TEXT));
|
||||
// assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(map)), containsInAnyOrder(toValues(id1, id2)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO: make sure match URLs don't delete
|
||||
|
||||
}
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.rest.param.StringAndListParam;
|
|||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
|
||||
|
@ -46,31 +47,35 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs1.setStatus(ObservationStatus.FINAL);
|
||||
obs1.setValue(new Quantity(123));
|
||||
obs1.setComments("obs1");
|
||||
IIdType id1 = myObservationDao.create(obs1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType id1 = myObservationDao.create(obs1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs2 = new Observation();
|
||||
obs2.getCode().setText("Diastolic Blood Pressure");
|
||||
obs2.setStatus(ObservationStatus.FINAL);
|
||||
obs2.setValue(new Quantity(81));
|
||||
IIdType id2 = myObservationDao.create(obs2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType id2 = myObservationDao.create(obs2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap map;
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(map)), containsInAnyOrder(toValues(id1, id2)));
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty());
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
|
||||
map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT));
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("obs1"));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(map)), containsInAnyOrder(toValues(id1)));
|
||||
|
||||
}
|
||||
|
||||
private ServletRequestDetails mockSrd() {
|
||||
return new ServletRequestDetails();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testStringTextSearch() {
|
||||
|
@ -78,13 +83,13 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs1.getCode().setText("AAAAA");
|
||||
obs1.setValue(new StringType("Systolic Blood Pressure"));
|
||||
obs1.setStatus(ObservationStatus.FINAL);
|
||||
IIdType id1 = myObservationDao.create(obs1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType id1 = myObservationDao.create(obs1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs2 = new Observation();
|
||||
obs1.getCode().setText("AAAAA");
|
||||
obs1.setValue(new StringType("Diastolic Blood Pressure"));
|
||||
obs2.setStatus(ObservationStatus.FINAL);
|
||||
IIdType id2 = myObservationDao.create(obs2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType id2 = myObservationDao.create(obs2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap map;
|
||||
|
||||
|
@ -99,7 +104,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
public void testSuggestIgnoresBase64Content() {
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("testSuggest");
|
||||
IIdType ptId = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Media med = new Media();
|
||||
med.getSubject().setReferenceElement(ptId);
|
||||
|
@ -107,7 +112,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
med.getContent().setContentType("LCws");
|
||||
med.getContent().setDataElement(new Base64BinaryType(new byte[] {44,44,44,44,44,44,44,44}));
|
||||
med.getContent().setTitle("bbbb syst");
|
||||
myMediaDao.create(med, new ServletRequestDetails());
|
||||
myMediaDao.create(med, mockSrd());
|
||||
ourLog.info(myFhirCtx.newJsonParser().encodeResourceToString(med));
|
||||
|
||||
List<Suggestion> output = mySearchDao.suggestKeywords("Patient/" + ptId.getIdPart() + "/$everything", "_content", "press");
|
||||
|
@ -139,35 +144,35 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
public void testSuggest() {
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("testSuggest");
|
||||
IIdType ptId = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getSubject().setReferenceElement(ptId);
|
||||
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
|
||||
myObservationDao.create(obs, new ServletRequestDetails());
|
||||
myObservationDao.create(obs, mockSrd());
|
||||
|
||||
obs = new Observation();
|
||||
obs.getSubject().setReferenceElement(ptId);
|
||||
obs.getCode().setText("MNBVCXZ");
|
||||
myObservationDao.create(obs, new ServletRequestDetails());
|
||||
myObservationDao.create(obs, mockSrd());
|
||||
|
||||
obs = new Observation();
|
||||
obs.getSubject().setReferenceElement(ptId);
|
||||
obs.getCode().setText("ZXC HELLO");
|
||||
obs.addComponent().getCode().setText("HHHHHHHHHH");
|
||||
myObservationDao.create(obs, new ServletRequestDetails());
|
||||
myObservationDao.create(obs, mockSrd());
|
||||
|
||||
/*
|
||||
* These shouldn't match since they're for another patient
|
||||
*/
|
||||
patient = new Patient();
|
||||
patient.addName().addFamily("testSuggest2");
|
||||
IIdType ptId2 = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId2 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs2 = new Observation();
|
||||
obs2.getSubject().setReferenceElement(ptId2);
|
||||
obs2.getCode().setText("ZXCVBNMZZ");
|
||||
myObservationDao.create(obs2, new ServletRequestDetails());
|
||||
myObservationDao.create(obs2, mockSrd());
|
||||
|
||||
List<Suggestion> output = mySearchDao.suggestKeywords("Patient/" + ptId.getIdPart() + "/$everything", "_content", "ZXCVBNM");
|
||||
ourLog.info("Found: " + output);
|
||||
|
@ -212,7 +217,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
patient = new Patient();
|
||||
patient.getText().setDivAsString("<div>DIVAAA</div>");
|
||||
patient.addName().addGiven("NAMEAAA");
|
||||
IIdType pId1 = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -230,7 +235,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
patient.setId(pId1);
|
||||
patient.getText().setDivAsString("<div>DIVBBB</div>");
|
||||
patient.addName().addGiven("NAMEBBB");
|
||||
myPatientDao.update(patient, new ServletRequestDetails());
|
||||
myPatientDao.update(patient, mockSrd());
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -254,19 +259,19 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
public void testEverythingInstanceWithContentFilter() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().addFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId1 = myPatientDao.create(pt1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId1 = myPatientDao.create(pt1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.addName().addFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId2 = myPatientDao.create(pt2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId2 = myPatientDao.create(pt2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Device dev1 = new Device();
|
||||
dev1.setManufacturer("Some Manufacturer");
|
||||
IIdType devId1 = myDeviceDao.create(dev1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType devId1 = myDeviceDao.create(dev1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Device dev2 = new Device();
|
||||
dev2.setManufacturer("Some Manufacturer 2");
|
||||
myDeviceDao.create(dev2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
myDeviceDao.create(dev2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs1 = new Observation();
|
||||
obs1.getText().setDivAsString("<div>OBSTEXT1</div>");
|
||||
|
@ -274,19 +279,19 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs1.getCode().addCoding().setCode("CODE1");
|
||||
obs1.setValue(new StringType("obsvalue1"));
|
||||
obs1.getDevice().setReferenceElement(devId1);
|
||||
IIdType obsId1 = myObservationDao.create(obs1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId1 = myObservationDao.create(obs1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs2 = new Observation();
|
||||
obs2.getSubject().setReferenceElement(ptId1);
|
||||
obs2.getCode().addCoding().setCode("CODE2");
|
||||
obs2.setValue(new StringType("obsvalue2"));
|
||||
IIdType obsId2 = myObservationDao.create(obs2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId2 = myObservationDao.create(obs2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs3 = new Observation();
|
||||
obs3.getSubject().setReferenceElement(ptId2);
|
||||
obs3.getCode().addCoding().setCode("CODE3");
|
||||
obs3.setValue(new StringType("obsvalue3"));
|
||||
IIdType obsId3 = myObservationDao.create(obs3, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId3 = myObservationDao.create(obs3, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
HttpServletRequest request;
|
||||
List<String> actual;
|
||||
|
@ -297,16 +302,16 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, devId1)));
|
||||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obstext1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, param, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, param, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, devId1)));
|
||||
|
||||
request = mock(HttpServletRequest.class);
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, obsId2, devId1)));
|
||||
|
||||
/*
|
||||
|
@ -317,12 +322,12 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs4.getSubject().setReferenceElement(ptId1);
|
||||
obs4.getCode().addCoding().setCode("CODE1");
|
||||
obs4.setValue(new StringType("obsvalue1"));
|
||||
IIdType obsId4 = myObservationDao.create(obs4, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId4 = myObservationDao.create(obs4, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
assertNotEquals(obsId1.getIdPart(), obsId4.getIdPart(), devId1);
|
||||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, obsId4, devId1)));
|
||||
|
||||
/*
|
||||
|
@ -334,11 +339,11 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs1.getSubject().setReferenceElement(ptId1);
|
||||
obs1.getCode().addCoding().setCode("CODE2");
|
||||
obs1.setValue(new StringType("obsvalue2"));
|
||||
myObservationDao.update(obs1, new ServletRequestDetails());
|
||||
myObservationDao.update(obs1, mockSrd());
|
||||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId4)));
|
||||
|
||||
}
|
||||
|
@ -347,38 +352,38 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
public void testEverythingTypeWithContentFilter() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().addFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId1 = myPatientDao.create(pt1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId1 = myPatientDao.create(pt1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.addName().addFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId2 = myPatientDao.create(pt2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType ptId2 = myPatientDao.create(pt2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Device dev1 = new Device();
|
||||
dev1.setManufacturer("Some Manufacturer");
|
||||
IIdType devId1 = myDeviceDao.create(dev1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType devId1 = myDeviceDao.create(dev1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Device dev2 = new Device();
|
||||
dev2.setManufacturer("Some Manufacturer 2");
|
||||
IIdType devId2 = myDeviceDao.create(dev2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
myDeviceDao.create(dev2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs1 = new Observation();
|
||||
obs1.getSubject().setReferenceElement(ptId1);
|
||||
obs1.getCode().addCoding().setCode("CODE1");
|
||||
obs1.setValue(new StringType("obsvalue1"));
|
||||
obs1.getDevice().setReferenceElement(devId1);
|
||||
IIdType obsId1 = myObservationDao.create(obs1, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId1 = myObservationDao.create(obs1, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs2 = new Observation();
|
||||
obs2.getSubject().setReferenceElement(ptId1);
|
||||
obs2.getCode().addCoding().setCode("CODE2");
|
||||
obs2.setValue(new StringType("obsvalue2"));
|
||||
IIdType obsId2 = myObservationDao.create(obs2, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId2 = myObservationDao.create(obs2, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs3 = new Observation();
|
||||
obs3.getSubject().setReferenceElement(ptId2);
|
||||
obs3.getCode().addCoding().setCode("CODE3");
|
||||
obs3.setValue(new StringType("obsvalue3"));
|
||||
IIdType obsId3 = myObservationDao.create(obs3, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId3 = myObservationDao.create(obs3, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
HttpServletRequest request;
|
||||
List<String> actual;
|
||||
|
@ -389,11 +394,11 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, devId1)));
|
||||
|
||||
request = mock(HttpServletRequest.class);
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, null, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, null, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, obsId2, devId1, ptId2, obsId3)));
|
||||
|
||||
/*
|
||||
|
@ -404,12 +409,12 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs4.getSubject().setReferenceElement(ptId1);
|
||||
obs4.getCode().addCoding().setCode("CODE1");
|
||||
obs4.setValue(new StringType("obsvalue1"));
|
||||
IIdType obsId4 = myObservationDao.create(obs4, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType obsId4 = myObservationDao.create(obs4, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
assertNotEquals(obsId1.getIdPart(), obsId4.getIdPart(), devId1);
|
||||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId1, obsId4, devId1)));
|
||||
|
||||
/*
|
||||
|
@ -421,11 +426,11 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
obs1.getSubject().setReferenceElement(ptId1);
|
||||
obs1.getCode().addCoding().setCode("CODE2");
|
||||
obs1.setValue(new StringType("obsvalue2"));
|
||||
myObservationDao.update(obs1, new ServletRequestDetails());
|
||||
myObservationDao.update(obs1, mockSrd());
|
||||
|
||||
param = new StringAndListParam();
|
||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, new ServletRequestDetails()));
|
||||
actual = toUnqualifiedVersionlessIdValues(myPatientDao.patientTypeEverything(request, null, null, null, param, null, mockSrd()));
|
||||
assertThat(actual, containsInAnyOrder(toValues(ptId1, obsId4)));
|
||||
|
||||
}
|
||||
|
@ -443,7 +448,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
patient = new Patient();
|
||||
patient.getText().setDivAsString("<div>DIVAAA</div>");
|
||||
patient.addName().addGiven("NAMEAAA");
|
||||
IIdType pId1 = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -461,7 +466,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
patient.setId(pId1);
|
||||
patient.getText().setDivAsString("<div>DIVBBB</div>");
|
||||
patient.addName().addGiven("NAMEBBB");
|
||||
myPatientDao.update(patient, null, false, new ServletRequestDetails());
|
||||
myPatientDao.update(patient, null, false, mockSrd());
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -470,7 +475,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEBBB"));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), not(contains(toValues(pId1))));
|
||||
|
||||
myPatientDao.update(patient, null, true, new ServletRequestDetails());
|
||||
myPatientDao.update(patient, null, true, mockSrd());
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -498,18 +503,18 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
Patient patient = new Patient();
|
||||
patient.addName().addGiven(methodName);
|
||||
patient.addAddress().addLine("My fulltext address");
|
||||
pId1 = myPatientDao.create(patient, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getSubject().setReferenceElement(pId1);
|
||||
obs.setValue(new StringType("This is the FULLtext of the observation"));
|
||||
IIdType oId1 = myObservationDao.create(obs, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType oId1 = myObservationDao.create(obs, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
obs = new Observation();
|
||||
obs.getSubject().setReferenceElement(pId1);
|
||||
obs.setValue(new StringType("Another fullText"));
|
||||
IIdType oId2 = myObservationDao.create(obs, new ServletRequestDetails()).getId().toUnqualifiedVersionless();
|
||||
IIdType oId2 = myObservationDao.create(obs, mockSrd()).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<String> patients;
|
||||
SearchParameterMap params;
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Set;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.model.BaseResource;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.ConceptMap;
|
||||
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
|
||||
|
@ -52,6 +51,7 @@ import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
|
|||
import org.hl7.fhir.dstu3.model.Substance;
|
||||
import org.hl7.fhir.dstu3.model.TemporalPrecisionEnum;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.Ignore;
|
||||
|
@ -586,21 +586,21 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_CA"));
|
||||
params.put(IAnyResource.SP_RES_LANGUAGE, new StringParam("en_CA"));
|
||||
List<IBaseResource> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id1.toUnqualifiedVersionless(), patients.get(0).getIdElement().toUnqualifiedVersionless());
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_US"));
|
||||
params.put(IAnyResource.SP_RES_LANGUAGE, new StringParam("en_US"));
|
||||
List<Patient> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id2.toUnqualifiedVersionless(), patients.get(0).getIdElement().toUnqualifiedVersionless());
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_GB"));
|
||||
params.put(IAnyResource.SP_RES_LANGUAGE, new StringParam("en_GB"));
|
||||
List<Patient> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(0, patients.size());
|
||||
}
|
||||
|
@ -629,18 +629,18 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1, id2));
|
||||
}
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
params.setLastUpdated(new DateRangeParam(betweenTime, null));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id2));
|
||||
}
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -648,7 +648,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -656,7 +656,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("ZZZZZ")));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), empty());
|
||||
}
|
||||
{
|
||||
|
@ -664,7 +664,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("ZZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), empty());
|
||||
}
|
||||
{
|
||||
|
@ -672,7 +672,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -681,7 +681,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -689,7 +689,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add(IAnyResource.SP_RES_LANGUAGE, and);
|
||||
params.add("_id", new StringParam(id1.getIdPart()));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
|
@ -767,8 +767,6 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
@Test
|
||||
public void testSearchLastUpdatedParamWithComparator() throws InterruptedException {
|
||||
String methodName = "testSearchLastUpdatedParamWithComparator";
|
||||
|
||||
IIdType id0;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
|
@ -781,7 +779,6 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
long start = System.currentTimeMillis();
|
||||
Thread.sleep(sleep);
|
||||
|
||||
DateTimeType beforeAny = new DateTimeType(new Date(), TemporalPrecisionEnum.MILLI);
|
||||
IIdType id1a;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
|
@ -815,12 +812,12 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a, id1b));
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, startDateTime), new DateParam(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS, endDateTime)));
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, startDateTime), new DateParam(ParamPrefixEnum.LESSTHAN_OR_EQUALS, endDateTime)));
|
||||
ourLog.info("Searching: {}", map.getLastUpdated());
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a, id1b));
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(QuantityCompararatorEnum.GREATERTHAN, startDateTime), new DateParam(QuantityCompararatorEnum.LESSTHAN, endDateTime)));
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN, startDateTime), new DateParam(ParamPrefixEnum.LESSTHAN, endDateTime)));
|
||||
ourLog.info("Searching: {}", map.getLastUpdated());
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a, id1b));
|
||||
|
||||
|
@ -1373,7 +1370,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
QuantityParam param;
|
||||
Set<Long> found;
|
||||
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
|
||||
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
|
||||
found = myObservationDao.searchForIds("value-quantity", param);
|
||||
int initialSize = found.size();
|
||||
|
||||
|
@ -1384,19 +1381,19 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
myObservationDao.create(o, new ServletRequestDetails());
|
||||
|
||||
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
|
||||
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
|
||||
found = myObservationDao.searchForIds("value-quantity", param);
|
||||
assertEquals(1 + initialSize, found.size());
|
||||
|
||||
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, methodName + "units");
|
||||
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, methodName + "units");
|
||||
found = myObservationDao.searchForIds("value-quantity", param);
|
||||
assertEquals(1, found.size());
|
||||
|
||||
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, null);
|
||||
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, null);
|
||||
found = myObservationDao.searchForIds("value-quantity", param);
|
||||
assertEquals(1, found.size());
|
||||
|
||||
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, methodName + "units");
|
||||
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, methodName + "units");
|
||||
found = myObservationDao.searchForIds("value-quantity", param);
|
||||
assertEquals(1, found.size());
|
||||
|
||||
|
@ -1406,8 +1403,8 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
public void testSearchWithEmptySort() {
|
||||
SearchParameterMap criteriaUrl = new SearchParameterMap();
|
||||
DateRangeParam range = new DateRangeParam();
|
||||
range.setLowerBound(new DateParam(QuantityCompararatorEnum.GREATERTHAN, 1000000));
|
||||
range.setUpperBound(new DateParam(QuantityCompararatorEnum.LESSTHAN, 2000000));
|
||||
range.setLowerBound(new DateParam(ParamPrefixEnum.GREATERTHAN, 1000000));
|
||||
range.setUpperBound(new DateParam(ParamPrefixEnum.LESSTHAN, 2000000));
|
||||
criteriaUrl.setLastUpdated(range);
|
||||
criteriaUrl.setSort(new SortSpec(Constants.PARAM_LASTUPDATED, SortOrderEnum.ASC));
|
||||
IBundleProvider results = myObservationDao.search(criteriaUrl);
|
||||
|
@ -1555,7 +1552,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(BaseResource.SP_RES_ID, new StringParam(orgId.getIdPart()));
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(orgId.getIdPart()));
|
||||
params.addInclude(Organization.INCLUDE_PARTOF.asNonRecursive());
|
||||
List<IIdType> resources = toUnqualifiedVersionlessIds(myOrganizationDao.search(params));
|
||||
assertThat(resources, contains(orgId, parentOrgId));
|
||||
|
@ -1597,7 +1594,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Organization.SP_RES_ID, new StringParam(orgId.getIdPart()));
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(orgId.getIdPart()));
|
||||
params.addInclude(Organization.INCLUDE_PARTOF.asRecursive());
|
||||
List<IIdType> resources = toUnqualifiedVersionlessIds(myOrganizationDao.search(params));
|
||||
ourLog.info(resources.toString());
|
||||
|
|
|
@ -42,8 +42,10 @@ import org.hl7.fhir.dstu3.model.UriType;
|
|||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
@ -112,7 +114,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
// Try making the resource unparseable
|
||||
|
||||
TransactionTemplate template = new TransactionTemplate(myTxManager);
|
||||
template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
template.execute(new TransactionCallback<ResourceTable>() {
|
||||
@Override
|
||||
public ResourceTable doInTransaction(TransactionStatus theStatus) {
|
||||
|
@ -305,6 +307,100 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.setAllowInlineMatchUrlReferences(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateInlineMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateInlineMatchUrlWithOneMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
myDaoConfig.setAllowInlineMatchUrlReferences(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IIdType id = myPatientDao.update(p, mySrd).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getCode().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
|
||||
BundleEntryComponent respEntry = resp.getEntry().get(0);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", respEntry.getResponse().getStatus());
|
||||
assertThat(respEntry.getResponse().getLocation(), containsString("Observation/"));
|
||||
assertThat(respEntry.getResponse().getLocation(), endsWith("/_history/1"));
|
||||
assertEquals("1", respEntry.getResponse().getEtag());
|
||||
|
||||
o = myObservationDao.read(new IdType(respEntry.getResponse().getLocationElement()), mySrd);
|
||||
assertEquals(id.toVersionless().getValue(), o.getSubject().getReference());
|
||||
assertEquals("1", o.getIdElement().getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateInlineMatchUrlWithNoMatches() {
|
||||
String methodName = "testTransactionCreateInlineMatchUrlWithNoMatches";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
myDaoConfig.setAllowInlineMatchUrlReferences(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
myPatientDao.create(p, mySrd).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
myPatientDao.create(p, mySrd).getId();
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getCode().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Invalid match URL \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateInlineMatchUrlWithNoMatches\" - Multiple resources match this search", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateInlineMatchUrlWithTwoMatches() {
|
||||
String methodName = "testTransactionCreateInlineMatchUrlWithTwoMatches";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
myDaoConfig.setAllowInlineMatchUrlReferences(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
myPatientDao.create(p, mySrd).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
myPatientDao.create(p, mySrd).getId();
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getCode().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Invalid match URL \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateInlineMatchUrlWithTwoMatches\" - Multiple resources match this search", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
|
|
@ -50,6 +50,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
retVal.setSubscriptionPollDelay(5000);
|
||||
retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
retVal.setAllowInlineMatchUrlReferences(true);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
retVal.setSubscriptionPollDelay(5000);
|
||||
retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
retVal.setAllowInlineMatchUrlReferences(true);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
|
@ -17,11 +19,9 @@ import org.apache.http.message.BasicStatusLine;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
|
@ -48,7 +48,7 @@ public class BinaryClientTest {
|
|||
|
||||
httpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ctx.getRestfulClientFactory().setHttpClient(httpClient);
|
||||
ctx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
||||
ctx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
|
||||
httpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class BinaryClientTest {
|
|||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", "foo/bar"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ByteArrayInputStream(new byte[] {1,2,3,4}));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }));
|
||||
|
||||
IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
|
||||
Binary resp = client.read(new IdDt("http://foo/Patient/123"));
|
||||
|
@ -67,24 +67,17 @@ public class BinaryClientTest {
|
|||
assertEquals(HttpGet.class, capt.getValue().getClass());
|
||||
HttpGet get = (HttpGet) capt.getValue();
|
||||
assertEquals("http://foo/Binary/123", get.getURI().toString());
|
||||
|
||||
|
||||
assertEquals("foo/bar", resp.getContentType());
|
||||
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, resp.getContent());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
IClient c = Mockito.mock(IClient.class, new ReturnsDeepStubs());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
Binary res = new Binary();
|
||||
res.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
res.setContentType("text/plain");
|
||||
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
|
@ -92,29 +85,23 @@ public class BinaryClientTest {
|
|||
when(httpResponse.getEntity().getContent()).thenReturn(new ByteArrayInputStream(new byte[] {}));
|
||||
|
||||
IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
|
||||
MethodOutcome resp = client.create(res);
|
||||
client.create(res);
|
||||
|
||||
assertEquals(HttpPost.class, capt.getValue().getClass());
|
||||
HttpPost post = (HttpPost) capt.getValue();
|
||||
assertEquals("http://foo/Binary", post.getURI().toString());
|
||||
|
||||
assertEquals("text/plain", post.getEntity().getContentType().getValue());
|
||||
|
||||
assertEquals("text/plain", capt.getValue().getFirstHeader("Content-Type").getValue());
|
||||
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, IOUtils.toByteArray(post.getEntity().getContent()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String createBundle() {
|
||||
return ctx.newXmlParser().encodeBundleToString(new Bundle());
|
||||
}
|
||||
|
||||
|
||||
private interface IClient extends IBasicClient {
|
||||
|
||||
@Read(type=Binary.class)
|
||||
@Read(type = Binary.class)
|
||||
public Binary read(@IdParam IdDt theBinary);
|
||||
|
||||
@Create(type=Binary.class)
|
||||
@Create(type = Binary.class)
|
||||
public MethodOutcome create(@ResourceParam Binary theBinary);
|
||||
|
||||
}
|
||||
|
|
|
@ -173,8 +173,8 @@ public class DynamicSearchTest {
|
|||
@Override
|
||||
public List<RuntimeSearchParam> getSearchParameters() {
|
||||
ArrayList<RuntimeSearchParam> retVal = new ArrayList<RuntimeSearchParam>();
|
||||
retVal.add(new RuntimeSearchParam("param1", "This is the first parameter", "Patient.param1", RestSearchParameterTypeEnum.STRING));
|
||||
retVal.add(new RuntimeSearchParam("param2", "This is the second parameter", "Patient.param2", RestSearchParameterTypeEnum.DATE));
|
||||
retVal.add(new RuntimeSearchParam("param1", "This is the first parameter", "Patient.param1", RestSearchParameterTypeEnum.STRING, null));
|
||||
retVal.add(new RuntimeSearchParam("param2", "This is the second parameter", "Patient.param2", RestSearchParameterTypeEnum.DATE, null));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ public class GenericClientDstu2Test {
|
|||
client.fetchConformance().ofType(Conformance.class).execute();
|
||||
assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
|
||||
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
|
||||
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON));
|
||||
idx++;
|
||||
|
||||
client.fetchConformance().ofType(Conformance.class).encodedJson().execute();
|
||||
|
@ -192,12 +192,12 @@ public class GenericClientDstu2Test {
|
|||
assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue());
|
||||
assertEquals("http://" + methodName + ".example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length);
|
||||
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
|
||||
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON));
|
||||
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
|
||||
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
|
||||
assertEquals("http://" + methodName + ".example.com/fhir/Patient/123", capt.getAllValues().get(1).getURI().toASCIIString());
|
||||
assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length);
|
||||
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
|
||||
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON));
|
||||
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
|
||||
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hl7.fhir.dstu3.model.Binary;
|
||||
import org.hl7.fhir.dstu3.model.Conformance;
|
||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
public class GenericClientDstu3Test {
|
||||
private static FhirContext ourCtx;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GenericClientDstu3Test.class);
|
||||
private HttpClient myHttpClient;
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
private byte[] extractBodyAsByteArray(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||
byte[] body = IOUtils.toByteArray(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent());
|
||||
return body;
|
||||
}
|
||||
|
||||
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
|
||||
return body;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAgentForConformance() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Conformance conf = new Conformance();
|
||||
conf.setCopyright("COPY");
|
||||
|
||||
final String respString = p.encodeResourceToString(conf);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
client.fetchConformance().ofType(Conformance.class).execute();
|
||||
assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
validateUserAgent(capt);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAgentForBinary() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Conformance conf = new Conformance();
|
||||
conf.setCopyright("COPY");
|
||||
|
||||
final String respString = p.encodeResourceToString(conf);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
Binary bin = new Binary();
|
||||
bin.setContentType("application/foo");
|
||||
bin.setContent(new byte[] { 0, 1, 2, 3, 4 });
|
||||
client.create().resource(bin).execute();
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString());
|
||||
|
||||
assertEquals("http://example.com/fhir/Binary", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
validateUserAgent(capt);
|
||||
|
||||
assertEquals("application/foo", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue());
|
||||
assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue());
|
||||
assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, extractBodyAsByteArray(capt));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBinaryCreateWithNoContentType() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
conf.getText().setDivAsString("OK!");
|
||||
|
||||
final String respString = p.encodeResourceToString(conf);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
Binary bin = new Binary();
|
||||
bin.setContent(new byte[] { 0, 1, 2, 3, 4 });
|
||||
client.create().resource(bin).execute();
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString());
|
||||
|
||||
assertEquals("http://example.com/fhir/Binary", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
validateUserAgent(capt);
|
||||
|
||||
assertEquals("application/xml+fhir;charset=utf-8", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue().toLowerCase().replace(" ", ""));
|
||||
assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue());
|
||||
assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, ourCtx.newXmlParser().parseResource(Binary.class, extractBodyAsString(capt)).getContent());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBinaryCreateWithFhirContentType() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
conf.getText().setDivAsString("OK!");
|
||||
|
||||
final String respString = p.encodeResourceToString(conf);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.getText().setDivAsString("A PATIENT");
|
||||
|
||||
Binary bin = new Binary();
|
||||
bin.setContent(ourCtx.newJsonParser().encodeResourceToString(pt).getBytes("UTF-8"));
|
||||
bin.setContentType(Constants.CT_FHIR_JSON);
|
||||
client.create().resource(bin).execute();
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString());
|
||||
|
||||
assertEquals("http://example.com/fhir/Binary", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
validateUserAgent(capt);
|
||||
|
||||
assertEquals("application/xml+fhir;charset=utf-8", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue().toLowerCase().replace(" ", ""));
|
||||
assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue());
|
||||
Binary output = ourCtx.newXmlParser().parseResource(Binary.class, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_FHIR_JSON, output.getContentType());
|
||||
|
||||
Patient outputPt = (Patient) ourCtx.newJsonParser().parseResource(new String(output.getContent(), "UTF-8"));
|
||||
assertEquals("<div>A PATIENT</div>", outputPt.getText().getDivAsString());
|
||||
}
|
||||
|
||||
private void validateUserAgent(ArgumentCaptor<HttpUriRequest> capt) {
|
||||
assertEquals(1, capt.getAllValues().get(0).getHeaders("User-Agent").length);
|
||||
assertEquals(expectedUserAgent(), capt.getAllValues().get(0).getHeaders("User-Agent")[0].getValue());
|
||||
}
|
||||
|
||||
private String expectedUserAgent() {
|
||||
return "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)";
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu3();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu3.model.Binary;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
|
||||
public class CreateBinaryDstu3Test {
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static int ourPort;
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private static Server ourServer;
|
||||
private static Binary ourLastBinary;
|
||||
private static String ourLastBinaryString;
|
||||
private static byte[] ourLastBinaryBytes;
|
||||
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourLastBinary = null;
|
||||
ourLastBinaryBytes = null;
|
||||
ourLastBinaryString = null;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRawBytesNoContentType() throws Exception {
|
||||
HttpPost post = new HttpPost("http://localhost:" + ourPort + "/Binary");
|
||||
post.setEntity(new ByteArrayEntity(new byte[] {0,1,2,3,4}));
|
||||
ourClient.execute(post);
|
||||
|
||||
assertNull(ourLastBinary.getContentType());
|
||||
assertArrayEquals(new byte[] {0,1,2,3,4}, ourLastBinary.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRawBytesBinaryContentType() throws Exception {
|
||||
HttpPost post = new HttpPost("http://localhost:" + ourPort + "/Binary");
|
||||
post.setEntity(new ByteArrayEntity(new byte[] {0,1,2,3,4}));
|
||||
post.addHeader("Content-Type", "application/foo");
|
||||
ourClient.execute(post);
|
||||
|
||||
assertEquals("application/foo", ourLastBinary.getContentType());
|
||||
assertArrayEquals(new byte[] {0,1,2,3,4}, ourLastBinary.getContent());
|
||||
assertArrayEquals(new byte[] {0,1,2,3,4}, ourLastBinaryBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Technically the client shouldn't be doing it this way,
|
||||
* but we'll be accepting
|
||||
*/
|
||||
@Test
|
||||
public void testRawBytesFhirContentType() throws Exception {
|
||||
|
||||
Binary b = new Binary();
|
||||
b.setContentType("application/foo");
|
||||
b.setContent(new byte[] {0,1,2,3,4});
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(b);
|
||||
|
||||
HttpPost post = new HttpPost("http://localhost:" + ourPort + "/Binary");
|
||||
post.setEntity(new StringEntity(encoded));
|
||||
post.addHeader("Content-Type", Constants.CT_FHIR_JSON);
|
||||
ourClient.execute(post);
|
||||
|
||||
assertEquals("application/foo", ourLastBinary.getContentType());
|
||||
assertArrayEquals(new byte[] {0,1,2,3,4}, ourLastBinary.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRawBytesFhirContentTypeContainingFhir() throws Exception {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.getText().setDivAsString("A PATIENT");
|
||||
|
||||
Binary b = new Binary();
|
||||
b.setContentType("application/xml+fhir");
|
||||
b.setContent(ourCtx.newXmlParser().encodeResourceToString(p).getBytes("UTF-8"));
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(b);
|
||||
|
||||
HttpPost post = new HttpPost("http://localhost:" + ourPort + "/Binary");
|
||||
post.setEntity(new StringEntity(encoded));
|
||||
post.addHeader("Content-Type", Constants.CT_FHIR_JSON);
|
||||
ourClient.execute(post);
|
||||
|
||||
assertEquals("application/xml+fhir", ourLastBinary.getContentType());
|
||||
assertArrayEquals(b.getContent(), ourLastBinary.getContent());
|
||||
assertEquals(encoded, ourLastBinaryString);
|
||||
assertArrayEquals(encoded.getBytes("UTF-8"), ourLastBinaryBytes);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
BinaryProvider binaryProvider = new BinaryProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||
servlet.setResourceProviders(binaryProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
}
|
||||
|
||||
public static class BinaryProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Binary.class;
|
||||
}
|
||||
|
||||
@Create()
|
||||
public MethodOutcome createBinary(@ResourceParam Binary theBinary, @ResourceParam String theBinaryString, @ResourceParam byte[] theBinaryBytes) {
|
||||
ourLastBinary = theBinary;
|
||||
ourLastBinaryString = theBinaryString;
|
||||
ourLastBinaryBytes = theBinaryBytes;
|
||||
return new MethodOutcome(new IdType("Binary/001/_history/002"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package ca.uhn.fhir.tinder;
|
||||
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
|
||||
import ca.uhn.fhir.tinder.parser.CompartmentParser;
|
||||
|
||||
public class CompartmentGeneratorMojo extends AbstractMojo {
|
||||
|
||||
@Parameter(required = true)
|
||||
private String fhirVersion;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
CompartmentParser p = new CompartmentParser(fhirVersion);
|
||||
try {
|
||||
p.parse();
|
||||
} catch (MojoExecutionException e) {
|
||||
throw e;
|
||||
} catch (MojoFailureException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new MojoFailureException("Failure during parse", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws MojoExecutionException, MojoFailureException {
|
||||
CompartmentGeneratorMojo mojo = new CompartmentGeneratorMojo();
|
||||
mojo.fhirVersion = "dstu2";
|
||||
mojo.execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -228,7 +228,7 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
String dtOutputDir = "target/generated-sources/tinder/ca/uhn/fhir/model/dev/composite";
|
||||
|
||||
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet("dstu2", ".");
|
||||
rp.setBaseResourceNames(Arrays.asList( "supplyrequest"
|
||||
rp.setBaseResourceNames(Arrays.asList( "patient", "auditevent" , "observation"
|
||||
// //, "contract"
|
||||
// "valueset", "organization", "location"
|
||||
// , "observation", "conformance"
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ca.uhn.fhir.tinder.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Resource extends BaseRootType {
|
||||
|
||||
@Override
|
||||
|
@ -20,4 +23,20 @@ public class Resource extends BaseRootType {
|
|||
return name;
|
||||
}
|
||||
|
||||
public SearchParameter getSearchParameterByName(String theName) {
|
||||
for (SearchParameter next : getSearchParameters()) {
|
||||
if (next.getName().equalsIgnoreCase(theName)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List<String> getSearchParameterNames() {
|
||||
ArrayList<String> retVal = new ArrayList<String>();
|
||||
for (SearchParameter next : getSearchParameters()) {
|
||||
retVal.add(next.getName());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
public class SearchParameter {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParameter.class);
|
||||
private List<String> myCompartments = new ArrayList<String>();
|
||||
private List<String> myCompositeOf;
|
||||
private List<String> myCompositeTypes;
|
||||
private String myDescription;
|
||||
|
@ -18,7 +19,6 @@ public class SearchParameter {
|
|||
private String myResourceName;
|
||||
private List<String> myTargetTypes;
|
||||
private String myType;
|
||||
|
||||
private String myVersion;
|
||||
|
||||
public SearchParameter(String theVersion, String theResourceName) {
|
||||
|
@ -26,6 +26,14 @@ public class SearchParameter {
|
|||
this.myResourceName = theResourceName;
|
||||
}
|
||||
|
||||
public void addCompartment(String theCompartment) {
|
||||
myCompartments.add(theCompartment);
|
||||
}
|
||||
|
||||
public List<String> getCompartments() {
|
||||
return myCompartments;
|
||||
}
|
||||
|
||||
public List<String> getCompositeOf() {
|
||||
if (myCompositeOf == null) {
|
||||
myCompositeOf = new ArrayList<String>();
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Set;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
@ -404,7 +405,7 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
protected void postProcess(BaseElement theTarget) {
|
||||
protected void postProcess(BaseElement theTarget) throws MojoFailureException {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
package ca.uhn.fhir.tinder.parser;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import ca.uhn.fhir.tinder.model.BaseElement;
|
||||
import ca.uhn.fhir.tinder.model.Resource;
|
||||
import ca.uhn.fhir.tinder.model.SearchParameter;
|
||||
import ca.uhn.fhir.tinder.util.XMLUtils;
|
||||
|
||||
public class CompartmentParser {
|
||||
|
||||
private String myVersion;
|
||||
private Resource myResourceDef;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CompartmentParser.class);
|
||||
|
||||
public CompartmentParser(String theVersion) {
|
||||
public CompartmentParser(String theVersion, Resource theResourceDef) {
|
||||
myVersion = theVersion;
|
||||
myResourceDef = theResourceDef;
|
||||
}
|
||||
|
||||
public void parse() throws Exception {
|
||||
|
@ -45,6 +56,67 @@ public class CompartmentParser {
|
|||
throw new Exception("Failed to find worksheet with name 'Data Elements' in spreadsheet: " + resName);
|
||||
}
|
||||
|
||||
Element table = (Element) resourcesSheet.getElementsByTagName("Table").item(0);
|
||||
NodeList rows = table.getElementsByTagName("Row");
|
||||
|
||||
Map<Integer, String> col2compartment = new HashMap<Integer, String>();
|
||||
Element headerRow = (Element) rows.item(0);
|
||||
for (int i = 1; i < headerRow.getElementsByTagName("Cell").getLength(); i++) {
|
||||
Element cellElement = (Element) headerRow.getElementsByTagName("Cell").item(i);
|
||||
Element dataElement = (Element) cellElement.getElementsByTagName("Data").item(0);
|
||||
col2compartment.put(i, dataElement.getTextContent());
|
||||
}
|
||||
|
||||
Element row = null;
|
||||
for (int i = 1; i < rows.getLength(); i++) {
|
||||
Element nextRow = (Element) rows.item(i);
|
||||
|
||||
NodeList cells = nextRow.getElementsByTagName("Cell");
|
||||
Element cellElement = (Element) cells.item(0);
|
||||
Element dataElement = (Element) cellElement.getElementsByTagName("Data").item(0);
|
||||
if (dataElement.getTextContent().equals(myResourceDef.getName())) {
|
||||
row = nextRow;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (row == null) {
|
||||
ourLog.debug("No compartments for resource {}", myResourceDef.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
NodeList cells = row.getElementsByTagName("Cell");
|
||||
for (int i = 1; i < cells.getLength(); i++) {
|
||||
Element cellElement = (Element) cells.item(i);
|
||||
int index = i;
|
||||
if (cellElement.hasAttribute("Index")) {
|
||||
index = Integer.parseInt(cellElement.getAttribute("Index"));
|
||||
}
|
||||
|
||||
String compartment = col2compartment.get(index);
|
||||
|
||||
Element dataElement = (Element) cellElement.getElementsByTagName("Data").item(0);
|
||||
String namesUnsplit = dataElement.getTextContent();
|
||||
String[] namesSplit = namesUnsplit.split("\\|");
|
||||
for (String nextName : namesSplit) {
|
||||
nextName = nextName.trim();
|
||||
if (isBlank(nextName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = nextName.split("\\.");
|
||||
if (parts[0].equals("{def}")) {
|
||||
continue;
|
||||
}
|
||||
Resource element = myResourceDef;
|
||||
SearchParameter sp = element.getSearchParameterByName(parts[0]);
|
||||
if (sp == null) {
|
||||
throw new MojoFailureException("Can't find child named " + parts[0] + " - Valid names: " + element.getSearchParameterNames());
|
||||
}
|
||||
|
||||
sp.addCompartment(compartment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import com.google.common.reflect.ClassPath.ClassInfo;
|
|||
public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetParser {
|
||||
|
||||
@Override
|
||||
protected void postProcess(BaseElement theTarget) {
|
||||
protected void postProcess(BaseElement theTarget) throws MojoFailureException {
|
||||
super.postProcess(theTarget);
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,12 +26,21 @@ public class ResourceGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BaseElement theTarget) {
|
||||
protected void postProcess(BaseElement theTarget) throws MojoFailureException {
|
||||
super.postProcess(theTarget);
|
||||
|
||||
if ("Bundle".equals(theTarget.getName())) {
|
||||
addEverythingToSummary(theTarget);
|
||||
}
|
||||
|
||||
if (getVersion().equals("dstu2") && theTarget instanceof Resource) {
|
||||
try {
|
||||
new CompartmentParser(getVersion(), (Resource) theTarget).parse();
|
||||
} catch (Exception e) {
|
||||
throw new MojoFailureException(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addEverythingToSummary(BaseElement theTarget) {
|
||||
|
|
|
@ -56,6 +56,13 @@ public class ${className} extends ca.uhn.fhir.model.${version}.resource.BaseReso
|
|||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="${param.name}", path="${param.path}", description="${param.description}", type="${param.type}" #{if}($param.compositeOf.empty == false) , compositeOf={ #{foreach}($compositeOf in $param.compositeOf) "${compositeOf}"#{if}($foreach.hasNext), #{end}#{end} } #{end} )
|
||||
#if ($param.compartments.size() > 0)
|
||||
@Compartments(providesMembershipIn={
|
||||
#foreach ($compartment in $param.compartments)
|
||||
@Compartment(name="$compartment") #{if}($foreach.hasNext), #{end}
|
||||
#end
|
||||
})
|
||||
#end
|
||||
public static final String $param.constantName = "${param.name}";
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,6 +59,50 @@
|
|||
<action type="add">
|
||||
JPA server now supports :above and :below qualifiers on URI search params
|
||||
</action>
|
||||
<action type="add">
|
||||
Add optional support (disabled by default for now) to JPA server to support
|
||||
inline references containing search URLs. These URLs will be resolved when
|
||||
a resource is being created/updated and replaced with the single matching
|
||||
resource. This is being used as a part of the May 2016 Connectathon for
|
||||
a testing scenario.
|
||||
</action>
|
||||
<action type="add">
|
||||
The server no longer adds a
|
||||
<![CDATA[<code>WWW-Authenticate</code>]]>
|
||||
header to the response if any resource provider code throws an
|
||||
<![CDATA[<code>AuthenticationException</code>]]>. This header is
|
||||
used for interactive authentication, which isn't generally
|
||||
appropriate for FHIR. We added code to add this header a long time
|
||||
ago for testing purposes and it never got removed. Please let us
|
||||
know if you need the ability to add this header automatically. Thanks
|
||||
to Lars Kristian Roland for pointing this out.
|
||||
</action>
|
||||
<action type="fix">
|
||||
In the client, the create/update operations on a Binary resource
|
||||
(which use the raw binary's content type as opposed to the FHIR
|
||||
content type) were not including any request headers (Content-Type,
|
||||
User-Agent, etc.) Thanks to Peter Van Houte of Agfa Healthcare for
|
||||
reporting!
|
||||
</action>
|
||||
<action type="fix">
|
||||
Handling of Binary resources containing embedded FHIR resources for
|
||||
create/update/etc operations has been corrected per the FHIR rules
|
||||
outlined at
|
||||
<a href="http://hl7.org/fhir/binary.html">Binary Resource</a> in both
|
||||
the client and server.
|
||||
<![CDATA[<br/><br/>]]>
|
||||
Essentially, if the Binary contains something
|
||||
that isn't FHIR (e.g. an image with an image content-type) the
|
||||
client will send the raw data with the image content type to the server. The
|
||||
server will place the content type and raw data into a Binary resource instance
|
||||
and pass those to the resource provider. This part was already correct previous
|
||||
to 1.5.
|
||||
<![CDATA[<br/><br/>]]>
|
||||
On the other hand, if the Binary contains a FHIR content type, the Binary
|
||||
is now sent by the client to the server as a Binary resource with a FHIR content-type,
|
||||
and the embedded FHIR content is contained in the appropriate fields. The server
|
||||
will pass this "outer" Binary resource to the resource provider code.
|
||||
</action>
|
||||
<action type="add">
|
||||
The RequestDetails and ActionRequestDetails objects which are passed to
|
||||
server interceptor methods and may also be used as server provider method
|
||||
|
|
|
@ -115,8 +115,9 @@
|
|||
Update methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Update.html">@Update</a>
|
||||
annotation, and have a parameter annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@Resource</a>
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@ResourceParam</a>
|
||||
annotation. This parameter contains the resource instance to be created.
|
||||
See the <a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@ResourceParam</a> for information on the types allowed for this parameter (resource types, String, byte[]).
|
||||
</p>
|
||||
<p>
|
||||
In addition, the method may optionally have a parameter annotated with the
|
||||
|
@ -316,8 +317,9 @@
|
|||
Create methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Create.html">@Create</a>
|
||||
annotation, and have a single parameter annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@Resource</a>
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@ResourceParam</a>
|
||||
annotation. This parameter contains the resource instance to be created.
|
||||
See the <a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@ResourceParam</a> for information on the types allowed for this parameter (resource types, String, byte[]).
|
||||
</p>
|
||||
<p>
|
||||
Create methods must return an object of type
|
||||
|
@ -1104,7 +1106,7 @@
|
|||
Validate methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Validate.html">@Validate</a>
|
||||
annotation, and have a parameter annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@Resource</a>
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@ResourceParam</a>
|
||||
annotation. This parameter contains the resource instance to be created.
|
||||
</p>
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue