Merge remote-tracking branch 'remotes/origin/master' into expunge-hooks
# Conflicts: # hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java
This commit is contained in:
commit
8d817b364c
|
@ -1401,6 +1401,41 @@ public enum Pointcut {
|
||||||
"ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails"
|
"ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the storage engine is about to reuse the results of
|
||||||
|
* a previously cached search.
|
||||||
|
* <p>
|
||||||
|
* Hooks may accept the following parameters:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* ca.uhn.fhir.jpa.searchparam.SearchParameterMap - Contains the details of the search being checked
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
||||||
|
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||||
|
* pulled out of the servlet request. Note that the bean
|
||||||
|
* properties are not all guaranteed to be populated, depending on how early during processing the
|
||||||
|
* exception occurred. <b>Note that this parameter may be null in contexts where the request is not
|
||||||
|
* known, such as while processing searches</b>
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* ca.uhn.fhir.rest.server.servlet.ServletRequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
||||||
|
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||||
|
* pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will
|
||||||
|
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Hooks should return <code>void</code>.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
JPA_PERFTRACE_SEARCH_REUSING_CACHED(boolean.class,
|
||||||
|
"ca.uhn.fhir.jpa.searchparam.SearchParameterMap",
|
||||||
|
"ca.uhn.fhir.rest.api.server.RequestDetails",
|
||||||
|
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"
|
||||||
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -65,6 +66,7 @@ public abstract class BaseParser implements IParser {
|
||||||
private boolean mySummaryMode;
|
private boolean mySummaryMode;
|
||||||
private boolean mySuppressNarratives;
|
private boolean mySuppressNarratives;
|
||||||
private Set<String> myDontStripVersionsFromReferencesAtPaths;
|
private Set<String> myDontStripVersionsFromReferencesAtPaths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -165,8 +167,6 @@ public abstract class BaseParser implements IParser {
|
||||||
myNext = null;
|
myNext = null;
|
||||||
} else if (!myNext.shouldBeEncoded(theContainedResource)) {
|
} else if (!myNext.shouldBeEncoded(theContainedResource)) {
|
||||||
myNext = null;
|
myNext = null;
|
||||||
} else if (isSummaryMode() && !myNext.getDef().isSummary()) {
|
|
||||||
myNext = null;
|
|
||||||
} else if (myNext.getDef() instanceof RuntimeChildNarrativeDefinition) {
|
} else if (myNext.getDef() instanceof RuntimeChildNarrativeDefinition) {
|
||||||
if (isSuppressNarratives() || isSummaryMode()) {
|
if (isSuppressNarratives() || isSummaryMode()) {
|
||||||
myNext = null;
|
myNext = null;
|
||||||
|
@ -1004,7 +1004,7 @@ public abstract class BaseParser implements IParser {
|
||||||
private final RuntimeResourceDefinition myResDef;
|
private final RuntimeResourceDefinition myResDef;
|
||||||
private final EncodeContext myEncodeContext;
|
private final EncodeContext myEncodeContext;
|
||||||
|
|
||||||
public CompositeChildElement(CompositeChildElement theParent, BaseRuntimeChildDefinition theDef, EncodeContext theEncodeContext) {
|
public CompositeChildElement(CompositeChildElement theParent, @Nullable BaseRuntimeChildDefinition theDef, EncodeContext theEncodeContext) {
|
||||||
myDef = theDef;
|
myDef = theDef;
|
||||||
myParent = theParent;
|
myParent = theParent;
|
||||||
myResDef = null;
|
myResDef = null;
|
||||||
|
@ -1015,7 +1015,9 @@ public abstract class BaseParser implements IParser {
|
||||||
StringBuilder path = theParent.buildPath();
|
StringBuilder path = theParent.buildPath();
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
path.append('.');
|
path.append('.');
|
||||||
|
if (myDef != null) {
|
||||||
path.append(myDef.getElementName());
|
path.append(myDef.getElementName());
|
||||||
|
}
|
||||||
ourLog.trace(" * Next path: {}", path.toString());
|
ourLog.trace(" * Next path: {}", path.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1165,6 +1167,21 @@ public abstract class BaseParser implements IParser {
|
||||||
if (theContainedResource) {
|
if (theContainedResource) {
|
||||||
retVal = !notEncodeForContainedResource.contains(myDef.getElementName());
|
retVal = !notEncodeForContainedResource.contains(myDef.getElementName());
|
||||||
}
|
}
|
||||||
|
if (retVal && isSummaryMode() && (getDef() == null || !getDef().isSummary())) {
|
||||||
|
String resourceName = myEncodeContext.getLeafResourceName();
|
||||||
|
// Technically the spec says we shouldn't include extensions in CapabilityStatement
|
||||||
|
// but we will do so because there are people who depend on this behaviour, at least
|
||||||
|
// as of 2019-07. See
|
||||||
|
// https://github.com/smart-on-fhir/Swift-FHIR/issues/26
|
||||||
|
// for example.
|
||||||
|
if (("Conformance".equals(resourceName) || "CapabilityStatement".equals(resourceName)) &&
|
||||||
|
("extension".equals(myDef.getElementName()) || "extension".equals(myEncodeContext.getLeafElementName())
|
||||||
|
)) {
|
||||||
|
// skip
|
||||||
|
} else {
|
||||||
|
retVal = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -1251,6 +1268,14 @@ public abstract class BaseParser implements IParser {
|
||||||
return myResourcePath;
|
return myResourcePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLeafElementName() {
|
||||||
|
return getPath().get(getPath().size() - 1).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLeafResourceName() {
|
||||||
|
return myResourcePath.get(myResourcePath.size() - 1).getName();
|
||||||
|
}
|
||||||
|
|
||||||
public String getLeafResourcePathFirstField() {
|
public String getLeafResourcePathFirstField() {
|
||||||
String retVal = null;
|
String retVal = null;
|
||||||
for (int i = getPath().size() - 1; i >= 0; i--) {
|
for (int i = getPath().size() - 1; i >= 0; i--) {
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
theListToAddTo.add(null);
|
theListToAddTo.add(null);
|
||||||
}
|
}
|
||||||
if (theListToAddTo.get(valueIdx) == null) {
|
if (theListToAddTo.get(valueIdx) == null) {
|
||||||
theListToAddTo.set(valueIdx, new ArrayList<String>());
|
theListToAddTo.set(valueIdx, new ArrayList<>());
|
||||||
}
|
}
|
||||||
theListToAddTo.get(valueIdx).addAll(theCommentsToAdd);
|
theListToAddTo.get(valueIdx).addAll(theCommentsToAdd);
|
||||||
return true;
|
return true;
|
||||||
|
@ -89,21 +89,34 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?, ?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier, CompositeChildElement theChildElem,
|
private boolean addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?, ?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier, CompositeChildElement theChildElem,
|
||||||
CompositeChildElement theParent) {
|
CompositeChildElement theParent, EncodeContext theEncodeContext, boolean theContainedResource, IBase theContainingElement) {
|
||||||
|
boolean retVal = false;
|
||||||
if (ext.size() > 0) {
|
if (ext.size() > 0) {
|
||||||
|
Boolean encodeExtension = null;
|
||||||
|
for (IBaseExtension<?, ?> next : ext) {
|
||||||
|
|
||||||
|
// Make sure we respect _summary and _elements
|
||||||
|
if (encodeExtension == null) {
|
||||||
|
encodeExtension = isEncodeExtension(theParent, theEncodeContext, theContainedResource, theContainingElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encodeExtension) {
|
||||||
|
HeldExtension extension = new HeldExtension(next, theIsModifier, theChildElem, theParent);
|
||||||
list.ensureCapacity(valueIdx);
|
list.ensureCapacity(valueIdx);
|
||||||
while (list.size() <= valueIdx) {
|
while (list.size() <= valueIdx) {
|
||||||
list.add(null);
|
list.add(null);
|
||||||
}
|
}
|
||||||
if (list.get(valueIdx) == null) {
|
ArrayList<HeldExtension> extensionList = list.get(valueIdx);
|
||||||
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
if (extensionList == null) {
|
||||||
|
extensionList = new ArrayList<>();
|
||||||
|
list.set(valueIdx, extensionList);
|
||||||
}
|
}
|
||||||
for (IBaseExtension<?, ?> next : ext) {
|
extensionList.add(extension);
|
||||||
list.get(valueIdx).add(new HeldExtension(next, theIsModifier, theChildElem, theParent));
|
retVal = true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToHeldIds(int theValueIdx, ArrayList<String> theListToAddTo, String theId) {
|
private void addToHeldIds(int theValueIdx, ArrayList<String> theListToAddTo, String theId) {
|
||||||
|
@ -342,7 +355,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (nextChildElem.getDef().getElementName().equals("extension") || nextChildElem.getDef().getElementName().equals("modifierExtension")
|
if (nextChildElem.getDef().getElementName().equals("extension") || nextChildElem.getDef().getElementName().equals("modifierExtension")
|
||||||
|| nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
|| nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
||||||
if (!haveWrittenExtensions) {
|
if (!haveWrittenExtensions) {
|
||||||
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, myContext.getElementDefinition(theElement.getClass()), theResDef, theResource, nextChildElem, theParent, theEncodeContext);
|
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, myContext.getElementDefinition(theElement.getClass()), theResDef, theResource, nextChildElem, theParent, theEncodeContext, theContainedResource);
|
||||||
haveWrittenExtensions = true;
|
haveWrittenExtensions = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -433,20 +446,20 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (primitive) {
|
if (primitive) {
|
||||||
if (nextValue instanceof ISupportsUndeclaredExtensions) {
|
if (nextValue instanceof ISupportsUndeclaredExtensions) {
|
||||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
||||||
force |= addToHeldExtensions(valueIdx, ext, extensions, false, nextChildElem, theParent);
|
force |= addToHeldExtensions(valueIdx, ext, extensions, false, nextChildElem, theParent, theEncodeContext, theContainedResource, theElement);
|
||||||
|
|
||||||
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
||||||
force |= addToHeldExtensions(valueIdx, ext, modifierExtensions, true, nextChildElem, theParent);
|
force |= addToHeldExtensions(valueIdx, ext, modifierExtensions, true, nextChildElem, theParent, theEncodeContext, theContainedResource, theElement);
|
||||||
} else {
|
} else {
|
||||||
if (nextValue instanceof IBaseHasExtensions) {
|
if (nextValue instanceof IBaseHasExtensions) {
|
||||||
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
|
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
|
||||||
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
||||||
force |= addToHeldExtensions(valueIdx, ext, extensions, false, nextChildElem, theParent);
|
force |= addToHeldExtensions(valueIdx, ext, extensions, false, nextChildElem, theParent, theEncodeContext, theContainedResource, theElement);
|
||||||
}
|
}
|
||||||
if (nextValue instanceof IBaseHasModifierExtensions) {
|
if (nextValue instanceof IBaseHasModifierExtensions) {
|
||||||
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
|
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
|
||||||
List<? extends IBaseExtension<?, ?>> ext = element.getModifierExtension();
|
List<? extends IBaseExtension<?, ?>> ext = element.getModifierExtension();
|
||||||
force |= addToHeldExtensions(valueIdx, ext, extensions, true, nextChildElem, theParent);
|
force |= addToHeldExtensions(valueIdx, ext, extensions, true, nextChildElem, theParent, theEncodeContext, theContainedResource, theElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nextValue.hasFormatComment()) {
|
if (nextValue.hasFormatComment()) {
|
||||||
|
@ -486,6 +499,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!extensions.isEmpty() || !modifierExtensions.isEmpty() || !comments.isEmpty()) {
|
if (!extensions.isEmpty() || !modifierExtensions.isEmpty() || !comments.isEmpty()) {
|
||||||
if (inArray) {
|
if (inArray) {
|
||||||
// If this is a repeatable field, the extensions go in an array too
|
// If this is a repeatable field, the extensions go in an array too
|
||||||
|
@ -541,7 +555,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts, theEncodeContext);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts, theEncodeContext, theContainedResource);
|
||||||
if (inArray) {
|
if (inArray) {
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
|
@ -626,7 +640,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
final List<HeldExtension> extensions = new ArrayList<>(0);
|
final List<HeldExtension> extensions = new ArrayList<>(0);
|
||||||
final List<HeldExtension> modifierExtensions = new ArrayList<>(0);
|
final List<HeldExtension> modifierExtensions = new ArrayList<>(0);
|
||||||
// Undeclared extensions
|
// Undeclared extensions
|
||||||
extractUndeclaredExtensions(theResourceId, extensions, modifierExtensions, null, null);
|
extractUndeclaredExtensions(theResourceId, extensions, modifierExtensions, null, null, theEncodeContext, theContainedResource);
|
||||||
boolean haveExtension = false;
|
boolean haveExtension = false;
|
||||||
if (!extensions.isEmpty()) {
|
if (!extensions.isEmpty()) {
|
||||||
haveExtension = true;
|
haveExtension = true;
|
||||||
|
@ -638,7 +652,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
writeCommentsPreAndPost(theResourceId, theEventWriter);
|
writeCommentsPreAndPost(theResourceId, theEventWriter);
|
||||||
}
|
}
|
||||||
if (haveExtension) {
|
if (haveExtension) {
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
|
@ -741,12 +755,12 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
* called _name): resource extensions, and extension extensions
|
* called _name): resource extensions, and extension extensions
|
||||||
*/
|
*/
|
||||||
private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonLikeWriter theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
|
private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonLikeWriter theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
|
||||||
IBaseResource theResource, CompositeChildElement theChildElem, CompositeChildElement theParent, EncodeContext theEncodeContext) throws IOException {
|
IBaseResource theResource, CompositeChildElement theChildElem, CompositeChildElement theParent, EncodeContext theEncodeContext, boolean theContainedResource) throws IOException {
|
||||||
List<HeldExtension> extensions = new ArrayList<>(0);
|
List<HeldExtension> extensions = new ArrayList<>(0);
|
||||||
List<HeldExtension> modifierExtensions = new ArrayList<>(0);
|
List<HeldExtension> modifierExtensions = new ArrayList<>(0);
|
||||||
|
|
||||||
// Undeclared extensions
|
// Undeclared extensions
|
||||||
extractUndeclaredExtensions(theElement, extensions, modifierExtensions, theChildElem, theParent);
|
extractUndeclaredExtensions(theElement, extensions, modifierExtensions, theChildElem, theParent, theEncodeContext, theContainedResource);
|
||||||
|
|
||||||
// Declared extensions
|
// Declared extensions
|
||||||
if (theElementDef != null) {
|
if (theElementDef != null) {
|
||||||
|
@ -754,7 +768,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the extensions
|
// Write the extensions
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractDeclaredExtensions(IBase theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions,
|
private void extractDeclaredExtensions(IBase theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions,
|
||||||
|
@ -782,7 +796,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractUndeclaredExtensions(IBase theElement, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions, CompositeChildElement theChildElem,
|
private void extractUndeclaredExtensions(IBase theElement, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions, CompositeChildElement theChildElem,
|
||||||
CompositeChildElement theParent) {
|
CompositeChildElement theParent, EncodeContext theEncodeContext, boolean theContainedResource) {
|
||||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||||
ISupportsUndeclaredExtensions element = (ISupportsUndeclaredExtensions) theElement;
|
ISupportsUndeclaredExtensions element = (ISupportsUndeclaredExtensions) theElement;
|
||||||
List<ExtensionDt> ext = element.getUndeclaredExtensions();
|
List<ExtensionDt> ext = element.getUndeclaredExtensions();
|
||||||
|
@ -804,11 +818,21 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (theElement instanceof IBaseHasExtensions) {
|
if (theElement instanceof IBaseHasExtensions) {
|
||||||
IBaseHasExtensions element = (IBaseHasExtensions) theElement;
|
IBaseHasExtensions element = (IBaseHasExtensions) theElement;
|
||||||
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
||||||
|
Boolean encodeExtension = null;
|
||||||
for (IBaseExtension<?, ?> next : ext) {
|
for (IBaseExtension<?, ?> next : ext) {
|
||||||
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
|
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
extensions.add(new HeldExtension(next, false, theChildElem, theParent));
|
|
||||||
|
// Make sure we respect _elements and _summary
|
||||||
|
if (encodeExtension == null) {
|
||||||
|
encodeExtension = isEncodeExtension(theParent, theEncodeContext, theContainedResource, element);
|
||||||
|
}
|
||||||
|
if (encodeExtension) {
|
||||||
|
HeldExtension extension = new HeldExtension(next, false, theChildElem, theParent);
|
||||||
|
extensions.add(extension);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (theElement instanceof IBaseHasModifierExtensions) {
|
if (theElement instanceof IBaseHasModifierExtensions) {
|
||||||
|
@ -818,12 +842,28 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (next == null || next.isEmpty()) {
|
if (next == null || next.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
modifierExtensions.add(new HeldExtension(next, true, theChildElem, theParent));
|
|
||||||
|
HeldExtension extension = new HeldExtension(next, true, theChildElem, theParent);
|
||||||
|
modifierExtensions.add(extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isEncodeExtension(CompositeChildElement theParent, EncodeContext theEncodeContext, boolean theContainedResource, IBase theElement) {
|
||||||
|
// theEncodeContext.pushPath("extension", false);
|
||||||
|
BaseRuntimeElementDefinition<?> runtimeElementDefinition = myContext.getElementDefinition(theElement.getClass());
|
||||||
|
boolean retVal = true;
|
||||||
|
if (runtimeElementDefinition instanceof BaseRuntimeElementCompositeDefinition) {
|
||||||
|
BaseRuntimeElementCompositeDefinition definition = (BaseRuntimeElementCompositeDefinition) runtimeElementDefinition;
|
||||||
|
BaseRuntimeChildDefinition childDef = definition.getChildByName("extension");
|
||||||
|
CompositeChildElement c = new CompositeChildElement(theParent, childDef, theEncodeContext);
|
||||||
|
retVal = c.shouldBeEncoded(theContainedResource);
|
||||||
|
}
|
||||||
|
// theEncodeContext.popPath();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EncodingEnum getEncoding() {
|
public EncodingEnum getEncoding() {
|
||||||
return EncodingEnum.JSON;
|
return EncodingEnum.JSON;
|
||||||
|
@ -1275,21 +1315,24 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonLikeWriter theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonLikeWriter theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
||||||
List<HeldExtension> modifierExtensions, EncodeContext theEncodeContext) throws IOException {
|
List<HeldExtension> modifierExtensions, EncodeContext theEncodeContext, boolean theContainedResource) throws IOException {
|
||||||
|
// Write Extensions
|
||||||
if (extensions.isEmpty() == false) {
|
if (extensions.isEmpty() == false) {
|
||||||
theEncodeContext.pushPath("extension", false);
|
theEncodeContext.pushPath("extension", false);
|
||||||
beginArray(theEventWriter, "extension");
|
beginArray(theEventWriter, "extension");
|
||||||
for (HeldExtension next : extensions) {
|
for (HeldExtension next : extensions) {
|
||||||
next.write(resDef, theResource, theEventWriter, theEncodeContext);
|
next.write(resDef, theResource, theEventWriter, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
theEncodeContext.popPath();
|
theEncodeContext.popPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write ModifierExtensions
|
||||||
if (modifierExtensions.isEmpty() == false) {
|
if (modifierExtensions.isEmpty() == false) {
|
||||||
theEncodeContext.pushPath("modifierExtension", false);
|
theEncodeContext.pushPath("modifierExtension", false);
|
||||||
beginArray(theEventWriter, "modifierExtension");
|
beginArray(theEventWriter, "modifierExtension");
|
||||||
for (HeldExtension next : modifierExtensions) {
|
for (HeldExtension next : modifierExtensions) {
|
||||||
next.write(resDef, theResource, theEventWriter, theEncodeContext);
|
next.write(resDef, theResource, theEventWriter, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
theEncodeContext.popPath();
|
theEncodeContext.popPath();
|
||||||
|
@ -1353,12 +1396,12 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
return url1.compareTo(url2);
|
return url1.compareTo(url2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void managePrimitiveExtension(final IBase theValue, final RuntimeResourceDefinition theResDef, final IBaseResource theResource, final JsonLikeWriter theEventWriter, final BaseRuntimeElementDefinition<?> def, final String childName, EncodeContext theEncodeContext) throws IOException {
|
private void managePrimitiveExtension(final IBase theValue, final RuntimeResourceDefinition theResDef, final IBaseResource theResource, final JsonLikeWriter theEventWriter, final BaseRuntimeElementDefinition<?> def, final String childName, EncodeContext theEncodeContext, boolean theContainedResource) throws IOException {
|
||||||
if (def.getChildType().equals(ID_DATATYPE) || def.getChildType().equals(PRIMITIVE_DATATYPE)) {
|
if (def.getChildType().equals(ID_DATATYPE) || def.getChildType().equals(PRIMITIVE_DATATYPE)) {
|
||||||
final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
||||||
final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
||||||
// Undeclared extensions
|
// Undeclared extensions
|
||||||
extractUndeclaredExtensions(theValue, extensions, modifierExtensions, myParent, null);
|
extractUndeclaredExtensions(theValue, extensions, modifierExtensions, myParent, null, theEncodeContext, theContainedResource);
|
||||||
// Declared extensions
|
// Declared extensions
|
||||||
if (def != null) {
|
if (def != null) {
|
||||||
extractDeclaredExtensions(theValue, def, extensions, modifierExtensions, myParent);
|
extractDeclaredExtensions(theValue, def, extensions, modifierExtensions, myParent);
|
||||||
|
@ -1369,15 +1412,15 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
if (haveContent) {
|
if (haveContent) {
|
||||||
beginObject(theEventWriter, '_' + childName);
|
beginObject(theEventWriter, '_' + childName);
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext, theContainedResource);
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, EncodeContext theEncodeContext) throws IOException {
|
public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, EncodeContext theEncodeContext, boolean theContainedResource) throws IOException {
|
||||||
if (myUndeclaredExtension != null) {
|
if (myUndeclaredExtension != null) {
|
||||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, myUndeclaredExtension, theEncodeContext);
|
writeUndeclaredExtension(theResDef, theResource, theEventWriter, myUndeclaredExtension, theEncodeContext, theContainedResource);
|
||||||
} else {
|
} else {
|
||||||
theEventWriter.beginObject();
|
theEventWriter.beginObject();
|
||||||
|
|
||||||
|
@ -1410,18 +1453,18 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
|
|
||||||
BaseRuntimeElementDefinition<?> def = myDef.getChildElementDefinitionByDatatype(myValue.getClass());
|
BaseRuntimeElementDefinition<?> def = myDef.getChildElementDefinitionByDatatype(myValue.getClass());
|
||||||
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
||||||
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, myChildElem, null, theEncodeContext);
|
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, myChildElem, null, theEncodeContext, theContainedResource);
|
||||||
} else {
|
} else {
|
||||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false, theEncodeContext);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false, theEncodeContext);
|
||||||
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName, theEncodeContext);
|
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBaseExtension<?, ?> ext, EncodeContext theEncodeContext) throws IOException {
|
private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBaseExtension<?, ?> ext, EncodeContext theEncodeContext, boolean theContainedResource) throws IOException {
|
||||||
IBase value = ext.getValue();
|
IBase value = ext.getValue();
|
||||||
final String extensionUrl = getExtensionUrl(ext.getUrl());
|
final String extensionUrl = getExtensionUrl(ext.getUrl());
|
||||||
|
|
||||||
|
@ -1465,7 +1508,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Object next : ext.getExtension()) {
|
for (Object next : ext.getExtension()) {
|
||||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next, theEncodeContext);
|
writeUndeclaredExtension(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next, theEncodeContext, theContainedResource);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
|
|
||||||
|
@ -1473,6 +1516,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
|
|
||||||
// Write value
|
// Write value
|
||||||
if (!noValue) {
|
if (!noValue) {
|
||||||
|
theEncodeContext.pushPath("value", false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-process value - This is called in case the value is a reference
|
* Pre-process value - This is called in case the value is a reference
|
||||||
|
@ -1490,8 +1534,9 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
|
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, false, myParent,false, theEncodeContext);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, false, myParent,false, theEncodeContext);
|
||||||
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName, theEncodeContext);
|
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName, theEncodeContext, theContainedResource);
|
||||||
|
|
||||||
|
theEncodeContext.popPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,15 +51,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
* This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use
|
* This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use
|
||||||
* {@link FhirContext#newXmlParser()} to get an instance.
|
* {@link FhirContext#newXmlParser()} to get an instance.
|
||||||
*/
|
*/
|
||||||
public class XmlParser extends BaseParser /* implements IParser */ {
|
public class XmlParser extends BaseParser {
|
||||||
|
|
||||||
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
|
||||||
static final String FHIR_NS = "http://hl7.org/fhir";
|
static final String FHIR_NS = "http://hl7.org/fhir";
|
||||||
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
|
||||||
static final String RESREF_DISPLAY = "display";
|
|
||||||
static final String RESREF_REFERENCE = "reference";
|
|
||||||
static final String TOMBSTONES_NS = "http://purl.org/atompub/tombstones/1.0";
|
|
||||||
static final String XHTML_NS = "http://www.w3.org/1999/xhtml";
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
|
||||||
|
|
||||||
// private static final Set<String> RESOURCE_NAMESPACES;
|
// private static final Set<String> RESOURCE_NAMESPACES;
|
||||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.util;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.*;
|
||||||
|
|
||||||
public class ValidateUtil {
|
public class ValidateUtil {
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class ValidateUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws {@link IllegalArgumentException} if theValue is <= theMinimum
|
* Throws {@link IllegalArgumentException} if theValue is < theMinimum
|
||||||
*/
|
*/
|
||||||
public static void isGreaterThanOrEqualTo(long theValue, long theMinimum, String theMessage) {
|
public static void isGreaterThanOrEqualTo(long theValue, long theMinimum, String theMessage) {
|
||||||
if (theValue < theMinimum) {
|
if (theValue < theMinimum) {
|
||||||
|
@ -45,6 +45,12 @@ public class ValidateUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void isNotBlankOrThrowIllegalArgument(String theString, String theMessage) {
|
||||||
|
if (isBlank(theString)) {
|
||||||
|
throw new IllegalArgumentException(theMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void isNotBlankOrThrowInvalidRequest(String theString, String theMessage) {
|
public static void isNotBlankOrThrowInvalidRequest(String theString, String theMessage) {
|
||||||
if (isBlank(theString)) {
|
if (isBlank(theString)) {
|
||||||
throw new InvalidRequestException(theMessage);
|
throw new InvalidRequestException(theMessage);
|
||||||
|
@ -57,6 +63,12 @@ public class ValidateUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void isNotTooLongOrThrowIllegalArgument(String theString, int theMaxLength, String theMessage) {
|
||||||
|
if (length(theString) > theMaxLength) {
|
||||||
|
throw new IllegalArgumentException(theMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void isTrueOrThrowInvalidRequest(boolean theSuccess, String theMessage) {
|
public static void isTrueOrThrowInvalidRequest(boolean theSuccess, String theMessage) {
|
||||||
if (theSuccess == false) {
|
if (theSuccess == false) {
|
||||||
throw new InvalidRequestException(theMessage);
|
throw new InvalidRequestException(theMessage);
|
||||||
|
|
|
@ -22,7 +22,7 @@ package org.hl7.fhir.instance.model.api;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IBaseHasExtensions {
|
public interface IBaseHasExtensions extends IBase {
|
||||||
|
|
||||||
IBaseExtension<?, ?> addExtension();
|
IBaseExtension<?, ?> addExtension();
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,9 @@ ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor.noParam=Note that cascadi
|
||||||
|
|
||||||
ca.uhn.fhir.jpa.provider.BaseJpaProvider.cantCombintAtAndSince=Unable to combine _at and _since parameters for history operation
|
ca.uhn.fhir.jpa.provider.BaseJpaProvider.cantCombintAtAndSince=Unable to combine _at and _since parameters for history operation
|
||||||
|
|
||||||
|
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateCodeSystemUrl=Can not create multiple CodeSystem resources with CodeSystem.url "{0}", already have one with resource ID: {1}
|
||||||
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1}
|
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1}
|
||||||
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateCodeSystemUri=Can not create multiple code systems with URI "{0}", already have one with resource ID: {1}
|
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateValueSetUrl=Can not create multiple ValueSet resources with ValueSet.url "{0}", already have one with resource ID: {1}
|
||||||
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted!
|
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted!
|
||||||
|
|
||||||
ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1}
|
ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1}
|
||||||
|
|
|
@ -145,6 +145,10 @@ public class DaoConfig {
|
||||||
private boolean myEnableInMemorySubscriptionMatching = true;
|
private boolean myEnableInMemorySubscriptionMatching = true;
|
||||||
private boolean myEnforceReferenceTargetTypes = true;
|
private boolean myEnforceReferenceTargetTypes = true;
|
||||||
private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
|
private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
|
||||||
|
/**
|
||||||
|
* EXPERIMENTAL - Do not use in production! Do not change default of {@code false}!
|
||||||
|
*/
|
||||||
|
private boolean myPreExpandValueSetsExperimental = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -1600,6 +1604,34 @@ public class DaoConfig {
|
||||||
myModelConfig.setWebsocketContextPath(theWebsocketContextPath);
|
myModelConfig.setWebsocketContextPath(theWebsocketContextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EXPERIMENTAL - Do not use in production!
|
||||||
|
* <p>
|
||||||
|
* If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
|
||||||
|
* future optimization of the $expand operation on large ValueSets.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is {@code false}.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public boolean isPreExpandValueSetsExperimental() {
|
||||||
|
return myPreExpandValueSetsExperimental;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EXPERIMENTAL - Do not use in production!
|
||||||
|
* <p>
|
||||||
|
* If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
|
||||||
|
* future optimization of the $expand operation on large ValueSets.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is {@code false}.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void setPreExpandValueSetsExperimental(boolean thePreExpandValueSetsExperimental) {
|
||||||
|
myPreExpandValueSetsExperimental = thePreExpandValueSetsExperimental;
|
||||||
|
}
|
||||||
|
|
||||||
public enum IndexEnabledEnum {
|
public enum IndexEnabledEnum {
|
||||||
ENABLED,
|
ENABLED,
|
||||||
DISABLED
|
DISABLED
|
||||||
|
|
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.jpa.entity.ResourceSearchView;
|
||||||
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
||||||
import ca.uhn.fhir.jpa.model.entity.*;
|
import ca.uhn.fhir.jpa.model.entity.*;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||||
|
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||||
import ca.uhn.fhir.jpa.model.util.StringNormalizer;
|
import ca.uhn.fhir.jpa.model.util.StringNormalizer;
|
||||||
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||||
|
@ -60,7 +61,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -113,10 +113,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
*/
|
*/
|
||||||
private static final int MAXIMUM_PAGE_SIZE = 800;
|
private static final int MAXIMUM_PAGE_SIZE = 800;
|
||||||
private static Long NO_MORE = -1L;
|
private static Long NO_MORE = -1L;
|
||||||
private static HandlerTypeEnum ourLastHandlerMechanismForUnitTest;
|
|
||||||
private static SearchParameterMap ourLastHandlerParamsForUnitTest;
|
|
||||||
private static String ourLastHandlerThreadForUnitTest;
|
|
||||||
private static boolean ourTrackHandlersForUnitTest;
|
|
||||||
private final boolean myDontUseHashesForSearch;
|
private final boolean myDontUseHashesForSearch;
|
||||||
private final DaoConfig myDaoConfig;
|
private final DaoConfig myDaoConfig;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -1546,12 +1542,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
myBuilder = myEntityManager.getCriteriaBuilder();
|
myBuilder = myEntityManager.getCriteriaBuilder();
|
||||||
mySearchUuid = theSearchRuntimeDetails.getSearchUuid();
|
mySearchUuid = theSearchRuntimeDetails.getSearchUuid();
|
||||||
|
|
||||||
if (ourTrackHandlersForUnitTest) {
|
|
||||||
ourLastHandlerParamsForUnitTest = theParams;
|
|
||||||
ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.STANDARD_QUERY;
|
|
||||||
ourLastHandlerThreadForUnitTest = Thread.currentThread().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myPidSet == null) {
|
if (myPidSet == null) {
|
||||||
myPidSet = new HashSet<>();
|
myPidSet = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
@ -2214,9 +2204,16 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
if (sb != null) {
|
if (sb != null) {
|
||||||
String indexString = sb.toString();
|
String indexString = sb.toString();
|
||||||
ourLog.debug("Checking for unique index for query: {}", indexString);
|
ourLog.debug("Checking for unique index for query: {}", indexString);
|
||||||
if (ourTrackHandlersForUnitTest) {
|
|
||||||
ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.UNIQUE_INDEX;
|
// Interceptor broadcast: JPA_PERFTRACE_INFO
|
||||||
}
|
StorageProcessingMessage msg = new StorageProcessingMessage()
|
||||||
|
.setMessage("Using unique index for query for search: " + indexString);
|
||||||
|
HookParams params = new HookParams()
|
||||||
|
.add(RequestDetails.class, theRequest)
|
||||||
|
.addIfMatchesType(ServletRequestDetails.class, theRequest)
|
||||||
|
.add(StorageProcessingMessage.class, msg);
|
||||||
|
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
|
||||||
|
|
||||||
addPredicateCompositeStringUnique(theParams, indexString);
|
addPredicateCompositeStringUnique(theParams, indexString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2788,24 +2785,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public static HandlerTypeEnum getLastHandlerMechanismForUnitTest() {
|
|
||||||
return ourLastHandlerMechanismForUnitTest;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public static String getLastHandlerParamsForUnitTest() {
|
|
||||||
return ourLastHandlerParamsForUnitTest.toString() + " on thread [" + ourLastHandlerThreadForUnitTest + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public static void resetLastHandlerMechanismForUnitTest() {
|
|
||||||
ourLastHandlerMechanismForUnitTest = null;
|
|
||||||
ourLastHandlerParamsForUnitTest = null;
|
|
||||||
ourLastHandlerThreadForUnitTest = null;
|
|
||||||
ourTrackHandlersForUnitTest = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Predicate[] toArray(List<Predicate> thePredicates) {
|
private static Predicate[] toArray(List<Predicate> thePredicates) {
|
||||||
return thePredicates.toArray(new Predicate[0]);
|
return thePredicates.toArray(new Predicate[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public interface ITermCodeSystemDao extends JpaRepository<TermCodeSystem, Long>
|
||||||
TermCodeSystem findByCodeSystemUri(@Param("code_system_uri") String theCodeSystemUri);
|
TermCodeSystem findByCodeSystemUri(@Param("code_system_uri") String theCodeSystemUri);
|
||||||
|
|
||||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResourcePid = :resource_pid")
|
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResourcePid = :resource_pid")
|
||||||
TermCodeSystem findByResourcePid(@Param("resource_pid") Long theReourcePid);
|
TermCodeSystem findByResourcePid(@Param("resource_pid") Long theResourcePid);
|
||||||
|
|
||||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCurrentVersion.myId = :csv_pid")
|
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCurrentVersion.myId = :csv_pid")
|
||||||
Optional<TermCodeSystem> findWithCodeSystemVersionAsCurrentVersion(@Param("csv_pid") Long theCodeSystemVersionPid);
|
Optional<TermCodeSystem> findWithCodeSystemVersionAsCurrentVersion(@Param("csv_pid") Long theCodeSystemVersionPid);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%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.entity.TermValueSetCode;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface ITermValueSetCodeDao extends JpaRepository<TermValueSetCode, Long> {
|
||||||
|
|
||||||
|
@Query("DELETE FROM TermValueSetCode vsc WHERE vsc.myValueSet.myId = :pid")
|
||||||
|
@Modifying
|
||||||
|
void deleteTermValueSetCodesByValueSetId(@Param("pid") Long theValueSetId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%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.entity.TermValueSet;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
|
||||||
|
|
||||||
|
@Query("DELETE FROM TermValueSet vs WHERE vs.myId = :pid")
|
||||||
|
@Modifying
|
||||||
|
void deleteTermValueSetById(@Param("pid") Long theId);
|
||||||
|
|
||||||
|
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid")
|
||||||
|
Optional<TermValueSet> findByResourcePid(@Param("resource_pid") Long theResourcePid);
|
||||||
|
|
||||||
|
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url")
|
||||||
|
Optional<TermValueSet> findByUrl(@Param("url") String theUrl);
|
||||||
|
|
||||||
|
}
|
|
@ -23,11 +23,15 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
|
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
|
@ -37,6 +41,8 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetFilterComponent;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -45,14 +51,18 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myJpaValidationSupportChainDstu3")
|
@Qualifier("myJpaValidationSupportChainDstu3")
|
||||||
private IValidationSupport myValidationSupport;
|
private IValidationSupport myValidationSupport;
|
||||||
|
@ -295,4 +305,26 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
|
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
|
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
|
if (myDaoConfig.isPreExpandValueSetsExperimental()) {
|
||||||
|
if (retVal.getDeleted() == null) {
|
||||||
|
try {
|
||||||
|
ValueSet valueSet = (ValueSet) theResource;
|
||||||
|
org.hl7.fhir.r4.model.ValueSet converted = VersionConvertor_30_40.convertValueSet(valueSet);
|
||||||
|
myHapiTerminologySvc.storeTermValueSetAndChildren(retVal, converted);
|
||||||
|
} catch (FHIRException fe) {
|
||||||
|
throw new InternalErrorException(fe);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
myHapiTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,8 @@ public class ExpungeEverythingService {
|
||||||
counter.addAndGet(expungeEverythingByType(ResourceLink.class));
|
counter.addAndGet(expungeEverythingByType(ResourceLink.class));
|
||||||
counter.addAndGet(expungeEverythingByType(SearchResult.class));
|
counter.addAndGet(expungeEverythingByType(SearchResult.class));
|
||||||
counter.addAndGet(expungeEverythingByType(SearchInclude.class));
|
counter.addAndGet(expungeEverythingByType(SearchInclude.class));
|
||||||
|
counter.addAndGet(expungeEverythingByType(TermValueSetCode.class));
|
||||||
|
counter.addAndGet(expungeEverythingByType(TermValueSet.class));
|
||||||
counter.addAndGet(expungeEverythingByType(TermConceptParentChildLink.class));
|
counter.addAndGet(expungeEverythingByType(TermConceptParentChildLink.class));
|
||||||
counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElementTarget.class));
|
counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElementTarget.class));
|
||||||
counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElement.class));
|
counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElement.class));
|
||||||
|
|
|
@ -57,6 +57,14 @@ public class IdHelperService {
|
||||||
myForcedIdDao.delete(forcedId);
|
myForcedIdDao.delete(forcedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ResourceNotFoundException If the ID can not be found
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public Long translateForcedIdToPid(IIdType theId, RequestDetails theRequestDetails) {
|
||||||
|
return translateForcedIdToPid(theId.getResourceType(), theId.getIdPart(), theRequestDetails);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws ResourceNotFoundException If the ID can not be found
|
* @throws ResourceNotFoundException If the ID can not be found
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,34 +20,43 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
|
||||||
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
|
|
||||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
|
||||||
import org.hl7.fhir.r4.model.*;
|
|
||||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
|
||||||
import org.hl7.fhir.r4.model.ValueSet.*;
|
|
||||||
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
|
||||||
|
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||||
|
import org.hl7.fhir.r4.model.*;
|
||||||
|
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
|
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
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 FhirResourceDaoR4<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myJpaValidationSupportChainR4")
|
@Qualifier("myJpaValidationSupportChainR4")
|
||||||
private IValidationSupport myValidationSupport;
|
private IValidationSupport myValidationSupport;
|
||||||
|
@ -296,4 +305,21 @@ public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> imple
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
|
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
|
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
|
if (myDaoConfig.isPreExpandValueSetsExperimental()) {
|
||||||
|
if (retVal.getDeleted() == null) {
|
||||||
|
ValueSet valueSet = (ValueSet) theResource;
|
||||||
|
myHapiTerminologySvc.storeTermValueSetAndChildren(retVal, valueSet);
|
||||||
|
} else {
|
||||||
|
myHapiTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,16 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.left;
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@Table(name = "TRM_CODESYSTEM", uniqueConstraints = {
|
@Table(name = "TRM_CODESYSTEM", uniqueConstraints = {
|
||||||
|
@ -37,9 +40,11 @@ import static org.apache.commons.lang3.StringUtils.left;
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class TermCodeSystem implements Serializable {
|
public class TermCodeSystem implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
public static final int CS_NAME_LENGTH = 200;
|
|
||||||
|
|
||||||
@Column(name = "CODE_SYSTEM_URI", nullable = false)
|
private static final int MAX_NAME_LENGTH = 200;
|
||||||
|
public static final int MAX_URL_LENGTH = 200;
|
||||||
|
|
||||||
|
@Column(name = "CODE_SYSTEM_URI", nullable = false, length = MAX_URL_LENGTH)
|
||||||
private String myCodeSystemUri;
|
private String myCodeSystemUri;
|
||||||
|
|
||||||
@OneToOne()
|
@OneToOne()
|
||||||
|
@ -55,7 +60,7 @@ public class TermCodeSystem implements Serializable {
|
||||||
private ResourceTable myResource;
|
private ResourceTable myResource;
|
||||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||||
private Long myResourcePid;
|
private Long myResourcePid;
|
||||||
@Column(name = "CS_NAME", nullable = true)
|
@Column(name = "CS_NAME", nullable = true, length = MAX_NAME_LENGTH)
|
||||||
private String myName;
|
private String myName;
|
||||||
|
|
||||||
public String getCodeSystemUri() {
|
public String getCodeSystemUri() {
|
||||||
|
@ -66,16 +71,21 @@ public class TermCodeSystem implements Serializable {
|
||||||
return myName;
|
return myName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSystemUri(String theCodeSystemUri) {
|
public TermCodeSystem setCodeSystemUri(@Nonnull String theCodeSystemUri) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCodeSystemUri, "theCodeSystemUri must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCodeSystemUri, MAX_URL_LENGTH,
|
||||||
|
"URI exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theCodeSystemUri));
|
||||||
myCodeSystemUri = theCodeSystemUri;
|
myCodeSystemUri = theCodeSystemUri;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermCodeSystemVersion getCurrentVersion() {
|
public TermCodeSystemVersion getCurrentVersion() {
|
||||||
return myCurrentVersion;
|
return myCurrentVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
|
public TermCodeSystem setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
|
||||||
myCurrentVersion = theCurrentVersion;
|
myCurrentVersion = theCurrentVersion;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getPid() {
|
public Long getPid() {
|
||||||
|
@ -86,12 +96,14 @@ public class TermCodeSystem implements Serializable {
|
||||||
return myResource;
|
return myResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String theName) {
|
public TermCodeSystem setName(String theName) {
|
||||||
myName = left(theName, CS_NAME_LENGTH);
|
myName = left(theName, MAX_NAME_LENGTH);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResource(ResourceTable theResource) {
|
public TermCodeSystem setResource(ResourceTable theResource) {
|
||||||
myResource = theResource;
|
myResource = theResource;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,12 +22,15 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@Table(name = "TRM_CODESYSTEM_VER"
|
@Table(name = "TRM_CODESYSTEM_VER"
|
||||||
// Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this)
|
// Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this)
|
||||||
|
@ -37,6 +40,8 @@ import java.util.Collection;
|
||||||
public class TermCodeSystemVersion implements Serializable {
|
public class TermCodeSystemVersion implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
static final int MAX_VERSION_LENGTH = 200;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")
|
||||||
private Collection<TermConcept> myConcepts;
|
private Collection<TermConcept> myConcepts;
|
||||||
|
|
||||||
|
@ -50,7 +55,7 @@ public class TermCodeSystemVersion implements Serializable {
|
||||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
|
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
|
||||||
private ResourceTable myResource;
|
private ResourceTable myResource;
|
||||||
|
|
||||||
@Column(name = "CS_VERSION_ID", nullable = true, updatable = false)
|
@Column(name = "CS_VERSION_ID", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
|
||||||
private String myCodeSystemVersionId;
|
private String myCodeSystemVersionId;
|
||||||
/**
|
/**
|
||||||
* This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
|
* This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
|
||||||
|
@ -104,16 +109,21 @@ public class TermCodeSystemVersion implements Serializable {
|
||||||
return myCodeSystem;
|
return myCodeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSystem(TermCodeSystem theCodeSystem) {
|
public TermCodeSystemVersion setCodeSystem(TermCodeSystem theCodeSystem) {
|
||||||
myCodeSystem = theCodeSystem;
|
myCodeSystem = theCodeSystem;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCodeSystemVersionId() {
|
public String getCodeSystemVersionId() {
|
||||||
return myCodeSystemVersionId;
|
return myCodeSystemVersionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSystemVersionId(String theCodeSystemVersionId) {
|
public TermCodeSystemVersion setCodeSystemVersionId(String theCodeSystemVersionId) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(
|
||||||
|
theCodeSystemVersionId, MAX_VERSION_LENGTH,
|
||||||
|
"Version ID exceeds maximum length (" + MAX_VERSION_LENGTH + "): " + length(theCodeSystemVersionId));
|
||||||
myCodeSystemVersionId = theCodeSystemVersionId;
|
myCodeSystemVersionId = theCodeSystemVersionId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<TermConcept> getConcepts() {
|
public Collection<TermConcept> getConcepts() {
|
||||||
|
@ -131,8 +141,9 @@ public class TermCodeSystemVersion implements Serializable {
|
||||||
return myResource;
|
return myResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResource(ResourceTable theResource) {
|
public TermCodeSystemVersion setResource(ResourceTable theResource) {
|
||||||
myResource = theResource;
|
myResource = theResource;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,25 +1,5 @@
|
||||||
package ca.uhn.fhir.jpa.entity;
|
package ca.uhn.fhir.jpa.entity;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
|
||||||
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
|
|
||||||
import ca.uhn.fhir.util.ValidateUtil;
|
|
||||||
import org.apache.commons.lang3.Validate;
|
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
|
||||||
import org.hibernate.search.annotations.*;
|
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.persistence.*;
|
|
||||||
import javax.persistence.Index;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
|
@ -40,6 +20,27 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.hibernate.search.annotations.*;
|
||||||
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Indexed(interceptor = DeferConceptIndexingInterceptor.class)
|
@Indexed(interceptor = DeferConceptIndexingInterceptor.class)
|
||||||
@Table(name = "TRM_CONCEPT", uniqueConstraints = {
|
@Table(name = "TRM_CONCEPT", uniqueConstraints = {
|
||||||
|
@ -49,16 +50,17 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
@Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED")
|
@Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED")
|
||||||
})
|
})
|
||||||
public class TermConcept implements Serializable {
|
public class TermConcept implements Serializable {
|
||||||
public static final int CODE_LENGTH = 500;
|
|
||||||
protected static final int MAX_DESC_LENGTH = 400;
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class);
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final int MAX_CODE_LENGTH = 500;
|
||||||
|
public static final int MAX_DESC_LENGTH = 400;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = {})
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = {})
|
||||||
private Collection<TermConceptParentChildLink> myChildren;
|
private Collection<TermConceptParentChildLink> myChildren;
|
||||||
|
|
||||||
@Column(name = "CODE", length = CODE_LENGTH, nullable = false)
|
@Column(name = "CODE", nullable = false, length = MAX_CODE_LENGTH)
|
||||||
@Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),})
|
@Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),})
|
||||||
private String myCode;
|
private String myCode;
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
@ -70,7 +72,7 @@ public class TermConcept implements Serializable {
|
||||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||||
@Fields({@Field(name = "myCodeSystemVersionPid")})
|
@Fields({@Field(name = "myCodeSystemVersionPid")})
|
||||||
private long myCodeSystemVersionPid;
|
private long myCodeSystemVersionPid;
|
||||||
@Column(name = "DISPLAY", length = MAX_DESC_LENGTH, nullable = true)
|
@Column(name = "DISPLAY", nullable = true, length = MAX_DESC_LENGTH)
|
||||||
@Fields({
|
@Fields({
|
||||||
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
||||||
@Field(name = "myDisplayEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteEdgeAnalyzer")),
|
@Field(name = "myDisplayEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteEdgeAnalyzer")),
|
||||||
|
@ -187,20 +189,24 @@ public class TermConcept implements Serializable {
|
||||||
return myCode;
|
return myCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCode(String theCode) {
|
public TermConcept setCode(@Nonnull String theCode) {
|
||||||
ValidateUtil.isNotBlankOrThrowInvalidRequest(theCode, "Code must not be null or empty");
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, MAX_CODE_LENGTH,
|
||||||
|
"Code exceeds maximum length (" + MAX_CODE_LENGTH + "): " + length(theCode));
|
||||||
myCode = theCode;
|
myCode = theCode;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermCodeSystemVersion getCodeSystemVersion() {
|
public TermCodeSystemVersion getCodeSystemVersion() {
|
||||||
return myCodeSystem;
|
return myCodeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
|
public TermConcept setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
|
||||||
myCodeSystem = theCodeSystemVersion;
|
myCodeSystem = theCodeSystemVersion;
|
||||||
if (theCodeSystemVersion.getPid() != null) {
|
if (theCodeSystemVersion.getPid() != null) {
|
||||||
myCodeSystemVersionPid = theCodeSystemVersion.getPid();
|
myCodeSystemVersionPid = theCodeSystemVersion.getPid();
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Coding> getCodingProperties(String thePropertyName) {
|
public List<Coding> getCodingProperties(String thePropertyName) {
|
||||||
|
@ -231,10 +237,7 @@ public class TermConcept implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConcept setDisplay(String theDisplay) {
|
public TermConcept setDisplay(String theDisplay) {
|
||||||
myDisplay = theDisplay;
|
myDisplay = left(theDisplay, MAX_DESC_LENGTH);
|
||||||
if (isNotBlank(theDisplay) && theDisplay.length() > MAX_DESC_LENGTH) {
|
|
||||||
myDisplay = myDisplay.substring(0, MAX_DESC_LENGTH);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,8 +249,9 @@ public class TermConcept implements Serializable {
|
||||||
return myIndexStatus;
|
return myIndexStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndexStatus(Long theIndexStatus) {
|
public TermConcept setIndexStatus(Long theIndexStatus) {
|
||||||
myIndexStatus = theIndexStatus;
|
myIndexStatus = theIndexStatus;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParentPidsAsString() {
|
public String getParentPidsAsString() {
|
||||||
|
@ -272,8 +276,9 @@ public class TermConcept implements Serializable {
|
||||||
return mySequence;
|
return mySequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSequence(Integer theSequence) {
|
public TermConcept setSequence(Integer theSequence) {
|
||||||
mySequence = theSequence;
|
mySequence = theSequence;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getStringProperties(String thePropertyName) {
|
public List<String> getStringProperties(String thePropertyName) {
|
||||||
|
@ -300,8 +305,9 @@ public class TermConcept implements Serializable {
|
||||||
return myUpdated;
|
return myUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpdated(Date theUpdated) {
|
public TermConcept setUpdated(Date theUpdated) {
|
||||||
myUpdated = theUpdated;
|
myUpdated = theUpdated;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -355,8 +361,9 @@ public class TermConcept implements Serializable {
|
||||||
myParentPids = b.toString();
|
myParentPids = b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParentPids(String theParentPids) {
|
public TermConcept setParentPids(String theParentPids) {
|
||||||
myParentPids = theParentPids;
|
myParentPids = theParentPids;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,16 +20,24 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_DESIG", uniqueConstraints = {
|
@Table(name = "TRM_CONCEPT_DESIG", uniqueConstraints = {
|
||||||
}, indexes = {
|
}, indexes = {
|
||||||
})
|
})
|
||||||
public class TermConceptDesignation implements Serializable {
|
public class TermConceptDesignation implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final int MAX_LENGTH = 500;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT"))
|
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT"))
|
||||||
private TermConcept myConcept;
|
private TermConcept myConcept;
|
||||||
|
@ -38,15 +46,15 @@ public class TermConceptDesignation implements Serializable {
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID")
|
||||||
@Column(name = "PID")
|
@Column(name = "PID")
|
||||||
private Long myId;
|
private Long myId;
|
||||||
@Column(name = "LANG", length = 500, nullable = true)
|
@Column(name = "LANG", nullable = true, length = MAX_LENGTH)
|
||||||
private String myLanguage;
|
private String myLanguage;
|
||||||
@Column(name = "USE_SYSTEM", length = 500, nullable = true)
|
@Column(name = "USE_SYSTEM", nullable = true, length = MAX_LENGTH)
|
||||||
private String myUseSystem;
|
private String myUseSystem;
|
||||||
@Column(name = "USE_CODE", length = 500, nullable = true)
|
@Column(name = "USE_CODE", nullable = true, length = MAX_LENGTH)
|
||||||
private String myUseCode;
|
private String myUseCode;
|
||||||
@Column(name = "USE_DISPLAY", length = 500, nullable = true)
|
@Column(name = "USE_DISPLAY", nullable = true, length = MAX_LENGTH)
|
||||||
private String myUseDisplay;
|
private String myUseDisplay;
|
||||||
@Column(name = "VAL", length = 500, nullable = false)
|
@Column(name = "VAL", nullable = false, length = MAX_LENGTH)
|
||||||
private String myValue;
|
private String myValue;
|
||||||
/**
|
/**
|
||||||
* TODO: Make this non-null
|
* TODO: Make this non-null
|
||||||
|
@ -62,6 +70,8 @@ public class TermConceptDesignation implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptDesignation setLanguage(String theLanguage) {
|
public TermConceptDesignation setLanguage(String theLanguage) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theLanguage, MAX_LENGTH,
|
||||||
|
"Language exceeds maximum length (" + MAX_LENGTH + "): " + length(theLanguage));
|
||||||
myLanguage = theLanguage;
|
myLanguage = theLanguage;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +81,8 @@ public class TermConceptDesignation implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptDesignation setUseCode(String theUseCode) {
|
public TermConceptDesignation setUseCode(String theUseCode) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUseCode, MAX_LENGTH,
|
||||||
|
"Use code exceeds maximum length (" + MAX_LENGTH + "): " + length(theUseCode));
|
||||||
myUseCode = theUseCode;
|
myUseCode = theUseCode;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +92,7 @@ public class TermConceptDesignation implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptDesignation setUseDisplay(String theUseDisplay) {
|
public TermConceptDesignation setUseDisplay(String theUseDisplay) {
|
||||||
myUseDisplay = theUseDisplay;
|
myUseDisplay = left(theUseDisplay, MAX_LENGTH);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +101,9 @@ public class TermConceptDesignation implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptDesignation setUseSystem(String theUseSystem) {
|
public TermConceptDesignation setUseSystem(String theUseSystem) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUseSystem, MAX_LENGTH,
|
||||||
|
"Use system exceeds maximum length (" + MAX_LENGTH + "): " + length(theUseSystem));
|
||||||
|
|
||||||
myUseSystem = theUseSystem;
|
myUseSystem = theUseSystem;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +112,10 @@ public class TermConceptDesignation implements Serializable {
|
||||||
return myValue;
|
return myValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptDesignation setValue(String theValue) {
|
public TermConceptDesignation setValue(@Nonnull String theValue) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theValue, "theValue must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theValue, MAX_LENGTH,
|
||||||
|
"Value exceeds maximum length (" + MAX_LENGTH + "): " + length(theValue));
|
||||||
myValue = theValue;
|
myValue = theValue;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,19 +21,27 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = {
|
@Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = {
|
||||||
@UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL"})
|
@UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL"})
|
||||||
})
|
})
|
||||||
public class TermConceptMap implements Serializable {
|
public class TermConceptMap implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
static final int MAX_URL_LENGTH = 200;
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID")
|
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_PID")
|
||||||
|
@ -47,13 +55,13 @@ public class TermConceptMap implements Serializable {
|
||||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||||
private Long myResourcePid;
|
private Long myResourcePid;
|
||||||
|
|
||||||
@Column(name = "SOURCE_URL", nullable = true, length = 200)
|
@Column(name = "SOURCE_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String mySource;
|
private String mySource;
|
||||||
|
|
||||||
@Column(name = "TARGET_URL", nullable = true, length = 200)
|
@Column(name = "TARGET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String myTarget;
|
private String myTarget;
|
||||||
|
|
||||||
@Column(name = "URL", length = 200, nullable = false)
|
@Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
|
||||||
private String myUrl;
|
private String myUrl;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "myConceptMap")
|
@OneToMany(mappedBy = "myConceptMap")
|
||||||
|
@ -75,47 +83,58 @@ public class TermConceptMap implements Serializable {
|
||||||
return myResource;
|
return myResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResource(ResourceTable resource) {
|
public TermConceptMap setResource(ResourceTable theResource) {
|
||||||
myResource = resource;
|
myResource = theResource;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getResourcePid() {
|
public Long getResourcePid() {
|
||||||
return myResourcePid;
|
return myResourcePid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResourcePid(Long resourcePid) {
|
public TermConceptMap setResourcePid(Long theResourcePid) {
|
||||||
myResourcePid = resourcePid;
|
myResourcePid = theResourcePid;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSource() {
|
public String getSource() {
|
||||||
return mySource;
|
return mySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSource(String source) {
|
public TermConceptMap setSource(String theSource) {
|
||||||
mySource = source;
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSource, TermValueSet.MAX_URL_LENGTH,
|
||||||
|
"Source exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theSource));
|
||||||
|
mySource = theSource;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTarget() {
|
public String getTarget() {
|
||||||
return myTarget;
|
return myTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTarget(String target) {
|
public TermConceptMap setTarget(String theTarget) {
|
||||||
myTarget = target;
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTarget, TermValueSet.MAX_URL_LENGTH,
|
||||||
|
"Target exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theTarget));
|
||||||
|
myTarget = theTarget;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return myUrl;
|
return myUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUrl(String theUrl) {
|
public TermConceptMap setUrl(@Nonnull String theUrl) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUrl, MAX_URL_LENGTH,
|
||||||
|
"URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl));
|
||||||
myUrl = theUrl;
|
myUrl = theUrl;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
.append("myId", myId)
|
.append("myId", myId)
|
||||||
.append("myResource", myResource.toString())
|
|
||||||
.append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
|
.append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
|
||||||
.append("myResourcePid", myResourcePid)
|
.append("myResourcePid", myResourcePid)
|
||||||
.append("mySource", mySource)
|
.append("mySource", mySource)
|
||||||
|
|
|
@ -20,17 +20,23 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_MAP_GROUP")
|
@Table(name = "TRM_CONCEPT_MAP_GROUP")
|
||||||
public class TermConceptMapGroup implements Serializable {
|
public class TermConceptMapGroup implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GROUP_PID", sequenceName = "SEQ_CONCEPT_MAP_GROUP_PID")
|
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GROUP_PID", sequenceName = "SEQ_CONCEPT_MAP_GROUP_PID")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GROUP_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GROUP_PID")
|
||||||
|
@ -41,36 +47,37 @@ public class TermConceptMapGroup implements Serializable {
|
||||||
@JoinColumn(name = "CONCEPT_MAP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGROUP_CONCEPTMAP"))
|
@JoinColumn(name = "CONCEPT_MAP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGROUP_CONCEPTMAP"))
|
||||||
private TermConceptMap myConceptMap;
|
private TermConceptMap myConceptMap;
|
||||||
|
|
||||||
@Column(name = "SOURCE_URL", nullable = false, length = 200)
|
@Column(name = "SOURCE_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
|
||||||
private String mySource;
|
private String mySource;
|
||||||
|
|
||||||
@Column(name = "SOURCE_VERSION", length = 100)
|
@Column(name = "SOURCE_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
|
||||||
private String mySourceVersion;
|
private String mySourceVersion;
|
||||||
|
|
||||||
@Column(name = "TARGET_URL", nullable = false, length = 200)
|
@Column(name = "TARGET_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
|
||||||
private String myTarget;
|
private String myTarget;
|
||||||
|
|
||||||
@Column(name = "TARGET_VERSION", length = 100)
|
@Column(name = "TARGET_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
|
||||||
private String myTargetVersion;
|
private String myTargetVersion;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "myConceptMapGroup")
|
@OneToMany(mappedBy = "myConceptMapGroup")
|
||||||
private List<TermConceptMapGroupElement> myConceptMapGroupElements;
|
private List<TermConceptMapGroupElement> myConceptMapGroupElements;
|
||||||
|
|
||||||
@Column(name= "CONCEPT_MAP_URL", length = 200, nullable = true)
|
@Column(name= "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
|
||||||
private String myConceptMapUrl;
|
private String myConceptMapUrl;
|
||||||
|
|
||||||
@Column(name= "SOURCE_VS", length = 200, nullable = true)
|
@Column(name= "SOURCE_VS", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String mySourceValueSet;
|
private String mySourceValueSet;
|
||||||
|
|
||||||
@Column(name= "TARGET_VS", length = 200, nullable = true)
|
@Column(name= "TARGET_VS", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String myTargetValueSet;
|
private String myTargetValueSet;
|
||||||
|
|
||||||
public TermConceptMap getConceptMap() {
|
public TermConceptMap getConceptMap() {
|
||||||
return myConceptMap;
|
return myConceptMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConceptMap(TermConceptMap theTermConceptMap) {
|
public TermConceptMapGroup setConceptMap(TermConceptMap theTermConceptMap) {
|
||||||
myConceptMap = theTermConceptMap;
|
myConceptMap = theTermConceptMap;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TermConceptMapGroupElement> getConceptMapGroupElements() {
|
public List<TermConceptMapGroupElement> getConceptMapGroupElements() {
|
||||||
|
@ -96,8 +103,12 @@ public class TermConceptMapGroup implements Serializable {
|
||||||
return mySource;
|
return mySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSource(String theSource) {
|
public TermConceptMapGroup setSource(@Nonnull String theSource) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theSource, "theSource must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSource, TermCodeSystem.MAX_URL_LENGTH,
|
||||||
|
"Source exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSource));
|
||||||
this.mySource = theSource;
|
this.mySource = theSource;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSourceValueSet() {
|
public String getSourceValueSet() {
|
||||||
|
@ -111,16 +122,23 @@ public class TermConceptMapGroup implements Serializable {
|
||||||
return mySourceVersion;
|
return mySourceVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSourceVersion(String theSourceVersion) {
|
public TermConceptMapGroup setSourceVersion(String theSourceVersion) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSourceVersion, TermCodeSystemVersion.MAX_VERSION_LENGTH,
|
||||||
|
"Source version ID exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): " + length(theSourceVersion));
|
||||||
mySourceVersion = theSourceVersion;
|
mySourceVersion = theSourceVersion;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTarget() {
|
public String getTarget() {
|
||||||
return myTarget;
|
return myTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTarget(String theTarget) {
|
public TermConceptMapGroup setTarget(@Nonnull String theTarget) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theTarget, "theTarget must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTarget, TermCodeSystem.MAX_URL_LENGTH,
|
||||||
|
"Target exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theTarget));
|
||||||
this.myTarget = theTarget;
|
this.myTarget = theTarget;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTargetValueSet() {
|
public String getTargetValueSet() {
|
||||||
|
@ -134,13 +152,16 @@ public class TermConceptMapGroup implements Serializable {
|
||||||
return myTargetVersion;
|
return myTargetVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTargetVersion(String theTargetVersion) {
|
public TermConceptMapGroup setTargetVersion(String theTargetVersion) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTargetVersion, TermCodeSystemVersion.MAX_VERSION_LENGTH,
|
||||||
|
"Target version ID exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): " + length(theTargetVersion));
|
||||||
myTargetVersion = theTargetVersion;
|
myTargetVersion = theTargetVersion;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
.append("myId", myId)
|
.append("myId", myId)
|
||||||
.append(myConceptMap != null ? ("myConceptMap - id=" + myConceptMap.getId()) : ("myConceptMap=(null)"))
|
.append(myConceptMap != null ? ("myConceptMap - id=" + myConceptMap.getId()) : ("myConceptMap=(null)"))
|
||||||
.append("mySource", mySource)
|
.append("mySource", mySource)
|
||||||
|
|
|
@ -20,22 +20,28 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_MAP_GRP_ELEMENT", indexes = {
|
@Table(name = "TRM_CONCEPT_MAP_GRP_ELEMENT", indexes = {
|
||||||
@Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE")
|
@Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE")
|
||||||
})
|
})
|
||||||
public class TermConceptMapGroupElement implements Serializable {
|
public class TermConceptMapGroupElement implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GRP_ELM_PID", sequenceName = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
|
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GRP_ELM_PID", sequenceName = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
|
||||||
|
@ -46,7 +52,7 @@ public class TermConceptMapGroupElement implements Serializable {
|
||||||
@JoinColumn(name = "CONCEPT_MAP_GROUP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP"))
|
@JoinColumn(name = "CONCEPT_MAP_GROUP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP"))
|
||||||
private TermConceptMapGroup myConceptMapGroup;
|
private TermConceptMapGroup myConceptMapGroup;
|
||||||
|
|
||||||
@Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.CODE_LENGTH)
|
@Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
|
||||||
private String myCode;
|
private String myCode;
|
||||||
|
|
||||||
@Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DESC_LENGTH)
|
@Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DESC_LENGTH)
|
||||||
|
@ -55,33 +61,37 @@ public class TermConceptMapGroupElement implements Serializable {
|
||||||
@OneToMany(mappedBy = "myConceptMapGroupElement")
|
@OneToMany(mappedBy = "myConceptMapGroupElement")
|
||||||
private List<TermConceptMapGroupElementTarget> myConceptMapGroupElementTargets;
|
private List<TermConceptMapGroupElementTarget> myConceptMapGroupElementTargets;
|
||||||
|
|
||||||
@Column(name = "CONCEPT_MAP_URL", length = 200)
|
@Column(name = "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
|
||||||
private String myConceptMapUrl;
|
private String myConceptMapUrl;
|
||||||
|
|
||||||
@Column(name = "SYSTEM_URL", length = 200)
|
@Column(name = "SYSTEM_URL", nullable = true, length = TermCodeSystem.MAX_URL_LENGTH)
|
||||||
private String mySystem;
|
private String mySystem;
|
||||||
|
|
||||||
@Column(name = "SYSTEM_VERSION", length = 200)
|
@Column(name = "SYSTEM_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
|
||||||
private String mySystemVersion;
|
private String mySystemVersion;
|
||||||
|
|
||||||
@Column(name = "VALUESET_URL", length = 200)
|
@Column(name = "VALUESET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String myValueSet;
|
private String myValueSet;
|
||||||
|
|
||||||
public String getCode() {
|
public String getCode() {
|
||||||
return myCode;
|
return myCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCode(String theCode) {
|
public TermConceptMapGroupElement setCode(@Nonnull String theCode) {
|
||||||
Validate.notBlank(theCode, "theCode must not be blank");
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
|
||||||
|
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
|
||||||
myCode = theCode;
|
myCode = theCode;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptMapGroup getConceptMapGroup() {
|
public TermConceptMapGroup getConceptMapGroup() {
|
||||||
return myConceptMapGroup;
|
return myConceptMapGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) {
|
public TermConceptMapGroupElement setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) {
|
||||||
myConceptMapGroup = theTermConceptMapGroup;
|
myConceptMapGroup = theTermConceptMapGroup;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TermConceptMapGroupElementTarget> getConceptMapGroupElementTargets() {
|
public List<TermConceptMapGroupElementTarget> getConceptMapGroupElementTargets() {
|
||||||
|
@ -103,8 +113,9 @@ public class TermConceptMapGroupElement implements Serializable {
|
||||||
return myDisplay;
|
return myDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplay(String theDisplay) {
|
public TermConceptMapGroupElement setDisplay(String theDisplay) {
|
||||||
myDisplay = theDisplay;
|
myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
@ -158,7 +169,7 @@ public class TermConceptMapGroupElement implements Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
.append("myId", myId)
|
.append("myId", myId)
|
||||||
.append(myConceptMapGroup != null ? ("myConceptMapGroup - id=" + myConceptMapGroup.getId()) : ("myConceptMapGroup=(null)"))
|
.append(myConceptMapGroup != null ? ("myConceptMapGroup - id=" + myConceptMapGroup.getId()) : ("myConceptMapGroup=(null)"))
|
||||||
.append("myCode", myCode)
|
.append("myCode", myCode)
|
||||||
|
|
|
@ -20,20 +20,28 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_MAP_GRP_ELM_TGT", indexes = {
|
@Table(name = "TRM_CONCEPT_MAP_GRP_ELM_TGT", indexes = {
|
||||||
@Index(name = "IDX_CNCPT_MP_GRP_ELM_TGT_CD", columnList = "TARGET_CODE")
|
@Index(name = "IDX_CNCPT_MP_GRP_ELM_TGT_CD", columnList = "TARGET_CODE")
|
||||||
})
|
})
|
||||||
public class TermConceptMapGroupElementTarget implements Serializable {
|
public class TermConceptMapGroupElementTarget implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
static final int MAX_EQUIVALENCE_LENGTH = 50;
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID", sequenceName = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
|
@SequenceGenerator(name = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID", sequenceName = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
|
||||||
|
@ -44,31 +52,38 @@ public class TermConceptMapGroupElementTarget implements Serializable {
|
||||||
@JoinColumn(name = "CONCEPT_MAP_GRP_ELM_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGETARGET_ELEMENT"))
|
@JoinColumn(name = "CONCEPT_MAP_GRP_ELM_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGETARGET_ELEMENT"))
|
||||||
private TermConceptMapGroupElement myConceptMapGroupElement;
|
private TermConceptMapGroupElement myConceptMapGroupElement;
|
||||||
|
|
||||||
@Column(name = "TARGET_CODE", nullable = false, length = TermConcept.CODE_LENGTH)
|
@Column(name = "TARGET_CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
|
||||||
private String myCode;
|
private String myCode;
|
||||||
|
|
||||||
@Column(name = "TARGET_DISPLAY", length = TermConcept.MAX_DESC_LENGTH)
|
@Column(name = "TARGET_DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH)
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@Column(name = "TARGET_EQUIVALENCE", length = 50)
|
@Column(name = "TARGET_EQUIVALENCE", nullable = true, length = MAX_EQUIVALENCE_LENGTH)
|
||||||
private ConceptMapEquivalence myEquivalence;
|
private ConceptMapEquivalence myEquivalence;
|
||||||
|
|
||||||
@Column(name = "CONCEPT_MAP_URL", length = 200)
|
@Column(name = "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
|
||||||
private String myConceptMapUrl;
|
private String myConceptMapUrl;
|
||||||
@Column(name = "SYSTEM_URL", length = 200)
|
|
||||||
|
@Column(name = "SYSTEM_URL", nullable = true, length = TermCodeSystem.MAX_URL_LENGTH)
|
||||||
private String mySystem;
|
private String mySystem;
|
||||||
@Column(name = "SYSTEM_VERSION", length = 200)
|
|
||||||
|
@Column(name = "SYSTEM_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
|
||||||
private String mySystemVersion;
|
private String mySystemVersion;
|
||||||
@Column(name = "VALUESET_URL", length = 200)
|
|
||||||
|
@Column(name = "VALUESET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||||
private String myValueSet;
|
private String myValueSet;
|
||||||
|
|
||||||
public String getCode() {
|
public String getCode() {
|
||||||
return myCode;
|
return myCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCode(String theCode) {
|
public TermConceptMapGroupElementTarget setCode(@Nonnull String theCode) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
|
||||||
|
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
|
||||||
myCode = theCode;
|
myCode = theCode;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptMapGroupElement getConceptMapGroupElement() {
|
public TermConceptMapGroupElement getConceptMapGroupElement() {
|
||||||
|
@ -90,16 +105,18 @@ public class TermConceptMapGroupElementTarget implements Serializable {
|
||||||
return myDisplay;
|
return myDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplay(String theDisplay) {
|
public TermConceptMapGroupElementTarget setDisplay(String theDisplay) {
|
||||||
myDisplay = theDisplay;
|
myDisplay = theDisplay;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConceptMapEquivalence getEquivalence() {
|
public ConceptMapEquivalence getEquivalence() {
|
||||||
return myEquivalence;
|
return myEquivalence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEquivalence(ConceptMapEquivalence theEquivalence) {
|
public TermConceptMapGroupElementTarget setEquivalence(ConceptMapEquivalence theEquivalence) {
|
||||||
myEquivalence = theEquivalence;
|
myEquivalence = theEquivalence;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
@ -155,7 +172,7 @@ public class TermConceptMapGroupElementTarget implements Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
.append("myId", myId)
|
.append("myId", myId)
|
||||||
.append(myConceptMapGroupElement != null ? ("myConceptMapGroupElement - id=" + myConceptMapGroupElement.getId()) : ("myConceptMapGroupElement=(null)"))
|
.append(myConceptMapGroupElement != null ? ("myConceptMapGroupElement - id=" + myConceptMapGroupElement.getId()) : ("myConceptMapGroupElement=(null)"))
|
||||||
.append("myCode", myCode)
|
.append("myCode", myCode)
|
||||||
|
|
|
@ -20,21 +20,9 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.EnumType;
|
|
||||||
import javax.persistence.Enumerated;
|
|
||||||
import javax.persistence.ForeignKey;
|
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.GenerationType;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
import javax.persistence.SequenceGenerator;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_PC_LINK")
|
@Table(name = "TRM_CONCEPT_PC_LINK")
|
||||||
public class TermConceptParentChildLink implements Serializable {
|
public class TermConceptParentChildLink implements Serializable {
|
||||||
|
@ -136,20 +124,24 @@ public class TermConceptParentChildLink implements Serializable {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChild(TermConcept theChild) {
|
public TermConceptParentChildLink setChild(TermConcept theChild) {
|
||||||
myChild = theChild;
|
myChild = theChild;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSystem(TermCodeSystemVersion theCodeSystem) {
|
public TermConceptParentChildLink setCodeSystem(TermCodeSystemVersion theCodeSystem) {
|
||||||
myCodeSystem = theCodeSystem;
|
myCodeSystem = theCodeSystem;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParent(TermConcept theParent) {
|
public TermConceptParentChildLink setParent(TermConcept theParent) {
|
||||||
myParent = theParent;
|
myParent = theParent;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRelationshipType(RelationshipTypeEnum theRelationshipType) {
|
public TermConceptParentChildLink setRelationshipType(RelationshipTypeEnum theRelationshipType) {
|
||||||
myRelationshipType = theRelationshipType;
|
myRelationshipType = theRelationshipType;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RelationshipTypeEnum {
|
public enum RelationshipTypeEnum {
|
||||||
|
|
|
@ -20,21 +20,29 @@ package ca.uhn.fhir.jpa.entity;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRM_CONCEPT_PROPERTY", uniqueConstraints = {
|
@Table(name = "TRM_CONCEPT_PROPERTY", uniqueConstraints = {
|
||||||
}, indexes = {
|
}, indexes = {
|
||||||
})
|
})
|
||||||
public class TermConceptProperty implements Serializable {
|
public class TermConceptProperty implements Serializable {
|
||||||
|
|
||||||
static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final int MAX_LENGTH = 500;
|
||||||
|
static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT"))
|
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT"))
|
||||||
private TermConcept myConcept;
|
private TermConcept myConcept;
|
||||||
|
@ -51,22 +59,22 @@ public class TermConceptProperty implements Serializable {
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PROP_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PROP_PID")
|
||||||
@Column(name = "PID")
|
@Column(name = "PID")
|
||||||
private Long myId;
|
private Long myId;
|
||||||
@Column(name = "PROP_KEY", length = 500, nullable = false)
|
@Column(name = "PROP_KEY", nullable = false, length = MAX_LENGTH)
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String myKey;
|
private String myKey;
|
||||||
@Column(name = "PROP_VAL", length = 500, nullable = true)
|
@Column(name = "PROP_VAL", nullable = true, length = MAX_LENGTH)
|
||||||
private String myValue;
|
private String myValue;
|
||||||
@Column(name = "PROP_TYPE", length = MAX_PROPTYPE_ENUM_LENGTH, nullable = false)
|
@Column(name = "PROP_TYPE", nullable = false, length = MAX_PROPTYPE_ENUM_LENGTH)
|
||||||
private TermConceptPropertyTypeEnum myType;
|
private TermConceptPropertyTypeEnum myType;
|
||||||
/**
|
/**
|
||||||
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
||||||
*/
|
*/
|
||||||
@Column(name = "PROP_CODESYSTEM", length = 500, nullable = true)
|
@Column(name = "PROP_CODESYSTEM", length = MAX_LENGTH, nullable = true)
|
||||||
private String myCodeSystem;
|
private String myCodeSystem;
|
||||||
/**
|
/**
|
||||||
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
||||||
*/
|
*/
|
||||||
@Column(name = "PROP_DISPLAY", length = 500, nullable = true)
|
@Column(name = "PROP_DISPLAY", length = MAX_LENGTH, nullable = true)
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,6 +88,8 @@ public class TermConceptProperty implements Serializable {
|
||||||
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
||||||
*/
|
*/
|
||||||
public TermConceptProperty setCodeSystem(String theCodeSystem) {
|
public TermConceptProperty setCodeSystem(String theCodeSystem) {
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCodeSystem, MAX_LENGTH,
|
||||||
|
"Property code system exceeds maximum length (" + MAX_LENGTH + "): " + length(theCodeSystem));
|
||||||
myCodeSystem = theCodeSystem;
|
myCodeSystem = theCodeSystem;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +105,7 @@ public class TermConceptProperty implements Serializable {
|
||||||
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
||||||
*/
|
*/
|
||||||
public TermConceptProperty setDisplay(String theDisplay) {
|
public TermConceptProperty setDisplay(String theDisplay) {
|
||||||
myDisplay = theDisplay;
|
myDisplay = left(theDisplay, MAX_LENGTH);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,15 +113,20 @@ public class TermConceptProperty implements Serializable {
|
||||||
return myKey;
|
return myKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKey(String theKey) {
|
public TermConceptProperty setKey(@Nonnull String theKey) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theKey, "theKey must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theKey, MAX_LENGTH,
|
||||||
|
"Code exceeds maximum length (" + MAX_LENGTH + "): " + length(theKey));
|
||||||
myKey = theKey;
|
myKey = theKey;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptPropertyTypeEnum getType() {
|
public TermConceptPropertyTypeEnum getType() {
|
||||||
return myType;
|
return myType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptProperty setType(TermConceptPropertyTypeEnum theType) {
|
public TermConceptProperty setType(@Nonnull TermConceptPropertyTypeEnum theType) {
|
||||||
|
Validate.notNull(theType);
|
||||||
myType = theType;
|
myType = theType;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -128,8 +143,9 @@ public class TermConceptProperty implements Serializable {
|
||||||
* This will contain the value for a {@link TermConceptPropertyTypeEnum#STRING string}
|
* This will contain the value for a {@link TermConceptPropertyTypeEnum#STRING string}
|
||||||
* property, and the code for a {@link TermConceptPropertyTypeEnum#CODING coding} property.
|
* property, and the code for a {@link TermConceptPropertyTypeEnum#CODING coding} property.
|
||||||
*/
|
*/
|
||||||
public void setValue(String theValue) {
|
public TermConceptProperty setValue(String theValue) {
|
||||||
myValue = theValue;
|
myValue = left(theValue, MAX_LENGTH);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConceptProperty setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
|
public TermConceptProperty setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
|
||||||
|
@ -137,8 +153,9 @@ public class TermConceptProperty implements Serializable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConcept(TermConcept theConcept) {
|
public TermConceptProperty setConcept(TermConcept theConcept) {
|
||||||
myConcept = theConcept;
|
myConcept = theConcept;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
package ca.uhn.fhir.jpa.entity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%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.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
|
@Table(name = "TRM_VALUESET", uniqueConstraints = {
|
||||||
|
@UniqueConstraint(name = "IDX_VALUESET_URL", columnNames = {"URL"})
|
||||||
|
})
|
||||||
|
@Entity()
|
||||||
|
public class TermValueSet implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final int MAX_NAME_LENGTH = 200;
|
||||||
|
public static final int MAX_URL_LENGTH = 200;
|
||||||
|
|
||||||
|
@Id()
|
||||||
|
@SequenceGenerator(name = "SEQ_VALUESET_PID", sequenceName = "SEQ_VALUESET_PID")
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_PID")
|
||||||
|
@Column(name = "PID")
|
||||||
|
private Long myId;
|
||||||
|
|
||||||
|
@Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
|
||||||
|
private String myUrl;
|
||||||
|
|
||||||
|
@OneToOne()
|
||||||
|
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES"))
|
||||||
|
private ResourceTable myResource;
|
||||||
|
|
||||||
|
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||||
|
private Long myResourcePid;
|
||||||
|
|
||||||
|
@Column(name = "NAME", nullable = true, length = MAX_NAME_LENGTH)
|
||||||
|
private String myName;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "myValueSet")
|
||||||
|
private List<TermValueSetCode> myCodes;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return myId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return myUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSet setUrl(@Nonnull String theUrl) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUrl, MAX_URL_LENGTH,
|
||||||
|
"URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl));
|
||||||
|
myUrl = theUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceTable getResource() {
|
||||||
|
return myResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSet setResource(ResourceTable theResource) {
|
||||||
|
myResource = theResource;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return myName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSet setName(String theName) {
|
||||||
|
myName = left(theName, MAX_NAME_LENGTH);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TermValueSetCode> getCodes() {
|
||||||
|
if (myCodes == null) {
|
||||||
|
myCodes = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return myCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object theO) {
|
||||||
|
if (this == theO) return true;
|
||||||
|
|
||||||
|
if (!(theO instanceof TermValueSet)) return false;
|
||||||
|
|
||||||
|
TermValueSet that = (TermValueSet) theO;
|
||||||
|
|
||||||
|
return new EqualsBuilder()
|
||||||
|
.append(getUrl(), that.getUrl())
|
||||||
|
.isEquals();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37)
|
||||||
|
.append(getUrl())
|
||||||
|
.toHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
|
.append("myId", myId)
|
||||||
|
.append("myUrl", myUrl)
|
||||||
|
.append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
|
||||||
|
.append("myResourcePid", myResourcePid)
|
||||||
|
.append("myName", myName)
|
||||||
|
.append(myCodes != null ? ("myCodes - size=" + myCodes.size()) : ("myCodes=(null)"))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
package ca.uhn.fhir.jpa.entity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%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.util.ValidateUtil;
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.left;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.length;
|
||||||
|
|
||||||
|
@Table(name = "TRM_VALUESET_CODE", indexes = {
|
||||||
|
@Index(name = "IDX_VALUESET_CODE_CS_CD", columnList = "SYSTEM, CODE")
|
||||||
|
})
|
||||||
|
@Entity()
|
||||||
|
public class TermValueSetCode implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id()
|
||||||
|
@SequenceGenerator(name = "SEQ_VALUESET_CODE_PID", sequenceName = "SEQ_VALUESET_CODE_PID")
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_CODE_PID")
|
||||||
|
@Column(name = "PID")
|
||||||
|
private Long myId;
|
||||||
|
|
||||||
|
@ManyToOne()
|
||||||
|
@JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID"))
|
||||||
|
private TermValueSet myValueSet;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private String myValueSetUrl;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private String myValueSetName;
|
||||||
|
|
||||||
|
@Column(name = "SYSTEM", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
|
||||||
|
private String mySystem;
|
||||||
|
|
||||||
|
@Column(name = "CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
|
||||||
|
private String myCode;
|
||||||
|
|
||||||
|
@Column(name = "DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH)
|
||||||
|
private String myDisplay;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return myId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSet getValueSet() {
|
||||||
|
return myValueSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSetCode setValueSet(TermValueSet theValueSet) {
|
||||||
|
myValueSet = theValueSet;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValueSetUrl() {
|
||||||
|
if (myValueSetUrl == null) {
|
||||||
|
myValueSetUrl = getValueSet().getUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
return myValueSetUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValueSetName() {
|
||||||
|
if (myValueSetName == null) {
|
||||||
|
myValueSetName = getValueSet().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return myValueSetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSetCode setSystem(@Nonnull String theSystem) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theSystem, "theSystem must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSystem, TermCodeSystem.MAX_URL_LENGTH,
|
||||||
|
"System exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSystem));
|
||||||
|
mySystem = theSystem;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return myCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSetCode setCode(@Nonnull String theCode) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
|
||||||
|
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
|
||||||
|
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
|
||||||
|
myCode = theCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplay() {
|
||||||
|
return myDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TermValueSetCode setDisplay(String theDisplay) {
|
||||||
|
myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object theO) {
|
||||||
|
if (this == theO) return true;
|
||||||
|
|
||||||
|
if (!(theO instanceof TermValueSetCode)) return false;
|
||||||
|
|
||||||
|
TermValueSetCode that = (TermValueSetCode) theO;
|
||||||
|
|
||||||
|
return new EqualsBuilder()
|
||||||
|
.append(getValueSetUrl(), that.getValueSetUrl())
|
||||||
|
.append(getSystem(), that.getSystem())
|
||||||
|
.append(getCode(), that.getCode())
|
||||||
|
.isEquals();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37)
|
||||||
|
.append(getValueSetUrl())
|
||||||
|
.append(getSystem())
|
||||||
|
.append(getCode())
|
||||||
|
.toHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
|
.append("myId", myId)
|
||||||
|
.append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)"))
|
||||||
|
.append("myValueSetUrl", this.getValueSetUrl())
|
||||||
|
.append("myValueSetName", this.getValueSetName())
|
||||||
|
.append("mySystem", mySystem)
|
||||||
|
.append("myCode", myCode)
|
||||||
|
.append("myDisplay", myDisplay)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -410,6 +410,14 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
||||||
PersistedJpaBundleProvider retVal = null;
|
PersistedJpaBundleProvider retVal = null;
|
||||||
if (searchToUse != null) {
|
if (searchToUse != null) {
|
||||||
ourLog.debug("Reusing search {} from cache", searchToUse.getUuid());
|
ourLog.debug("Reusing search {} from cache", searchToUse.getUuid());
|
||||||
|
|
||||||
|
// Interceptor call: JPA_PERFTRACE_SEARCH_REUSING_CACHED
|
||||||
|
params = new HookParams()
|
||||||
|
.add(SearchParameterMap.class, theParams)
|
||||||
|
.add(RequestDetails.class, theRequestDetails)
|
||||||
|
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequestDetails, Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED, params);
|
||||||
|
|
||||||
searchToUse.setSearchLastReturned(new Date());
|
searchToUse.setSearchLastReturned(new Date());
|
||||||
mySearchDao.updateSearchLastReturned(searchToUse.getId(), new Date());
|
mySearchDao.updateSearchLastReturned(searchToUse.getId(), new Date());
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ITermConceptDesignationDao myConceptDesignationDao;
|
protected ITermConceptDesignationDao myConceptDesignationDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected ITermValueSetDao myValueSetDao;
|
||||||
|
@Autowired
|
||||||
|
protected ITermValueSetCodeDao myValueSetCodeDao;
|
||||||
|
@Autowired
|
||||||
protected FhirContext myContext;
|
protected FhirContext myContext;
|
||||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||||
protected EntityManager myEntityManager;
|
protected EntityManager myEntityManager;
|
||||||
|
@ -388,6 +392,31 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
deleteConceptMap(theResourceTable);
|
deleteConceptMap(theResourceTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteValueSet(ResourceTable theResourceTable) {
|
||||||
|
// Get existing entity so it can be deleted.
|
||||||
|
Optional<TermValueSet> optionalExistingTermValueSetById = myValueSetDao.findByResourcePid(theResourceTable.getId());
|
||||||
|
|
||||||
|
if (optionalExistingTermValueSetById.isPresent()) {
|
||||||
|
TermValueSet existingTermValueSet = optionalExistingTermValueSetById.get();
|
||||||
|
|
||||||
|
ourLog.info("Deleting existing TermValueSet {} and its children...", existingTermValueSet.getId());
|
||||||
|
myValueSetCodeDao.deleteTermValueSetCodesByValueSetId(existingTermValueSet.getId());
|
||||||
|
myValueSetDao.deleteTermValueSetById(existingTermValueSet.getId());
|
||||||
|
ourLog.info("Done deleting existing TermValueSet {} and its children.", existingTermValueSet.getId());
|
||||||
|
|
||||||
|
ourLog.info("Flushing...");
|
||||||
|
myValueSetCodeDao.flush();
|
||||||
|
myValueSetDao.flush();
|
||||||
|
ourLog.info("Done flushing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void deleteValueSetAndChildren(ResourceTable theResourceTable) {
|
||||||
|
deleteValueSet(theResourceTable);
|
||||||
|
}
|
||||||
|
|
||||||
private <T> void doDelete(String theDescriptor, Supplier<Slice<T>> theLoader, Supplier<Integer> theCounter, JpaRepository<T, ?> theDao) {
|
private <T> void doDelete(String theDescriptor, Supplier<Slice<T>> theLoader, Supplier<Integer> theCounter, JpaRepository<T, ?> theDao) {
|
||||||
int count;
|
int count;
|
||||||
ourLog.info(" * Deleting {}", theDescriptor);
|
ourLog.info(" * Deleting {}", theDescriptor);
|
||||||
|
@ -690,7 +719,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
|
|
||||||
private void expandWithoutHibernateSearch(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) {
|
private void expandWithoutHibernateSearch(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) {
|
||||||
ourLog.trace("Hibernate search is not enabled");
|
ourLog.trace("Hibernate search is not enabled");
|
||||||
Validate.isTrue(theExpansionComponent.getParameter().isEmpty(), "Can not exapnd ValueSet with parameters - Hibernate Search is not enabled on this server.");
|
Validate.isTrue(theExpansionComponent.getParameter().isEmpty(), "Can not expand ValueSet with parameters - Hibernate Search is not enabled on this server.");
|
||||||
Validate.isTrue(theInclude.getFilter().isEmpty(), "Can not expand ValueSet with filters - Hibernate Search is not enabled on this server.");
|
Validate.isTrue(theInclude.getFilter().isEmpty(), "Can not expand ValueSet with filters - Hibernate Search is not enabled on this server.");
|
||||||
Validate.isTrue(isNotBlank(theSystem), "Can not expand ValueSet without explicit system - Hibernate Search is not enabled on this server.");
|
Validate.isTrue(isNotBlank(theSystem), "Can not expand ValueSet without explicit system - Hibernate Search is not enabled on this server.");
|
||||||
|
|
||||||
|
@ -1144,7 +1173,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
myCodeSystemDao.save(codeSystem);
|
myCodeSystemDao.save(codeSystem);
|
||||||
} else {
|
} else {
|
||||||
if (!ObjectUtil.equals(codeSystem.getResource().getId(), theCodeSystemVersion.getResource().getId())) {
|
if (!ObjectUtil.equals(codeSystem.getResource().getId(), theCodeSystemVersion.getResource().getId())) {
|
||||||
String msg = myContext.getLocalizer().getMessage(BaseHapiTerminologySvcImpl.class, "cannotCreateDuplicateCodeSystemUri", theSystemUri,
|
String msg = myContext.getLocalizer().getMessage(BaseHapiTerminologySvcImpl.class, "cannotCreateDuplicateCodeSystemUrl", theSystemUri,
|
||||||
codeSystem.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
codeSystem.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||||
throw new UnprocessableEntityException(msg);
|
throw new UnprocessableEntityException(msg);
|
||||||
}
|
}
|
||||||
|
@ -1310,7 +1339,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
|
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
|
||||||
|
|
||||||
if (codesSaved++ % 250 == 0) {
|
if (codesSaved++ % 250 == 0) {
|
||||||
ourLog.info("Have saved {} codes in conceptmap", codesSaved);
|
ourLog.info("Have saved {} codes in ConceptMap", codesSaved);
|
||||||
myConceptMapGroupElementTargetDao.flush();
|
myConceptMapGroupElementTargetDao.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1334,6 +1363,69 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
ourLog.info("Done storing TermConceptMap.");
|
ourLog.info("Done storing TermConceptMap.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void storeTermValueSetAndChildren(ResourceTable theResourceTable, ValueSet theValueSet) {
|
||||||
|
ourLog.info("Storing TermValueSet {}", theValueSet.getIdElement().getValue());
|
||||||
|
|
||||||
|
ValidateUtil.isTrueOrThrowInvalidRequest(theResourceTable != null, "No resource supplied");
|
||||||
|
ValidateUtil.isNotBlankOrThrowUnprocessableEntity(theValueSet.getUrl(), "ValueSet has no value for ValueSet.url");
|
||||||
|
|
||||||
|
TermValueSet termValueSet = new TermValueSet();
|
||||||
|
termValueSet.setResource(theResourceTable);
|
||||||
|
termValueSet.setUrl(theValueSet.getUrl());
|
||||||
|
termValueSet.setName(theValueSet.hasName() ? theValueSet.getName() : null);
|
||||||
|
|
||||||
|
// We delete old versions; we don't support versioned ValueSets.
|
||||||
|
deleteValueSet(theResourceTable);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the upload.
|
||||||
|
*/
|
||||||
|
String url = termValueSet.getUrl();
|
||||||
|
Optional<TermValueSet> optionalExistingTermValueSetByUrl = myValueSetDao.findByUrl(url);
|
||||||
|
if (!optionalExistingTermValueSetByUrl.isPresent()) {
|
||||||
|
myValueSetDao.save(termValueSet);
|
||||||
|
int codesSaved = 0;
|
||||||
|
|
||||||
|
ValueSet expandedValueSet = expandValueSet(theValueSet);
|
||||||
|
if (expandedValueSet.hasExpansion()) {
|
||||||
|
if (expandedValueSet.getExpansion().hasTotal() && expandedValueSet.getExpansion().getTotal() > 0) {
|
||||||
|
TermValueSetCode code;
|
||||||
|
for (ValueSet.ValueSetExpansionContainsComponent contains : expandedValueSet.getExpansion().getContains()) {
|
||||||
|
ValidateUtil.isNotBlankOrThrowInvalidRequest(contains.getSystem(), "ValueSet contains a code with no system value");
|
||||||
|
ValidateUtil.isNotBlankOrThrowInvalidRequest(contains.getCode(), "ValueSet contains a code with no code value");
|
||||||
|
|
||||||
|
code = new TermValueSetCode();
|
||||||
|
code.setValueSet(termValueSet);
|
||||||
|
code.setSystem(contains.getSystem());
|
||||||
|
code.setCode(contains.getCode());
|
||||||
|
code.setDisplay(contains.hasDisplay() ? contains.getDisplay() : null);
|
||||||
|
myValueSetCodeDao.save(code);
|
||||||
|
|
||||||
|
if (codesSaved++ % 250 == 0) {
|
||||||
|
ourLog.info("Have pre-expanded {} codes in ValueSet", codesSaved);
|
||||||
|
myValueSetCodeDao.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
TermValueSet existingTermValueSet = optionalExistingTermValueSetByUrl.get();
|
||||||
|
|
||||||
|
String msg = myContext.getLocalizer().getMessage(
|
||||||
|
BaseHapiTerminologySvcImpl.class,
|
||||||
|
"cannotCreateDuplicateValueSetUrl",
|
||||||
|
url,
|
||||||
|
existingTermValueSet.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||||
|
|
||||||
|
throw new UnprocessableEntityException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info("Done storing TermValueSet.");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
|
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
|
||||||
VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
|
VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
|
||||||
|
@ -1581,9 +1673,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
|
|
||||||
private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, ArrayList<String> theConceptsStack,
|
private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, ArrayList<String> theConceptsStack,
|
||||||
IdentityHashMap<TermConcept, Object> theAllConcepts) {
|
IdentityHashMap<TermConcept, Object> theAllConcepts) {
|
||||||
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() != null, "CodesystemValue is null");
|
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() != null, "CodeSystemVersion is null");
|
||||||
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() == theCodeSystem, "CodeSystems are not equal");
|
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() == theCodeSystem, "CodeSystems are not equal");
|
||||||
ValidateUtil.isNotBlankOrThrowInvalidRequest(theConcept.getCode(), "Codesystem contains a code with no code value");
|
ValidateUtil.isNotBlankOrThrowInvalidRequest(theConcept.getCode(), "CodeSystem contains a code with no code value");
|
||||||
|
|
||||||
if (theConceptsStack.contains(theConcept.getCode())) {
|
if (theConceptsStack.contains(theConcept.getCode())) {
|
||||||
throw new InvalidRequestException("CodeSystem contains circular reference around code " + theConcept.getCode());
|
throw new InvalidRequestException("CodeSystem contains circular reference around code " + theConcept.getCode());
|
||||||
|
|
|
@ -81,8 +81,12 @@ public interface IHapiTerminologySvc {
|
||||||
|
|
||||||
void deleteConceptMapAndChildren(ResourceTable theResourceTable);
|
void deleteConceptMapAndChildren(ResourceTable theResourceTable);
|
||||||
|
|
||||||
|
void deleteValueSetAndChildren(ResourceTable theResourceTable);
|
||||||
|
|
||||||
void storeTermConceptMapAndChildren(ResourceTable theResourceTable, ConceptMap theConceptMap);
|
void storeTermConceptMapAndChildren(ResourceTable theResourceTable, ConceptMap theConceptMap);
|
||||||
|
|
||||||
|
void storeTermValueSetAndChildren(ResourceTable theResourceTable, ValueSet theValueSet);
|
||||||
|
|
||||||
boolean supportsSystem(String theCodeSystem);
|
boolean supportsSystem(String theCodeSystem);
|
||||||
|
|
||||||
List<TermConceptMapGroupElementTarget> translate(TranslationRequest theTranslationRequest);
|
List<TermConceptMapGroupElementTarget> translate(TranslationRequest theTranslationRequest);
|
||||||
|
|
|
@ -5,7 +5,6 @@ import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
import net.ttddyy.dsproxy.listener.SingleQueryCountHolder;
|
import net.ttddyy.dsproxy.listener.SingleQueryCountHolder;
|
||||||
import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel;
|
|
||||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -104,7 +103,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
||||||
|
|
||||||
DataSource dataSource = ProxyDataSourceBuilder
|
DataSource dataSource = ProxyDataSourceBuilder
|
||||||
.create(retVal)
|
.create(retVal)
|
||||||
.logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
|
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
|
||||||
// .logSlowQueryBySlf4j(10, TimeUnit.SECONDS)
|
// .logSlowQueryBySlf4j(10, TimeUnit.SECONDS)
|
||||||
// .countQuery(new ThreadQueryCountHolder())
|
// .countQuery(new ThreadQueryCountHolder())
|
||||||
.beforeQuery(new BlockLargeNumbersOfParamsListener())
|
.beforeQuery(new BlockLargeNumbersOfParamsListener())
|
||||||
|
|
|
@ -1,31 +1,13 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
|
||||||
import static org.hamcrest.Matchers.empty;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
|
||||||
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
|
||||||
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.*;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.junit.*;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
import ca.uhn.fhir.jpa.model.entity.*;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.*;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
@ -35,6 +17,25 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import ca.uhn.fhir.validation.FhirValidator;
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
import ca.uhn.fhir.validation.ValidationResult;
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
|
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
||||||
|
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
|
@ -226,7 +227,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
myCodeSystemDao.create(codeSystem, mySrd);
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnprocessableEntityException e) {
|
} catch (UnprocessableEntityException e) {
|
||||||
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,345 +0,0 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
|
||||||
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.rest.api.server.IBundleProvider;
|
|
||||||
import ca.uhn.fhir.rest.param.DateParam;
|
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
|
||||||
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.test.context.TestPropertySource;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.hamcrest.Matchers.empty;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "deprecation"})
|
|
||||||
@TestPropertySource(properties = {
|
|
||||||
// Since scheduled tasks can cause searches, which messes up the
|
|
||||||
// value returned by SearchBuilder.getLastHandlerMechanismForUnitTest()
|
|
||||||
"scheduling_disabled=true"
|
|
||||||
})
|
|
||||||
public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test {
|
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3UniqueSearchParamTest.class);
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void after() {
|
|
||||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void before() {
|
|
||||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createUniqueBirthdateAndGenderSps() {
|
|
||||||
SearchParameter sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-gender");
|
|
||||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
|
||||||
sp.setCode("gender");
|
|
||||||
sp.setExpression("Patient.gender");
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-birthdate");
|
|
||||||
sp.setType(Enumerations.SearchParamType.DATE);
|
|
||||||
sp.setCode("birthdate");
|
|
||||||
sp.setExpression("Patient.birthDate");
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-gender-birthdate");
|
|
||||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Patient")
|
|
||||||
.setDefinition(new Reference("SearchParameter/patient-gender"));
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Patient")
|
|
||||||
.setDefinition(new Reference("SearchParameter/patient-birthdate"));
|
|
||||||
sp.addExtension()
|
|
||||||
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
|
|
||||||
.setValue(new BooleanType(true));
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
mySearchParamRegistry.forceRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createUniqueIndexCoverageBeneficiary() {
|
|
||||||
SearchParameter sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/coverage-beneficiary");
|
|
||||||
sp.setCode("beneficiary");
|
|
||||||
sp.setExpression("Coverage.beneficiary");
|
|
||||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Coverage");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/coverage-identifier");
|
|
||||||
sp.setCode("identifier");
|
|
||||||
sp.setExpression("Coverage.identifier");
|
|
||||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Coverage");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/coverage-beneficiary-identifier");
|
|
||||||
sp.setCode("coverage-beneficiary-identifier");
|
|
||||||
sp.setExpression("Coverage.beneficiary");
|
|
||||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Coverage");
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Coverage")
|
|
||||||
.setDefinition(new Reference("/SearchParameter/coverage-beneficiary"));
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Coverage")
|
|
||||||
.setDefinition(new Reference("/SearchParameter/coverage-identifier"));
|
|
||||||
sp.addExtension()
|
|
||||||
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
|
|
||||||
.setValue(new BooleanType(true));
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
mySearchParamRegistry.forceRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createUniqueNameAndManagingOrganizationSps() {
|
|
||||||
SearchParameter sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-name");
|
|
||||||
sp.setType(Enumerations.SearchParamType.STRING);
|
|
||||||
sp.setCode("name");
|
|
||||||
sp.setExpression("Patient.name");
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-organization");
|
|
||||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
|
||||||
sp.setCode("organization");
|
|
||||||
sp.setExpression("Patient.managingOrganization");
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
sp = new SearchParameter();
|
|
||||||
sp.setId("SearchParameter/patient-name-organization");
|
|
||||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
|
||||||
sp.setStatus(PublicationStatus.ACTIVE);
|
|
||||||
sp.addBase("Patient");
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Patient")
|
|
||||||
.setDefinition(new Reference("SearchParameter/patient-name"));
|
|
||||||
sp.addComponent()
|
|
||||||
.setExpression("Patient")
|
|
||||||
.setDefinition(new Reference("SearchParameter/patient-organization"));
|
|
||||||
sp.addExtension()
|
|
||||||
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
|
|
||||||
.setValue(new BooleanType(true));
|
|
||||||
mySearchParameterDao.update(sp);
|
|
||||||
|
|
||||||
mySearchParamRegistry.forceRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDetectUniqueSearchParams() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
List<JpaRuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
|
|
||||||
|
|
||||||
assertEquals(1, params.size());
|
|
||||||
assertEquals(params.get(0).isUnique(), true);
|
|
||||||
assertEquals(2, params.get(0).getCompositeOf().size());
|
|
||||||
// Should be alphabetical order
|
|
||||||
assertEquals("birthdate", params.get(0).getCompositeOf().get(0).getName());
|
|
||||||
assertEquals("gender", params.get(0).getCompositeOf().get(1).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDuplicateUniqueValuesAreRejected() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
|
|
||||||
Patient pt1 = new Patient();
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
try {
|
|
||||||
myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
// good
|
|
||||||
}
|
|
||||||
|
|
||||||
Patient pt2 = new Patient();
|
|
||||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
pt2 = new Patient();
|
|
||||||
pt2.setId(id2);
|
|
||||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt2.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
try {
|
|
||||||
myPatientDao.update(pt2);
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
// good
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReplaceOneWithAnother() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
|
|
||||||
Patient pt1 = new Patient();
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualified();
|
|
||||||
assertNotNull(id1);
|
|
||||||
|
|
||||||
ourLog.info("** Replacing");
|
|
||||||
|
|
||||||
pt1 = new Patient();
|
|
||||||
pt1.setId(id1);
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
id1 = myPatientDao.update(pt1).getId().toUnqualified();
|
|
||||||
assertNotNull(id1);
|
|
||||||
assertEquals("2", id1.getVersionIdPart());
|
|
||||||
|
|
||||||
Patient pt2 = new Patient();
|
|
||||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt2.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
|
||||||
String searchId = results.getUuid();
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id2.getValue()));
|
|
||||||
assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchSynchronousUsingUniqueComposite() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
|
|
||||||
Patient pt1 = new Patient();
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Patient pt2 = new Patient();
|
|
||||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
|
||||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.setLoadSynchronousUpTo(100);
|
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
|
||||||
assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchUsingUniqueComposite() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
|
|
||||||
Patient pt1 = new Patient();
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
|
||||||
assertNotNull(id1);
|
|
||||||
|
|
||||||
Patient pt2 = new Patient();
|
|
||||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
|
||||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
|
||||||
String searchId = results.getUuid();
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
|
||||||
assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
|
||||||
// Other order
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
|
||||||
results = myPatientDao.search(params);
|
|
||||||
assertEquals(searchId, results.getUuid());
|
|
||||||
String id1Value = id1.getValue();
|
|
||||||
List<String> actualValues = toUnqualifiedVersionlessIdValues(results);
|
|
||||||
assertThat(actualValues, containsInAnyOrder(id1Value));
|
|
||||||
// Null because we just reuse the last search
|
|
||||||
assertEquals(null, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
|
||||||
params.add("birthdate", new DateParam("2011-01-03"));
|
|
||||||
results = myPatientDao.search(params);
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
|
||||||
assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add("birthdate", new DateParam("2011-01-03"));
|
|
||||||
results = myPatientDao.search(params);
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
|
||||||
assertEquals(SearchBuilder.HandlerTypeEnum.STANDARD_QUERY, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUniqueValuesAreIndexed_DateAndToken() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
|
|
||||||
Patient pt1 = new Patient();
|
|
||||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
|
||||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
|
||||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
|
||||||
assertEquals(1, uniques.size());
|
|
||||||
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
|
||||||
assertEquals("Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale", uniques.get(0).getIndexString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() {
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -118,6 +118,10 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
||||||
@Qualifier("myCodeSystemDaoR4")
|
@Qualifier("myCodeSystemDaoR4")
|
||||||
protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
|
protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected ITermCodeSystemDao myTermCodeSystemDao;
|
||||||
|
@Autowired
|
||||||
|
protected ITermCodeSystemVersionDao myTermCodeSystemVersionDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myCompartmentDefinitionDaoR4")
|
@Qualifier("myCompartmentDefinitionDaoR4")
|
||||||
protected IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao;
|
protected IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -287,6 +291,10 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
||||||
@Qualifier("myValueSetDaoR4")
|
@Qualifier("myValueSetDaoR4")
|
||||||
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected ITermValueSetDao myTermValueSetDao;
|
||||||
|
@Autowired
|
||||||
|
protected ITermValueSetCodeDao myTermValueSetCodeDao;
|
||||||
|
@Autowired
|
||||||
protected ITermConceptMapDao myTermConceptMapDao;
|
protected ITermConceptMapDao myTermConceptMapDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ITermConceptMapGroupElementTargetDao myTermConceptMapGroupElementTargetDao;
|
protected ITermConceptMapGroupElementTargetDao myTermConceptMapGroupElementTargetDao;
|
||||||
|
|
|
@ -222,7 +222,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
myCodeSystemDao.create(codeSystem, mySrd);
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnprocessableEntityException e) {
|
} catch (UnprocessableEntityException e) {
|
||||||
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
|
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
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.searchparam.JpaRuntimeSearchParam;
|
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
|
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.DateParam;
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
|
@ -17,6 +20,7 @@ import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
|
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.*;
|
||||||
|
@ -25,6 +29,7 @@ import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.test.context.TestPropertySource;
|
import org.springframework.test.context.TestPropertySource;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
@ -32,6 +37,7 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -40,8 +46,10 @@ import java.util.stream.Collectors;
|
||||||
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.INDEX_STATUS_INDEXED;
|
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.INDEX_STATUS_INDEXED;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "deprecation"})
|
|
||||||
@TestPropertySource(properties = {
|
@TestPropertySource(properties = {
|
||||||
// Since scheduled tasks can cause searches, which messes up the
|
// Since scheduled tasks can cause searches, which messes up the
|
||||||
// value returned by SearchBuilder.getLastHandlerMechanismForUnitTest()
|
// value returned by SearchBuilder.getLastHandlerMechanismForUnitTest()
|
||||||
|
@ -52,6 +60,8 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UniqueSearchParamTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UniqueSearchParamTest.class);
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchParamRegistry mySearchParamRegistry;
|
private ISearchParamRegistry mySearchParamRegistry;
|
||||||
|
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||||
|
private List<String> myMessages = new ArrayList<>();
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
|
@ -66,9 +76,31 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||||
myDaoConfig.setSchedulingDisabled(true);
|
myDaoConfig.setSchedulingDisabled(true);
|
||||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
|
||||||
|
myInterceptorBroadcaster = mock(IInterceptorBroadcaster.class);
|
||||||
|
when(mySrd.getInterceptorBroadcaster()).thenReturn(myInterceptorBroadcaster);
|
||||||
|
when(mySrd.getServer().getPagingProvider()).thenReturn(new DatabaseBackedPagingProvider());
|
||||||
|
|
||||||
|
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_WARNING))).thenReturn(true);
|
||||||
|
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_INFO))).thenReturn(true);
|
||||||
|
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_INFO), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||||
|
HookParams params = t.getArgument(1, HookParams.class);
|
||||||
|
myMessages.add("INFO " + params.get(StorageProcessingMessage.class).getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||||
|
HookParams params = t.getArgument(1, HookParams.class);
|
||||||
|
myMessages.add("WARN " + params.get(StorageProcessingMessage.class).getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||||
|
HookParams params = t.getArgument(1, HookParams.class);
|
||||||
|
myMessages.add("REUSING CACHED SEARCH");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createUniqueBirthdateAndGenderSps() {
|
private void createUniqueBirthdateAndGenderSps() {
|
||||||
SearchParameter sp = new SearchParameter();
|
SearchParameter sp = new SearchParameter();
|
||||||
sp.setId("SearchParameter/patient-gender");
|
sp.setId("SearchParameter/patient-gender");
|
||||||
|
@ -106,7 +138,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
mySearchParamRegistry.forceRefresh();
|
mySearchParamRegistry.forceRefresh();
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createUniqueIndexCoverageBeneficiary() {
|
private void createUniqueIndexCoverageBeneficiary() {
|
||||||
|
@ -322,19 +354,6 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
mySearchParamRegistry.forceRefresh();
|
mySearchParamRegistry.forceRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDetectUniqueSearchParams() {
|
|
||||||
createUniqueBirthdateAndGenderSps();
|
|
||||||
List<JpaRuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
|
|
||||||
|
|
||||||
assertEquals(1, params.size());
|
|
||||||
assertTrue(params.get(0).isUnique());
|
|
||||||
assertEquals(2, params.get(0).getCompositeOf().size());
|
|
||||||
// Should be alphabetical order
|
|
||||||
assertEquals("birthdate", params.get(0).getCompositeOf().get(0).getName());
|
|
||||||
assertEquals("gender", params.get(0).getCompositeOf().get(1).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoubleMatchingOnAnd_Search() {
|
public void testDoubleMatchingOnAnd_Search() {
|
||||||
createUniqueIndexPatientIdentifier();
|
createUniqueIndexPatientIdentifier();
|
||||||
|
@ -981,15 +1000,19 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
myCaptureQueriesListener.clear();
|
myCaptureQueriesListener.clear();
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.setLoadSynchronousUpTo(100);
|
params.setLoadSynchronousUpTo(100);
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
params.add("birthdate", new DateParam("2011-01-01"));
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
|
||||||
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1007,40 +1030,50 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
||||||
myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
params.add("birthdate", new DateParam("2011-01-01"));
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||||
String searchId = results.getUuid();
|
String searchId = results.getUuid();
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
// Other order
|
// Other order
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.add("birthdate", new DateParam("2011-01-01"));
|
params.add("birthdate", new DateParam("2011-01-01"));
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params, mySrd);
|
||||||
assertEquals(searchId, results.getUuid());
|
assertEquals(searchId, results.getUuid());
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
||||||
// Null because we just reuse the last search
|
// Because we just reuse the last search
|
||||||
assertNull(SearchBuilder.getLastHandlerMechanismForUnitTest());
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("REUSING"));
|
||||||
|
assertThat(myMessages.toString(), not(containsString("Using unique index")));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||||
params.add("birthdate", new DateParam("2011-01-03"));
|
params.add("birthdate", new DateParam("2011-01-03"));
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params, mySrd);
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
myMessages.clear();
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.add("birthdate", new DateParam("2011-01-03"));
|
params.add("birthdate", new DateParam("2011-01-03"));
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params, mySrd);
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.STANDARD_QUERY, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
// STANDARD QUERY
|
||||||
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), not(containsString("unique index")));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,9 +1137,12 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
pt1.addName().setFamily("FAMILY1");
|
pt1.addName().setFamily("FAMILY1");
|
||||||
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
IIdType id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||||
IIdType id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG").getId().toUnqualifiedVersionless();
|
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||||
assertEquals(1, uniques.size());
|
assertEquals(1, uniques.size());
|
||||||
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||||
|
@ -1118,9 +1154,12 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
pt1.addName().setFamily("FAMILY1");
|
pt1.addName().setFamily("FAMILY1");
|
||||||
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
||||||
|
|
||||||
SearchBuilder.resetLastHandlerMechanismForUnitTest();
|
id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||||
id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG").getId().toUnqualifiedVersionless();
|
|
||||||
assertEquals(SearchBuilder.getLastHandlerParamsForUnitTest(), SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||||
assertEquals(1, uniques.size());
|
assertEquals(1, uniques.size());
|
||||||
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||||
|
@ -1128,6 +1167,10 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logCapturedMessages() {
|
||||||
|
ourLog.info("Messages:\n {}", String.join("\n ", myMessages));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUniqueValuesAreIndexed_StringAndReference() {
|
public void testUniqueValuesAreIndexed_StringAndReference() {
|
||||||
createUniqueNameAndManagingOrganizationSps();
|
createUniqueNameAndManagingOrganizationSps();
|
||||||
|
@ -1375,6 +1418,93 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDetectUniqueSearchParams() {
|
||||||
|
createUniqueBirthdateAndGenderSps();
|
||||||
|
List<JpaRuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
|
||||||
|
|
||||||
|
assertEquals(1, params.size());
|
||||||
|
assertEquals(params.get(0).isUnique(), true);
|
||||||
|
assertEquals(2, params.get(0).getCompositeOf().size());
|
||||||
|
// Should be alphabetical order
|
||||||
|
assertEquals("birthdate", params.get(0).getCompositeOf().get(0).getName());
|
||||||
|
assertEquals("gender", params.get(0).getCompositeOf().get(1).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateUniqueValuesAreRejected() {
|
||||||
|
createUniqueBirthdateAndGenderSps();
|
||||||
|
|
||||||
|
Patient pt1 = new Patient();
|
||||||
|
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
|
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||||
|
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
try {
|
||||||
|
myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
Patient pt2 = new Patient();
|
||||||
|
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
|
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
pt2 = new Patient();
|
||||||
|
pt2.setId(id2);
|
||||||
|
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
|
pt2.setBirthDateElement(new DateType("2011-01-01"));
|
||||||
|
try {
|
||||||
|
myPatientDao.update(pt2);
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReplaceOneWithAnother() {
|
||||||
|
createUniqueBirthdateAndGenderSps();
|
||||||
|
|
||||||
|
Patient pt1 = new Patient();
|
||||||
|
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
|
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||||
|
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualified();
|
||||||
|
assertNotNull(id1);
|
||||||
|
|
||||||
|
ourLog.info("** Replacing");
|
||||||
|
|
||||||
|
pt1 = new Patient();
|
||||||
|
pt1.setId(id1);
|
||||||
|
pt1.setGender(Enumerations.AdministrativeGender.FEMALE);
|
||||||
|
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||||
|
id1 = myPatientDao.update(pt1).getId().toUnqualified();
|
||||||
|
assertNotNull(id1);
|
||||||
|
assertEquals("2", id1.getVersionIdPart());
|
||||||
|
|
||||||
|
Patient pt2 = new Patient();
|
||||||
|
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
|
pt2.setBirthDateElement(new DateType("2011-01-01"));
|
||||||
|
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
myMessages.clear();
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||||
|
params.add("birthdate", new DateParam("2011-01-01"));
|
||||||
|
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||||
|
String searchId = results.getUuid();
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id2.getValue()));
|
||||||
|
|
||||||
|
logCapturedMessages();
|
||||||
|
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||||
|
myMessages.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
|
|
@ -1,34 +1,20 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||||
import static org.hamcrest.Matchers.not;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
|
||||||
import org.hl7.fhir.r4.model.CodeType;
|
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
|
@ -224,7 +210,7 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValiedateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
|
public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
|
||||||
IPrimitiveType<String> display = null;
|
IPrimitiveType<String> display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
|
|
|
@ -36,6 +36,7 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.awaitility.Awaitility.await;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -471,6 +472,9 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.getCode());
|
assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.getCode());
|
||||||
assertEquals("In-memory", tag.getDisplay());
|
assertEquals("In-memory", tag.getDisplay());
|
||||||
|
|
||||||
|
// Wait for subscription to be moved to active
|
||||||
|
await().until(()-> Subscription.SubscriptionStatus.ACTIVE.equals(ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute().getStatus()));
|
||||||
|
|
||||||
Subscription subscriptionActivated = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
|
Subscription subscriptionActivated = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
|
||||||
assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscriptionActivated.getStatus());
|
assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscriptionActivated.getStatus());
|
||||||
tags = subscriptionActivated.getMeta().getTag();
|
tags = subscriptionActivated.getMeta().getTag();
|
||||||
|
@ -495,6 +499,9 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
assertEquals(SubscriptionMatchingStrategy.DATABASE.toString(), tag.getCode());
|
assertEquals(SubscriptionMatchingStrategy.DATABASE.toString(), tag.getCode());
|
||||||
assertEquals("Database", tag.getDisplay());
|
assertEquals("Database", tag.getDisplay());
|
||||||
|
|
||||||
|
// Wait for subscription to be moved to active
|
||||||
|
await().until(()-> Subscription.SubscriptionStatus.ACTIVE.equals(ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute().getStatus()));
|
||||||
|
|
||||||
Subscription subscription = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
|
Subscription subscription = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
|
||||||
assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscription.getStatus());
|
assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscription.getStatus());
|
||||||
tags = subscription.getMeta().getTag();
|
tags = subscription.getMeta().getTag();
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
||||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnprocessableEntityException e) {
|
} catch (UnprocessableEntityException e) {
|
||||||
assertThat(e.getMessage(), containsString("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/"));
|
assertThat(e.getMessage(), containsString("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,12 @@ package ca.uhn.fhir.jpa.term;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMap;
|
import ca.uhn.fhir.jpa.entity.*;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.CanonicalType;
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.hl7.fhir.r4.model.ConceptMap;
|
|
||||||
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -21,6 +16,7 @@ import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -31,6 +27,8 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
@Rule
|
@Rule
|
||||||
public final ExpectedException expectedException = ExpectedException.none();
|
public final ExpectedException expectedException = ExpectedException.none();
|
||||||
private IIdType myConceptMapId;
|
private IIdType myConceptMapId;
|
||||||
|
private IIdType myExtensionalCsId;
|
||||||
|
private IIdType myExtensionalVsId;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
@ -40,6 +38,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
||||||
|
myDaoConfig.setPreExpandValueSetsExperimental(new DaoConfig().isPreExpandValueSetsExperimental());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAndPersistConceptMap() {
|
private void createAndPersistConceptMap() {
|
||||||
|
@ -56,6 +55,39 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadAndPersistCodeSystemAndValueSet() throws IOException {
|
||||||
|
loadAndPersistCodeSystem();
|
||||||
|
loadAndPersistValueSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadAndPersistCodeSystem() throws IOException {
|
||||||
|
CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
|
||||||
|
persistCodeSystem(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistCodeSystem(CodeSystem theCodeSystem) {
|
||||||
|
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||||
|
@Override
|
||||||
|
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
||||||
|
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadAndPersistValueSet() throws IOException {
|
||||||
|
ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||||
|
persistValueSet(valueSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistValueSet(ValueSet theValueSet) {
|
||||||
|
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||||
|
@Override
|
||||||
|
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
||||||
|
myExtensionalVsId = myValueSetDao.create(theValueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateConceptMapWithMissingSourceSystem() {
|
public void testCreateConceptMapWithMissingSourceSystem() {
|
||||||
ConceptMap conceptMap = new ConceptMap();
|
ConceptMap conceptMap = new ConceptMap();
|
||||||
|
@ -137,6 +169,16 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateCodeSystemUrls() throws Exception {
|
||||||
|
loadAndPersistCodeSystem();
|
||||||
|
|
||||||
|
expectedException.expect(UnprocessableEntityException.class);
|
||||||
|
expectedException.expectMessage("Can not create multiple CodeSystem resources with CodeSystem.url \"http://acme.org\", already have one with resource ID: CodeSystem/" + myExtensionalCsId.getIdPart());
|
||||||
|
|
||||||
|
loadAndPersistCodeSystem();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDuplicateConceptMapUrls() {
|
public void testDuplicateConceptMapUrls() {
|
||||||
createAndPersistConceptMap();
|
createAndPersistConceptMap();
|
||||||
|
@ -147,6 +189,19 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
createAndPersistConceptMap();
|
createAndPersistConceptMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateValueSetUrls() throws Exception {
|
||||||
|
myDaoConfig.setPreExpandValueSetsExperimental(true);
|
||||||
|
|
||||||
|
// DM 2019-03-05 - We pre-load our custom CodeSystem otherwise pre-expansion of the ValueSet will fail.
|
||||||
|
loadAndPersistCodeSystemAndValueSet();
|
||||||
|
|
||||||
|
expectedException.expect(UnprocessableEntityException.class);
|
||||||
|
expectedException.expectMessage("Can not create multiple ValueSet resources with ValueSet.url \"http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2\", already have one with resource ID: ValueSet/" + myExtensionalVsId.getIdPart());
|
||||||
|
|
||||||
|
loadAndPersistValueSet();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStoreTermConceptMapAndChildren() {
|
public void testStoreTermConceptMapAndChildren() {
|
||||||
createAndPersistConceptMap();
|
createAndPersistConceptMap();
|
||||||
|
@ -325,6 +380,63 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStoreTermValueSetAndChildren() throws Exception {
|
||||||
|
myDaoConfig.setPreExpandValueSetsExperimental(true);
|
||||||
|
|
||||||
|
loadAndPersistCodeSystemAndValueSet();
|
||||||
|
|
||||||
|
CodeSystem codeSystem = myCodeSystemDao.read(myExtensionalCsId);
|
||||||
|
ourLog.info("CodeSystem:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(codeSystem));
|
||||||
|
|
||||||
|
ValueSet valueSet = myValueSetDao.read(myExtensionalVsId);
|
||||||
|
ourLog.info("ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(valueSet));
|
||||||
|
|
||||||
|
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||||
|
@Override
|
||||||
|
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
||||||
|
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsId.getIdPartAsLong());
|
||||||
|
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||||
|
|
||||||
|
Optional<TermValueSet> optionalValueSetByUrl = myTermValueSetDao.findByUrl("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||||
|
assertTrue(optionalValueSetByUrl.isPresent());
|
||||||
|
|
||||||
|
TermValueSet valueSet = optionalValueSetByUrl.get();
|
||||||
|
assertSame(optionalValueSetByResourcePid.get(), valueSet);
|
||||||
|
ourLog.info("ValueSet:\n" + valueSet.toString());
|
||||||
|
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", valueSet.getUrl());
|
||||||
|
assertEquals("Terminology Services Connectation #1 Extensional case #2", valueSet.getName());
|
||||||
|
assertEquals(codeSystem.getConcept().size(), valueSet.getCodes().size());
|
||||||
|
|
||||||
|
TermValueSetCode code = valueSet.getCodes().get(0);
|
||||||
|
ourLog.info("Code:\n" + code.toString());
|
||||||
|
assertEquals("http://acme.org", code.getSystem());
|
||||||
|
assertEquals("8450-9", code.getCode());
|
||||||
|
assertEquals("Systolic blood pressure--expiration", code.getDisplay());
|
||||||
|
|
||||||
|
code = valueSet.getCodes().get(1);
|
||||||
|
ourLog.info("Code:\n" + code.toString());
|
||||||
|
assertEquals("http://acme.org", code.getSystem());
|
||||||
|
assertEquals("11378-7", code.getCode());
|
||||||
|
assertEquals("Systolic blood pressure at First encounter", code.getDisplay());
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
code = valueSet.getCodes().get(22);
|
||||||
|
ourLog.info("Code:\n" + code.toString());
|
||||||
|
assertEquals("http://acme.org", code.getSystem());
|
||||||
|
assertEquals("8491-3", code.getCode());
|
||||||
|
assertEquals("Systolic blood pressure 1 hour minimum", code.getDisplay());
|
||||||
|
|
||||||
|
code = valueSet.getCodes().get(23);
|
||||||
|
ourLog.info("Code:\n" + code.toString());
|
||||||
|
assertEquals("http://acme.org", code.getSystem());
|
||||||
|
assertEquals("8492-1", code.getCode());
|
||||||
|
assertEquals("Systolic blood pressure 8 hour minimum", code.getDisplay());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTranslateByCodeSystemsAndSourceCodeOneToMany() {
|
public void testTranslateByCodeSystemsAndSourceCodeOneToMany() {
|
||||||
createAndPersistConceptMap();
|
createAndPersistConceptMap();
|
||||||
|
|
|
@ -102,7 +102,7 @@ public abstract class BaseTableColumnTypeTask<T extends BaseTableTask> extends B
|
||||||
Validate.notNull(myNullable);
|
Validate.notNull(myNullable);
|
||||||
|
|
||||||
if (myColumnType == ColumnTypeEnum.STRING) {
|
if (myColumnType == ColumnTypeEnum.STRING) {
|
||||||
Validate.notNull(myColumnLength);
|
Validate.notNull(myColumnLength, "No length specified for " + ColumnTypeEnum.STRING + " column {}.", getColumnName());
|
||||||
} else {
|
} else {
|
||||||
Validate.isTrue(myColumnLength == null);
|
Validate.isTrue(myColumnLength == null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ package ca.uhn.fhir.jpa.migrate.tasks;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.AddColumnTask;
|
import ca.uhn.fhir.jpa.migrate.taskdef.AddColumnTask;
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.ArbitrarySqlTask;
|
import ca.uhn.fhir.jpa.migrate.taskdef.ArbitrarySqlTask;
|
||||||
|
@ -56,7 +59,7 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
||||||
init400();
|
init400();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init400() {
|
protected void init400() {
|
||||||
Builder version = forVersion(VersionEnum.V4_0_0);
|
Builder version = forVersion(VersionEnum.V4_0_0);
|
||||||
|
|
||||||
version.onTable("TRM_CONCEPT_MAP_GROUP")
|
version.onTable("TRM_CONCEPT_MAP_GROUP")
|
||||||
|
@ -75,6 +78,41 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
||||||
.renameColumn("mySystem", "SYSTEM_URL")
|
.renameColumn("mySystem", "SYSTEM_URL")
|
||||||
.renameColumn("mySystemVersion", "SYSTEM_VERSION")
|
.renameColumn("mySystemVersion", "SYSTEM_VERSION")
|
||||||
.renameColumn("myValueSet", "VALUESET_URL");
|
.renameColumn("myValueSet", "VALUESET_URL");
|
||||||
|
|
||||||
|
// TermValueSet
|
||||||
|
version.startSectionWithMessage("Processing table: TRM_VALUESET");
|
||||||
|
version.addIdGenerator("SEQ_VALUESET_PID");
|
||||||
|
Builder.BuilderAddTableByColumns termValueSetTable = version.addTableByColumns("TRM_VALUESET", "PID");
|
||||||
|
termValueSetTable.addColumn("PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||||
|
termValueSetTable.addColumn("URL").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermValueSet.MAX_URL_LENGTH);
|
||||||
|
termValueSetTable
|
||||||
|
.addIndex("IDX_VALUESET_URL")
|
||||||
|
.unique(true)
|
||||||
|
.withColumns("URL");
|
||||||
|
termValueSetTable.addColumn("RES_ID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||||
|
termValueSetTable
|
||||||
|
.addForeignKey("FK_TRMVALUESET_RES")
|
||||||
|
.toColumn("RES_ID")
|
||||||
|
.references("HFJ_RESOURCE", "RES_ID");
|
||||||
|
termValueSetTable.addColumn("NAME").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermValueSet.MAX_NAME_LENGTH);
|
||||||
|
|
||||||
|
// TermValueSetCode
|
||||||
|
version.startSectionWithMessage("Processing table: TRM_VALUESET_CODE");
|
||||||
|
version.addIdGenerator("SEQ_VALUESET_CODE_PID");
|
||||||
|
Builder.BuilderAddTableByColumns termValueSetCodeTable = version.addTableByColumns("TRM_VALUESET_CODE", "PID");
|
||||||
|
termValueSetCodeTable.addColumn("PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||||
|
termValueSetCodeTable.addColumn("VALUESET_PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||||
|
termValueSetCodeTable
|
||||||
|
.addForeignKey("FK_TRM_VALUESET_PID")
|
||||||
|
.toColumn("VALUESET_PID")
|
||||||
|
.references("TRM_VALUESET", "PID");
|
||||||
|
termValueSetCodeTable.addColumn("SYSTEM").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermCodeSystem.MAX_URL_LENGTH);
|
||||||
|
termValueSetCodeTable.addColumn("CODE").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_CODE_LENGTH);
|
||||||
|
termValueSetCodeTable
|
||||||
|
.addIndex("IDX_VALUESET_CODE_CS_CD")
|
||||||
|
.unique(false)
|
||||||
|
.withColumns("SYSTEM", "CODE");
|
||||||
|
termValueSetCodeTable.addColumn("DISPLAY").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_DESC_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -446,7 +446,7 @@ public class SearchParameterMap implements Serializable {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||||
if (isEmpty() == false) {
|
if (isEmpty() == false) {
|
||||||
b.append("params", super.toString());
|
b.append("params", mySearchParameterMap);
|
||||||
}
|
}
|
||||||
if (getIncludes().isEmpty() == false) {
|
if (getIncludes().isEmpty() == false) {
|
||||||
b.append("includes", getIncludes());
|
b.append("includes", getIncludes());
|
||||||
|
|
|
@ -210,6 +210,12 @@
|
||||||
<artifactId>spring-web</artifactId>
|
<artifactId>spring-web</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-test-utilities</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.hamcrest.Matchers.emptyOrNullString;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import static org.hamcrest.Matchers.is;
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||||
import static org.junit.Assert.assertEquals;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
import static org.junit.Assert.assertNull;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import static org.junit.Assert.assertThat;
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import java.util.concurrent.TimeUnit;
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Update;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
@ -26,19 +30,12 @@ import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import static org.hamcrest.Matchers.emptyOrNullString;
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class PreferTest {
|
public class PreferTest {
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
package ca.uhn.fhir.rest.server.interceptor;
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.contains;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.interceptor.api.Hook;
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.DateDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
@ -24,37 +32,30 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.junit.*;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.util.*;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
import static org.awaitility.Awaitility.await;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
|
|
||||||
import ca.uhn.fhir.model.primitive.*;
|
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class InterceptorUserDataMapDstu2Test {
|
public class InterceptorUserDataMapDstu2Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(InterceptorUserDataMapDstu2Test.class);
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(InterceptorUserDataMapDstu2Test.class);
|
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static RestfulServer servlet;
|
private static RestfulServer servlet;
|
||||||
private final Object myKey = "KEY";
|
private final Object myKey = "KEY";
|
||||||
|
private final Object myValue = "VALUE";
|
||||||
private Map<Object, Object> myMap;
|
private Map<Object, Object> myMap;
|
||||||
private Set<String> myMapCheckMethods;
|
private Set<String> myMapCheckMethods;
|
||||||
private final Object myValue = "VALUE";
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
@ -78,7 +79,7 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
ourLog.info(myMapCheckMethods.toString());
|
ourLog.info(myMapCheckMethods.toString());
|
||||||
assertThat(myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "preProcessOutgoingException", "handleException", "processingCompleted"));
|
await().until(() -> myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "preProcessOutgoingException", "handleException", "processingCompleted"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -95,8 +96,7 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info(myMapCheckMethods.toString());
|
await().until(() -> myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally", "processingCompleted"));
|
||||||
assertThat(myMapCheckMethods.toString(), myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally", "processingCompleted"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMapUsing(Map<Object, Object> theUserData, String theMethod) {
|
private void updateMapUsing(Map<Object, Object> theUserData, String theMethod) {
|
||||||
|
@ -111,125 +111,6 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
myMapCheckMethods.add(theMethod);
|
myMapCheckMethods.add(theMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
servlet = new RestfulServer(ourCtx);
|
|
||||||
|
|
||||||
servlet.setResourceProviders(new DummyPatientResourceProvider());
|
|
||||||
servlet.setPlainProviders(new PlainProvider());
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
|
||||||
|
|
||||||
private Patient createPatient1() {
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.addIdentifier();
|
|
||||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
|
||||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
|
||||||
patient.getIdentifier().get(0).setValue("00001");
|
|
||||||
patient.addName();
|
|
||||||
patient.getName().get(0).addFamily("Test");
|
|
||||||
patient.getName().get(0).addGiven("PatientOne");
|
|
||||||
patient.setGender(AdministrativeGenderEnum.MALE);
|
|
||||||
patient.getId().setValue("1");
|
|
||||||
return patient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Patient> getIdToPatient() {
|
|
||||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
|
||||||
{
|
|
||||||
Patient patient = createPatient1();
|
|
||||||
idToPatient.put("1", patient);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.getIdentifier().add(new IdentifierDt());
|
|
||||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
|
||||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
|
||||||
patient.getIdentifier().get(0).setValue("00002");
|
|
||||||
patient.getName().add(new HumanNameDt());
|
|
||||||
patient.getName().get(0).addFamily("Test");
|
|
||||||
patient.getName().get(0).addGiven("PatientTwo");
|
|
||||||
patient.setGender(AdministrativeGenderEnum.FEMALE);
|
|
||||||
patient.getId().setValue("2");
|
|
||||||
idToPatient.put("2", patient);
|
|
||||||
}
|
|
||||||
return idToPatient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the resource by its identifier
|
|
||||||
*
|
|
||||||
* @param theId
|
|
||||||
* The resource identity
|
|
||||||
* @return The resource
|
|
||||||
*/
|
|
||||||
@Read()
|
|
||||||
public Patient getResourceById(@IdParam IdDt theId) {
|
|
||||||
if (theId.getIdPart().equals("EX")) {
|
|
||||||
throw new InvalidRequestException("FOO");
|
|
||||||
}
|
|
||||||
String key = theId.getIdPart();
|
|
||||||
Patient retVal = getIdToPatient().get(key);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the resource by its identifier
|
|
||||||
*
|
|
||||||
* @param theId
|
|
||||||
* The resource identity
|
|
||||||
* @return The resource
|
|
||||||
*/
|
|
||||||
@Search()
|
|
||||||
public List<Patient> getResourceById(@RequiredParam(name = "_id") String theId) {
|
|
||||||
throw new InvalidRequestException("FOO");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<Patient> getResourceType() {
|
|
||||||
return Patient.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(name = "$everything", idempotent = true)
|
|
||||||
public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
|
||||||
|
|
||||||
Bundle retVal = new Bundle();
|
|
||||||
// Populate bundle with matching resources
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(name = "$everything", idempotent = true)
|
|
||||||
public Bundle patientTypeOperation(@IdParam IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
|
||||||
|
|
||||||
Bundle retVal = new Bundle();
|
|
||||||
// Populate bundle with matching resources
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Interceptor
|
@Interceptor
|
||||||
public class MyInterceptor {
|
public class MyInterceptor {
|
||||||
|
|
||||||
|
@ -276,6 +157,94 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
private Patient createPatient1() {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier();
|
||||||
|
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||||
|
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||||
|
patient.getIdentifier().get(0).setValue("00001");
|
||||||
|
patient.addName();
|
||||||
|
patient.getName().get(0).addFamily("Test");
|
||||||
|
patient.getName().get(0).addGiven("PatientOne");
|
||||||
|
patient.setGender(AdministrativeGenderEnum.MALE);
|
||||||
|
patient.getId().setValue("1");
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Patient> getIdToPatient() {
|
||||||
|
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
||||||
|
{
|
||||||
|
Patient patient = createPatient1();
|
||||||
|
idToPatient.put("1", patient);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.getIdentifier().add(new IdentifierDt());
|
||||||
|
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||||
|
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||||
|
patient.getIdentifier().get(0).setValue("00002");
|
||||||
|
patient.getName().add(new HumanNameDt());
|
||||||
|
patient.getName().get(0).addFamily("Test");
|
||||||
|
patient.getName().get(0).addGiven("PatientTwo");
|
||||||
|
patient.setGender(AdministrativeGenderEnum.FEMALE);
|
||||||
|
patient.getId().setValue("2");
|
||||||
|
idToPatient.put("2", patient);
|
||||||
|
}
|
||||||
|
return idToPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the resource by its identifier
|
||||||
|
*
|
||||||
|
* @param theId The resource identity
|
||||||
|
* @return The resource
|
||||||
|
*/
|
||||||
|
@Read()
|
||||||
|
public Patient getResourceById(@IdParam IdDt theId) {
|
||||||
|
if (theId.getIdPart().equals("EX")) {
|
||||||
|
throw new InvalidRequestException("FOO");
|
||||||
|
}
|
||||||
|
String key = theId.getIdPart();
|
||||||
|
Patient retVal = getIdToPatient().get(key);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the resource by its identifier
|
||||||
|
*
|
||||||
|
* @param theId The resource identity
|
||||||
|
* @return The resource
|
||||||
|
*/
|
||||||
|
@Search()
|
||||||
|
public List<Patient> getResourceById(@RequiredParam(name = "_id") String theId) {
|
||||||
|
throw new InvalidRequestException("FOO");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = "$everything", idempotent = true)
|
||||||
|
public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||||
|
|
||||||
|
Bundle retVal = new Bundle();
|
||||||
|
// Populate bundle with matching resources
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = "$everything", idempotent = true)
|
||||||
|
public Bundle patientTypeOperation(@IdParam IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||||
|
|
||||||
|
Bundle retVal = new Bundle();
|
||||||
|
// Populate bundle with matching resources
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class PlainProvider {
|
public static class PlainProvider {
|
||||||
|
|
||||||
@Operation(name = "$everything", idempotent = true)
|
@Operation(name = "$everything", idempotent = true)
|
||||||
|
@ -288,4 +257,33 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
JettyUtil.closeServer(ourServer);
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourServer = new Server(0);
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
servlet = new RestfulServer(ourCtx);
|
||||||
|
|
||||||
|
servlet.setResourceProviders(new DummyPatientResourceProvider());
|
||||||
|
servlet.setPlainProviders(new PlainProvider());
|
||||||
|
|
||||||
|
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
JettyUtil.startServer(ourServer);
|
||||||
|
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ import net.sf.json.JsonConfig;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import org.hl7.fhir.dstu3.model.Address.AddressUse;
|
import org.hl7.fhir.dstu3.model.Address.AddressUse;
|
||||||
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
|
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.UnknownContentCode;
|
import org.hl7.fhir.dstu3.model.CapabilityStatement.UnknownContentCode;
|
||||||
|
@ -33,7 +33,6 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
@ -45,9 +44,8 @@ import static org.apache.commons.lang3.StringUtils.countMatches;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
import static org.mockito.Matchers.isNull;
|
|
||||||
import static org.mockito.Mockito.nullable;
|
import static org.mockito.Mockito.nullable;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ -110,16 +108,16 @@ public class JsonParserDstu3Test {
|
||||||
// Deserialize then check that valueReference value is still correct
|
// Deserialize then check that valueReference value is still correct
|
||||||
fhirPat = parser.parseResource(Patient.class, output);
|
fhirPat = parser.parseResource(Patient.class, output);
|
||||||
|
|
||||||
List<Extension> extlst = fhirPat.getExtensionsByUrl("x1");
|
List<Extension> extensions = fhirPat.getExtensionsByUrl("x1");
|
||||||
Assert.assertEquals(1, extlst.size());
|
Assert.assertEquals(1, extensions.size());
|
||||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
Assert.assertEquals(refVal, ((Reference) extensions.get(0).getValue()).getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #544
|
* See #544
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testBundleStitchReferencesByUuid() throws Exception {
|
public void testBundleStitchReferencesByUuid() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
|
|
||||||
DocumentManifest dm = new DocumentManifest();
|
DocumentManifest dm = new DocumentManifest();
|
||||||
|
@ -175,7 +173,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCustomUrlExtensioninBundle() {
|
public void testCustomUrlExtensionInBundle() {
|
||||||
final String expected = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}}]}";
|
final String expected = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}}]}";
|
||||||
|
|
||||||
final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||||
|
@ -213,7 +211,7 @@ public class JsonParserDstu3Test {
|
||||||
* See #276
|
* See #276
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDoubleEncodingContainedResources() throws Exception {
|
public void testDoubleEncodingContainedResources() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.setId("#patient-1");
|
patient.setId("#patient-1");
|
||||||
patient.setActive(true);
|
patient.setActive(true);
|
||||||
|
@ -236,7 +234,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseExtensions() throws Exception {
|
public void testEncodeAndParseExtensions() {
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
|
patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
|
||||||
|
@ -402,6 +400,7 @@ public class JsonParserDstu3Test {
|
||||||
/**
|
/**
|
||||||
* See #336
|
* See #336
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
||||||
|
|
||||||
|
@ -458,7 +457,7 @@ public class JsonParserDstu3Test {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addName().setFamily("FAMILY");
|
p.addName().setFamily("FAMILY");
|
||||||
|
|
||||||
List<Coding> labels = new ArrayList<Coding>();
|
List<Coding> labels = new ArrayList<>();
|
||||||
labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1"));
|
labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1"));
|
||||||
labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2"));
|
labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2"));
|
||||||
p.getMeta().getSecurity().addAll(labels);
|
p.getMeta().getSecurity().addAll(labels);
|
||||||
|
@ -602,7 +601,7 @@ public class JsonParserDstu3Test {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeEmptyTag() {
|
public void testEncodeEmptyTag() {
|
||||||
ArrayList<Coding> tagList = new ArrayList<Coding>();
|
ArrayList<Coding> tagList = new ArrayList<>();
|
||||||
tagList.add(new Coding());
|
tagList.add(new Coding());
|
||||||
tagList.add(new Coding().setDisplay("Label"));
|
tagList.add(new Coding().setDisplay("Label"));
|
||||||
|
|
||||||
|
@ -618,7 +617,7 @@ public class JsonParserDstu3Test {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeEmptyTag2() {
|
public void testEncodeEmptyTag2() {
|
||||||
ArrayList<Coding> tagList = new ArrayList<Coding>();
|
ArrayList<Coding> tagList = new ArrayList<>();
|
||||||
tagList.add(new Coding().setSystem("scheme").setCode("code"));
|
tagList.add(new Coding().setSystem("scheme").setCode("code"));
|
||||||
tagList.add(new Coding().setDisplay("Label"));
|
tagList.add(new Coding().setDisplay("Label"));
|
||||||
|
|
||||||
|
@ -715,13 +714,26 @@ public class JsonParserDstu3Test {
|
||||||
.setValue(new Reference("Practitioner/A"));
|
.setValue(new Reference("Practitioner/A"));
|
||||||
|
|
||||||
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||||
parser.setDontEncodeElements(new HashSet<String>(Arrays.asList("*.id", "*.meta")));
|
parser.setDontEncodeElements(new HashSet<>(Arrays.asList("*.id", "*.meta")));
|
||||||
|
|
||||||
String encoded = parser.encodeResourceToString(p);
|
String encoded = parser.encodeResourceToString(p);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
|
|
||||||
assertThat(encoded, containsString("http://foo"));
|
assertThat(encoded, containsString("http://foo"));
|
||||||
assertThat(encoded, containsString("Practitioner/A"));
|
assertThat(encoded, containsString("Practitioner/A"));
|
||||||
|
|
||||||
|
// Now with exclude
|
||||||
|
|
||||||
|
parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||||
|
parser.setDontEncodeElements(new HashSet<>(Arrays.asList("*.id", "*.meta", "*.extension")));
|
||||||
|
|
||||||
|
encoded = parser.encodeResourceToString(p);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertThat(encoded, not(containsString("http://foo")));
|
||||||
|
assertThat(encoded, not(containsString("Practitioner/A")));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -818,7 +830,7 @@ public class JsonParserDstu3Test {
|
||||||
TestPatientFor327 patient = new TestPatientFor327();
|
TestPatientFor327 patient = new TestPatientFor327();
|
||||||
patient.setBirthDateElement(new DateType("2016-04-14"));
|
patient.setBirthDateElement(new DateType("2016-04-14"));
|
||||||
|
|
||||||
List<Reference> conditions = new ArrayList<Reference>();
|
List<Reference> conditions = new ArrayList<>();
|
||||||
Condition condition = new Condition();
|
Condition condition = new Condition();
|
||||||
condition.addBodySite().setText("BODY SITE");
|
condition.addBodySite().setText("BODY SITE");
|
||||||
conditions.add(new Reference(condition));
|
conditions.add(new Reference(condition));
|
||||||
|
@ -896,7 +908,7 @@ public class JsonParserDstu3Test {
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
||||||
|
|
||||||
parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList<String>());
|
parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList<>());
|
||||||
enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
|
enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
|
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
|
||||||
|
@ -930,12 +942,12 @@ public class JsonParserDstu3Test {
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
||||||
|
|
||||||
ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(Arrays.asList("Patient.managingOrganization"));
|
ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(Collections.singletonList("Patient.managingOrganization"));
|
||||||
enc = parser.setPrettyPrint(true).encodeResourceToString(p);
|
enc = parser.setPrettyPrint(true).encodeResourceToString(p);
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
||||||
|
|
||||||
ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(new HashSet<String>(Arrays.asList("Patient.managingOrganization")));
|
ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(new HashSet<>(Collections.singletonList("Patient.managingOrganization")));
|
||||||
enc = parser.setPrettyPrint(true).encodeResourceToString(p);
|
enc = parser.setPrettyPrint(true).encodeResourceToString(p);
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
|
||||||
|
@ -1013,7 +1025,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeNarrativeSuppressed() throws Exception {
|
public void testEncodeNarrativeSuppressed() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.setId("Patient/1/_history/1");
|
patient.setId("Patient/1/_history/1");
|
||||||
patient.getText().setDivAsString("<div>THE DIV</div>");
|
patient.getText().setDivAsString("<div>THE DIV</div>");
|
||||||
|
@ -1064,6 +1076,57 @@ public class JsonParserDstu3Test {
|
||||||
assertThat(encoded, not(containsString("maritalStatus")));
|
assertThat(encoded, not(containsString("maritalStatus")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We specifically include extensions on CapabilityStatment even in
|
||||||
|
* summary mode, since this is behaviour that people depend on
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEncodeSummaryCapabilityStatementExtensions() {
|
||||||
|
|
||||||
|
CapabilityStatement cs = new CapabilityStatement();
|
||||||
|
CapabilityStatement.CapabilityStatementRestComponent rest = cs.addRest();
|
||||||
|
rest.setMode(CapabilityStatement.RestfulCapabilityMode.CLIENT);
|
||||||
|
rest.getSecurity()
|
||||||
|
.addExtension()
|
||||||
|
.setUrl("http://foo")
|
||||||
|
.setValue(new StringType("bar"));
|
||||||
|
|
||||||
|
cs.getVersionElement().addExtension()
|
||||||
|
.setUrl("http://goo")
|
||||||
|
.setValue(new StringType("ber"));
|
||||||
|
|
||||||
|
String encoded = ourCtx.newJsonParser().setSummaryMode(true).setPrettyPrint(true).setPrettyPrint(true).encodeResourceToString(cs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertThat(encoded, (containsString("http://foo")));
|
||||||
|
assertThat(encoded, (containsString("bar")));
|
||||||
|
assertThat(encoded, (containsString("http://goo")));
|
||||||
|
assertThat(encoded, (containsString("ber")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeSummaryPatientExtensions() {
|
||||||
|
|
||||||
|
Patient cs = new Patient();
|
||||||
|
Address address = cs.addAddress();
|
||||||
|
address.setCity("CITY");
|
||||||
|
address
|
||||||
|
.addExtension()
|
||||||
|
.setUrl("http://foo")
|
||||||
|
.setValue(new StringType("bar"));
|
||||||
|
address.getCityElement().addExtension()
|
||||||
|
.setUrl("http://goo")
|
||||||
|
.setValue(new StringType("ber"));
|
||||||
|
|
||||||
|
String encoded = ourCtx.newJsonParser().setSummaryMode(true).setPrettyPrint(true).setPrettyPrint(true).encodeResourceToString(cs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertThat(encoded, not(containsString("http://foo")));
|
||||||
|
assertThat(encoded, not(containsString("bar")));
|
||||||
|
assertThat(encoded, not(containsString("http://goo")));
|
||||||
|
assertThat(encoded, not(containsString("ber")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeSummary2() {
|
public void testEncodeSummary2() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -1107,7 +1170,7 @@ public class JsonParserDstu3Test {
|
||||||
* See #241
|
* See #241
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeThenParseShouldNotAddSpuriousId() throws Exception {
|
public void testEncodeThenParseShouldNotAddSpuriousId() {
|
||||||
Condition condition = new Condition().setVerificationStatus(ConditionVerificationStatus.CONFIRMED);
|
Condition condition = new Condition().setVerificationStatus(ConditionVerificationStatus.CONFIRMED);
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
BundleEntryComponent entry = new Bundle.BundleEntryComponent();
|
BundleEntryComponent entry = new Bundle.BundleEntryComponent();
|
||||||
|
@ -1126,7 +1189,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeUndeclaredBlock() throws Exception {
|
public void testEncodeUndeclaredBlock() {
|
||||||
FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent();
|
FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent();
|
||||||
source.getMessageHeaderApplicationId().setValue("APPID");
|
source.getMessageHeaderApplicationId().setValue("APPID");
|
||||||
source.setName("NAME");
|
source.setName("NAME");
|
||||||
|
@ -1153,7 +1216,7 @@ public class JsonParserDstu3Test {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addAddress().setUse(AddressUse.HOME);
|
patient.addAddress().setUse(AddressUse.HOME);
|
||||||
EnumFactory<AddressUse> fact = new AddressUseEnumFactory();
|
EnumFactory<AddressUse> fact = new AddressUseEnumFactory();
|
||||||
PrimitiveType<AddressUse> enumeration = new Enumeration<AddressUse>(fact).setValue(AddressUse.HOME);
|
PrimitiveType<AddressUse> enumeration = new Enumeration<>(fact).setValue(AddressUse.HOME);
|
||||||
patient.addExtension().setUrl("urn:foo").setValue(enumeration);
|
patient.addExtension().setUrl("urn:foo").setValue(enumeration);
|
||||||
|
|
||||||
String val = parser.encodeResourceToString(patient);
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
@ -1168,7 +1231,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeWithDontEncodeElements() throws Exception {
|
public void testEncodeWithDontEncodeElements() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.setId("123");
|
patient.setId("123");
|
||||||
|
|
||||||
|
@ -1224,7 +1287,7 @@ public class JsonParserDstu3Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newJsonParser();
|
IParser p = ourCtx.newJsonParser();
|
||||||
p.setDontEncodeElements(Sets.newHashSet("Patient.meta"));
|
p.setDontEncodeElements(Sets.newHashSet("Patient.meta"));
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<>(Collections.singletonList("Patient.name")));
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(patient);
|
String out = p.encodeResourceToString(patient);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1438,7 +1501,7 @@ public class JsonParserDstu3Test {
|
||||||
String res = "{ \"resourceType\": \"ValueSet\", \"url\": \"http://sample/ValueSet/education-levels\", \"version\": \"1\", \"name\": \"Education Levels\", \"status\": \"draft\", \"compose\": { \"include\": [ { \"filter\": [ { \"property\": \"n\", \"op\": \"n\", \"value\": \"365460000\" } ], \"system\": \"http://snomed.info/sct\" } ], \"exclude\": [ { \"concept\": [ { \"code\": \"224298008\" }, { \"code\": \"365460000\" }, { \"code\": \"473462005\" }, { \"code\": \"424587006\" } ], \"system\": \"http://snomed.info/sct\" } ] }, \"description\": \"A selection of Education Levels\", \"text\": { \"status\": \"generated\", \"div\": \"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\"><h2>Education Levels</h2><tt>http://csiro.au/ValueSet/education-levels</tt><p>A selection of Education Levels</p></div>\" }, \"experimental\": true, \"date\": \"2016-07-26\" }";
|
String res = "{ \"resourceType\": \"ValueSet\", \"url\": \"http://sample/ValueSet/education-levels\", \"version\": \"1\", \"name\": \"Education Levels\", \"status\": \"draft\", \"compose\": { \"include\": [ { \"filter\": [ { \"property\": \"n\", \"op\": \"n\", \"value\": \"365460000\" } ], \"system\": \"http://snomed.info/sct\" } ], \"exclude\": [ { \"concept\": [ { \"code\": \"224298008\" }, { \"code\": \"365460000\" }, { \"code\": \"473462005\" }, { \"code\": \"424587006\" } ], \"system\": \"http://snomed.info/sct\" } ] }, \"description\": \"A selection of Education Levels\", \"text\": { \"status\": \"generated\", \"div\": \"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\"><h2>Education Levels</h2><tt>http://csiro.au/ValueSet/education-levels</tt><p>A selection of Education Levels</p></div>\" }, \"experimental\": true, \"date\": \"2016-07-26\" }";
|
||||||
IParser parser = ourCtx.newJsonParser();
|
IParser parser = ourCtx.newJsonParser();
|
||||||
parser.setParserErrorHandler(new StrictErrorHandler());
|
parser.setParserErrorHandler(new StrictErrorHandler());
|
||||||
ValueSet parsed = parser.parseResource(ValueSet.class, res);
|
parser.parseResource(ValueSet.class, res);
|
||||||
fail("DataFormat Invalid attribute exception should be thrown");
|
fail("DataFormat Invalid attribute exception should be thrown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1671,53 +1734,6 @@ public class JsonParserDstu3Test {
|
||||||
assertThat(reencoded, containsString("contained"));
|
assertThat(reencoded, containsString("contained"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testParseAndEncodeBundleNewStyle() throws Exception {
|
|
||||||
String content = IOUtils.toString(JsonParserDstu3Test.class.getResourceAsStream("/bundle-example.json"), StandardCharsets.UTF_8);
|
|
||||||
|
|
||||||
Bundle parsed = ourCtx.newJsonParser().parseResource(Bundle.class, content);
|
|
||||||
assertEquals("Bundle/example/_history/1", parsed.getIdElement().getValue());
|
|
||||||
assertEquals("1", parsed.getIdElement().getVersionIdPart());
|
|
||||||
assertEquals("2014-08-18T01:43:30Z", parsed.getMeta().getLastUpdatedElement().getValueAsString());
|
|
||||||
assertEquals("searchset", parsed.getType());
|
|
||||||
assertEquals(3, parsed.getTotal());
|
|
||||||
assertEquals("https://example.com/base/MedicationRequest?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2", parsed.getLink().get(0).getUrlElement().getValueAsString());
|
|
||||||
assertEquals("https://example.com/base/MedicationRequest?patient=347&_include=MedicationRequest.medication", parsed.getLink().get(1).getUrlElement().getValueAsString());
|
|
||||||
|
|
||||||
assertEquals(2, parsed.getEntry().size());
|
|
||||||
assertEquals("alternate", parsed.getEntry().get(0).getLink().get(0).getRelation());
|
|
||||||
assertEquals("http://example.com/base/MedicationRequest/3123/_history/1", parsed.getEntry().get(0).getLink().get(0).getUrl());
|
|
||||||
assertEquals("http://foo?search", parsed.getEntry().get(0).getRequest().getUrlElement().getValueAsString());
|
|
||||||
|
|
||||||
MedicationRequest p = (MedicationRequest) parsed.getEntry().get(0).getResource();
|
|
||||||
assertEquals("Patient/347", p.getSubject().getReference());
|
|
||||||
assertEquals("2014-08-16T05:31:17Z", p.getMeta().getLastUpdatedElement().getValueAsString());
|
|
||||||
assertEquals("http://example.com/base/MedicationRequest/3123/_history/1", p.getId());
|
|
||||||
// assertEquals("3123", p.getId());
|
|
||||||
|
|
||||||
Medication m = (Medication) parsed.getEntry().get(1).getResource();
|
|
||||||
assertEquals("http://example.com/base/Medication/example", m.getId());
|
|
||||||
assertSame(((Reference) p.getMedication()).getResource(), m);
|
|
||||||
|
|
||||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
|
||||||
ourLog.info(reencoded);
|
|
||||||
|
|
||||||
JsonConfig cfg = new JsonConfig();
|
|
||||||
|
|
||||||
JSON expected = JSONSerializer.toJSON(content.trim(), cfg);
|
|
||||||
JSON actual = JSONSerializer.toJSON(reencoded.trim(), cfg);
|
|
||||||
|
|
||||||
String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("§", "§");
|
|
||||||
String act = actual.toString().replace("\\r\\n", "\\n");
|
|
||||||
|
|
||||||
ourLog.info("Expected: {}", exp);
|
|
||||||
ourLog.info("Actual : {}", act);
|
|
||||||
|
|
||||||
assertEquals(exp, act);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseAndEncodeBundleWithUuidBase() {
|
public void testParseAndEncodeBundleWithUuidBase() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -2221,20 +2237,18 @@ public class JsonParserDstu3Test {
|
||||||
|
|
||||||
@Test(expected = DataFormatException.class)
|
@Test(expected = DataFormatException.class)
|
||||||
public void testParseWithTrailingContent() {
|
public void testParseWithTrailingContent() {
|
||||||
//@formatter:off
|
|
||||||
String bundle = "{\n" +
|
String bundle = "{\n" +
|
||||||
" \"resourceType\" : \"Bundle\",\n" +
|
" \"resourceType\" : \"Bundle\",\n" +
|
||||||
" \"total\" : 1\n" +
|
" \"total\" : 1\n" +
|
||||||
"}}";
|
"}}";
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, bundle);
|
ourCtx.newJsonParser().parseResource(Bundle.class, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void testParseWithWrongTypeObjectShouldBeArray() throws Exception {
|
public void testParseWithWrongTypeObjectShouldBeArray() throws Exception {
|
||||||
String input = IOUtils.toString(getClass().getResourceAsStream("/invalid_metadata.json"));
|
String input = IOUtils.toString(getClass().getResourceAsStream("/invalid_metadata.json"), Charsets.UTF_8);
|
||||||
try {
|
try {
|
||||||
ourCtx.newJsonParser().parseResource(CapabilityStatement.class, input);
|
ourCtx.newJsonParser().parseResource(CapabilityStatement.class, input);
|
||||||
fail();
|
fail();
|
||||||
|
@ -2346,14 +2360,14 @@ public class JsonParserDstu3Test {
|
||||||
ArgumentCaptor<ValueType> actual = ArgumentCaptor.forClass(ValueType.class);
|
ArgumentCaptor<ValueType> actual = ArgumentCaptor.forClass(ValueType.class);
|
||||||
ArgumentCaptor<ScalarType> expectedScalar = ArgumentCaptor.forClass(ScalarType.class);
|
ArgumentCaptor<ScalarType> expectedScalar = ArgumentCaptor.forClass(ScalarType.class);
|
||||||
ArgumentCaptor<ScalarType> actualScalar = ArgumentCaptor.forClass(ScalarType.class);
|
ArgumentCaptor<ScalarType> actualScalar = ArgumentCaptor.forClass(ScalarType.class);
|
||||||
verify(errorHandler, atLeastOnce()).incorrectJsonType(Mockito.nullable(IParseLocation.class), elementName.capture(), expected.capture(), expectedScalar.capture(), actual.capture(),
|
verify(errorHandler, atLeastOnce()).incorrectJsonType(nullable(IParseLocation.class), elementName.capture(), expected.capture(), expectedScalar.capture(), actual.capture(),
|
||||||
actualScalar.capture());
|
actualScalar.capture());
|
||||||
verify(errorHandler, atLeastOnce()).incorrectJsonType(Mockito.nullable(IParseLocation.class), Mockito.eq("_id"), Mockito.eq(ValueType.OBJECT), expectedScalar.capture(), Mockito.eq(ValueType.SCALAR),
|
verify(errorHandler, atLeastOnce()).incorrectJsonType(nullable(IParseLocation.class), eq("_id"), eq(ValueType.OBJECT), expectedScalar.capture(), eq(ValueType.SCALAR),
|
||||||
actualScalar.capture());
|
actualScalar.capture());
|
||||||
verify(errorHandler, atLeastOnce()).incorrectJsonType(Mockito.nullable(IParseLocation.class), Mockito.eq("__v"), Mockito.eq(ValueType.OBJECT), expectedScalar.capture(), Mockito.eq(ValueType.SCALAR),
|
verify(errorHandler, atLeastOnce()).incorrectJsonType(nullable(IParseLocation.class), eq("__v"), eq(ValueType.OBJECT), expectedScalar.capture(), eq(ValueType.SCALAR),
|
||||||
actualScalar.capture());
|
actualScalar.capture());
|
||||||
verify(errorHandler, atLeastOnce()).incorrectJsonType(Mockito.nullable(IParseLocation.class), Mockito.eq("_status"), Mockito.eq(ValueType.OBJECT), expectedScalar.capture(),
|
verify(errorHandler, atLeastOnce()).incorrectJsonType(nullable(IParseLocation.class), eq("_status"), eq(ValueType.OBJECT), expectedScalar.capture(),
|
||||||
Mockito.eq(ValueType.SCALAR), actualScalar.capture());
|
eq(ValueType.SCALAR), actualScalar.capture());
|
||||||
|
|
||||||
assertEquals("_id", elementName.getAllValues().get(0));
|
assertEquals("_id", elementName.getAllValues().get(0));
|
||||||
assertEquals(ValueType.OBJECT, expected.getAllValues().get(0));
|
assertEquals(ValueType.OBJECT, expected.getAllValues().get(0));
|
||||||
|
@ -2363,7 +2377,7 @@ public class JsonParserDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCustomStructure() throws Exception {
|
public void testValidateCustomStructure() {
|
||||||
|
|
||||||
FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent();
|
FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent();
|
||||||
source.getMessageHeaderApplicationId().setValue("APPID");
|
source.getMessageHeaderApplicationId().setValue("APPID");
|
||||||
|
@ -2392,13 +2406,13 @@ public class JsonParserDstu3Test {
|
||||||
containedOrganization.getMeta().addProfile(UUID.randomUUID().toString());
|
containedOrganization.getMeta().addProfile(UUID.randomUUID().toString());
|
||||||
containedOrganization.getMeta().setLastUpdated(new Date());
|
containedOrganization.getMeta().setLastUpdated(new Date());
|
||||||
containedOrganization.getMeta().setVersionId(UUID.randomUUID().toString());
|
containedOrganization.getMeta().setVersionId(UUID.randomUUID().toString());
|
||||||
containedOrganization.getMeta().setSecurity(Arrays.asList(new Coding(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString())));
|
containedOrganization.getMeta().setSecurity(Collections.singletonList(new Coding(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString())));
|
||||||
containedOrganization.getMeta().setTag(Arrays.asList(new Coding(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString())));
|
containedOrganization.getMeta().setTag(Collections.singletonList(new Coding(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString())));
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.setId(UUID.randomUUID().toString());
|
patient.setId(UUID.randomUUID().toString());
|
||||||
patient.getMeta().addProfile(UUID.randomUUID().toString());
|
patient.getMeta().addProfile(UUID.randomUUID().toString());
|
||||||
patient.setGeneralPractitioner(Arrays.asList(new Reference(containedOrganization)));
|
patient.setGeneralPractitioner(Collections.singletonList(new Reference(containedOrganization)));
|
||||||
|
|
||||||
HashSet<String> excludeElementsInEncoded = new HashSet<>(); // ResourceMetaParams.EXCLUDE_ELEMENTS_IN_ENCODED
|
HashSet<String> excludeElementsInEncoded = new HashSet<>(); // ResourceMetaParams.EXCLUDE_ELEMENTS_IN_ENCODED
|
||||||
excludeElementsInEncoded.add("id");
|
excludeElementsInEncoded.add("id");
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.google.common.collect.Sets;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.hamcrest.collection.IsEmptyCollection;
|
import org.hamcrest.collection.IsEmptyCollection;
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
import org.hamcrest.text.StringContainsInOrder;
|
import org.hamcrest.text.StringContainsInOrder;
|
||||||
|
@ -69,6 +70,35 @@ public class XmlParserDstu3Test {
|
||||||
ourCtx.setNarrativeGenerator(null);
|
ourCtx.setNarrativeGenerator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We specifically include extensions on CapabilityStatment even in
|
||||||
|
* summary mode, since this is behaviour that people depend on
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEncodeSummaryCapabilityStatementExtensions() {
|
||||||
|
|
||||||
|
CapabilityStatement cs = new CapabilityStatement();
|
||||||
|
CapabilityStatement.CapabilityStatementRestComponent rest = cs.addRest();
|
||||||
|
rest.setMode(CapabilityStatement.RestfulCapabilityMode.CLIENT);
|
||||||
|
rest.getSecurity()
|
||||||
|
.addExtension()
|
||||||
|
.setUrl("http://foo")
|
||||||
|
.setValue(new StringType("bar"));
|
||||||
|
|
||||||
|
cs.getVersionElement().addExtension()
|
||||||
|
.setUrl("http://goo")
|
||||||
|
.setValue(new StringType("ber"));
|
||||||
|
|
||||||
|
String encoded = ourCtx.newXmlParser().setSummaryMode(true).setPrettyPrint(true).setPrettyPrint(true).encodeResourceToString(cs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertThat(encoded, Matchers.containsString("http://foo"));
|
||||||
|
assertThat(encoded, Matchers.containsString("bar"));
|
||||||
|
assertThat(encoded, Matchers.containsString("http://goo"));
|
||||||
|
assertThat(encoded, Matchers.containsString("ber"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeInvalidMetaTime() {
|
public void testEncodeInvalidMetaTime() {
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,16 @@ public class ElementsParamR4Test {
|
||||||
assertEquals("mg", ((Quantity) procedure.getExtension().get(0).getValue()).getCode());
|
assertEquals("mg", ((Quantity) procedure.getExtension().get(0).getValue()).getCode());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Procedure?_elements=Procedure.extension.value",
|
||||||
|
bundle -> {
|
||||||
|
Procedure procedure = (Procedure) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals("SUBSETTED", procedure.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals(0, procedure.getReasonCode().size());
|
||||||
|
assertEquals("1.1", ((Quantity) procedure.getExtension().get(0).getValue()).getValueElement().getValueAsString());
|
||||||
|
assertEquals("mg", ((Quantity) procedure.getExtension().get(0).getValue()).getCode());
|
||||||
|
});
|
||||||
|
|
||||||
verifyXmlAndJson(
|
verifyXmlAndJson(
|
||||||
"http://localhost:" + ourPort + "/Procedure?_elements=Procedure.extension.value.value",
|
"http://localhost:" + ourPort + "/Procedure?_elements=Procedure.extension.value.value",
|
||||||
bundle -> {
|
bundle -> {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
@ -31,6 +32,8 @@ import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsStringIgnoringCase;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsStringIgnoringCase;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
@ -220,7 +223,7 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, (containsString("entry")));
|
assertThat(responseContent, (containsString("entry")));
|
||||||
assertThat(responseContent, (containsString(">TEXT<")));
|
assertThat(responseContent, (containsString(">TEXT<")));
|
||||||
assertThat(responseContent, (containsString("Medication/123")));
|
assertThat(responseContent, (containsString("Medication/123")));
|
||||||
assertThat(responseContent, not(containsStringIgnoringCase("note")));
|
assertThat(responseContent, not(CoreMatchers.containsStringIgnoringCase("note")));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,11 @@
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
60
pom.xml
60
pom.xml
|
@ -1022,6 +1022,25 @@
|
||||||
<artifactId>velocity-tools</artifactId>
|
<artifactId>velocity-tools</artifactId>
|
||||||
<version>2.0</version>
|
<version>2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<version>3.1.6</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>java-hamcrest</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-library</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
<artifactId>plexus-compiler-api</artifactId>
|
<artifactId>plexus-compiler-api</artifactId>
|
||||||
|
@ -1792,23 +1811,6 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>license-maven-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>update-project-license</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>update-project-license</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<licenseName>apache_v2</licenseName>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-antrun-plugin</artifactId>
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
<inherited>false</inherited>
|
<inherited>false</inherited>
|
||||||
|
@ -2196,9 +2198,27 @@
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>DIST</id>
|
<id>DIST</id>
|
||||||
<modules>
|
<build>
|
||||||
<!--<module>hapi-fhir-osgi-core</module>-->
|
<plugins>
|
||||||
</modules>
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>license-maven-plugin</artifactId>
|
||||||
|
<inherited>false</inherited>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>update-project-license</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>update-project-license</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<licenseName>apache_v2</licenseName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
<profile>
|
||||||
<id>ROOT</id>
|
<id>ROOT</id>
|
||||||
|
|
|
@ -266,6 +266,10 @@
|
||||||
A new server interceptor hook called PROCESSING_COMPLETED has been added. This
|
A new server interceptor hook called PROCESSING_COMPLETED has been added. This
|
||||||
hook is called by the server at the end of processing every request (success and failure).
|
hook is called by the server at the end of processing every request (success and failure).
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
The <![CDATA[<code>_summary</code>]]> element was not always respected when encoding
|
||||||
|
JSON resources.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.8.0" date="2019-05-30" description="Hippo">
|
<release version="3.8.0" date="2019-05-30" description="Hippo">
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
|
|
|
@ -276,7 +276,7 @@ public DaoConfig daoConfig() {
|
||||||
If the client knows that they will only want a small number of results
|
If the client knows that they will only want a small number of results
|
||||||
(for example, a UI containing 20 results is being shown and the client
|
(for example, a UI containing 20 results is being shown and the client
|
||||||
knows that they will never load the next page of results) the client
|
knows that they will never load the next page of results) the client
|
||||||
may also use the <code>nostore</code> directive along with a HAPI FHIR
|
may also use the <code>no-store</code> directive along with a HAPI FHIR
|
||||||
extension called <code>max-results</code> in order to specify that
|
extension called <code>max-results</code> in order to specify that
|
||||||
only the given number of results should be fetched. This directive
|
only the given number of results should be fetched. This directive
|
||||||
disabled paging entirely for the request and causes the request to
|
disabled paging entirely for the request and causes the request to
|
||||||
|
@ -285,7 +285,7 @@ public DaoConfig daoConfig() {
|
||||||
</p>
|
</p>
|
||||||
<div class="source">
|
<div class="source">
|
||||||
<pre>
|
<pre>
|
||||||
Cache-Control: nostore, max-results=20
|
Cache-Control: no-store, max-results=20
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue