Work on cleanup
This commit is contained in:
parent
b028337d8f
commit
a1bf50685d
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.context;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
@ -68,8 +69,8 @@ public abstract class BaseRuntimeChildDefinition {
|
|||
public interface IAccessor {
|
||||
List<IBase> getValues(IBase theTarget);
|
||||
|
||||
default IBase getFirstValueOrNull(IBase theTarget) {
|
||||
return getValues(theTarget).stream().findFirst().orElse(null);
|
||||
default <T extends IBase> Optional<T> getFirstValueOrNull(IBase theTarget) {
|
||||
return (Optional<T>) getValues(theTarget).stream().findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.lang.reflect.Field;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChildDefinition {
|
||||
private final IAccessor myAccessor;
|
||||
|
@ -184,8 +185,8 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
|||
}
|
||||
|
||||
@Override
|
||||
public IBase getFirstValueOrNull(IBase theTarget) {
|
||||
return (IBase) getFieldValue(theTarget, myField);
|
||||
public <T extends IBase> Optional<T> getFirstValueOrNull(IBase theTarget) {
|
||||
return Optional.ofNullable(((T)getFieldValue(theTarget, myField)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hl7.fhir.instance.model.api.IBase;
|
|||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
@ -274,6 +275,7 @@ public class FhirContext {
|
|||
* Note that this method is case insensitive!
|
||||
* </p>
|
||||
*/
|
||||
@Nullable
|
||||
public BaseRuntimeElementDefinition<?> getElementDefinition(final String theElementName) {
|
||||
validateInitialized();
|
||||
return myNameToElementDefinition.get(theElementName.toLowerCase());
|
||||
|
|
|
@ -79,19 +79,19 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean elementIsRepeating(String theChildName) {
|
||||
boolean elementIsRepeating(String theChildName) {
|
||||
return myState.elementIsRepeating(theChildName);
|
||||
}
|
||||
|
||||
public void endingElement() throws DataFormatException {
|
||||
void endingElement() throws DataFormatException {
|
||||
myState.endingElement();
|
||||
}
|
||||
|
||||
public void enteringNewElement(String theNamespaceUri, String theName) throws DataFormatException {
|
||||
void enteringNewElement(String theNamespaceUri, String theName) throws DataFormatException {
|
||||
myState.enteringNewElement(theNamespaceUri, theName);
|
||||
}
|
||||
|
||||
public void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
|
||||
void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
|
||||
myState.enteringNewElementExtension(theElem, theUrlAttr, theIsModifier, baseServerUrl);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ class ParserState<T> {
|
|||
return myObject;
|
||||
}
|
||||
|
||||
public boolean isPreResource() {
|
||||
boolean isPreResource() {
|
||||
return myState.isPreResource();
|
||||
}
|
||||
|
||||
|
@ -135,18 +135,11 @@ class ParserState<T> {
|
|||
myState.string(theData);
|
||||
}
|
||||
|
||||
public boolean verifyNamespace(String theExpect, String theActual) {
|
||||
if (myJsonMode) {
|
||||
return true;
|
||||
}
|
||||
return StringUtils.equals(theExpect, theActual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked after any new XML event is individually processed, containing a copy of the XML event. This is basically
|
||||
* intended for embedded XHTML content
|
||||
*/
|
||||
public void xmlEvent(XMLEvent theNextEvent) {
|
||||
void xmlEvent(XMLEvent theNextEvent) {
|
||||
if (myState != null) {
|
||||
myState.xmlEvent(theNextEvent);
|
||||
}
|
||||
|
@ -157,7 +150,7 @@ class ParserState<T> {
|
|||
private PreResourceState myPreResourceState;
|
||||
private BaseState myStack;
|
||||
|
||||
public BaseState(PreResourceState thePreResourceState) {
|
||||
BaseState(PreResourceState thePreResourceState) {
|
||||
super();
|
||||
myPreResourceState = thePreResourceState;
|
||||
}
|
||||
|
@ -223,7 +216,7 @@ class ParserState<T> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public PreResourceState getPreResourceState() {
|
||||
PreResourceState getPreResourceState() {
|
||||
return myPreResourceState;
|
||||
}
|
||||
|
||||
|
@ -231,7 +224,7 @@ class ParserState<T> {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void logAndSwallowUnexpectedElement(String theLocalPart) {
|
||||
void logAndSwallowUnexpectedElement(String theLocalPart) {
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
}
|
||||
|
@ -340,6 +333,7 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
|
||||
private class DeclaredExtensionState extends BaseState {
|
||||
|
||||
private IBase myChildInstance;
|
||||
|
@ -431,10 +425,10 @@ class ParserState<T> {
|
|||
|
||||
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
|
||||
private IBase myInstance;
|
||||
private Set<String> myParsedNonRepeatableNames = new HashSet<String>();
|
||||
private Set<String> myParsedNonRepeatableNames = new HashSet<>();
|
||||
private String myElementName;
|
||||
|
||||
public ElementCompositeState(PreResourceState thePreResourceState, String theElementName, BaseRuntimeElementCompositeDefinition<?> theDef, IBase theInstance) {
|
||||
ElementCompositeState(PreResourceState thePreResourceState, String theElementName, BaseRuntimeElementCompositeDefinition<?> theDef, IBase theInstance) {
|
||||
super(thePreResourceState);
|
||||
myDefinition = theDef;
|
||||
myInstance = theInstance;
|
||||
|
@ -553,12 +547,9 @@ class ParserState<T> {
|
|||
}
|
||||
case CONTAINED_RESOURCES: {
|
||||
List<? extends IBase> values = child.getAccessor().getValues(myInstance);
|
||||
Object newDt;
|
||||
if (values == null || values.isEmpty() || values.get(0) == null) {
|
||||
newDt = newContainedDt((IResource) getPreResourceState().myInstance);
|
||||
Object newDt = newContainedDt((IResource) getPreResourceState().myInstance);
|
||||
child.getMutator().addValue(myInstance, (IBase) newDt);
|
||||
} else {
|
||||
newDt = values.get(0);
|
||||
}
|
||||
ContainedResourcesStateHapi state = new ContainedResourcesStateHapi(getPreResourceState());
|
||||
push(state);
|
||||
|
@ -611,7 +602,7 @@ class ParserState<T> {
|
|||
|
||||
private IBaseElement myElement;
|
||||
|
||||
public ElementIdState(ParserState<T>.PreResourceState thePreResourceState, IBaseElement theElement) {
|
||||
ElementIdState(ParserState<T>.PreResourceState thePreResourceState, IBaseElement theElement) {
|
||||
super(thePreResourceState);
|
||||
myElement = theElement;
|
||||
}
|
||||
|
@ -632,7 +623,7 @@ class ParserState<T> {
|
|||
|
||||
private IBaseExtension<?, ?> myExtension;
|
||||
|
||||
public ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?, ?> theExtension) {
|
||||
ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?, ?> theExtension) {
|
||||
super(thePreResourceState);
|
||||
myExtension = theExtension;
|
||||
}
|
||||
|
@ -712,7 +703,6 @@ class ParserState<T> {
|
|||
// We hit an invalid type for the extension
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -758,15 +748,18 @@ class ParserState<T> {
|
|||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
if (theLocalPart.equals("versionId")) {
|
||||
switch (theLocalPart) {
|
||||
case "versionId":
|
||||
push(new MetaVersionElementState(getPreResourceState(), myMap));
|
||||
// } else if (theLocalPart.equals("profile")) {
|
||||
//
|
||||
} else if (theLocalPart.equals("lastUpdated")) {
|
||||
break;
|
||||
case "lastUpdated":
|
||||
InstantDt updated = new InstantDt();
|
||||
push(new PrimitiveState(getPreResourceState(), updated));
|
||||
myMap.put(ResourceMetadataKeyEnum.UPDATED, updated);
|
||||
} else if (theLocalPart.equals("security")) {
|
||||
break;
|
||||
case "security":
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IBase> securityLabels = (List<IBase>) myMap.get(ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||
if (securityLabels == null) {
|
||||
|
@ -777,31 +770,33 @@ class ParserState<T> {
|
|||
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
|
||||
securityLabels.add(securityLabel);
|
||||
} else if (theLocalPart.equals("profile")) {
|
||||
break;
|
||||
case "profile":
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IdDt> profiles = (List<IdDt>) myMap.get(ResourceMetadataKeyEnum.PROFILES);
|
||||
List<IdDt> newProfiles;
|
||||
if (profiles != null) {
|
||||
newProfiles = new ArrayList<IdDt>(profiles.size() + 1);
|
||||
newProfiles = new ArrayList<>(profiles.size() + 1);
|
||||
newProfiles.addAll(profiles);
|
||||
} else {
|
||||
newProfiles = new ArrayList<IdDt>(1);
|
||||
newProfiles = new ArrayList<>(1);
|
||||
}
|
||||
IdDt profile = new IdDt();
|
||||
push(new PrimitiveState(getPreResourceState(), profile));
|
||||
newProfiles.add(profile);
|
||||
myMap.put(ResourceMetadataKeyEnum.PROFILES, Collections.unmodifiableList(newProfiles));
|
||||
} else if (theLocalPart.equals("tag")) {
|
||||
break;
|
||||
case "tag":
|
||||
TagList tagList = (TagList) myMap.get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (tagList == null) {
|
||||
tagList = new TagList();
|
||||
myMap.put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
|
||||
}
|
||||
push(new TagState(tagList));
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,7 +825,7 @@ class ParserState<T> {
|
|||
|
||||
private ResourceMetadataMap myMap;
|
||||
|
||||
public MetaVersionElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
|
||||
MetaVersionElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
|
||||
super(thePreResourceState);
|
||||
myMap = theMap;
|
||||
}
|
||||
|
@ -849,7 +844,6 @@ class ParserState<T> {
|
|||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -859,13 +853,12 @@ class ParserState<T> {
|
|||
private Map<String, IBaseResource> myContainedResources;
|
||||
private IBaseResource myInstance;
|
||||
private FhirVersionEnum myParentVersion;
|
||||
private boolean myRequireResourceType = true;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
|
||||
public PreResourceState(Class<? extends IBaseResource> theResourceType) {
|
||||
PreResourceState(Class<? extends IBaseResource> theResourceType) {
|
||||
super(null);
|
||||
myResourceType = theResourceType;
|
||||
myContainedResources = new HashMap<String, IBaseResource>();
|
||||
myContainedResources = new HashMap<>();
|
||||
if (theResourceType != null) {
|
||||
myParentVersion = myContext.getResourceDefinition(theResourceType).getStructureVersion();
|
||||
} else {
|
||||
|
@ -873,7 +866,7 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
public PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
|
||||
PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) {
|
||||
super(thePreResourcesState);
|
||||
Validate.notNull(theParentVersion);
|
||||
myParentVersion = theParentVersion;
|
||||
|
@ -888,7 +881,7 @@ class ParserState<T> {
|
|||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
BaseRuntimeElementDefinition<?> definition;
|
||||
RuntimeResourceDefinition definition;
|
||||
if (myResourceType == null) {
|
||||
definition = null;
|
||||
if (myParser.getPreferTypes() != null) {
|
||||
|
@ -908,17 +901,11 @@ class ParserState<T> {
|
|||
} else {
|
||||
definition = myContext.getResourceDefinition(myResourceType);
|
||||
if (!StringUtils.equals(theLocalPart, definition.getName())) {
|
||||
if (myRequireResourceType) {
|
||||
throw new DataFormatException(myContext.getLocalizer().getMessage(ParserState.class, "wrongResourceTypeFound", definition.getName(), theLocalPart));
|
||||
}
|
||||
definition = myContext.getResourceDefinition(theLocalPart);
|
||||
if (!(definition instanceof RuntimeResourceDefinition)) {
|
||||
throw new DataFormatException("Element '" + theLocalPart + "' is not a resource, expected a resource at this position");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
|
||||
RuntimeResourceDefinition def = definition;
|
||||
if (!definition.getName().equals(theLocalPart) && definition.getName().equalsIgnoreCase(theLocalPart)) {
|
||||
throw new DataFormatException("Unknown resource type '" + theLocalPart + "': Resource names are case sensitive, found similar name: '" + definition.getName() + "'");
|
||||
}
|
||||
|
@ -971,7 +958,7 @@ class ParserState<T> {
|
|||
|
||||
if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) {
|
||||
if (myResourceType == null || myResourceType.isAssignableFrom(wantedProfileType)) {
|
||||
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", new Object[]{myInstance.getClass().getName(), usedProfile, wantedProfileType});
|
||||
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", myInstance.getClass().getName(), usedProfile, wantedProfileType);
|
||||
|
||||
/*
|
||||
* This isn't the most efficient thing really.. If we want a specific
|
||||
|
@ -998,7 +985,7 @@ class ParserState<T> {
|
|||
|
||||
FhirTerser t = myContext.newTerser();
|
||||
|
||||
Map<String, IBaseResource> idToResource = new HashMap<String, IBaseResource>();
|
||||
Map<String, IBaseResource> idToResource = new HashMap<>();
|
||||
List<IBase> entries = t.getValues(myInstance, "Bundle.entry", IBase.class);
|
||||
for (IBase nextEntry : entries) {
|
||||
IPrimitiveType<?> fullUrl = t.getSingleValueOrNull(nextEntry, "fullUrl", IPrimitiveType.class);
|
||||
|
@ -1051,7 +1038,7 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
protected void weaveContainedResources() {
|
||||
void weaveContainedResources() {
|
||||
FhirTerser terser = myContext.newTerser();
|
||||
terser.visit(myInstance, new IModelVisitor() {
|
||||
|
||||
|
@ -1103,12 +1090,12 @@ class ParserState<T> {
|
|||
private IBase myTarget;
|
||||
|
||||
|
||||
public PreResourceStateHapi(Class<? extends IBaseResource> theResourceType) {
|
||||
PreResourceStateHapi(Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
|
||||
}
|
||||
|
||||
public PreResourceStateHapi(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
|
||||
PreResourceStateHapi(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
myTarget = theTarget;
|
||||
myMutator = theMutator;
|
||||
|
@ -1160,11 +1147,11 @@ class ParserState<T> {
|
|||
private IMutator myMutator;
|
||||
private IBase myTarget;
|
||||
|
||||
public PreResourceStateHl7Org(Class<? extends IBaseResource> theResourceType) {
|
||||
PreResourceStateHl7Org(Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
}
|
||||
|
||||
public PreResourceStateHl7Org(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
|
||||
PreResourceStateHl7Org(IBase theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
myMutator = theMutator;
|
||||
myTarget = theTarget;
|
||||
|
@ -1202,7 +1189,7 @@ class ParserState<T> {
|
|||
|
||||
private TagList myTagList;
|
||||
|
||||
public PreTagListState() {
|
||||
PreTagListState() {
|
||||
super(null);
|
||||
myTagList = new TagList();
|
||||
}
|
||||
|
@ -1236,7 +1223,7 @@ class ParserState<T> {
|
|||
private class PrimitiveState extends BaseState {
|
||||
private IPrimitiveType<?> myInstance;
|
||||
|
||||
public PrimitiveState(PreResourceState thePreResourceState, IPrimitiveType<?> theInstance) {
|
||||
PrimitiveState(PreResourceState thePreResourceState, IPrimitiveType<?> theInstance) {
|
||||
super(thePreResourceState);
|
||||
myInstance = theInstance;
|
||||
}
|
||||
|
@ -1288,7 +1275,6 @@ class ParserState<T> {
|
|||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1321,7 +1307,7 @@ class ParserState<T> {
|
|||
|
||||
private class ResourceStateHl7Org extends ElementCompositeState {
|
||||
|
||||
public ResourceStateHl7Org(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBaseResource theInstance) {
|
||||
ResourceStateHl7Org(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBaseResource theInstance) {
|
||||
super(thePreResourceState, theDef.getName(), theDef, theInstance);
|
||||
}
|
||||
|
||||
|
@ -1329,7 +1315,7 @@ class ParserState<T> {
|
|||
|
||||
private class SecurityLabelElementStateHapi extends ElementCompositeState {
|
||||
|
||||
public SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBase codingDt) {
|
||||
SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBase codingDt) {
|
||||
super(thePreResourceState, theDef.getName(), theDef, codingDt);
|
||||
}
|
||||
|
||||
|
@ -1344,7 +1330,7 @@ class ParserState<T> {
|
|||
|
||||
private int myDepth;
|
||||
|
||||
public SwallowChildrenWholeState(PreResourceState thePreResourceState) {
|
||||
SwallowChildrenWholeState(PreResourceState thePreResourceState) {
|
||||
super(thePreResourceState);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public interface IBaseEnumFactory<T extends Enum<?>> extends Serializable {
|
|||
* @return the enumeration value
|
||||
* @throws IllegalArgumentException is the value is not known
|
||||
*/
|
||||
public T fromCode(String codeString) throws IllegalArgumentException;
|
||||
T fromCode(String codeString) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get the XML/JSON representation for an enumerated value
|
||||
|
@ -39,6 +39,11 @@ public interface IBaseEnumFactory<T extends Enum<?>> extends Serializable {
|
|||
* @param code - the enumeration value
|
||||
* @return the XML/JSON representation
|
||||
*/
|
||||
public String toCode(T code);
|
||||
String toCode(T code);
|
||||
|
||||
/**
|
||||
* Get the system for a given enum value
|
||||
*/
|
||||
String toSystem(T theValue);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,6 @@ package org.hl7.fhir.instance.model.api;
|
|||
|
||||
public interface IBaseEnumeration<T extends Enum<?>> extends IPrimitiveType<T> {
|
||||
|
||||
// Marker interface
|
||||
IBaseEnumFactory<T> getEnumFactory();
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
/**
|
||||
* @see ResourceEncodingEnum
|
||||
*/
|
||||
public static final int ENCODING_COL_LENGTH = 5;
|
||||
static final int ENCODING_COL_LENGTH = 5;
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_RESOURCE_HISTORY_ID", sequenceName = "SEQ_RESOURCE_HISTORY_ID")
|
||||
|
@ -82,19 +82,6 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
return myProvenance;
|
||||
}
|
||||
|
||||
public void setProvenance(ResourceHistoryProvenanceEntity theProvenance) {
|
||||
myProvenance = theProvenance;
|
||||
}
|
||||
|
||||
public void addTag(ResourceHistoryTag theTag) {
|
||||
for (ResourceHistoryTag next : getTags()) {
|
||||
if (next.equals(theTag)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
getTags().add(theTag);
|
||||
}
|
||||
|
||||
public void addTag(ResourceTag theTag) {
|
||||
ResourceHistoryTag tag = new ResourceHistoryTag(this, theTag.getTag());
|
||||
tag.setResourceType(theTag.getResourceType());
|
||||
|
@ -159,7 +146,7 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
@Override
|
||||
public Collection<ResourceHistoryTag> getTags() {
|
||||
if (myTags == null) {
|
||||
myTags = new ArrayList<ResourceHistoryTag>();
|
||||
myTags = new ArrayList<>();
|
||||
}
|
||||
return myTags;
|
||||
}
|
||||
|
@ -173,13 +160,4 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
myResourceVersion = theVersion;
|
||||
}
|
||||
|
||||
public boolean hasTag(String theTerm, String theScheme) {
|
||||
for (ResourceHistoryTag next : getTags()) {
|
||||
if (next.getTag().getSystem().equals(theScheme) && next.getTag().getCode().equals(theTerm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,22 +20,25 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public abstract class BaseSearchParamExtractor implements ISearchParamExtractor {
|
||||
|
||||
public static final Pattern SPLIT = Pattern.compile("\\||( or )");
|
||||
|
@ -47,6 +50,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
@Autowired
|
||||
private ModelConfig myModelConfig;
|
||||
private Set<Class<?>> myIgnoredForSearchDatatypes;
|
||||
|
||||
public BaseSearchParamExtractor() {
|
||||
super();
|
||||
|
@ -58,6 +62,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
mySearchParamRegistry = theSearchParamRegistry;
|
||||
}
|
||||
|
||||
protected Set<Class<?>> getIgnoredForSearchDatatypes() {
|
||||
return myIgnoredForSearchDatatypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
|
||||
List<PathAndRef> refs = new ArrayList<PathAndRef>();
|
||||
|
@ -65,16 +73,43 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
for (String nextPath : nextPathsSplit) {
|
||||
nextPath = nextPath.trim();
|
||||
for (Object nextObject : extractValues(nextPath, theResource)) {
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
if (nextObject != null) {
|
||||
refs.add(new PathAndRef(nextPath, nextObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
protected abstract List<Object> extractValues(String thePaths, IBaseResource theResource);
|
||||
/**
|
||||
* Override parent because we're using FHIRPath here
|
||||
*/
|
||||
protected List<IBase> extractValues(String thePaths, IBaseResource theResource) {
|
||||
List<IBase> values = new ArrayList<>();
|
||||
if (isNotBlank(thePaths)) {
|
||||
String[] nextPathsSplit = SPLIT_R4.split(thePaths);
|
||||
for (String nextPath : nextPathsSplit) {
|
||||
List<? extends IBase> allValues;
|
||||
|
||||
Supplier<List<? extends IBase>> allValuesFunc = getPathValueExtractor(theResource, nextPath);
|
||||
allValues = allValuesFunc.get();
|
||||
|
||||
values.addAll(allValues);
|
||||
}
|
||||
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
IBase nextObject = values.get(i);
|
||||
if (nextObject instanceof IBaseExtension) {
|
||||
IBaseExtension nextExtension = (IBaseExtension) nextObject;
|
||||
nextObject = nextExtension.getValue();
|
||||
values.set(i, nextObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
protected abstract Supplier<List<? extends IBase>> getPathValueExtractor(IBaseResource theResource, String theNextPath);
|
||||
|
||||
protected FhirContext getContext() {
|
||||
return myContext;
|
||||
|
@ -92,9 +127,25 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setContextForUnitTest(FhirContext theContext) {
|
||||
myContext = theContext;
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myIgnoredForSearchDatatypes = new HashSet<>();
|
||||
addIgnoredType(getContext(), "Age", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Annotation", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Attachment", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Count", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Distance", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Ratio", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "SampledData", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Signature", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "LocationPositionComponent", myIgnoredForSearchDatatypes);
|
||||
}
|
||||
|
||||
private static void addIgnoredType(FhirContext theCtx, String theType, Set<Class<?>> theIgnoredTypes) {
|
||||
BaseRuntimeElementDefinition<?> elementDefinition = theCtx.getElementDefinition(theType);
|
||||
if (elementDefinition != null) {
|
||||
theIgnoredTypes.add(elementDefinition.getImplementingClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -713,6 +713,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||
myValidationSupport = theValidationSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myWorkerContext = new HapiWorkerContext(getContext(), myValidationSupport);
|
||||
|
|
|
@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.*;
|
||||
|
@ -27,20 +29,18 @@ import ca.uhn.fhir.jpa.model.util.StringNormalizer;
|
|||
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.PathEngineException;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext;
|
||||
import org.hl7.fhir.r5.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestSecurityComponent;
|
||||
import org.hl7.fhir.r5.model.Location.LocationPositionComponent;
|
||||
import org.hl7.fhir.r5.model.Patient.PatientCommunicationComponent;
|
||||
|
@ -52,6 +52,7 @@ import javax.measure.unit.NonSI;
|
|||
import javax.measure.unit.Unit;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -59,22 +60,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements ISearchParamExtractor {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorR5.class);
|
||||
private static final Set<Class<?>> ourIgnoredForSearchDatatypes;
|
||||
|
||||
static {
|
||||
//noinspection unchecked
|
||||
ourIgnoredForSearchDatatypes = Collections.unmodifiableSet(Sets.newHashSet(
|
||||
Age.class,
|
||||
Annotation.class,
|
||||
Attachment.class,
|
||||
Count.class,
|
||||
Distance.class,
|
||||
Ratio.class,
|
||||
SampledData.class,
|
||||
Signature.class,
|
||||
LocationPositionComponent.class
|
||||
));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
@ -87,33 +72,51 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
|||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void initFhirPath() {
|
||||
public void start() {
|
||||
super.start();
|
||||
IWorkerContext worker = new HapiWorkerContext(getContext(), myValidationSupport);
|
||||
myFhirPathEngine = new FHIRPathEngine(worker);
|
||||
myFhirPathEngine.setHostServices(new SearchParamExtractorR5HostServices());
|
||||
}
|
||||
|
||||
private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Quantity nextValue) {
|
||||
if (!nextValue.getValueElement().isEmpty()) {
|
||||
BigDecimal nextValueValue = nextValue.getValueElement().getValue();
|
||||
String nextValueString = nextValue.getSystemElement().getValueAsString();
|
||||
String nextValueCode = nextValue.getCode();
|
||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValueValue, nextValueString, nextValueCode);
|
||||
private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, IBase theQuantity) {
|
||||
BaseRuntimeElementCompositeDefinition<?> quantityDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Quantity");
|
||||
BaseRuntimeChildDefinition quantityValueChild = quantityDefinition.getChildByName("value");
|
||||
BaseRuntimeChildDefinition quantitySystemChild = quantityDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition quantityCodeChild = quantityDefinition.getChildByName("code");
|
||||
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = quantityValueChild.getAccessor().getFirstValueOrNull(theQuantity);
|
||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||
BigDecimal nextValueValue = valueField.get().getValue();
|
||||
String system = quantitySystemChild.getAccessor().<IPrimitiveType<String>>getFirstValueOrNull(theQuantity).map(t-> t.getValue()).orElse(null);
|
||||
String code = quantityCodeChild.getAccessor().<IPrimitiveType<String>>getFirstValueOrNull(theQuantity).map(t-> t.getValue()).orElse(null);
|
||||
|
||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValueValue, system, code);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void addMoney(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Money nextValue) {
|
||||
if (!nextValue.getValueElement().isEmpty()) {
|
||||
BigDecimal nextValueValue = nextValue.getValueElement().getValue();
|
||||
}
|
||||
|
||||
|
||||
private void addMoney(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, IBase theMoney) {
|
||||
BaseRuntimeElementCompositeDefinition<?> moneyDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Money");
|
||||
BaseRuntimeChildDefinition moneyValueChild = moneyDefinition.getChildByName("value");
|
||||
BaseRuntimeChildDefinition moneyCurrencyChild = moneyDefinition.getChildByName("currency");
|
||||
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = moneyValueChild.getAccessor().getFirstValueOrNull(theMoney);
|
||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||
BigDecimal nextValueValue = valueField.get().getValue();
|
||||
|
||||
String nextValueString = "urn:iso:std:iso:4217";
|
||||
String nextValueCode = nextValue.getCurrency();
|
||||
String nextValueCode = moneyCurrencyChild.getAccessor().<IPrimitiveType<String>>getFirstValueOrNull(theMoney).map(t-> t.getValue()).orElse(null);
|
||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValueValue, nextValueString, nextValueCode);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addSearchTerm(ResourceTable theEntity, Set<ResourceIndexedSearchParamString> retVal, String resourceName, String searchTerm) {
|
||||
|
@ -355,30 +358,24 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
|||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
if (isBlank(nextPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Object nextObject : extractValues(nextPath, theResource)) {
|
||||
if (nextObject == null || ((IBase) nextObject).isEmpty()) {
|
||||
for (IBase nextObject : extractValues(nextPath, theResource)) {
|
||||
if (nextObject == null || nextObject.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
String typeName = getContext().getElementDefinition(nextObject.getClass()).getName();
|
||||
|
||||
if (nextObject instanceof Quantity) {
|
||||
Quantity nextValue = (Quantity) nextObject;
|
||||
addQuantity(theEntity, retVal, resourceName, nextValue);
|
||||
} else if (nextObject instanceof Money) {
|
||||
Money nextValue = (Money) nextObject;
|
||||
addMoney(theEntity, retVal, resourceName, nextValue);
|
||||
if (typeName.equals("Quantity")) {
|
||||
addQuantity(theEntity, retVal, resourceName, nextObject);
|
||||
} else if (typeName.equals("Money")) {
|
||||
addMoney(theEntity, retVal, resourceName, nextObject);
|
||||
} else if (nextObject instanceof Range) {
|
||||
Range nextValue = (Range) nextObject;
|
||||
addQuantity(theEntity, retVal, resourceName, nextValue.getLow());
|
||||
addQuantity(theEntity, retVal, resourceName, nextValue.getHigh());
|
||||
} else if (ourIgnoredForSearchDatatypes.contains(nextObject.getClass())) {
|
||||
continue;
|
||||
} else {
|
||||
} else if (!getIgnoredForSearchDatatypes().contains(nextObject.getClass())) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
}
|
||||
}
|
||||
|
@ -545,8 +542,8 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
|||
}
|
||||
systems.add(nextValue.getSystemElement().getValueAsString());
|
||||
codes.add(nextValue.getValueElement().getValue());
|
||||
} else if (nextObject instanceof Enumeration<?>) {
|
||||
Enumeration<?> obj = (Enumeration<?>) nextObject;
|
||||
} else if (nextObject instanceof IBaseEnumeration<?>) {
|
||||
IBaseEnumeration<?> obj = (IBaseEnumeration<?>) nextObject;
|
||||
String system = extractSystem(obj);
|
||||
String code = obj.getValueAsString();
|
||||
if (isNotBlank(code)) {
|
||||
|
@ -698,48 +695,22 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override parent because we're using FHIRPath here
|
||||
*/
|
||||
@Override
|
||||
protected List<Object> extractValues(String thePaths, IBaseResource theResource) {
|
||||
IWorkerContext worker = new org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
|
||||
protected Supplier<List<? extends IBase>> getPathValueExtractor(IBaseResource theResource, String nextPath) {
|
||||
return () -> {
|
||||
try {
|
||||
IWorkerContext worker = new HapiWorkerContext(getContext(), myValidationSupport);
|
||||
FHIRPathEngine fp = new FHIRPathEngine(worker);
|
||||
fp.setHostServices(new SearchParamExtractorR5HostServices());
|
||||
|
||||
List<Object> values = new ArrayList<>();
|
||||
String[] nextPathsSplit = SPLIT_R4.split(thePaths);
|
||||
for (String nextPath : nextPathsSplit) {
|
||||
List<Base> allValues;
|
||||
try {
|
||||
allValues = fp.evaluate((Base) theResource, nextPath);
|
||||
return fp.evaluate((Base) theResource, nextPath);
|
||||
} catch (FHIRException e) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseSearchParamExtractor.class, "failedToExtractPaths", nextPath, e.toString());
|
||||
throw new InternalErrorException(msg, e);
|
||||
}
|
||||
if (allValues.isEmpty() == false) {
|
||||
values.addAll(allValues);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
Object nextObject = values.get(i);
|
||||
if (nextObject instanceof Extension) {
|
||||
Extension nextExtension = (Extension) nextObject;
|
||||
nextObject = nextExtension.getValue();
|
||||
values.set(i, nextObject);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setValidationSupportForTesting(IValidationSupport theValidationSupport) {
|
||||
myValidationSupport = theValidationSupport;
|
||||
}
|
||||
|
||||
private class SearchParamExtractorR5HostServices implements FHIRPathEngine.IEvaluationContext {
|
||||
private static class SearchParamExtractorR5HostServices implements FHIRPathEngine.IEvaluationContext {
|
||||
|
||||
private Map<String, Base> myResourceTypeToStub = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
|
@ -826,9 +797,10 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
|||
public ValueSet resolveValueSet(Object theO, String theS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static <T extends Enum<?>> String extractSystem(Enumeration<T> theBoundCode) {
|
||||
private static <T extends Enum<?>> String extractSystem(IBaseEnumeration<T> theBoundCode) {
|
||||
if (theBoundCode.getValue() != null) {
|
||||
return theBoundCode.getEnumFactory().toSystem(theBoundCode.getValue());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue