Merge pull request #1566 from jamesagnew/ja_20190928_rationalize_search_param_extractor

Rationalize search param extractors across FHIR versions
This commit is contained in:
James Agnew 2019-11-02 16:18:23 -04:00 committed by GitHub
commit 3b6709e1d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
324 changed files with 66147 additions and 1020528 deletions

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.context;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Map.Entry;
@ -68,8 +69,8 @@ public abstract class BaseRuntimeChildDefinition {
public interface IAccessor {
List<IBase> getValues(IBase theTarget);
default IBase getFirstValueOrNull(IBase theTarget) {
return getValues(theTarget).stream().findFirst().orElse(null);
default <T extends IBase> Optional<T> getFirstValueOrNull(IBase theTarget) {
return (Optional<T>) getValues(theTarget).stream().findFirst();
}
}

View File

@ -30,6 +30,7 @@ import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChildDefinition {
private final IAccessor myAccessor;
@ -184,8 +185,8 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
}
@Override
public IBase getFirstValueOrNull(IBase theTarget) {
return (IBase) getFieldValue(theTarget, myField);
public <T extends IBase> Optional<T> getFirstValueOrNull(IBase theTarget) {
return Optional.ofNullable(((T)getFieldValue(theTarget, myField)));
}
}

View File

@ -20,25 +20,25 @@ package ca.uhn.fhir.context;
* #L%
*/
import java.lang.reflect.Constructor;
import java.util.*;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBase;
import java.lang.reflect.Constructor;
import java.util.*;
public abstract class BaseRuntimeElementDefinition<T extends IBase> {
private static final Class<Void> VOID_CLASS = Void.class;
private final Class<? extends T> myImplementingClass;
private final String myName;
private final boolean myStandardType;
private Map<Class<?>, Constructor<T>> myConstructors = Collections.synchronizedMap(new HashMap<Class<?>, Constructor<T>>());
private List<RuntimeChildDeclaredExtensionDefinition> myExtensions = new ArrayList<RuntimeChildDeclaredExtensionDefinition>();
private List<RuntimeChildDeclaredExtensionDefinition> myExtensionsModifier = new ArrayList<RuntimeChildDeclaredExtensionDefinition>();
private List<RuntimeChildDeclaredExtensionDefinition> myExtensionsNonModifier = new ArrayList<RuntimeChildDeclaredExtensionDefinition>();
private final Class<? extends T> myImplementingClass;
private final String myName;
private final boolean myStandardType;
private Map<String, RuntimeChildDeclaredExtensionDefinition> myUrlToExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();
private BaseRuntimeElementDefinition<?> myRootParentDefinition;
public BaseRuntimeElementDefinition(String theName, Class<? extends T> theImplementingClass, boolean theStandardType) {
assert StringUtils.isNotBlank(theName);
@ -49,8 +49,8 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
if (name.endsWith("Dt")) {
name = name.substring(0, name.length() - 2);
}
myName = name;
myStandardType = theStandardType;
myImplementingClass = theImplementingClass;
@ -67,14 +67,14 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
@SuppressWarnings("unchecked")
private Constructor<T> getConstructor(Object theArgument) {
Class<? extends Object> argumentType;
if (theArgument == null) {
argumentType = VOID_CLASS;
} else {
argumentType = theArgument.getClass();
}
Constructor<T> retVal = myConstructors.get(argumentType);
if (retVal == null) {
for (Constructor<?> next : getImplementingClass().getConstructors()) {
@ -137,7 +137,7 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
/**
* @return Returns the runtime name for this resource (i.e. the name that
* will be used in encoded messages)
* will be used in encoded messages)
*/
public String getName() {
return myName;
@ -168,9 +168,14 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
}
}
public BaseRuntimeElementDefinition<?> getRootParentDefinition() {
return myRootParentDefinition;
}
/**
* Invoked prior to use to perform any initialization and make object
* mutable.
*
* @param theContext TODO
*/
void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
@ -193,44 +198,57 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
}
myExtensions = Collections.unmodifiableList(myExtensions);
Class parent = myImplementingClass;
do {
BaseRuntimeElementDefinition<?> parentDefinition = theClassToElementDefinitions.get(parent);
if (parentDefinition != null) {
myRootParentDefinition = parentDefinition;
}
parent = parent.getSuperclass();
} while (!parent.equals(Object.class));
}
@Override
public String toString() {
return getClass().getSimpleName()+"[" + getName() + ", " + getImplementingClass().getSimpleName() + "]";
return getClass().getSimpleName() + "[" + getName() + ", " + getImplementingClass().getSimpleName() + "]";
}
protected void validateSealed() {
/*
/*
* this does nothing, but BaseRuntimeElementCompositeDefinition
* overrides this method to provide functionality because that class
* defers the dealing process
*/
}
public enum ChildTypeEnum {
COMPOSITE_DATATYPE, /**
COMPOSITE_DATATYPE,
/**
* HL7.org structure style.
*/
CONTAINED_RESOURCE_LIST, /**
CONTAINED_RESOURCE_LIST,
/**
* HAPI structure style.
*/
CONTAINED_RESOURCES, EXTENSION_DECLARED,
ID_DATATYPE,
PRIMITIVE_DATATYPE, /**
CONTAINED_RESOURCES, EXTENSION_DECLARED,
ID_DATATYPE,
PRIMITIVE_DATATYPE,
/**
* HAPI style.
*/
PRIMITIVE_XHTML,
PRIMITIVE_XHTML,
/**
* HL7.org style.
*/
PRIMITIVE_XHTML_HL7ORG,
RESOURCE,
RESOURCE_BLOCK,
UNDECL_EXT,
PRIMITIVE_XHTML_HL7ORG,
RESOURCE,
RESOURCE_BLOCK,
UNDECL_EXT,
}
}

View File

@ -26,6 +26,7 @@ import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@ -275,6 +276,7 @@ public class FhirContext {
* Note that this method is case insensitive!
* </p>
*/
@Nullable
public BaseRuntimeElementDefinition<?> getElementDefinition(final String theElementName) {
validateInitialized();
return myNameToElementDefinition.get(theElementName.toLowerCase());

View File

@ -93,8 +93,6 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
boolean nonPreferred = false;
if (IBaseResource.class.isAssignableFrom(next)) {
elementName = getElementName() + StringUtils.capitalize(next.getSimpleName());
List<Class<? extends IBaseResource>> types = new ArrayList<Class<? extends IBaseResource>>();
types.add((Class<? extends IBaseResource>) next);
nextDef = findResourceReferenceDefinition(theClassToElementDefinitions);
myNameToChildDefinition.put(getElementName() + "Reference", nextDef);

View File

@ -28,47 +28,9 @@ import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildPrimitiveDatatypeDefinition extends BaseRuntimeChildDatatypeDefinition {
// private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RuntimeChildPrimitiveDatatypeDefinition.class);
// private IMutator myReferenceMutator;
public RuntimeChildPrimitiveDatatypeDefinition(Field theField, String theElementName, Description theDescriptionAnnotation, Child theChildAnnotation, Class<? extends IBase> theDatatype) {
super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation, theDatatype);
}
// @Override
// void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
// super.sealAndInitialize(theContext, theClassToElementDefinitions);
//
// if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
// if (IReference.class.isAssignableFrom(getDatatype())) {
// String fieldName = getField().getName() + "Target";
// try {
// Field targetField = getField().getDeclaringClass().getField(fieldName);
// if (List.class.isAssignableFrom(targetField.getType())) {
// myReferenceMutator = new FieldListMutator();
// } else if (IBaseResource.class.isAssignableFrom(targetField.getType())) {
// myReferenceMutator = new FieldPlainMutator();
// }
// } catch (Exception e) {
// ourLog.debug("Unable to find target field named {}", fieldName);
// }
// }
// } else {
// if (BaseResourceReferenceDt.class.isAssignableFrom(getDatatype())) {
// myReferenceMutator = new IMutator() {
// @Override
// public void addValue(Object theTarget, IBase theValue) {
// BaseResourceReferenceDt dt = (BaseResourceReferenceDt)theTarget;
// dt.setResource((IBaseResource) theValue);
// }};
// }
// }
//
// }
//
// public IMutator getReferenceMutator() {
// return myReferenceMutator;
// }
}

View File

@ -79,19 +79,19 @@ class ParserState<T> {
}
}
public boolean elementIsRepeating(String theChildName) {
boolean elementIsRepeating(String theChildName) {
return myState.elementIsRepeating(theChildName);
}
public void endingElement() throws DataFormatException {
void endingElement() throws DataFormatException {
myState.endingElement();
}
public void enteringNewElement(String theNamespaceUri, String theName) throws DataFormatException {
void enteringNewElement(String theNamespaceUri, String theName) throws DataFormatException {
myState.enteringNewElement(theNamespaceUri, theName);
}
public void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
myState.enteringNewElementExtension(theElem, theUrlAttr, theIsModifier, baseServerUrl);
}
@ -99,7 +99,7 @@ class ParserState<T> {
return myObject;
}
public boolean isPreResource() {
boolean isPreResource() {
return myState.isPreResource();
}
@ -135,18 +135,11 @@ class ParserState<T> {
myState.string(theData);
}
public boolean verifyNamespace(String theExpect, String theActual) {
if (myJsonMode) {
return true;
}
return StringUtils.equals(theExpect, theActual);
}
/**
* Invoked after any new XML event is individually processed, containing a copy of the XML event. This is basically
* intended for embedded XHTML content
*/
public void xmlEvent(XMLEvent theNextEvent) {
void xmlEvent(XMLEvent theNextEvent) {
if (myState != null) {
myState.xmlEvent(theNextEvent);
}
@ -157,7 +150,7 @@ class ParserState<T> {
private PreResourceState myPreResourceState;
private BaseState myStack;
public BaseState(PreResourceState thePreResourceState) {
BaseState(PreResourceState thePreResourceState) {
super();
myPreResourceState = thePreResourceState;
}
@ -223,7 +216,7 @@ class ParserState<T> {
return null;
}
public PreResourceState getPreResourceState() {
PreResourceState getPreResourceState() {
return myPreResourceState;
}
@ -231,7 +224,7 @@ class ParserState<T> {
return false;
}
protected void logAndSwallowUnexpectedElement(String theLocalPart) {
void logAndSwallowUnexpectedElement(String theLocalPart) {
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
}
@ -340,6 +333,7 @@ class ParserState<T> {
}
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
private class DeclaredExtensionState extends BaseState {
private IBase myChildInstance;
@ -431,10 +425,10 @@ class ParserState<T> {
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
private IBase myInstance;
private Set<String> myParsedNonRepeatableNames = new HashSet<String>();
private Set<String> myParsedNonRepeatableNames = new HashSet<>();
private String myElementName;
public ElementCompositeState(PreResourceState thePreResourceState, String theElementName, BaseRuntimeElementCompositeDefinition<?> theDef, IBase theInstance) {
ElementCompositeState(PreResourceState thePreResourceState, String theElementName, BaseRuntimeElementCompositeDefinition<?> theDef, IBase theInstance) {
super(thePreResourceState);
myDefinition = theDef;
myInstance = theInstance;
@ -448,11 +442,7 @@ class ParserState<T> {
((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
} else if (myInstance instanceof IBaseElement) {
((IBaseElement) myInstance).setId(theValue);
} else if (myInstance instanceof IBaseResource) {
new IdDt(theValue).applyTo((IBaseResource) myInstance);
}
} else if ("url".equals(theName) && myInstance instanceof ExtensionDt) {
((ExtensionDt) myInstance).setUrl(theValue);
} else {
if (myJsonMode) {
myErrorHandler.incorrectJsonType(null, myElementName, ValueType.OBJECT, null, ValueType.SCALAR, ScalarType.STRING);
@ -553,12 +543,9 @@ class ParserState<T> {
}
case CONTAINED_RESOURCES: {
List<? extends IBase> values = child.getAccessor().getValues(myInstance);
Object newDt;
if (values == null || values.isEmpty() || values.get(0) == null) {
newDt = newContainedDt((IResource) getPreResourceState().myInstance);
Object newDt = newContainedDt((IResource) getPreResourceState().myInstance);
child.getMutator().addValue(myInstance, (IBase) newDt);
} else {
newDt = values.get(0);
}
ContainedResourcesStateHapi state = new ContainedResourcesStateHapi(getPreResourceState());
push(state);
@ -611,7 +598,7 @@ class ParserState<T> {
private IBaseElement myElement;
public ElementIdState(ParserState<T>.PreResourceState thePreResourceState, IBaseElement theElement) {
ElementIdState(ParserState<T>.PreResourceState thePreResourceState, IBaseElement theElement) {
super(thePreResourceState);
myElement = theElement;
}
@ -632,7 +619,7 @@ class ParserState<T> {
private IBaseExtension<?, ?> myExtension;
public ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?, ?> theExtension) {
ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?, ?> theExtension) {
super(thePreResourceState);
myExtension = theExtension;
}
@ -712,7 +699,6 @@ class ParserState<T> {
// We hit an invalid type for the extension
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
}
@Override
@ -758,50 +744,55 @@ class ParserState<T> {
@Override
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
if (theLocalPart.equals("versionId")) {
push(new MetaVersionElementState(getPreResourceState(), myMap));
// } else if (theLocalPart.equals("profile")) {
//
} else if (theLocalPart.equals("lastUpdated")) {
InstantDt updated = new InstantDt();
push(new PrimitiveState(getPreResourceState(), updated));
myMap.put(ResourceMetadataKeyEnum.UPDATED, updated);
} else if (theLocalPart.equals("security")) {
@SuppressWarnings("unchecked")
List<IBase> securityLabels = (List<IBase>) myMap.get(ResourceMetadataKeyEnum.SECURITY_LABELS);
if (securityLabels == null) {
securityLabels = new ArrayList<>();
myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels);
}
IBase securityLabel = myContext.getVersion().newCodingDt();
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
securityLabels.add(securityLabel);
} else if (theLocalPart.equals("profile")) {
@SuppressWarnings("unchecked")
List<IdDt> profiles = (List<IdDt>) myMap.get(ResourceMetadataKeyEnum.PROFILES);
List<IdDt> newProfiles;
if (profiles != null) {
newProfiles = new ArrayList<IdDt>(profiles.size() + 1);
newProfiles.addAll(profiles);
} else {
newProfiles = new ArrayList<IdDt>(1);
}
IdDt profile = new IdDt();
push(new PrimitiveState(getPreResourceState(), profile));
newProfiles.add(profile);
myMap.put(ResourceMetadataKeyEnum.PROFILES, Collections.unmodifiableList(newProfiles));
} else if (theLocalPart.equals("tag")) {
TagList tagList = (TagList) myMap.get(ResourceMetadataKeyEnum.TAG_LIST);
if (tagList == null) {
tagList = new TagList();
myMap.put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
}
push(new TagState(tagList));
} else {
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
switch (theLocalPart) {
case "versionId":
push(new MetaVersionElementState(getPreResourceState(), myMap));
// } else if (theLocalPart.equals("profile")) {
//
break;
case "lastUpdated":
InstantDt updated = new InstantDt();
push(new PrimitiveState(getPreResourceState(), updated));
myMap.put(ResourceMetadataKeyEnum.UPDATED, updated);
break;
case "security":
@SuppressWarnings("unchecked")
List<IBase> securityLabels = (List<IBase>) myMap.get(ResourceMetadataKeyEnum.SECURITY_LABELS);
if (securityLabels == null) {
securityLabels = new ArrayList<>();
myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels);
}
IBase securityLabel = myContext.getVersion().newCodingDt();
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
securityLabels.add(securityLabel);
break;
case "profile":
@SuppressWarnings("unchecked")
List<IdDt> profiles = (List<IdDt>) myMap.get(ResourceMetadataKeyEnum.PROFILES);
List<IdDt> newProfiles;
if (profiles != null) {
newProfiles = new ArrayList<>(profiles.size() + 1);
newProfiles.addAll(profiles);
} else {
newProfiles = new ArrayList<>(1);
}
IdDt profile = new IdDt();
push(new PrimitiveState(getPreResourceState(), profile));
newProfiles.add(profile);
myMap.put(ResourceMetadataKeyEnum.PROFILES, Collections.unmodifiableList(newProfiles));
break;
case "tag":
TagList tagList = (TagList) myMap.get(ResourceMetadataKeyEnum.TAG_LIST);
if (tagList == null) {
tagList = new TagList();
myMap.put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
}
push(new TagState(tagList));
break;
default:
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
}
}
@ -830,7 +821,7 @@ class ParserState<T> {
private ResourceMetadataMap myMap;
public MetaVersionElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
MetaVersionElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
super(thePreResourceState);
myMap = theMap;
}
@ -849,7 +840,6 @@ class ParserState<T> {
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
}
}
@ -859,13 +849,12 @@ class ParserState<T> {
private Map<String, IBaseResource> myContainedResources;
private IBaseResource myInstance;
private FhirVersionEnum myParentVersion;
private boolean myRequireResourceType = true;
private Class<? extends IBaseResource> myResourceType;
public PreResourceState(Class<? extends IBaseResource> theResourceType) {
PreResourceState(Class<? extends IBaseResource> theResourceType) {
super(null);
myResourceType = theResourceType;
myContainedResources = new HashMap<String, IBaseResource>();
myContainedResources = new HashMap<>();
if (theResourceType != null) {
myParentVersion = myContext.getResourceDefinition(theResourceType).getStructureVersion();
} else {
@ -873,7 +862,7 @@ class ParserState<T> {
}
}
public PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
super(thePreResourcesState);
Validate.notNull(theParentVersion);
myParentVersion = theParentVersion;
@ -888,7 +877,7 @@ class ParserState<T> {
@Override
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
BaseRuntimeElementDefinition<?> definition;
RuntimeResourceDefinition definition;
if (myResourceType == null) {
definition = null;
if (myParser.getPreferTypes() != null) {
@ -908,17 +897,11 @@ class ParserState<T> {
} else {
definition = myContext.getResourceDefinition(myResourceType);
if (!StringUtils.equals(theLocalPart, definition.getName())) {
if (myRequireResourceType) {
throw new DataFormatException(myContext.getLocalizer().getMessage(ParserState.class, "wrongResourceTypeFound", definition.getName(), theLocalPart));
}
definition = myContext.getResourceDefinition(theLocalPart);
if (!(definition instanceof RuntimeResourceDefinition)) {
throw new DataFormatException("Element '" + theLocalPart + "' is not a resource, expected a resource at this position");
}
throw new DataFormatException(myContext.getLocalizer().getMessage(ParserState.class, "wrongResourceTypeFound", definition.getName(), theLocalPart));
}
}
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
RuntimeResourceDefinition def = definition;
if (!definition.getName().equals(theLocalPart) && definition.getName().equalsIgnoreCase(theLocalPart)) {
throw new DataFormatException("Unknown resource type '" + theLocalPart + "': Resource names are case sensitive, found similar name: '" + definition.getName() + "'");
}
@ -971,7 +954,7 @@ class ParserState<T> {
if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) {
if (myResourceType == null || myResourceType.isAssignableFrom(wantedProfileType)) {
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", new Object[]{myInstance.getClass().getName(), usedProfile, wantedProfileType});
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", myInstance.getClass().getName(), usedProfile, wantedProfileType);
/*
* This isn't the most efficient thing really.. If we want a specific
@ -998,7 +981,7 @@ class ParserState<T> {
FhirTerser t = myContext.newTerser();
Map<String, IBaseResource> idToResource = new HashMap<String, IBaseResource>();
Map<String, IBaseResource> idToResource = new HashMap<>();
List<IBase> entries = t.getValues(myInstance, "Bundle.entry", IBase.class);
for (IBase nextEntry : entries) {
IPrimitiveType<?> fullUrl = t.getSingleValueOrNull(nextEntry, "fullUrl", IPrimitiveType.class);
@ -1051,7 +1034,7 @@ class ParserState<T> {
}
}
protected void weaveContainedResources() {
void weaveContainedResources() {
FhirTerser terser = myContext.newTerser();
terser.visit(myInstance, new IModelVisitor() {
@ -1103,12 +1086,12 @@ class ParserState<T> {
private IBase myTarget;
public PreResourceStateHapi(Class<? extends IBaseResource> theResourceType) {
PreResourceStateHapi(Class<? extends IBaseResource> theResourceType) {
super(theResourceType);
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
}
public PreResourceStateHapi(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
PreResourceStateHapi(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
super(theResourceType);
myTarget = theTarget;
myMutator = theMutator;
@ -1160,11 +1143,11 @@ class ParserState<T> {
private IMutator myMutator;
private IBase myTarget;
public PreResourceStateHl7Org(Class<? extends IBaseResource> theResourceType) {
PreResourceStateHl7Org(Class<? extends IBaseResource> theResourceType) {
super(theResourceType);
}
public PreResourceStateHl7Org(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
PreResourceStateHl7Org(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
super(theResourceType);
myMutator = theMutator;
myTarget = theTarget;
@ -1202,7 +1185,7 @@ class ParserState<T> {
private TagList myTagList;
public PreTagListState() {
PreTagListState() {
super(null);
myTagList = new TagList();
}
@ -1236,7 +1219,7 @@ class ParserState<T> {
private class PrimitiveState extends BaseState {
private IPrimitiveType<?> myInstance;
public PrimitiveState(PreResourceState thePreResourceState, IPrimitiveType<?> theInstance) {
PrimitiveState(PreResourceState thePreResourceState, IPrimitiveType<?> theInstance) {
super(thePreResourceState);
myInstance = theInstance;
}
@ -1264,7 +1247,7 @@ class ParserState<T> {
myErrorHandler.unknownAttribute(null, theName);
}
} else {
myErrorHandler.unknownAttribute(null, theName);
super.attributeValue(theName, theValue);
}
}
@ -1286,9 +1269,8 @@ class ParserState<T> {
@Override
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
myErrorHandler.unknownElement(null, theLocalPart);
super.enteringNewElement(theNamespaceUri, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
}
@Override
@ -1321,7 +1303,7 @@ class ParserState<T> {
private class ResourceStateHl7Org extends ElementCompositeState {
public ResourceStateHl7Org(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBaseResource theInstance) {
ResourceStateHl7Org(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBaseResource theInstance) {
super(thePreResourceState, theDef.getName(), theDef, theInstance);
}
@ -1329,7 +1311,7 @@ class ParserState<T> {
private class SecurityLabelElementStateHapi extends ElementCompositeState {
public SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBase codingDt) {
SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBase codingDt) {
super(thePreResourceState, theDef.getName(), theDef, codingDt);
}
@ -1344,7 +1326,7 @@ class ParserState<T> {
private int myDepth;
public SwallowChildrenWholeState(PreResourceState thePreResourceState) {
SwallowChildrenWholeState(PreResourceState thePreResourceState) {
super(thePreResourceState);
}

View File

@ -43,6 +43,7 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@ -354,17 +355,18 @@ public class XmlParser extends BaseParser {
}
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
INarrative narr = (INarrative) nextChild.getAccessor().getFirstValueOrNull(theElement);
Optional<IBase> narr = nextChild.getAccessor().getFirstValueOrNull(theElement);
INarrativeGenerator gen = myContext.getNarrativeGenerator();
if (gen != null && (narr == null || narr.isEmpty())) {
if (gen != null && narr.isPresent() == false) {
gen.populateResourceNarrative(myContext, theResource);
}
if (narr != null && narr.isEmpty() == false) {
narr = nextChild.getAccessor().getFirstValueOrNull(theElement);
if (narr.isPresent()) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextChild, narr, childName, type, null, theContainedResource, nextChildElem, theEncodeContext);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextChild, narr.get(), childName, type, null, theContainedResource, nextChildElem, theEncodeContext);
continue;
}
}

View File

@ -475,11 +475,10 @@ public class FhirTerser {
* @param thePath The path for the element to be accessed.
* @return A list of values of type {@link Object}.
*/
public List<Object> getValues(IBaseResource theResource, String thePath) {
public List<IBase> getValues(IBaseResource theResource, String thePath) {
Class<IBase> wantedClass = IBase.class;
List values = getValues(theResource, thePath, wantedClass);
return values;
return getValues(theResource, thePath, wantedClass);
}
/**
@ -491,11 +490,10 @@ public class FhirTerser {
* @param theCreate When set to <code>true</code>, the terser will create a null-valued element where none exists.
* @return A list of values of type {@link Object}.
*/
public List<Object> getValues(IBaseResource theResource, String thePath, boolean theCreate) {
public List<IBase> getValues(IBaseResource theResource, String thePath, boolean theCreate) {
Class<IBase> wantedClass = IBase.class;
List retVal = getValues(theResource, thePath, wantedClass, theCreate);
return retVal;
return getValues(theResource, thePath, wantedClass, theCreate);
}
/**
@ -508,11 +506,10 @@ public class FhirTerser {
* @param theAddExtension When set to <code>true</code>, the terser will add a null-valued extension where one or more such extensions already exist.
* @return A list of values of type {@link Object}.
*/
public List<Object> getValues(IBaseResource theResource, String thePath, boolean theCreate, boolean theAddExtension) {
public List<IBase> getValues(IBaseResource theResource, String thePath, boolean theCreate, boolean theAddExtension) {
Class<IBase> wantedClass = IBase.class;
List retVal = getValues(theResource, thePath, wantedClass, theCreate, theAddExtension);
return retVal;
return getValues(theResource, thePath, wantedClass, theCreate, theAddExtension);
}
/**

View File

@ -45,7 +45,6 @@
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
<!-- HAPI-FHIR uses Logback for logging support. The logback library is included automatically by Maven as a part of the hapi-fhir-base dependency, but you also need to include a logging library. Logback

View File

@ -19,59 +19,48 @@ package ca.uhn.fhir.rest.client.method;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationMethodBinding.class);
private BundleTypeEnum myBundleType;
private boolean myCanOperateAtInstanceLevel;
private boolean myCanOperateAtServerLevel;
private boolean myCanOperateAtTypeLevel;
private String myDescription;
private final boolean myIdempotent;
private final Integer myIdParamIndex;
private final String myName;
private final RestOperationTypeEnum myOtherOperatiopnType;
private List<ReturnType> myReturnParams;
private final RestOperationTypeEnum myOtherOperationType;
private final ReturnTypeEnum myReturnType;
private BundleTypeEnum myBundleType;
private String myDescription;
protected OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType,
OperationParam[] theReturnParams, BundleTypeEnum theBundleType) {
boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType,
BundleTypeEnum theBundleType) {
super(theReturnResourceType, theMethod, theContext, theProvider);
myBundleType = theBundleType;
myIdempotent = theIdempotent;
myIdParamIndex = ParameterUtil.findIdParameterIndex(theMethod, getContext());
if (myIdParamIndex != null) {
for (Annotation next : theMethod.getParameterAnnotations()[myIdParamIndex]) {
if (next instanceof IdParam) {
myCanOperateAtTypeLevel = ((IdParam) next).optional() == true;
}
}
} else {
myCanOperateAtTypeLevel = true;
}
Description description = theMethod.getAnnotation(Description.class);
if (description != null) {
@ -86,7 +75,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
if (isBlank(theOperationName)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName()
+ " but this annotation has no name defined");
+ " but this annotation has no name defined");
}
if (theOperationName.startsWith("$") == false) {
theOperationName = "$" + theOperationName;
@ -106,52 +95,28 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
myReturnType = ReturnTypeEnum.RESOURCE;
if (getResourceName() == null) {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_SERVER;
myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_SERVER;
} else if (myIdParamIndex == null) {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_TYPE;
myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_TYPE;
} else {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
}
myReturnParams = new ArrayList<OperationMethodBinding.ReturnType>();
if (theReturnParams != null) {
for (OperationParam next : theReturnParams) {
ReturnType type = new ReturnType();
type.setName(next.name());
type.setMin(next.min());
type.setMax(next.max());
if (type.getMax() == OperationParam.MAX_DEFAULT) {
type.setMax(1);
}
if (!next.type().equals(IBase.class)) {
if (next.type().isInterface() || Modifier.isAbstract(next.type().getModifiers())) {
throw new ConfigurationException("Invalid value for @OperationParam.type(): " + next.type().getName());
}
type.setType(theContext.getElementDefinition(next.type()).getName());
}
myReturnParams.add(type);
}
}
if (myIdParamIndex != null) {
myCanOperateAtInstanceLevel = true;
}
if (getResourceName() == null) {
myCanOperateAtServerLevel = true;
myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
}
}
public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
Operation theAnnotation) {
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.returnParameters(),
theAnnotation.bundleType());
Operation theAnnotation) {
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.bundleType());
}
public String getDescription() {
return myDescription;
}
public void setDescription(String theDescription) {
myDescription = theDescription;
}
/**
* Returns the name of the operation, starting with "$"
*/
@ -166,11 +131,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
@Override
public RestOperationTypeEnum getRestOperationType() {
return myOtherOperatiopnType;
}
public List<ReturnType> getReturnParams() {
return Collections.unmodifiableList(myReturnParams);
return myOtherOperationType;
}
@Override
@ -197,28 +158,12 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
return createOperationInvocation(getContext(), getResourceName(), id, null, myName, parameters, false);
}
public boolean isCanOperateAtInstanceLevel() {
return this.myCanOperateAtInstanceLevel;
}
public boolean isCanOperateAtServerLevel() {
return this.myCanOperateAtServerLevel;
}
public boolean isCanOperateAtTypeLevel() {
return myCanOperateAtTypeLevel;
}
public boolean isIdempotent() {
return myIdempotent;
}
public void setDescription(String theDescription) {
myDescription = theDescription;
}
public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theVersion, String theOperationName, IBaseParameters theInput,
boolean theUseHttpGet) {
boolean theUseHttpGet) {
StringBuilder b = new StringBuilder();
if (theResourceName != null) {
b.append(theResourceName);
@ -243,9 +188,9 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
return new HttpPostClientInvocation(theContext, theInput, b.toString());
}
FhirTerser t = theContext.newTerser();
List<Object> parameters = t.getValues(theInput, "Parameters.parameter");
List<IBase> parameters = t.getValues(theInput, "Parameters.parameter");
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
Map<String, List<String>> params = new LinkedHashMap<>();
for (Object nextParameter : parameters) {
IPrimitiveType<?> nextNameDt = (IPrimitiveType<?>) t.getSingleValueOrNull((IBase) nextParameter, "name");
if (nextNameDt == null || nextNameDt.isEmpty()) {
@ -254,7 +199,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
}
String nextName = nextNameDt.getValueAsString();
if (!params.containsKey(nextName)) {
params.put(nextName, new ArrayList<String>());
params.put(nextName, new ArrayList<>());
}
IBaseDatatype value = (IBaseDatatype) t.getSingleValueOrNull((IBase) nextParameter, "value[x]");
@ -263,7 +208,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
}
if (!(value instanceof IPrimitiveType)) {
throw new IllegalArgumentException(
"Can not invoke operation as HTTP GET when it has parameters with a composite (non priitive) datatype as the value. Found value: " + value.getClass().getName());
"Can not invoke operation as HTTP GET when it has parameters with a composite (non priitive) datatype as the value. Found value: " + value.getClass().getName());
}
IPrimitiveType<?> primitive = (IPrimitiveType<?>) value;
params.get(nextName).add(primitive.getValueAsString());
@ -288,46 +233,4 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
}
public static class ReturnType {
private int myMax;
private int myMin;
private String myName;
/**
* http://hl7-fhir.github.io/valueset-operation-parameter-type.html
*/
private String myType;
public int getMax() {
return myMax;
}
public int getMin() {
return myMin;
}
public String getName() {
return myName;
}
public String getType() {
return myType;
}
public void setMax(int theMax) {
myMax = theMax;
}
public void setMin(int theMin) {
myMin = theMin;
}
public void setName(String theName) {
myName = theName;
}
public void setType(String theType) {
myType = theType;
}
}
}

View File

@ -40,7 +40,7 @@ public class ValidateMethodBindingDstu2Plus extends OperationMethodBinding {
public ValidateMethodBindingDstu2Plus(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
Validate theAnnotation) {
super(null, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION);
super(null, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), BundleTypeEnum.COLLECTION);
List<IParameter> newParams = new ArrayList<IParameter>();
int idx = 0;

View File

@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu2;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.hapi.validation.CachingValidationSupport;
@ -85,7 +86,7 @@ public class BaseDstu2Config extends BaseConfig {
@Bean(name = "myInstanceValidatorDstu2")
@Lazy
public IValidatorModule instanceValidatorDstu2() {
public IInstanceValidatorModule instanceValidatorDstu2() {
FhirInstanceValidator retVal = new FhirInstanceValidator();
retVal.setBestPracticeWarningLevel(IResourceValidator.BestPracticeWarningLevel.Warning);
retVal.setValidationSupport(new CachingValidationSupport(new ValidationSupportChain(new DefaultProfileValidationSupport(), jpaValidationSupportDstu2())));

View File

@ -21,6 +21,7 @@ import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.dstu3.hapi.ctx.DefaultProfileValidationSupport;
@ -100,7 +101,7 @@ public class BaseDstu3Config extends BaseConfigDstu3Plus {
@Bean(name = "myInstanceValidatorDstu3")
@Lazy
public IValidatorModule instanceValidatorDstu3() {
public IInstanceValidatorModule instanceValidatorDstu3() {
FhirInstanceValidator val = new FhirInstanceValidator();
val.setBestPracticeWarningLevel(IResourceValidator.BestPracticeWarningLevel.Warning);
val.setValidationSupport(validationSupportChainDstu3());

View File

@ -19,6 +19,7 @@ import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
@ -99,7 +100,7 @@ public class BaseR4Config extends BaseConfigDstu3Plus {
@Bean(name = "myInstanceValidatorR4")
@Lazy
public IValidatorModule instanceValidatorR4() {
public IInstanceValidatorModule instanceValidatorR4() {
FhirInstanceValidator val = new FhirInstanceValidator();
IResourceValidator.BestPracticeWarningLevel level = IResourceValidator.BestPracticeWarningLevel.Warning;
val.setBestPracticeWarningLevel(level);

View File

@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.config.r5;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ParserOptions;
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
@ -13,13 +12,15 @@ import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR5;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR5;
import ca.uhn.fhir.jpa.term.*;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcR5;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR5;
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR5;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR5;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.r5.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r5.hapi.ctx.IValidationSupport;
@ -99,7 +100,7 @@ public class BaseR5Config extends BaseConfigDstu3Plus {
@Bean(name = "myInstanceValidatorR5")
@Lazy
public IValidatorModule instanceValidatorR5() {
public IInstanceValidatorModule instanceValidatorR5() {
FhirInstanceValidator val = new FhirInstanceValidator();
IResourceValidator.BestPracticeWarningLevel level = IResourceValidator.BestPracticeWarningLevel.Warning;
val.setBestPracticeWarningLevel(level);

View File

@ -168,6 +168,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
private FhirContext myContext;
private ApplicationContext myApplicationContext;
protected ApplicationContext getApplicationContext() {
return myApplicationContext;
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
/*
@ -906,16 +910,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
return retVal;
}
static String cleanProvenanceSourceUri(String theProvenanceSourceUri) {
if (isNotBlank(theProvenanceSourceUri)) {
int hashIndex = theProvenanceSourceUri.indexOf('#');
if (hashIndex != -1) {
theProvenanceSourceUri = theProvenanceSourceUri.substring(0, hashIndex);
}
}
return defaultString(theProvenanceSourceUri);
}
public String toResourceName(Class<? extends IBaseResource> theResourceType) {
return myContext.getResourceDefinition(theResourceType).getName();
}
@ -933,7 +927,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
@Override
public ResourceTable updateEntity(RequestDetails theRequest, final IBaseResource theResource, ResourceTable
theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
Validate.notNull(theEntity);
Validate.isTrue(theDeletedTimestampOrNull != null || theResource != null, "Must have either a resource[%s] or a deleted timestamp[%s] for resource PID[%s]", theDeletedTimestampOrNull != null, theResource != null, theEntity.getId());
@ -985,7 +979,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
if (thePerformIndexing) {
newParams = new ResourceIndexedSearchParams();
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, this, theUpdateTime, theEntity, theResource, existingParams, theRequest);
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, theUpdateTime, theEntity, theResource, existingParams, theRequest);
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true);
if (changed.isChanged()) {
@ -1385,6 +1379,16 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
// nothing yet
}
static String cleanProvenanceSourceUri(String theProvenanceSourceUri) {
if (isNotBlank(theProvenanceSourceUri)) {
int hashIndex = theProvenanceSourceUri.indexOf('#');
if (hashIndex != -1) {
theProvenanceSourceUri = theProvenanceSourceUri.substring(0, hashIndex);
}
}
return defaultString(theProvenanceSourceUri);
}
@SuppressWarnings("unchecked")
public static String parseContentTextIntoWords(FhirContext theContext, IBaseResource theResource) {

View File

@ -20,7 +20,6 @@ package ca.uhn.fhir.jpa.dao;
* #L%
*/
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
@ -29,7 +28,6 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.delete.DeleteConflictList;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
@ -57,6 +55,7 @@ import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.InstantType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Propagation;
@ -74,7 +73,6 @@ import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import static ca.uhn.fhir.jpa.model.util.JpaConstants.EXT_EXTERNALIZED_BINARY_ID;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@Transactional(propagation = Propagation.REQUIRED)
@ -92,7 +90,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
private MatchResourceUrlService myMatchResourceUrlService;
@Autowired
private IResourceReindexingSvc myResourceReindexingSvc;
private IInstanceValidatorModule myInstanceValidator;
private String myResourceName;
private Class<T> myResourceType;
@ -178,9 +176,15 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return createOperationOutcome(OO_SEVERITY_INFO, theMessage, "informational");
}
protected abstract IValidatorModule getInstanceValidator();
private IInstanceValidatorModule getInstanceValidator() {
return myInstanceValidator;
}
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode);
private IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
OperationOutcomeUtil.addIssue(getContext(), oo, theSeverity, theMessage, null, theCode);
return oo;
}
@Override
public DaoMethodOutcome delete(IIdType theId) {
@ -826,6 +830,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
public void start() {
ourLog.debug("Starting resource DAO for type: {}", getResourceName());
myInstanceValidator = getApplicationContext().getBean(IInstanceValidatorModule.class);
super.start();
}

View File

@ -28,7 +28,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleDstu2 extends FhirResourceDaoDstu2<Bundle> {
public class FhirResourceDaoBundleDstu2 extends BaseHapiFhirResourceDao<Bundle> {
@Override
protected void preProcessResourceForStorage(Bundle theResource) {

View File

@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
public class FhirResourceDaoCompositionDstu2 extends FhirResourceDaoDstu2<Composition>implements IFhirResourceDaoComposition<Composition> {
public class FhirResourceDaoCompositionDstu2 extends BaseHapiFhirResourceDao<Composition>implements IFhirResourceDaoComposition<Composition> {
@Override
public IBundleProvider getDocumentForComposition(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdate, SortSpec theSort, RequestDetails theRequestDetails) {

View File

@ -1,51 +0,0 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.validation.IValidatorModule;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 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%
*/
public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResourceDao<T> {
@Autowired
@Qualifier("myInstanceValidatorDstu2")
private IValidatorModule myInstanceValidator;
@Override
protected IValidatorModule getInstanceValidator() {
return myInstanceValidator;
}
@Override
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
oo.getIssueFirstRep().getDiagnosticsElement().setValue(theMessage);
oo.getIssueFirstRep().getCodeElement().setValue(theCode);
return oo;
}
}

View File

@ -36,7 +36,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringParam;
public class FhirResourceDaoEncounterDstu2 extends FhirResourceDaoDstu2<Encounter>implements IFhirResourceDaoEncounter<Encounter> {
public class FhirResourceDaoEncounterDstu2 extends BaseHapiFhirResourceDao<Encounter>implements IFhirResourceDaoEncounter<Encounter> {
@Override
public IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort) {

View File

@ -25,7 +25,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import org.hl7.fhir.instance.model.api.IBaseBundle;
public class FhirResourceDaoMessageHeaderDstu2 extends FhirResourceDaoDstu2<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
public class FhirResourceDaoMessageHeaderDstu2 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
public static IBaseBundle throwProcessMessageNotImplemented() {
throw new NotImplementedOperationException("This operation is not yet implemented on this server");

View File

@ -37,7 +37,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> {
public class FhirResourceDaoPatientDstu2 extends BaseHapiFhirResourceDao<Patient>implements IFhirResourceDaoPatient<Patient> {
public FhirResourceDaoPatientDstu2() {
super();

View File

@ -22,6 +22,6 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDstu2<QuestionnaireResponse> {
public class FhirResourceDaoQuestionnaireResponseDstu2 extends BaseHapiFhirResourceDao<QuestionnaireResponse> {
// nothing
}

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
@ -35,10 +36,12 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
@Autowired
private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
@ -77,7 +80,7 @@ public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<Se
FhirContext context = getContext();
SearchParamTypeEnum type = theResource.getTypeElement().getValueAsEnum();
FhirResourceDaoSearchParameterR4.validateSearchParam(type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
}

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
public class FhirResourceDaoStructureDefinitionDstu2 extends FhirResourceDaoDstu2<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
public class FhirResourceDaoStructureDefinitionDstu2 extends BaseHapiFhirResourceDao<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
@Override
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theWebUrl, String theName) {
// FIXME: implement

View File

@ -38,7 +38,7 @@ import java.util.Date;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
public class FhirResourceDaoSubscriptionDstu2 extends BaseHapiFhirResourceDao<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
@Autowired
private ISubscriptionTableDao mySubscriptionTableDao;
@ -83,55 +83,5 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
return retVal;
}
public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(Subscription theResource) {
if (theResource.getStatus() == null) {
throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
}
String query = theResource.getCriteria();
if (isBlank(query)) {
throw new UnprocessableEntityException("Subscription.criteria must be populated");
}
int sep = query.indexOf('?');
if (sep <= 1) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
String resType = query.substring(0, sep);
if (resType.contains("/")) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
RuntimeResourceDefinition resDef;
try {
resDef = getContext().getResourceDefinition(resType);
} catch (DataFormatException e) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
}
return resDef;
}
@Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);
IFhirResourceDao<? extends IBaseResource> dao = getDao(resDef.getImplementingClass());
if (dao == null) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resDef);
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
}
SubscriptionStatusEnum status = theResource.getStatusElement().getValueAsEnum();
if (status == null) {
throw new UnprocessableEntityException("Subscription.status must be populated on this server");
}
}
}

View File

@ -57,7 +57,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueSet>
implements IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>, IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt> {
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;

View File

@ -0,0 +1,13 @@
package ca.uhn.fhir.jpa.dao;
import org.hl7.fhir.instance.model.api.IBaseResource;
/**
* Standard resource DAO
* @param <T> The resource type
*/
public class JpaResourceDao<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> {
// nothing yet
}

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
@ -29,7 +30,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleDstu3 extends FhirResourceDaoDstu3<Bundle> {
public class FhirResourceDaoBundleDstu3 extends BaseHapiFhirResourceDao<Bundle> {
@Override
protected void preProcessResourceForStorage(Bundle theResource) {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
@ -50,7 +51,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemDstu3.class);

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoComposition;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IResource;
@ -35,7 +36,7 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
public class FhirResourceDaoCompositionDstu3 extends FhirResourceDaoDstu3<Composition> implements IFhirResourceDaoComposition<Composition> {
public class FhirResourceDaoCompositionDstu3 extends BaseHapiFhirResourceDao<Composition> implements IFhirResourceDaoComposition<Composition> {
@Override
public IBundleProvider getDocumentForComposition(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdate, SortSpec theSort, RequestDetails theRequestDetails) {

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.term.TranslationMatch;
import ca.uhn.fhir.jpa.term.TranslationRequest;
@ -42,7 +43,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FhirResourceDaoConceptMapDstu3 extends FhirResourceDaoDstu3<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
public class FhirResourceDaoConceptMapDstu3 extends BaseHapiFhirResourceDao<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;

View File

@ -1,65 +0,0 @@
package ca.uhn.fhir.jpa.dao.dstu3;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 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 ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.validation.IValidationContext;
import ca.uhn.fhir.validation.IValidatorModule;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirResourceDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3.class);
@Autowired()
@Qualifier("myInstanceValidatorDstu3")
private IValidatorModule myInstanceValidator;
@Override
protected IValidatorModule getInstanceValidator() {
return myInstanceValidator;
}
@Override
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
OperationOutcomeIssueComponent issue = oo.addIssue();
issue.getSeverityElement().setValueAsString(theSeverity);
issue.setDiagnostics(theMessage);
try {
issue.setCode(org.hl7.fhir.dstu3.model.OperationOutcome.IssueType.fromCode(theCode));
} catch (FHIRException e) {
ourLog.error("Unknown code: {}", theCode);
}
return oo;
}
}

View File

@ -24,6 +24,7 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.dstu3.model.Encounter;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -37,7 +38,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringParam;
public class FhirResourceDaoEncounterDstu3 extends FhirResourceDaoDstu3<Encounter>implements IFhirResourceDaoEncounter<Encounter> {
public class FhirResourceDaoEncounterDstu3 extends BaseHapiFhirResourceDao<Encounter> implements IFhirResourceDaoEncounter<Encounter> {
@Override
public IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort) {

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import org.hl7.fhir.dstu3.model.MessageHeader;
public class FhirResourceDaoMessageHeaderDstu3 extends FhirResourceDaoDstu3<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
public class FhirResourceDaoMessageHeaderDstu3 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
// nothing right now
}

View File

@ -39,7 +39,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*;
public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>implements IFhirResourceDaoPatient<Patient> {
public class FhirResourceDaoPatientDstu3 extends BaseHapiFhirResourceDao<Patient>implements IFhirResourceDaoPatient<Patient> {
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, StringAndListParam theFilter, RequestDetails theRequest) {
SearchParameterMap paramMap = new SearchParameterMap();

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
public class FhirResourceDaoQuestionnaireResponseDstu3 extends FhirResourceDaoDstu3<QuestionnaireResponse> {
public class FhirResourceDaoQuestionnaireResponseDstu3 extends BaseHapiFhirResourceDao<QuestionnaireResponse> {
// @Override

View File

@ -1,9 +1,9 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.hl7.fhir.dstu3.model.*;
@ -31,7 +31,10 @@ import java.util.List;
* #L%
*/
public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public class FhirResourceDaoSearchParameterDstu3 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
@ -68,7 +71,7 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
FhirContext context = getContext();
Enumerations.SearchParamType type = theResource.getType();
FhirResourceDaoSearchParameterR4.validateSearchParam(type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
}
}

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoStructureDefinition;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
@ -26,7 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
* #L%
*/
public class FhirResourceDaoStructureDefinitionDstu3 extends FhirResourceDaoDstu3<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
public class FhirResourceDaoStructureDefinitionDstu3 extends BaseHapiFhirResourceDao<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
@Autowired
private IValidationSupport myValidationSupport;

View File

@ -20,39 +20,24 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L%
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.apache.commons.lang3.ObjectUtils;
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.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import java.util.Date;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoSubscriptionDstu3.class);
public class FhirResourceDaoSubscriptionDstu3 extends BaseHapiFhirResourceDao<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
@Autowired
private ISubscriptionTableDao mySubscriptionTableDao;
@Autowired
private PlatformTransactionManager myTxManager;
private void createSubscriptionTable(ResourceTable theEntity, Subscription theSubscription) {
SubscriptionTable subscriptionEntity = new SubscriptionTable();
subscriptionEntity.setCreated(new Date());
@ -71,8 +56,6 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
}
@Override
protected void postPersist(ResourceTable theEntity, Subscription theSubscription) {
super.postPersist(theEntity, theSubscription);
@ -81,7 +64,6 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
}
@Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
@ -93,87 +75,5 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
return retVal;
}
protected void validateChannelEndpoint(Subscription theResource) {
if (isBlank(theResource.getChannel().getEndpoint())) {
throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
}
}
protected void validateChannelPayload(Subscription theResource) {
if (!isBlank(theResource.getChannel().getPayload()) && EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getChannel().getPayload());
}
}
public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(Subscription theResource) {
if (theResource.getStatus() == null) {
throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
}
switch (theResource.getStatus()) {
case REQUESTED:
case ACTIVE:
break;
case ERROR:
case OFF:
case NULL:
return null;
}
String query = theResource.getCriteria();
if (isBlank(query)) {
throw new UnprocessableEntityException("Subscription.criteria must be populated");
}
int sep = query.indexOf('?');
if (sep <= 1) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
String resType = query.substring(0, sep);
if (resType.contains("/")) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated");
} else if (theResource.getChannel().getType() == SubscriptionChannelType.RESTHOOK) {
validateChannelPayload(theResource);
validateChannelEndpoint(theResource);
}
RuntimeResourceDefinition resDef;
try {
resDef = getContext().getResourceDefinition(resType);
} catch (DataFormatException e) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
}
return resDef;
}
@Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);
if (resDef == null) {
return;
}
IFhirResourceDao<? extends IBaseResource> dao = getDao(resDef.getImplementingClass());
if (dao == null) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resDef);
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
}
SubscriptionStatus status = theResource.getStatus();
if (status == null) {
throw new UnprocessableEntityException("Subscription.status must be populated on this server");
}
}
}

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -58,7 +59,7 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
@Autowired
@ -67,13 +68,17 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
@Autowired
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
@Autowired
@Qualifier("myJpaValidationSupportChainDstu3")
private IValidationSupport myValidationSupport;
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Override
public void start() {
super.start();
myValidationSupport = getApplicationContext().getBean(org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.class,"myJpaValidationSupportChainDstu3" );
}
@Override
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
ValueSet source = read(theId, theRequestDetails);

View File

@ -88,8 +88,8 @@ public class SearchParamWithInlineReferencesExtractor {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
public void populateFromResource(ResourceIndexedSearchParams theParams, IDao theCallingDao, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams theExistingParams, RequestDetails theRequest) {
mySearchParamExtractorService.extractFromResource(theParams, theEntity, theResource);
public void populateFromResource(ResourceIndexedSearchParams theParams, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams theExistingParams, RequestDetails theRequest) {
mySearchParamExtractorService.extractFromResource(theRequest, theParams, theEntity, theResource);
Set<Map.Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).entrySet();
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleType;
@ -30,7 +31,7 @@ import java.util.TreeSet;
import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleR4 extends FhirResourceDaoR4<Bundle> {
public class FhirResourceDaoBundleR4 extends BaseHapiFhirResourceDao<Bundle> {
@Override
protected void preProcessResourceForStorage(Bundle theResource) {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
@ -49,7 +50,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class);

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoComposition;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IResource;
@ -35,7 +36,7 @@ import org.hl7.fhir.r4.model.Composition;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
public class FhirResourceDaoCompositionR4 extends FhirResourceDaoR4<Composition>implements IFhirResourceDaoComposition<Composition> {
public class FhirResourceDaoCompositionR4 extends BaseHapiFhirResourceDao<Composition> implements IFhirResourceDaoComposition<Composition> {
@Override
public IBundleProvider getDocumentForComposition(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdate, SortSpec theSort, RequestDetails theRequestDetails) {

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
@ -38,7 +39,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FhirResourceDaoConceptMapR4 extends FhirResourceDaoR4<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
public class FhirResourceDaoConceptMapR4 extends BaseHapiFhirResourceDao<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;

View File

@ -24,6 +24,7 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -37,7 +38,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringParam;
public class FhirResourceDaoEncounterR4 extends FhirResourceDaoR4<Encounter>implements IFhirResourceDaoEncounter<Encounter> {
public class FhirResourceDaoEncounterR4 extends BaseHapiFhirResourceDao<Encounter> implements IFhirResourceDaoEncounter<Encounter> {
@Override
public IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort) {

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import org.hl7.fhir.r4.model.MessageHeader;
public class FhirResourceDaoMessageHeaderR4 extends FhirResourceDaoR4<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
public class FhirResourceDaoMessageHeaderR4 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
// nothing right now
}

View File

@ -39,7 +39,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*;
public class FhirResourceDaoPatientR4 extends FhirResourceDaoR4<Patient>implements IFhirResourceDaoPatient<Patient> {
public class FhirResourceDaoPatientR4 extends BaseHapiFhirResourceDao<Patient>implements IFhirResourceDaoPatient<Patient> {
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, StringAndListParam theFilter, RequestDetails theRequest) {
SearchParameterMap paramMap = new SearchParameterMap();

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.r4.model.QuestionnaireResponse;
public class FhirResourceDaoQuestionnaireResponseR4 extends FhirResourceDaoR4<QuestionnaireResponse> {
public class FhirResourceDaoQuestionnaireResponseR4 extends BaseHapiFhirResourceDao<QuestionnaireResponse> {
// @Override

View File

@ -1,83 +0,0 @@
package ca.uhn.fhir.jpa.dao.r4;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 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 ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.delete.DeleteConflictList;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.IValidationContext;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ValidationResult;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.OperationOutcome;
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoR4<T extends IAnyResource> extends BaseHapiFhirResourceDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4.class);
@Autowired()
@Qualifier("myInstanceValidatorR4")
private IValidatorModule myInstanceValidator;
@Override
protected IValidatorModule getInstanceValidator() {
return myInstanceValidator;
}
@Override
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
OperationOutcomeIssueComponent issue = oo.addIssue();
issue.getSeverityElement().setValueAsString(theSeverity);
issue.setDiagnostics(theMessage);
try {
issue.setCode(org.hl7.fhir.r4.model.OperationOutcome.IssueType.fromCode(theCode));
} catch (FHIRException e) {
ourLog.error("Unknown code: {}", theCode);
}
return oo;
}
}

View File

@ -2,11 +2,13 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ElementUtil;
@ -44,11 +46,13 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* #L%
*/
public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public static final DefaultProfileValidationSupport VALIDATION_SUPPORT = new DefaultProfileValidationSupport();
@Autowired
private IFhirSystemDao<Bundle, Meta> mySystemDao;
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
@ -85,10 +89,10 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchPa
FhirContext context = getContext();
Enum<?> type = theResource.getType();
FhirResourceDaoSearchParameterR4.validateSearchParam(type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
}
public static void validateSearchParam(Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
public static void validateSearchParam(ISearchParamExtractor theSearchParamExtractor, Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
if (theStatus == null) {
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
}
@ -110,7 +114,7 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchPa
theExpression = theExpression.trim();
if (!theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
String[] expressionSplit = BaseSearchParamExtractor.SPLIT.split(theExpression);
String[] expressionSplit = theSearchParamExtractor.split(theExpression);
for (String nextPath : expressionSplit) {
nextPath = nextPath.trim();

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoStructureDefinition;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
@ -26,7 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
* #L%
*/
public class FhirResourceDaoStructureDefinitionR4 extends FhirResourceDaoR4<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
public class FhirResourceDaoStructureDefinitionR4 extends BaseHapiFhirResourceDao<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
@Autowired
private IValidationSupport myValidationSupport;

View File

@ -20,30 +20,20 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L%
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.apache.commons.lang3.ObjectUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Subscription;
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nullable;
import java.util.Date;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class FhirResourceDaoSubscriptionR4 extends FhirResourceDaoR4<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
public class FhirResourceDaoSubscriptionR4 extends BaseHapiFhirResourceDao<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
@Autowired
private ISubscriptionTableDao mySubscriptionTableDao;
@ -89,83 +79,4 @@ public class FhirResourceDaoSubscriptionR4 extends FhirResourceDaoR4<Subscriptio
return retVal;
}
protected void validateChannelEndpoint(Subscription theResource) {
if (isBlank(theResource.getChannel().getEndpoint())) {
throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
}
}
protected void validateChannelPayload(Subscription theResource) {
if (!isBlank(theResource.getChannel().getPayload()) && EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getChannel().getPayload());
}
}
@Nullable
public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(Subscription theResource) {
if (theResource.getStatus() == null) {
throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
}
switch (theResource.getStatus()) {
case REQUESTED:
case ACTIVE:
break;
case ERROR:
case OFF:
case NULL:
return null;
}
String query = theResource.getCriteria();
if (isBlank(query)) {
throw new UnprocessableEntityException("Subscription.criteria must be populated");
}
int sep = query.indexOf('?');
if (sep <= 1) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
String resType = query.substring(0, sep);
if (resType.contains("/")) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated");
} else if (theResource.getChannel().getType() == SubscriptionChannelType.RESTHOOK) {
validateChannelPayload(theResource);
validateChannelEndpoint(theResource);
}
RuntimeResourceDefinition resDef;
try {
resDef = getContext().getResourceDefinition(resType);
} catch (DataFormatException e) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
}
return resDef;
}
@Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);
if (resDef == null) {
return;
}
IFhirResourceDao<? extends IBaseResource> dao = getDao(resDef.getImplementingClass());
if (dao == null) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resDef);
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
}
}
}

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -53,7 +54,7 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@ -61,10 +62,14 @@ public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> imple
@Autowired
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
@Autowired
@Qualifier("myJpaValidationSupportChainR4")
private IValidationSupport myValidationSupport;
@Override
public void start() {
super.start();
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class,"myJpaValidationSupportChainR4" );
}
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.r5.model.Bundle;
@ -27,7 +28,7 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
* #L%
*/
public class FhirResourceDaoBundleR5 extends FhirResourceDaoR5<Bundle> {
public class FhirResourceDaoBundleR5 extends BaseHapiFhirResourceDao<Bundle> {
@Override
protected void preProcessResourceForStorage(Bundle theResource) {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.r5;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
@ -49,7 +50,7 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemR5 extends FhirResourceDaoR5<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR5.class);

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoComposition;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.SortSpec;
@ -35,7 +36,7 @@ import org.hl7.fhir.r5.model.Composition;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
public class FhirResourceDaoCompositionR5 extends FhirResourceDaoR5<Composition> implements IFhirResourceDaoComposition<Composition> {
public class FhirResourceDaoCompositionR5 extends BaseHapiFhirResourceDao<Composition> implements IFhirResourceDaoComposition<Composition> {
@Override
public IBundleProvider getDocumentForComposition(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdate, SortSpec theSort, RequestDetails theRequestDetails) {

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
@ -39,7 +40,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FhirResourceDaoConceptMapR5 extends FhirResourceDaoR5<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoEncounter;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
@ -35,7 +36,7 @@ import org.hl7.fhir.r5.model.Encounter;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
public class FhirResourceDaoEncounterR5 extends FhirResourceDaoR5<Encounter> implements IFhirResourceDaoEncounter<Encounter> {
public class FhirResourceDaoEncounterR5 extends BaseHapiFhirResourceDao<Encounter> implements IFhirResourceDaoEncounter<Encounter> {
@Override
public IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort) {

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import org.hl7.fhir.r5.model.MessageHeader;
public class FhirResourceDaoMessageHeaderR5 extends FhirResourceDaoR5<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
public class FhirResourceDaoMessageHeaderR5 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
// nothing right now
}

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
@ -39,7 +40,7 @@ import org.hl7.fhir.r5.model.Patient;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
public class FhirResourceDaoPatientR5 extends FhirResourceDaoR5<Patient> implements IFhirResourceDaoPatient<Patient> {
public class FhirResourceDaoPatientR5 extends BaseHapiFhirResourceDao<Patient> implements IFhirResourceDaoPatient<Patient> {
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequest) {
SearchParameterMap paramMap = new SearchParameterMap();

View File

@ -20,9 +20,10 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L%
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import org.hl7.fhir.r5.model.QuestionnaireResponse;
public class FhirResourceDaoQuestionnaireResponseR5 extends FhirResourceDaoR5<QuestionnaireResponse> {
public class FhirResourceDaoQuestionnaireResponseR5 extends BaseHapiFhirResourceDao<QuestionnaireResponse> {
// @Override

View File

@ -1,61 +0,0 @@
package ca.uhn.fhir.jpa.dao.r5;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 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 ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.validation.IValidatorModule;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class FhirResourceDaoR5<T extends IAnyResource> extends BaseHapiFhirResourceDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR5.class);
@Autowired()
@Qualifier("myInstanceValidatorR5")
private IValidatorModule myInstanceValidator;
@Override
protected IValidatorModule getInstanceValidator() {
return myInstanceValidator;
}
@Override
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
OperationOutcomeIssueComponent issue = oo.addIssue();
issue.getSeverityElement().setValueAsString(theSeverity);
issue.setDiagnostics(theMessage);
try {
issue.setCode(OperationOutcome.IssueType.fromCode(theCode));
} catch (FHIRException e) {
ourLog.error("Unknown code: {}", theCode);
}
return oo;
}
}

View File

@ -2,11 +2,14 @@ package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ElementUtil;
@ -44,11 +47,13 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* #L%
*/
public class FhirResourceDaoSearchParameterR5 extends FhirResourceDaoR5<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public class FhirResourceDaoSearchParameterR5 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
public static final DefaultProfileValidationSupport VALIDATION_SUPPORT = new DefaultProfileValidationSupport();
@Autowired
private IFhirSystemDao<Bundle, Meta> mySystemDao;
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
@ -85,71 +90,8 @@ public class FhirResourceDaoSearchParameterR5 extends FhirResourceDaoR5<SearchPa
FhirContext context = getContext();
Enum<?> type = theResource.getType();
FhirResourceDaoSearchParameterR5.validateSearchParam(type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
}
public static void validateSearchParam(Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
if (theStatus == null) {
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
}
if (ElementUtil.isEmpty(theBase) && (theType == null || !Enumerations.SearchParamType.COMPOSITE.name().equals(theType.name()))) {
throw new UnprocessableEntityException("SearchParameter.base is missing");
}
if (theType != null && theType.name().equals(Enumerations.SearchParamType.COMPOSITE.name()) && isBlank(theExpression)) {
// this is ok
} else if (isBlank(theExpression)) {
throw new UnprocessableEntityException("SearchParameter.expression is missing");
} else {
theExpression = theExpression.trim();
if (!theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R5)) {
String[] expressionSplit = BaseSearchParamExtractor.SPLIT.split(theExpression);
for (String nextPath : expressionSplit) {
nextPath = nextPath.trim();
int dotIdx = nextPath.indexOf('.');
if (dotIdx == -1) {
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name");
}
String resourceName = nextPath.substring(0, dotIdx);
try {
theContext.getResourceDefinition(resourceName);
} catch (DataFormatException e) {
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\": " + e.getMessage());
}
if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
if (theDaoConfig.isValidateSearchParameterExpressionsOnSave()) {
IBaseResource temporaryInstance = theContext.getResourceDefinition(resourceName).newInstance();
try {
theContext.newFluentPath().evaluate(temporaryInstance, nextPath, IBase.class);
} catch (Exception e) {
String msg = theContext.getLocalizer().getMessage(FhirResourceDaoSearchParameterR5.class, "invalidSearchParamExpression", nextPath, e.getMessage());
throw new UnprocessableEntityException(msg, e);
}
}
}
}
} else {
FHIRPathEngine fhirPathEngine = new FHIRPathEngine(new HapiWorkerContext(theContext, VALIDATION_SUPPORT));
try {
fhirPathEngine.parse(theExpression);
} catch (FHIRLexer.FHIRLexerException e) {
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + theExpression + "\": " + e.getMessage());
}
}
} // if have expression
}
}

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoStructureDefinition;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.r5.hapi.ctx.IValidationSupport;
@ -26,7 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
* #L%
*/
public class FhirResourceDaoStructureDefinitionR5 extends FhirResourceDaoR5<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
public class FhirResourceDaoStructureDefinitionR5 extends BaseHapiFhirResourceDao<StructureDefinition> implements IFhirResourceDaoStructureDefinition<StructureDefinition> {
@Autowired
private IValidationSupport myValidationSupport;

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.r5;
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
@ -33,7 +34,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r5.model.Subscription;
import org.hl7.fhir.r5.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.r5.model.codesystems.SubscriptionChannelType;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nullable;
@ -41,7 +42,7 @@ import java.util.Date;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class FhirResourceDaoSubscriptionR5 extends FhirResourceDaoR5<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
public class FhirResourceDaoSubscriptionR5 extends BaseHapiFhirResourceDao<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
@Autowired
private ISubscriptionTableDao mySubscriptionTableDao;
@ -87,83 +88,4 @@ public class FhirResourceDaoSubscriptionR5 extends FhirResourceDaoR5<Subscriptio
return retVal;
}
protected void validateChannelEndpoint(Subscription theResource) {
if (isBlank(theResource.getChannel().getEndpoint())) {
throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
}
}
protected void validateChannelPayload(Subscription theResource) {
if (!isBlank(theResource.getChannel().getPayload()) && EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getChannel().getPayload());
}
}
@Nullable
public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(Subscription theResource) {
if (theResource.getStatus() == null) {
throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
}
switch (theResource.getStatus()) {
case REQUESTED:
case ACTIVE:
break;
case ERROR:
case OFF:
case NULL:
return null;
}
String query = theResource.getCriteria();
if (isBlank(query)) {
throw new UnprocessableEntityException("Subscription.criteria must be populated");
}
int sep = query.indexOf('?');
if (sep <= 1) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
String resType = query.substring(0, sep);
if (resType.contains("/")) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated");
} else if (theResource.getChannel().getType() == SubscriptionChannelType.RESTHOOK) {
validateChannelPayload(theResource);
validateChannelEndpoint(theResource);
}
RuntimeResourceDefinition resDef;
try {
resDef = getContext().getResourceDefinition(resType);
} catch (DataFormatException e) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
}
return resDef;
}
@Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);
if (resDef == null) {
return;
}
IFhirResourceDao<? extends IBaseResource> dao = getDao(resDef.getImplementingClass());
if (dao == null) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resDef);
}
if (theResource.getChannel().getType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
}
}
}

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.r5;
*/
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -53,7 +54,7 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetR5 extends FhirResourceDaoR5<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@ -61,13 +62,17 @@ public class FhirResourceDaoValueSetR5 extends FhirResourceDaoR5<ValueSet> imple
@Autowired
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
@Autowired
@Qualifier("myJpaValidationSupportChainR5")
private IValidationSupport myValidationSupport;
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Override
public void start() {
super.start();
myValidationSupport = getApplicationContext().getBean(org.hl7.fhir.r5.hapi.ctx.IValidationSupport.class,"myJpaValidationSupportChainR5" );
}
@Override
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
ValueSet source = read(theId, theRequestDetails);

View File

@ -148,7 +148,7 @@ public class ResourceReindexingSvcImpl implements IResourceReindexingSvc {
initExecutor();
}
private void initExecutor() {
public void initExecutor() {
// Create the threadpool executor used for reindex jobs
int reindexThreadCount = myDaoConfig.getReindexThreadCount();
RejectedExecutionHandler rejectHandler = new Executors.BlockPolicy();

View File

@ -29,6 +29,8 @@ import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionConstants;
@ -37,6 +39,7 @@ import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchingStrategy;
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionStrategyEvaluator;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.SubscriptionUtil;
@ -58,23 +61,24 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.StringUtils.isBlank;
/**
* Responsible for transitioning subscription resources from REQUESTED to ACTIVE
* Once activated, the subscription is added to the SubscriptionRegistry.
*
* <p>
* Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
*/
@Service
@Lazy
@Interceptor()
public class SubscriptionActivatingInterceptor {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingInterceptor.class);
private static boolean ourWaitForSubscriptionActivationSynchronouslyForUnitTest;
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingInterceptor.class);
@Autowired
private PlatformTransactionManager myTransactionManager;
@Autowired
@ -96,15 +100,10 @@ public class SubscriptionActivatingInterceptor {
public boolean activateOrRegisterSubscriptionIfRequired(final IBaseResource theSubscription) {
// Grab the value for "Subscription.channel.type" so we can see if this
// subscriber applies..
String subscriptionChannelTypeCode = myFhirContext
.newTerser()
.getSingleValueOrNull(theSubscription, SubscriptionConstants.SUBSCRIPTION_TYPE, IPrimitiveType.class)
.getValueAsString();
Subscription.SubscriptionChannelType subscriptionChannelType = Subscription.SubscriptionChannelType.fromCode(subscriptionChannelTypeCode);
CanonicalSubscriptionChannelType subscriptionChannelType = mySubscriptionCanonicalizer.getChannelType(theSubscription);
// Only activate supported subscriptions
if (!myDaoConfig.getSupportedSubscriptionTypes().contains(subscriptionChannelType)) {
if (subscriptionChannelType == null || !myDaoConfig.getSupportedSubscriptionTypes().contains(subscriptionChannelType.toCanonical())) {
return false;
}
@ -180,46 +179,110 @@ public class SubscriptionActivatingInterceptor {
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
}
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
public void addStrategyTagCreated(IBaseResource theResource) {
if (isSubscription(theResource)) {
validateCriteriaAndAddStrategy(theResource);
}
}
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
public void addStrategyTagUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
if (isSubscription(theNewResource)) {
validateCriteriaAndAddStrategy(theNewResource);
}
}
// TODO KHS add third type of strategy DISABLED if that subscription type is disabled on this server
public void validateCriteriaAndAddStrategy(final IBaseResource theResource) {
String criteria = mySubscriptionCanonicalizer.getCriteria(theResource);
try {
SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(criteria);
mySubscriptionCanonicalizer.setMatchingStrategyTag(theResource, strategy);
} catch (InvalidRequestException | DataFormatException e) {
throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + criteria + " " + e.getMessage());
}
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED)
public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
public void resourceUpdatedPreCommit(IBaseResource theOldResource, IBaseResource theNewResource) {
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
public void resourceCreated(IBaseResource theResource) {
public void resourceCreatedPreCommit(IBaseResource theResource) {
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED)
public void resourceDeleted(IBaseResource theResource) {
public void resourceDeletedPreCommit(IBaseResource theResource) {
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE);
}
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
public void resourceCreatedPreStorage(IBaseResource theResource) {
if (isSubscription(theResource)) {
validateSubmittedSubscription(theResource);
}
}
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
public void resourceUpdatedPreStorage(IBaseResource theOldResource, IBaseResource theNewResource) {
if (isSubscription(theNewResource)) {
validateSubmittedSubscription(theNewResource);
}
}
private void validateSubmittedSubscription(IBaseResource theSubscription) {
CanonicalSubscription subscription = mySubscriptionCanonicalizer.canonicalize(theSubscription);
boolean finished = false;
if (subscription.getStatus() == null) {
throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
}
switch (subscription.getStatus()) {
case REQUESTED:
case ACTIVE:
break;
case ERROR:
case OFF:
case NULL:
finished = true;
break;
}
mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, null);
if (!finished) {
String query = subscription.getCriteriaString();
if (isBlank(query)) {
throw new UnprocessableEntityException("Subscription.criteria must be populated");
}
int sep = query.indexOf('?');
if (sep <= 1) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
String resType = query.substring(0, sep);
if (resType.contains("/")) {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
if (subscription.getChannelType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated");
} else if (subscription.getChannelType() == CanonicalSubscriptionChannelType.RESTHOOK) {
validateChannelPayload(subscription);
validateChannelEndpoint(subscription);
}
if (!myDaoRegistry.isResourceTypeSupported(resType)) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
}
try {
SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(query);
mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, strategy);
} catch (InvalidRequestException | DataFormatException e) {
throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + query + " " + e.getMessage());
}
if (subscription.getChannelType() == null) {
throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
}
}
}
private void validateChannelEndpoint(CanonicalSubscription theResource) {
if (isBlank(theResource.getEndpointUrl())) {
throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
}
}
private void validateChannelPayload(CanonicalSubscription theResource) {
if (!isBlank(theResource.getPayloadString()) && EncodingEnum.forContentType(theResource.getPayloadString()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getPayloadString());
}
}
private void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType) {
if (isSubscription(theNewResource)) {
submitResourceModified(new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType));
@ -240,6 +303,7 @@ public class SubscriptionActivatingInterceptor {
case UPDATE:
activateAndRegisterSubscriptionIfRequiredInTransaction(theMsg.getNewPayload(myFhirContext));
break;
case MANUALLY_TRIGGERED:
default:
break;
}
@ -249,7 +313,7 @@ public class SubscriptionActivatingInterceptor {
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
activateOrRegisterSubscriptionIfRequired(theSubscription);
}
});

View File

@ -3,7 +3,7 @@ package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.FhirResourceDaoDstu2;
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3Test;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
@ -359,23 +359,6 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals(ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum.WARNING.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_WARN);
}
@Test
public void testCreateOperationOutcomeError() {
FhirResourceDaoDstu2<Bundle> dao = new FhirResourceDaoDstu2<Bundle>();
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message", "incomplete");
assertEquals(IssueSeverityEnum.ERROR.getCode(), oo.getIssue().get(0).getSeverity());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
assertEquals(IssueTypeEnum.INCOMPLETE_RESULTS, oo.getIssue().get(0).getCodeElement().getValueAsEnum());
}
@Test
public void testCreateOperationOutcomeInfo() {
FhirResourceDaoDstu2<Bundle> dao = new FhirResourceDaoDstu2<Bundle>();
OperationOutcome oo = (OperationOutcome) dao.createInfoOperationOutcome("my message");
assertEquals(IssueSeverityEnum.INFORMATION.getCode(), oo.getIssue().get(0).getSeverity());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
}
@Test
public void testCreateSummaryFails() {
Patient p = new Patient();

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
@ -201,8 +202,13 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
Patient pat = new Patient();
pat.setId("Patient/123");
pat.addName().addFamily(methodName);
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
try {
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
} catch (PreconditionFailedException e) {
// should not happen
IBaseOperationOutcome oo = e.getOperationOutcome();
fail(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));
}
pat.setId("");
try {

View File

@ -1,147 +0,0 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingInterceptor;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.Subscription;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.Query;
import static org.junit.Assert.*;
public class FhirResourceDaoDstu3InvalidSubscriptionTest extends BaseJpaDstu3Test {
@Autowired
private DaoConfig myDaoConfig;
@After
public void afterResetDao() {
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
@Before
public void before() {
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
}
@Test
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.OFF);
s.setCriteria("FOO");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualified();
s = mySubscriptionDao.read(id);
assertEquals("FOO", s.getCriteria());
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
try {
mySubscriptionDao.update(s);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Subscription.criteria must be in the form \"{Resource Type}?[params]\"", e.getMessage());
}
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionMarkedDeleted() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?foo");
final IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
new TransactionTemplate(myTransactionMgr).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Query q = myEntityManager.createNativeQuery("UPDATE HFJ_RESOURCE SET RES_DELETED_AT = RES_UPDATED WHERE RES_ID = " + id.getIdPart());
q.executeUpdate();
}
});
myEntityManager.clear();
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithInvalidCriteria() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setType(Subscription.SubscriptionChannelType.RESTHOOK);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("BLAH");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithNoStatus() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.getChannel().setType(Subscription.SubscriptionChannelType.RESTHOOK);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?active=true");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithNoType() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?foo");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
}

View File

@ -613,24 +613,6 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
}
@Test
public void testCreateOperationOutcomeError() {
FhirResourceDaoDstu3<Bundle> dao = new FhirResourceDaoDstu3<Bundle>();
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message", "incomplete");
assertEquals(IssueSeverity.ERROR.toCode(), oo.getIssue().get(0).getSeverity().toCode());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
assertEquals(IssueType.INCOMPLETE, oo.getIssue().get(0).getCode());
}
@Test
public void testCreateOperationOutcomeInfo() {
FhirResourceDaoDstu3<Bundle> dao = new FhirResourceDaoDstu3<Bundle>();
OperationOutcome oo = (OperationOutcome) dao.createInfoOperationOutcome("my message");
assertEquals(IssueSeverity.INFORMATION.toCode(), oo.getIssue().get(0).getSeverity().toCode());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
assertEquals(IssueType.INFORMATIONAL, oo.getIssue().get(0).getCode());
}
@Test
public void testCreateReferenceToDeletedResource() {
Organization org = new Organization();

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingInterceptor;
import ca.uhn.fhir.jpa.subscription.SubscriptionTestUtil;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
@ -11,6 +12,7 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@ -21,6 +23,9 @@ import static org.junit.Assert.*;
public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
@Autowired
private SubscriptionTestUtil mySubscriptionTestUtil;
@After
public void afterResetDao() {
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
@ -33,6 +38,18 @@ public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
}
@After
public void afterUnregisterRestHookListener() {
mySubscriptionTestUtil.unregisterSubscriptionInterceptor();
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
}
@Before
public void beforeRegisterRestHookListener() {
mySubscriptionTestUtil.registerRestHookInterceptor();
}
@Test
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
Subscription s = new Subscription();
@ -52,88 +69,6 @@ public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
}
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionMarkedDeleted() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?foo");
final IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
new TransactionTemplate(myTransactionMgr).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Query q = myEntityManager.createNativeQuery("UPDATE HFJ_RESOURCE SET RES_DELETED_AT = RES_UPDATED WHERE RES_ID = " + id.getIdPart());
q.executeUpdate();
}
});
myEntityManager.clear();
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithInvalidCriteria() throws InterruptedException {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setType(Subscription.SubscriptionChannelType.RESTHOOK);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("BLAH");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithNoStatus() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.getChannel().setType(Subscription.SubscriptionChannelType.RESTHOOK);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?active=true");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
/**
* Make sure that bad data in the database doesn't prevent startup
*/
@Test
public void testSubscriptionWithNoType() {
BaseHapiFhirDao.setValidationDisabledForUnitTest(true);
Subscription s = new Subscription();
s.setStatus(Subscription.SubscriptionStatus.REQUESTED);
s.getChannel().setEndpoint("http://foo");
s.getChannel().setPayload("application/fhir+json");
s.setCriteria("Patient?foo");
IIdType id = mySubscriptionDao.create(s).getId().toUnqualifiedVersionless();
assertNotNull(id.getIdPart());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -794,10 +794,10 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
List<ResourceIndexedSearchParamNumber> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
ourLog.info(toStringMultiline(results));
ResourceIndexedSearchParamNumber expect0 = new ResourceIndexedSearchParamNumber(RiskAssessment.SP_PROBABILITY, new BigDecimal("1.00"));
ResourceIndexedSearchParamNumber expect0 = new ResourceIndexedSearchParamNumber("RiskAssessment", RiskAssessment.SP_PROBABILITY, new BigDecimal("1.00"));
expect0.setResource(resource);
expect0.calculateHashes();
ResourceIndexedSearchParamNumber expect1 = new ResourceIndexedSearchParamNumber(RiskAssessment.SP_PROBABILITY, new BigDecimal("2.00"));
ResourceIndexedSearchParamNumber expect1 = new ResourceIndexedSearchParamNumber("RiskAssessment", RiskAssessment.SP_PROBABILITY, new BigDecimal("2.00"));
expect1.setResource(resource);
expect1.calculateHashes();
@ -1142,6 +1142,10 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
SearchParameterMap params = new SearchParameterMap();
assertThat(toUnqualifiedVersionlessIds(mySubscriptionDao.search(params)), contains(id));
params = new SearchParameterMap();
params.add(Subscription.SP_TYPE, new TokenParam(null, SubscriptionChannelType.WEBSOCKET.toCode()));
assertThat(toUnqualifiedVersionlessIds(mySubscriptionDao.search(params)), contains(id));
params = new SearchParameterMap();
params.add(Subscription.SP_TYPE, new TokenParam(null, SubscriptionChannelType.WEBSOCKET.toCode()));
params.add(Subscription.SP_STATUS, new TokenParam(null, SubscriptionStatus.ACTIVE.toCode()));
@ -1173,7 +1177,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
{
TokenParam v0 = new TokenParam("foo", "testSearchCompositeParamN01");
StringParam v1 = new StringParam("testSearchCompositeParamS01");
CompositeParam<TokenParam, StringParam> val = new CompositeParam<TokenParam, StringParam>(v0, v1);
CompositeParam<TokenParam, StringParam> val = new CompositeParam<>(v0, v1);
IBundleProvider result = myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE_VALUE_STRING, val));
assertEquals(1, result.size().intValue());
assertEquals(id1.toUnqualifiedVersionless(), result.getResources(0, 1).get(0).getIdElement().toUnqualifiedVersionless());

View File

@ -652,10 +652,10 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
List<ResourceIndexedSearchParamNumber> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
ourLog.info(toStringMultiline(results));
ResourceIndexedSearchParamNumber expect0 = new ResourceIndexedSearchParamNumber(RiskAssessment.SP_PROBABILITY, new BigDecimal("1.00"));
ResourceIndexedSearchParamNumber expect0 = new ResourceIndexedSearchParamNumber("RiskAssessment", RiskAssessment.SP_PROBABILITY, new BigDecimal("1.00"));
expect0.setResource(resource);
expect0.calculateHashes();
ResourceIndexedSearchParamNumber expect1 = new ResourceIndexedSearchParamNumber(RiskAssessment.SP_PROBABILITY, new BigDecimal("2.00"));
ResourceIndexedSearchParamNumber expect1 = new ResourceIndexedSearchParamNumber("RiskAssessment", RiskAssessment.SP_PROBABILITY, new BigDecimal("2.00"));
expect1.setResource(resource);
expect1.calculateHashes();

View File

@ -1,9 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
@ -769,7 +766,8 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
@Test
public void testCreateOperationOutcomeError() {
FhirResourceDaoR4<Bundle> dao = new FhirResourceDaoR4<Bundle>();
JpaResourceDao<Bundle> dao = new JpaResourceDao<Bundle>();
dao.setContext(myFhirCtx);
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message", "incomplete");
assertEquals(IssueSeverity.ERROR.toCode(), oo.getIssue().get(0).getSeverity().toCode());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
@ -778,7 +776,8 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
@Test
public void testCreateOperationOutcomeInfo() {
FhirResourceDaoR4<Bundle> dao = new FhirResourceDaoR4<Bundle>();
JpaResourceDao<Bundle> dao = new JpaResourceDao<Bundle>();
dao.setContext(myFhirCtx);
OperationOutcome oo = (OperationOutcome) dao.createInfoOperationOutcome("my message");
assertEquals(IssueSeverity.INFORMATION.toCode(), oo.getIssue().get(0).getSeverity().toCode());
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());

View File

@ -9,10 +9,12 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.SpringObjectCaster;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
@ -30,7 +32,9 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.ProxyUtils;
import org.springframework.test.context.TestPropertySource;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
@ -64,11 +68,15 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
private List<String> myMessages = new ArrayList<>();
@After
public void after() {
public void after() throws Exception {
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave());
myDaoConfig.setSchedulingDisabled(new DaoConfig().isSchedulingDisabled());
myDaoConfig.setUniqueIndexesEnabled(new DaoConfig().isUniqueIndexesEnabled());
myDaoConfig.setReindexThreadCount(new DaoConfig().getReindexThreadCount());
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
svc.initExecutor();
}
@Before
@ -647,8 +655,15 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
}
@Test
public void testDuplicateUniqueValuesAreReIndexed() {
public void testDuplicateUniqueValuesAreReIndexed() throws Exception {
myDaoConfig.setSchedulingDisabled(true);
myDaoConfig.setReindexThreadCount(1);
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
svc.initExecutor();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
assertEquals(0, uniqueSearchParams.size());
Patient pt1 = new Patient();
pt1.setActive(true);
@ -676,7 +691,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
createUniqueObservationSubjectDateCode();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
assertEquals(1, uniqueSearchParams.size());
assertEquals(3, uniqueSearchParams.get(0).getComponents().size());
@ -685,12 +700,14 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
assertEquals(1, myResourceReindexingSvc.forceReindexingPass());
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
assertEquals(uniques.toString(), 1, uniques.size());
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
runInTransaction(()->{
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
assertEquals(uniques.toString(), 1, uniques.size());
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
myResourceIndexedCompositeStringUniqueDao.deleteAll();
myResourceIndexedCompositeStringUniqueDao.deleteAll();
});
assertEquals(1, mySearchParamRegistry.getActiveUniqueSearchParams("Observation").size());
@ -700,10 +717,12 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
myResourceReindexingSvc.forceReindexingPass();
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
assertEquals(uniques.toString(), 1, uniques.size());
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
runInTransaction(()->{
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
assertEquals(uniques.toString(), 1, uniques.size());
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
});
}

View File

@ -9,25 +9,35 @@ import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.SearchParameter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@RunWith(MockitoJUnitRunner.class)
public class FhirResourceDaoSearchParameterR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoSearchParameterR4Test.class);
private FhirContext myCtx;
private FhirResourceDaoSearchParameterR4 myDao;
@Mock
private ApplicationContext myApplicationContext;
@Before
public void before() {
myCtx = FhirContext.forR4();
myDao = new FhirResourceDaoSearchParameterR4();
myDao.setContext(myCtx);
myDao.setConfig(new DaoConfig());
myDao.setApplicationContext(myApplicationContext);
myDao.start();
}

View File

@ -37,64 +37,7 @@ public class SearchParamExtractorR4Test {
@Before
public void before() {
mySearchParamRegistry = new ISearchParamRegistry() {
@Override
public void forceRefresh() {
// nothing
}
@Override
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
return getActiveSearchParams(theResourceName).get(theParamName);
}
@Override
public boolean refreshCacheIfNecessary() {
// nothing
return false;
}
@Override
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
throw new UnsupportedOperationException();
}
@Override
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
Map<String, RuntimeSearchParam> sps = new HashMap<>();
RuntimeResourceDefinition nextResDef = ourCtx.getResourceDefinition(theResourceName);
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
sps.put(nextSp.getName(), nextSp);
}
return sps;
}
@Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException();
}
@Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
throw new UnsupportedOperationException();
}
@Override
public void requestRefresh() {
// nothing
}
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
return null;
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
};
mySearchParamRegistry = new MySearchParamRegistry();
}
@ -104,7 +47,7 @@ public class SearchParamExtractorR4Test {
obs.addCategory().addCoding().setSystem("SYSTEM").setCode("CODE");
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(new ResourceTable(), obs);
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs);
assertEquals(1, tokens.size());
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
assertEquals("category", token.getParamName());
@ -112,6 +55,20 @@ public class SearchParamExtractorR4Test {
assertEquals("CODE", token.getValue());
}
@Test
public void testTokenOnSearchParamContext() {
SearchParameter sp = new SearchParameter();
sp.addUseContext().setCode(new Coding().setSystem("http://system").setCode("code"));
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(sp);
assertEquals(1, tokens.size());
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
assertEquals("context-type", token.getParamName());
assertEquals("http://system", token.getSystem());
assertEquals("code", token.getValue());
}
@Test
public void testReferenceWithResolve() {
Encounter enc = new Encounter();
@ -166,11 +123,70 @@ public class SearchParamExtractorR4Test {
.setValue(new Quantity().setSystem("http://bar").setCode("code2").setValue(200));
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
Set<ResourceIndexedSearchParamQuantity> links = extractor.extractSearchParamQuantity(new ResourceTable(), o1);
Set<ResourceIndexedSearchParamQuantity> links = extractor.extractSearchParamQuantity(o1);
ourLog.info("Links:\n {}", links.stream().map(t -> t.toString()).collect(Collectors.joining("\n ")));
assertEquals(4, links.size());
}
private static class MySearchParamRegistry implements ISearchParamRegistry {
@Override
public void forceRefresh() {
// nothing
}
@Override
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
return getActiveSearchParams(theResourceName).get(theParamName);
}
@Override
public boolean refreshCacheIfNecessary() {
// nothing
return false;
}
@Override
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
throw new UnsupportedOperationException();
}
@Override
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
Map<String, RuntimeSearchParam> sps = new HashMap<>();
RuntimeResourceDefinition nextResDef = ourCtx.getResourceDefinition(theResourceName);
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
sps.put(nextSp.getName(), nextSp);
}
return sps;
}
@Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException();
}
@Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
throw new UnsupportedOperationException();
}
@Override
public void requestRefresh() {
// nothing
}
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
return null;
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -186,9 +186,6 @@ public abstract class BaseJpaR5Test extends BaseJpaTest {
@Qualifier("myLocationDaoR5")
protected IFhirResourceDao<Location> myLocationDao;
@Autowired
@Qualifier("myMediaDaoR5")
protected IFhirResourceDao<Media> myMediaDao;
@Autowired
@Qualifier("myMedicationAdministrationDaoR5")
protected IFhirResourceDao<MedicationAdministration> myMedicationAdministrationDao;
@Autowired

View File

@ -47,7 +47,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
public void testValidateCodeOperationByCodeAndSystemInstance() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
@ -55,7 +54,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
@ -65,7 +63,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
public void testValidateCodeOperationByCodeAndSystemType() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
@ -73,7 +70,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "code", new CodeDt("8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
@ -83,7 +79,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
public void testLookupOperationByCodeAndSystem() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
@ -91,7 +86,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "code", new CodeDt("8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
@ -107,7 +101,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
@Ignore
public void testLookupOperationForBuiltInCode() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
@ -115,7 +108,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "code", new CodeDt("M"))
.andParameter("system", new UriDt("http://hl7.org/fhir/v3/MaritalStatus"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
@ -130,14 +122,12 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
public void testLookupOperationByCoding() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
@ -152,7 +142,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
@Test
public void testLookupOperationByInvalidCombination() {
//@formatter:off
try {
ourClient
.operation()
@ -166,12 +155,10 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage());
}
//@formatter:on
}
@Test
public void testLookupOperationByInvalidCombination2() {
//@formatter:off
try {
ourClient
.operation()
@ -184,12 +171,10 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage());
}
//@formatter:on
}
@Test
public void testLookupOperationByInvalidCombination3() {
//@formatter:off
try {
ourClient
.operation()
@ -201,12 +186,10 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: No code, coding, or codeableConcept provided to validate", e.getMessage());
}
//@formatter:on
}
@Test
public void testExpandById() throws IOException {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
@ -214,11 +197,9 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withNoParameters(Parameters.class)
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
// @formatter:off
assertThat(resp,
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
"<expansion>",
@ -234,13 +215,11 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
"</contains>",
"</expansion>"
));
//@formatter:on
/*
* Filter with display name
*/
//@formatter:off
respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
@ -248,22 +227,18 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "filter", new StringDt("systolic"))
.execute();
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
/*
* Filter with code
*/
//@formatter:off
respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
@ -271,19 +246,15 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.withParameter(Parameters.class, "filter", new StringDt("11378"))
.execute();
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
}
@Test
public void testExpandByIdentifier() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
@ -292,15 +263,12 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.andParameter("filter", new StringDt("11378"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
@ -309,7 +277,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
public void testExpandByValueSet() throws IOException {
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
@ -318,22 +285,18 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
.andParameter("filter", new StringDt("11378"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
@Test
public void testExpandInvalidParams() throws IOException {
//@formatter:off
try {
ourClient
.operation()
@ -345,9 +308,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request", e.getMessage());
}
//@formatter:on
//@formatter:off
try {
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
ourClient
@ -361,9 +322,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.", e.getMessage());
}
//@formatter:on
//@formatter:off
try {
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
ourClient
@ -377,7 +336,6 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.", e.getMessage());
}
//@formatter:on
}

View File

@ -22,6 +22,7 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.codesystems.SubscriptionChannelType;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -120,14 +121,19 @@ public abstract class BaseSubscriptionsR5Test extends BaseResourceProviderR5Test
}
protected Subscription newSubscription(String theCriteria, String thePayload) {
Topic topic = new Topic();
topic.getResourceTrigger().getQueryCriteria().setCurrent(theCriteria);
Subscription subscription = new Subscription();
subscription.getTopic().setResource(topic);
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED);
subscription.setCriteria(theCriteria);
Subscription.SubscriptionChannelComponent channel = subscription.getChannel();
channel.setType(Subscription.SubscriptionChannelType.RESTHOOK);
channel.setPayload(thePayload);
channel.getType().addCoding()
.setSystem(SubscriptionChannelType.RESTHOOK.getSystem())
.setCode(SubscriptionChannelType.RESTHOOK.toCode());
channel.getPayload().setContentType(thePayload);
channel.setEndpoint(ourListenerServerBase);
return subscription;
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.jpa.subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptor;
@ -11,14 +13,15 @@ public class CountingInterceptor implements ChannelInterceptor {
private List<String> mySent = new ArrayList<>();
public int getSentCount() {
return mySent.size();
public int getSentCount(String theContainingKeyword) {
return (int)mySent.stream().filter(t -> t.contains(theContainingKeyword)).count();
}
private static final Logger ourLog = LoggerFactory.getLogger(CountingInterceptor.class);
@Override
public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
if (sent) {
mySent.add(message.toString());
public void afterSendCompletion(Message<?> theMessage, MessageChannel theChannel, boolean theSent, Exception theException) {
ourLog.info("Counting another instance: {}", theMessage);
if (theSent) {
mySent.add(theMessage.toString());
}
}

View File

@ -305,9 +305,9 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test {
.addExtension(JpaConstants.EXT_SUBSCRIPTION_RESTHOOK_STRIP_VERSION_IDS, new BooleanType("true"));
ourLog.info("** About to update subscription");
int modCount = myCountingInterceptor.getSentCount();
int modCount = (int) myCountingInterceptor.getSentCount("Subscription");
ourClient.update().resource(subscription1).execute();
waitForSize(modCount + 1, () -> myCountingInterceptor.getSentCount(), () -> myCountingInterceptor.toString());
waitForSize(modCount + 2, () -> myCountingInterceptor.getSentCount("Subscription"), () -> myCountingInterceptor.toString());
ourLog.info("** About to send observation");
Observation observation2 = sendObservation(code, "SNOMED-CT");

View File

@ -303,9 +303,10 @@ public class RestHookTestR5Test extends BaseSubscriptionsR5Test {
.addExtension(JpaConstants.EXT_SUBSCRIPTION_RESTHOOK_STRIP_VERSION_IDS, new BooleanType("true"));
ourLog.info("** About to update subscription");
int modCount = myCountingInterceptor.getSentCount();
int modCount = myCountingInterceptor.getSentCount("Subscription");
ourLog.info("** About to send another...");
ourClient.update().resource(subscription1).execute();
waitForSize(modCount + 1, () -> myCountingInterceptor.getSentCount(), () -> myCountingInterceptor.toString());
waitForSize(modCount + 2, () -> myCountingInterceptor.getSentCount("Subscription"), () -> myCountingInterceptor.toString());
ourLog.info("** About to send observation");
Observation observation2 = sendObservation(code, "SNOMED-CT");
@ -438,7 +439,9 @@ public class RestHookTestR5Test extends BaseSubscriptionsR5Test {
Subscription subscriptionTemp = ourClient.read(Subscription.class, subscription2.getId());
Assert.assertNotNull(subscriptionTemp);
subscriptionTemp.setCriteria(criteria1);
Topic topic = (Topic) subscriptionTemp.getTopic().getResource();
topic.getResourceTrigger().getQueryCriteria().setCurrent(criteria1);
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
waitForQueueToDrain();
@ -518,7 +521,9 @@ public class RestHookTestR5Test extends BaseSubscriptionsR5Test {
Subscription subscriptionTemp = ourClient.read(Subscription.class, subscription2.getId());
Assert.assertNotNull(subscriptionTemp);
subscriptionTemp.setCriteria(criteria1);
Topic topic = (Topic) subscriptionTemp.getTopic().getResource();
topic.getResourceTrigger().getQueryCriteria().setCurrent(criteria1);
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
waitForQueueToDrain();
@ -593,7 +598,8 @@ public class RestHookTestR5Test extends BaseSubscriptionsR5Test {
Subscription subscriptionTemp = ourClient.read(Subscription.class, subscription2.getId());
Assert.assertNotNull(subscriptionTemp);
subscriptionTemp.setCriteria(criteria1);
Topic topic = (Topic) subscriptionTemp.getTopic().getResource();
topic.getResourceTrigger().getQueryCriteria().setCurrent(criteria1);
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
waitForQueueToDrain();
@ -719,7 +725,10 @@ public class RestHookTestR5Test extends BaseSubscriptionsR5Test {
Subscription subscriptionTemp = ourClient.read().resource(Subscription.class).withId(subscription2.getId()).execute();
Assert.assertNotNull(subscriptionTemp);
String criteriaGood = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
subscriptionTemp.setCriteria(criteriaGood);
Topic topic = (Topic) subscriptionTemp.getTopic().getResource();
topic.getResourceTrigger().getQueryCriteria().setCurrent(criteriaGood);
ourLog.info("** About to update subscription");
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
waitForQueueToDrain();

View File

@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.provider.BaseResourceProviderDstu2Test;
import ca.uhn.fhir.jpa.subscription.SubscriptionTestUtil;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.resource.Observation;
@ -19,7 +20,9 @@ import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.test.utilities.JettyUtil;
import ca.uhn.fhir.util.TestUtil;
import com.google.common.collect.Lists;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
@ -31,6 +34,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.fail;
/**
* Test the rest-hook subscriptions
*/
@ -43,7 +48,8 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
private static Server ourListenerServer;
private static String ourListenerServerBase;
private static List<Observation> ourUpdatedObservations = Collections.synchronizedList(Lists.newArrayList());
@Autowired
protected SubscriptionRegistry mySubscriptionRegistry;
@Autowired
private SubscriptionTestUtil mySubscriptionTestUtil;
@ -76,6 +82,22 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
mySubscriptionTestUtil.waitForQueueToDrain();
}
protected void waitForActivatedSubscriptionCount(int theSize) throws Exception {
for (int i = 0; ; i++) {
if (i == 10) {
fail("Failed to init subscriptions");
}
try {
mySubscriptionLoader.doSyncSubscriptionsForUnitTest();
break;
} catch (ResourceVersionConflictException e) {
Thread.sleep(250);
}
}
TestUtil.waitForSize(theSize, () -> mySubscriptionRegistry.size());
Thread.sleep(500);
}
private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException {
Subscription subscription = new Subscription();
@ -125,6 +147,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
Subscription subscription1 = createSubscription(criteria1, payload, ourListenerServerBase);
Subscription subscription2 = createSubscription(criteria2, payload, ourListenerServerBase);
waitForActivatedSubscriptionCount(2);
Observation observation1 = sendObservation(code, "SNOMED-CT");
@ -198,11 +221,11 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
Subscription subscription1 = createSubscription(criteria1, payload, ourListenerServerBase);
Subscription subscription2 = createSubscription(criteria2, payload, ourListenerServerBase);
waitForActivatedSubscriptionCount(2);
Observation observation1 = sendObservation(code, "SNOMED-CT");
// Should see 1 subscription notification
waitForQueueToDrain();
waitForSize(0, ourCreatedObservations);
waitForSize(1, ourUpdatedObservations);
@ -302,8 +325,8 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
ourListenerServer.setHandler(proxyHandler);
JettyUtil.startServer(ourListenerServer);
ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer);
ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context";
ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer);
ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context";
}
@AfterClass

View File

@ -57,17 +57,16 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
private String myParamName;
@ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID")
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false)
@ContainedIn
private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false)
@Column(name = "RES_ID", insertable = false, updatable = false, nullable = false)
private Long myResourcePid;
@Field()
@Column(name = "RES_TYPE", nullable = false, length = Constants.MAX_RESOURCE_NAME_LENGTH)
private String myResourceType;
@Field()
@Column(name = "SP_UPDATED", nullable = true) // TODO: make this false after HAPI 2.3
@Temporal(TemporalType.TIMESTAMP)
@ -111,6 +110,10 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
return myResourceType;
}
public void setResourceType(String theResourceType) {
myResourceType = theResourceType;
}
public Date getUpdated() {
return myUpdated;
}
@ -130,6 +133,10 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
public abstract IQueryParameterType toQueryParameterType();
public boolean matches(IQueryParameterType theParam) {
throw new UnsupportedOperationException("No parameter matcher for " + theParam);
}
public static long calculateHashIdentity(String theResourceType, String theParamName) {
return hash(theResourceType, theParamName);
}
@ -154,8 +161,4 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
HashCode hashCode = hasher.hash();
return hashCode.asLong();
}
public boolean matches(IQueryParameterType theParam) {
throw new UnsupportedOperationException("No parameter matcher for "+theParam);
}
}

View File

@ -61,8 +61,9 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
public ResourceIndexedSearchParamCoords() {
}
public ResourceIndexedSearchParamCoords(String theName, double theLatitude, double theLongitude) {
setParamName(theName);
public ResourceIndexedSearchParamCoords(String theResourceType, String theParamName, double theLatitude, double theLongitude) {
setResourceType(theResourceType);
setParamName(theParamName);
setLatitude(theLatitude);
setLongitude(theLongitude);
}
@ -95,19 +96,14 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
}
ResourceIndexedSearchParamCoords obj = (ResourceIndexedSearchParamCoords) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getLatitude(), obj.getLatitude());
b.append(getLongitude(), obj.getLongitude());
b.append(getHashIdentity(), obj.getHashIdentity());
b.append(isMissing(), obj.isMissing());
return b.isEquals();
}
public Long getHashIdentity() {
calculateHashes();
return myHashIdentity;
}
public void setHashIdentity(Long theHashIdentity) {
myHashIdentity = theHashIdentity;
}
@ -145,7 +141,7 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
public int hashCode() {
HashCodeBuilder b = new HashCodeBuilder();
b.append(getParamName());
b.append(getResource());
b.append(getResourceType());
b.append(getLatitude());
b.append(getLongitude());
return b.toHashCode();

View File

@ -77,8 +77,9 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
/**
* Constructor
*/
public ResourceIndexedSearchParamDate(String theName, Date theLow, Date theHigh, String theOriginalValue) {
setParamName(theName);
public ResourceIndexedSearchParamDate(String theResourceType, String theParamName, Date theLow, Date theHigh, String theOriginalValue) {
setResourceType(theResourceType);
setParamName(theParamName);
setValueLow(theLow);
setValueHigh(theHigh);
myOriginalValue = theOriginalValue;
@ -112,20 +113,14 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
}
ResourceIndexedSearchParamDate obj = (ResourceIndexedSearchParamDate) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getTimeFromDate(getValueHigh()), getTimeFromDate(obj.getValueHigh()));
b.append(getTimeFromDate(getValueLow()), getTimeFromDate(obj.getValueLow()));
b.append(getHashIdentity(), obj.getHashIdentity());
b.append(isMissing(), obj.isMissing());
return b.isEquals();
}
public Long getHashIdentity() {
calculateHashes();
return myHashIdentity;
}
public void setHashIdentity(Long theHashIdentity) {
myHashIdentity = theHashIdentity;
}
@ -168,8 +163,8 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
@Override
public int hashCode() {
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());
b.append(getResource());
b.append(getTimeFromDate(getValueHigh()));
b.append(getTimeFromDate(getValueLow()));
return b.toHashCode();

View File

@ -65,7 +65,8 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP
public ResourceIndexedSearchParamNumber() {
}
public ResourceIndexedSearchParamNumber(String theParamName, BigDecimal theValue) {
public ResourceIndexedSearchParamNumber(String theResourceType, String theParamName, BigDecimal theValue) {
setResourceType(theResourceType);
setParamName(theParamName);
setValue(theValue);
}
@ -98,11 +99,10 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP
}
ResourceIndexedSearchParamNumber obj = (ResourceIndexedSearchParamNumber) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getValue(), obj.getValue());
b.append(isMissing(), obj.isMissing());
b.append(getHashIdentity(), obj.getHashIdentity());
return b.isEquals();
}
@ -136,8 +136,8 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP
@Override
public int hashCode() {
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());
b.append(getResource());
b.append(getValue());
b.append(isMissing());
return b.toHashCode();

View File

@ -91,8 +91,9 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
}
public ResourceIndexedSearchParamQuantity(String theParamName, BigDecimal theValue, String theSystem, String theUnits) {
public ResourceIndexedSearchParamQuantity(String theResourceType, String theParamName, BigDecimal theValue, String theSystem, String theUnits) {
this();
setResourceType(theResourceType);
setParamName(theParamName);
setSystem(theSystem);
setValue(theValue);
@ -132,14 +133,12 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
}
ResourceIndexedSearchParamQuantity obj = (ResourceIndexedSearchParamQuantity) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getSystem(), obj.getSystem());
b.append(getUnits(), obj.getUnits());
b.append(getValue(), obj.getValue());
b.append(getHashIdentity(), obj.getHashIdentity());
b.append(getHashIdentitySystemAndUnits(), obj.getHashIdentitySystemAndUnits());
b.append(getHashIdentityAndUnits(), obj.getHashIdentityAndUnits());
b.append(isMissing(), obj.isMissing());
return b.isEquals();
}
@ -210,7 +209,6 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
@Override
public int hashCode() {
calculateHashes();
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());

View File

@ -146,13 +146,15 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
private Long myHashExact;
@Transient
private transient ModelConfig myModelConfig;
public ResourceIndexedSearchParamString() {
super();
}
public ResourceIndexedSearchParamString(ModelConfig theModelConfig, String theName, String theValueNormalized, String theValueExact) {
public ResourceIndexedSearchParamString(ModelConfig theModelConfig, String theResourceType, String theParamName, String theValueNormalized, String theValueExact) {
setModelConfig(theModelConfig);
setParamName(theName);
setResourceType(theResourceType);
setParamName(theParamName);
setValueNormalized(theValueNormalized);
setValueExact(theValueExact);
}
@ -195,8 +197,8 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
}
ResourceIndexedSearchParamString obj = (ResourceIndexedSearchParamString) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getValueExact(), obj.getValueExact());
b.append(getHashIdentity(), obj.getHashIdentity());
b.append(getHashExact(), obj.getHashExact());
@ -265,8 +267,8 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
@Override
public int hashCode() {
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());
b.append(getResource());
b.append(getValueExact());
return b.toHashCode();
}

View File

@ -101,9 +101,10 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
/**
* Constructor
*/
public ResourceIndexedSearchParamToken(String theName, String theSystem, String theValue) {
public ResourceIndexedSearchParamToken(String theResourceType, String theParamName, String theSystem, String theValue) {
super();
setParamName(theName);
setResourceType(theResourceType);
setParamName(theParamName);
setSystem(theSystem);
setValue(theValue);
}
@ -143,14 +144,10 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
}
ResourceIndexedSearchParamToken obj = (ResourceIndexedSearchParamToken) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getSystem(), obj.getSystem());
b.append(getValue(), obj.getValue());
b.append(getHashIdentity(), obj.getHashIdentity());
b.append(getHashSystem(), obj.getHashSystem());
b.append(getHashSystemAndValue(), obj.getHashSystemAndValue());
b.append(getHashValue(), obj.getHashValue());
return b.isEquals();
}
@ -163,11 +160,6 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
myHashSystem = theHashSystem;
}
private Long getHashIdentity() {
calculateHashes();
return myHashIdentity;
}
private void setHashIdentity(Long theHashIdentity) {
myHashIdentity = theHashIdentity;
}
@ -224,8 +216,8 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
public int hashCode() {
calculateHashes();
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());
b.append(getResource());
b.append(getSystem());
b.append(getValue());
return b.toHashCode();
@ -239,8 +231,8 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
b.append("resourceType", getResourceType());
b.append("paramName", getParamName());
b.append("resourceId", getResourcePid());
b.append("system", getSystem());
b.append("value", getValue());
return b.build();
@ -283,7 +275,9 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
}
public static long calculateHashValue(String theResourceType, String theParamName, String theValue) {
return hash(theResourceType, theParamName, trim(theValue));
String value = trim(theValue);
return hash(theResourceType, theParamName, value);
}
}

View File

@ -80,8 +80,9 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
/**
* Constructor
*/
public ResourceIndexedSearchParamUri(String theName, String theUri) {
setParamName(theName);
public ResourceIndexedSearchParamUri(String theResourceType, String theParamName, String theUri) {
setResourceType(theResourceType);
setParamName(theParamName);
setUri(theUri);
}
@ -115,8 +116,8 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
}
ResourceIndexedSearchParamUri obj = (ResourceIndexedSearchParamUri) theObj;
EqualsBuilder b = new EqualsBuilder();
b.append(getResourceType(), obj.getResourceType());
b.append(getParamName(), obj.getParamName());
b.append(getResource(), obj.getResource());
b.append(getUri(), obj.getUri());
b.append(getHashUri(), obj.getHashUri());
b.append(getHashIdentity(), obj.getHashIdentity());
@ -164,8 +165,8 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
@Override
public int hashCode() {
HashCodeBuilder b = new HashCodeBuilder();
b.append(getResourceType());
b.append(getParamName());
b.append(getResource());
b.append(getUri());
b.append(getHashUri());
return b.toHashCode();

View File

@ -35,8 +35,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsTrueForMatchingNullDates() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
assertTrue(param.equals(param2));
assertTrue(param2.equals(param));
@ -45,8 +45,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsTrueForMatchingDates() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", date1B, date2B, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1B, date2B, "SomeValue");
assertTrue(param.equals(param2));
assertTrue(param2.equals(param));
@ -55,8 +55,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsTrueForMatchingTimeStampsThatMatch() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp1B, timestamp2B, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1B, timestamp2B, "SomeValue");
assertTrue(param.equals(param2));
assertTrue(param2.equals(param));
@ -67,8 +67,8 @@ public class ResourceIndexedSearchParamDateTest {
// other will be equivalent but will be a java.sql.Timestamp. Equals should work in both directions.
@Test
public void equalsIsTrueForMixedTimestampsAndDates() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
assertTrue(param.equals(param2));
assertTrue(param2.equals(param));
@ -77,8 +77,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsFalseForNonMatchingDates() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", date2A, date1A, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date2A, date1A, "SomeValue");
assertFalse(param.equals(param2));
assertFalse(param2.equals(param));
@ -87,8 +87,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsFalseForNonMatchingDatesNullCase() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
assertFalse(param.equals(param2));
assertFalse(param2.equals(param));
@ -97,8 +97,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsFalseForNonMatchingTimeStamps() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp2A, timestamp1A, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp1A, "SomeValue");
assertFalse(param.equals(param2));
assertFalse(param2.equals(param));
@ -107,8 +107,8 @@ public class ResourceIndexedSearchParamDateTest {
@Test
public void equalsIsFalseForMixedTimestampsAndDatesThatDoNotMatch() {
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp2A, timestamp1A, "SomeValue");
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp1A, "SomeValue");
assertFalse(param.equals(param2));
assertFalse(param2.equals(param));

Some files were not shown because too many files have changed in this diff Show More