Start working on compartment support
This commit is contained in:
parent
d383b402d1
commit
39f6420066
|
@ -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));
|
||||
|
@ -589,7 +540,8 @@ class ModelScanner {
|
|||
List<Class<? extends IBaseResource>> refTypesList = new ArrayList<Class<? extends IBaseResource>>();
|
||||
for (Class<? extends IElement> nextType : childAnnotation.type()) {
|
||||
if (IBaseResource.class.isAssignableFrom(nextType) == false) {
|
||||
throw new ConfigurationException("Field '" + next.getName() + "' in class '" + next.getDeclaringClass().getCanonicalName() + "' is of type " + BaseResourceReferenceDt.class + " but contains a non-resource type: " + nextType.getCanonicalName());
|
||||
throw new ConfigurationException("Field '" + next.getName() + "' in class '" + next.getDeclaringClass().getCanonicalName() + "' is of type " + BaseResourceReferenceDt.class
|
||||
+ " but contains a non-resource type: " + nextType.getCanonicalName());
|
||||
}
|
||||
refTypesList.add((Class<? extends IBaseResource>) nextType);
|
||||
addScanAlso(nextType);
|
||||
|
@ -597,10 +549,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;
|
||||
|
@ -608,13 +560,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);
|
||||
|
@ -642,10 +595,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);
|
||||
|
@ -708,21 +662,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +704,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) {
|
||||
|
@ -758,7 +714,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);
|
||||
}
|
||||
|
@ -771,13 +737,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();
|
||||
|
||||
}
|
|
@ -38,54 +38,35 @@ public class DaoConfig {
|
|||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private boolean myAllowInlineMatchUrlReferences = false;
|
||||
|
||||
/**
|
||||
* @see #setAllowInlineMatchUrlReferences(boolean)
|
||||
*/
|
||||
public boolean isAllowInlineMatchUrlReferences() {
|
||||
return myAllowInlineMatchUrlReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
private boolean myAllowMultipleDelete;
|
||||
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.
|
||||
*
|
||||
|
@ -110,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;
|
||||
}
|
||||
|
@ -125,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;
|
||||
}
|
||||
|
@ -146,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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -46,6 +46,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;
|
||||
|
@ -225,14 +226,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,58 @@
|
|||
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;
|
||||
|
||||
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).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.getCode().setText("Some Observation");
|
||||
o2.setSubject(new Reference(p));
|
||||
IIdType oid2 = myObservationDao.create(o2).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addName().addFamily("MYFAMILY").addGiven("MYGIVEN");
|
||||
IIdType pid2 = myPatientDao.create(p2).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;
|
||||
|
||||
public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
||||
|
@ -56,15 +57,15 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
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)));
|
||||
|
||||
|
@ -358,7 +359,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
Device dev2 = new Device();
|
||||
dev2.setManufacturer("Some Manufacturer 2");
|
||||
IIdType devId2 = myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
|
||||
myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obs1 = new Observation();
|
||||
obs1.getSubject().setReferenceElement(ptId1);
|
||||
|
|
|
@ -23,9 +23,9 @@ 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;
|
||||
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||
import org.hl7.fhir.dstu3.model.DateType;
|
||||
import org.hl7.fhir.dstu3.model.Device;
|
||||
|
@ -46,12 +46,12 @@ import org.hl7.fhir.dstu3.model.Quantity;
|
|||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.dstu3.model.Subscription;
|
||||
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
|
||||
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.dstu3.model.ContactPoint.ContactPointSystem;
|
||||
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
|
||||
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
|
||||
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;
|
||||
|
@ -68,7 +68,6 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
|
@ -585,21 +584,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());
|
||||
}
|
||||
|
@ -628,18 +627,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));
|
||||
}
|
||||
{
|
||||
|
@ -647,7 +646,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));
|
||||
}
|
||||
{
|
||||
|
@ -655,7 +654,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());
|
||||
}
|
||||
{
|
||||
|
@ -663,7 +662,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());
|
||||
}
|
||||
{
|
||||
|
@ -671,7 +670,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));
|
||||
}
|
||||
{
|
||||
|
@ -680,7 +679,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));
|
||||
}
|
||||
{
|
||||
|
@ -688,7 +687,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));
|
||||
}
|
||||
|
@ -766,8 +765,6 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
@Test
|
||||
public void testSearchLastUpdatedParamWithComparator() throws InterruptedException {
|
||||
String methodName = "testSearchLastUpdatedParamWithComparator";
|
||||
|
||||
IIdType id0;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
|
@ -780,7 +777,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();
|
||||
|
@ -814,17 +810,17 @@ 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));
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(QuantityCompararatorEnum.GREATERTHAN, startDateTime.getValue()), new DateParam(QuantityCompararatorEnum.LESSTHAN, myPatientDao.read(id1b).getMeta().getLastUpdatedElement().getValue())));
|
||||
map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN, startDateTime.getValue()), new DateParam(ParamPrefixEnum.LESSTHAN, myPatientDao.read(id1b).getMeta().getLastUpdatedElement().getValue())));
|
||||
ourLog.info("Searching: {}", map.getLastUpdated());
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a));
|
||||
}
|
||||
|
@ -1372,7 +1368,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();
|
||||
|
||||
|
@ -1383,19 +1379,19 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
myObservationDao.create(o);
|
||||
|
||||
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());
|
||||
|
||||
|
@ -1405,8 +1401,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);
|
||||
|
@ -1554,7 +1550,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));
|
||||
|
@ -1596,7 +1592,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());
|
||||
|
@ -1891,7 +1887,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
ourLog.info("Initial size: " + value.size());
|
||||
for (IBaseResource next : value.getResources(0, value.size())) {
|
||||
ourLog.info("Deleting: {}", next.getIdElement());
|
||||
myDeviceDao.delete((IIdType) next.getIdElement());
|
||||
myDeviceDao.delete(next.getIdElement());
|
||||
}
|
||||
|
||||
value = myDeviceDao.search(new SearchParameterMap());
|
||||
|
@ -2098,7 +2094,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
ValueSet vs2 = new ValueSet();
|
||||
vs2.setUrl("http://hl7.org/foo/bar");
|
||||
IIdType id2 = myValueSetDao.create(vs2).getId().toUnqualifiedVersionless();
|
||||
myValueSetDao.create(vs2).getId().toUnqualifiedVersionless();
|
||||
|
||||
IBundleProvider result;
|
||||
result = myValueSetDao.search(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type"));
|
||||
|
|
|
@ -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}";
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue