Enhanced elements (#1192)
Squashed merge: Add elements exclude mode * Start working on elements enhancement * Work on elements projection * Work on elements filter * Feature is now working * Just some cleanup * Address compile issues
This commit is contained in:
parent
447c394cac
commit
e401ec86e4
|
@ -30,11 +30,13 @@ import ca.uhn.fhir.util.UrlUtil;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -47,11 +49,9 @@ public abstract class BaseParser implements IParser {
|
||||||
private ContainedResources myContainedResources;
|
private ContainedResources myContainedResources;
|
||||||
private boolean myEncodeElementsAppliesToChildResourcesOnly;
|
private boolean myEncodeElementsAppliesToChildResourcesOnly;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private Set<String> myDontEncodeElements;
|
private List<ElementsPath> myDontEncodeElements;
|
||||||
private boolean myDontEncodeElementsIncludesStars;
|
private List<ElementsPath> myEncodeElements;
|
||||||
private Set<String> myEncodeElements;
|
|
||||||
private Set<String> myEncodeElementsAppliesToResourceTypes;
|
private Set<String> myEncodeElementsAppliesToResourceTypes;
|
||||||
private boolean myEncodeElementsIncludesStars;
|
|
||||||
private IIdType myEncodeForceResourceId;
|
private IIdType myEncodeForceResourceId;
|
||||||
private IParserErrorHandler myErrorHandler;
|
private IParserErrorHandler myErrorHandler;
|
||||||
private boolean myOmitResourceId;
|
private boolean myOmitResourceId;
|
||||||
|
@ -65,20 +65,19 @@ public abstract class BaseParser implements IParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
|
||||||
* @param theParserErrorHandler
|
|
||||||
*/
|
*/
|
||||||
public BaseParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) {
|
public BaseParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) {
|
||||||
myContext = theContext;
|
myContext = theContext;
|
||||||
myErrorHandler = theParserErrorHandler;
|
myErrorHandler = theParserErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Iterable<CompositeChildElement> compositeChildIterator(IBase theCompositeElement, final boolean theContainedResource, final boolean theSubResource, final CompositeChildElement theParent) {
|
protected Iterable<CompositeChildElement> compositeChildIterator(IBase theCompositeElement, final boolean theContainedResource, final CompositeChildElement theParent, EncodeContext theEncodeContext) {
|
||||||
|
|
||||||
BaseRuntimeElementCompositeDefinition<?> elementDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(theCompositeElement.getClass());
|
BaseRuntimeElementCompositeDefinition<?> elementDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(theCompositeElement.getClass());
|
||||||
final List<BaseRuntimeChildDefinition> children = elementDef.getChildrenAndExtension();
|
final List<BaseRuntimeChildDefinition> children = elementDef.getChildrenAndExtension();
|
||||||
|
|
||||||
return new Iterable<BaseParser.CompositeChildElement>() {
|
return new Iterable<BaseParser.CompositeChildElement>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<CompositeChildElement> iterator() {
|
public Iterator<CompositeChildElement> iterator() {
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ public abstract class BaseParser implements IParser {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
myNext = new CompositeChildElement(theParent, myChildrenIter.next(), theSubResource);
|
myNext = new CompositeChildElement(theParent, myChildrenIter.next(), theEncodeContext);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are lots of reasons we might skip encoding a particular child
|
* There are lots of reasons we might skip encoding a particular child
|
||||||
|
@ -181,8 +180,6 @@ public abstract class BaseParser implements IParser {
|
||||||
theContained.getExistingIdToContainedResource().put(nextId, next);
|
theContained.getExistingIdToContainedResource().put(nextId, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// no resources to contain
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IBaseReference> allReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
|
List<IBaseReference> allReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
|
||||||
|
@ -279,7 +276,7 @@ public abstract class BaseParser implements IParser {
|
||||||
return ref.getValue();
|
return ref.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
|
protected abstract void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter, EncodeContext theEncodeContext) throws IOException, DataFormatException;
|
||||||
|
|
||||||
protected abstract <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
|
protected abstract <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
|
||||||
|
|
||||||
|
@ -296,15 +293,27 @@ public abstract class BaseParser implements IParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException {
|
public final void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException {
|
||||||
|
EncodeContext encodeContext = new EncodeContext();
|
||||||
|
|
||||||
|
encodeResourceToWriter(theResource, theWriter, encodeContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void encodeResourceToWriter(IBaseResource theResource, Writer theWriter, EncodeContext theEncodeContext) throws IOException {
|
||||||
Validate.notNull(theResource, "theResource can not be null");
|
Validate.notNull(theResource, "theResource can not be null");
|
||||||
Validate.notNull(theWriter, "theWriter can not be null");
|
Validate.notNull(theWriter, "theWriter can not be null");
|
||||||
|
Validate.notNull(theEncodeContext, "theEncodeContext can not be null");
|
||||||
|
|
||||||
if (theResource.getStructureFhirVersionEnum() != myContext.getVersion().getVersion()) {
|
if (theResource.getStructureFhirVersionEnum() != myContext.getVersion().getVersion()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not encode a structure for version " + theResource.getStructureFhirVersionEnum());
|
"This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not encode a structure for version " + theResource.getStructureFhirVersionEnum());
|
||||||
}
|
}
|
||||||
|
|
||||||
doEncodeResourceToWriter(theResource, theWriter);
|
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
||||||
|
theEncodeContext.pushPath(resourceName, true);
|
||||||
|
|
||||||
|
doEncodeResourceToWriter(theResource, theWriter, theEncodeContext);
|
||||||
|
|
||||||
|
theEncodeContext.popPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterCodingsWithNoCodeOrSystem(List<? extends IBaseCoding> tagList) {
|
private void filterCodingsWithNoCodeOrSystem(List<? extends IBaseCoding> tagList) {
|
||||||
|
@ -392,43 +401,32 @@ public abstract class BaseParser implements IParser {
|
||||||
return myDontStripVersionsFromReferencesAtPaths;
|
return myDontStripVersionsFromReferencesAtPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link #setEncodeElements(Set)}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<String> getEncodeElements() {
|
|
||||||
return myEncodeElements;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEncodeElements(Set<String> theEncodeElements) {
|
public void setEncodeElements(Set<String> theEncodeElements) {
|
||||||
myEncodeElementsIncludesStars = false;
|
|
||||||
if (theEncodeElements == null || theEncodeElements.isEmpty()) {
|
if (theEncodeElements == null || theEncodeElements.isEmpty()) {
|
||||||
myEncodeElements = null;
|
myEncodeElements = null;
|
||||||
} else {
|
|
||||||
myEncodeElements = theEncodeElements;
|
|
||||||
for (String next : theEncodeElements) {
|
|
||||||
if (next.startsWith("*.")) {
|
|
||||||
myEncodeElementsIncludesStars = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link #setEncodeElementsAppliesToResourceTypes(Set)}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<String> getEncodeElementsAppliesToResourceTypes() {
|
|
||||||
return myEncodeElementsAppliesToResourceTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEncodeElementsAppliesToResourceTypes(Set<String> theEncodeElementsAppliesToResourceTypes) {
|
|
||||||
if (theEncodeElementsAppliesToResourceTypes == null || theEncodeElementsAppliesToResourceTypes.isEmpty()) {
|
|
||||||
myEncodeElementsAppliesToResourceTypes = null;
|
myEncodeElementsAppliesToResourceTypes = null;
|
||||||
} else {
|
} else {
|
||||||
myEncodeElementsAppliesToResourceTypes = theEncodeElementsAppliesToResourceTypes;
|
myEncodeElements = theEncodeElements
|
||||||
|
.stream()
|
||||||
|
.map(ElementsPath::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
myEncodeElementsAppliesToResourceTypes = new HashSet<>();
|
||||||
|
for (String next : myEncodeElements.stream().map(t -> t.getPath().get(0).getName()).collect(Collectors.toList())) {
|
||||||
|
if (next.startsWith("*")) {
|
||||||
|
myEncodeElementsAppliesToResourceTypes = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int dotIdx = next.indexOf('.');
|
||||||
|
if (dotIdx == -1) {
|
||||||
|
myEncodeElementsAppliesToResourceTypes.add(next);
|
||||||
|
} else {
|
||||||
|
myEncodeElementsAppliesToResourceTypes.add(next.substring(0, dotIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +446,7 @@ public abstract class BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> getExtensionMetadataKeys(IResource resource) {
|
protected List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> getExtensionMetadataKeys(IResource resource) {
|
||||||
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = new ArrayList<Map.Entry<ResourceMetadataKeyEnum<?>, Object>>();
|
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = new ArrayList<>();
|
||||||
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : resource.getResourceMetadata().entrySet()) {
|
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : resource.getResourceMetadata().entrySet()) {
|
||||||
if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) {
|
if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) {
|
||||||
extensionMetadataKeys.add(entry);
|
extensionMetadataKeys.add(entry);
|
||||||
|
@ -466,9 +464,9 @@ public abstract class BaseParser implements IParser {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TagList getMetaTagsForEncoding(IResource theIResource) {
|
protected TagList getMetaTagsForEncoding(IResource theIResource, EncodeContext theEncodeContext) {
|
||||||
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(theIResource);
|
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(theIResource);
|
||||||
if (shouldAddSubsettedTag()) {
|
if (shouldAddSubsettedTag(theEncodeContext)) {
|
||||||
tags = new TagList(tags);
|
tags = new TagList(tags);
|
||||||
tags.add(new Tag(getSubsettedCodeSystem(), Constants.TAG_SUBSETTED_CODE, subsetDescription()));
|
tags.add(new Tag(getSubsettedCodeSystem(), Constants.TAG_SUBSETTED_CODE, subsetDescription()));
|
||||||
}
|
}
|
||||||
|
@ -709,7 +707,7 @@ public abstract class BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<? extends IBase> preProcessValues(BaseRuntimeChildDefinition theMetaChildUncast, IBaseResource theResource, List<? extends IBase> theValues,
|
protected List<? extends IBase> preProcessValues(BaseRuntimeChildDefinition theMetaChildUncast, IBaseResource theResource, List<? extends IBase> theValues,
|
||||||
CompositeChildElement theCompositeChildElement) {
|
CompositeChildElement theCompositeChildElement, EncodeContext theEncodeContext) {
|
||||||
if (myContext.getVersion().getVersion().isRi()) {
|
if (myContext.getVersion().getVersion().isRi()) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -754,7 +752,7 @@ public abstract class BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldAddSubsettedTag()) {
|
if (shouldAddSubsettedTag(theEncodeContext)) {
|
||||||
IBaseCoding coding = metaValue.addTag();
|
IBaseCoding coding = metaValue.addTag();
|
||||||
coding.setCode(Constants.TAG_SUBSETTED_CODE);
|
coding.setCode(Constants.TAG_SUBSETTED_CODE);
|
||||||
coding.setSystem(getSubsettedCodeSystem());
|
coding.setSystem(getSubsettedCodeSystem());
|
||||||
|
@ -806,16 +804,13 @@ public abstract class BaseParser implements IParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDontEncodeElements(Set<String> theDontEncodeElements) {
|
public void setDontEncodeElements(Set<String> theDontEncodeElements) {
|
||||||
myDontEncodeElementsIncludesStars = false;
|
|
||||||
if (theDontEncodeElements == null || theDontEncodeElements.isEmpty()) {
|
if (theDontEncodeElements == null || theDontEncodeElements.isEmpty()) {
|
||||||
myDontEncodeElements = null;
|
myDontEncodeElements = null;
|
||||||
} else {
|
} else {
|
||||||
myDontEncodeElements = theDontEncodeElements;
|
myDontEncodeElements = theDontEncodeElements
|
||||||
for (String next : theDontEncodeElements) {
|
.stream()
|
||||||
if (next.startsWith("*.")) {
|
.map(ElementsPath::new)
|
||||||
myDontEncodeElementsIncludesStars = true;
|
.collect(Collectors.toList());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,22 +880,39 @@ public abstract class BaseParser implements IParser {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldAddSubsettedTag() {
|
protected boolean shouldAddSubsettedTag(EncodeContext theEncodeContext) {
|
||||||
return isSummaryMode() || isSuppressNarratives() || getEncodeElements() != null;
|
if (isSummaryMode()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (isSuppressNarratives()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (myEncodeElements != null) {
|
||||||
|
if (isEncodeElementsAppliesToChildResourcesOnly() && theEncodeContext.getResourcePath().size() < 2) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldEncodeResourceId(IBaseResource theResource, boolean theSubResource) {
|
String currentResourceName = theEncodeContext.getResourcePath().get(theEncodeContext.getResourcePath().size() - 1).getName();
|
||||||
|
if (myEncodeElementsAppliesToResourceTypes == null || myEncodeElementsAppliesToResourceTypes.contains(currentResourceName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean shouldEncodeResourceId(IBaseResource theResource, EncodeContext theEncodeContext) {
|
||||||
boolean retVal = true;
|
boolean retVal = true;
|
||||||
if (isOmitResourceId()) {
|
if (isOmitResourceId()) {
|
||||||
retVal = false;
|
retVal = false;
|
||||||
} else {
|
} else {
|
||||||
if (myDontEncodeElements != null) {
|
if (myDontEncodeElements != null) {
|
||||||
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
||||||
if (myDontEncodeElements.contains(resourceName + ".id")) {
|
if (myDontEncodeElements.stream().anyMatch(t -> t.startsWithPath(resourceName + ".id"))) {
|
||||||
retVal = false;
|
retVal = false;
|
||||||
} else if (myDontEncodeElements.contains("*.id")) {
|
} else if (myDontEncodeElements.stream().anyMatch(t -> t.startsWithPath("*.id"))) {
|
||||||
retVal = false;
|
retVal = false;
|
||||||
} else if (theSubResource == false && myDontEncodeElements.contains("id")) {
|
} else if (theEncodeContext.getResourcePath().size() == 1 && myDontEncodeElements.stream().anyMatch(t -> t.startsWithPath("id"))) {
|
||||||
retVal = false;
|
retVal = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -914,9 +926,11 @@ public abstract class BaseParser implements IParser {
|
||||||
protected boolean shouldEncodeResourceMeta(IResource theResource) {
|
protected boolean shouldEncodeResourceMeta(IResource theResource) {
|
||||||
if (myDontEncodeElements != null) {
|
if (myDontEncodeElements != null) {
|
||||||
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
||||||
if (myDontEncodeElements.contains(resourceName + ".meta")) {
|
if (myDontEncodeElements.stream().anyMatch(t -> t.startsWithPath(resourceName + ".meta"))) {
|
||||||
return false;
|
return false;
|
||||||
} else return !myDontEncodeElements.contains("*.meta");
|
} else {
|
||||||
|
return myDontEncodeElements.stream().anyMatch(t -> t.startsWithPath("*.meta"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -965,13 +979,13 @@ public abstract class BaseParser implements IParser {
|
||||||
private final BaseRuntimeChildDefinition myDef;
|
private final BaseRuntimeChildDefinition myDef;
|
||||||
private final CompositeChildElement myParent;
|
private final CompositeChildElement myParent;
|
||||||
private final RuntimeResourceDefinition myResDef;
|
private final RuntimeResourceDefinition myResDef;
|
||||||
private final boolean mySubResource;
|
private final EncodeContext myEncodeContext;
|
||||||
|
|
||||||
public CompositeChildElement(CompositeChildElement theParent, BaseRuntimeChildDefinition theDef, boolean theSubResource) {
|
public CompositeChildElement(CompositeChildElement theParent, BaseRuntimeChildDefinition theDef, EncodeContext theEncodeContext) {
|
||||||
myDef = theDef;
|
myDef = theDef;
|
||||||
myParent = theParent;
|
myParent = theParent;
|
||||||
myResDef = null;
|
myResDef = null;
|
||||||
mySubResource = theSubResource;
|
myEncodeContext = theEncodeContext;
|
||||||
|
|
||||||
if (ourLog.isTraceEnabled()) {
|
if (ourLog.isTraceEnabled()) {
|
||||||
if (theParent != null) {
|
if (theParent != null) {
|
||||||
|
@ -986,11 +1000,11 @@ public abstract class BaseParser implements IParser {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompositeChildElement(RuntimeResourceDefinition theResDef, boolean theSubResource) {
|
public CompositeChildElement(RuntimeResourceDefinition theResDef, EncodeContext theEncodeContext) {
|
||||||
myResDef = theResDef;
|
myResDef = theResDef;
|
||||||
myDef = null;
|
myDef = null;
|
||||||
myParent = null;
|
myParent = null;
|
||||||
mySubResource = theSubResource;
|
myEncodeContext = theEncodeContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addParent(CompositeChildElement theParent, StringBuilder theB) {
|
private void addParent(CompositeChildElement theParent, StringBuilder theB) {
|
||||||
|
@ -1038,71 +1052,75 @@ public abstract class BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkIfParentShouldBeEncodedAndBuildPath(StringBuilder thePathBuilder, boolean theStarPass) {
|
private boolean checkIfParentShouldBeEncodedAndBuildPath() {
|
||||||
Set<String> encodeElements = myEncodeElements;
|
List<ElementsPath> encodeElements = myEncodeElements;
|
||||||
if (encodeElements != null && encodeElements.isEmpty() == false) {
|
|
||||||
if (isEncodeElementsAppliesToChildResourcesOnly() && !mySubResource) {
|
String currentResourceName = myEncodeContext.getResourcePath().get(myEncodeContext.getResourcePath().size() - 1).getName();
|
||||||
|
if (myEncodeElementsAppliesToResourceTypes != null && !myEncodeElementsAppliesToResourceTypes.contains(currentResourceName)) {
|
||||||
encodeElements = null;
|
encodeElements = null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return checkIfPathMatchesForEncoding(thePathBuilder, theStarPass, myEncodeElementsAppliesToResourceTypes, encodeElements, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkIfParentShouldNotBeEncodedAndBuildPath(StringBuilder thePathBuilder, boolean theStarPass) {
|
boolean retVal = checkIfPathMatchesForEncoding(encodeElements, true);
|
||||||
return checkIfPathMatchesForEncoding(thePathBuilder, theStarPass, null, myDontEncodeElements, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkIfPathMatchesForEncoding(StringBuilder thePathBuilder, boolean theStarPass, Set<String> theResourceTypes, Set<String> theElements, boolean theCheckingForWhitelist) {
|
/*
|
||||||
if (myResDef != null) {
|
* We force the meta tag to be encoded even if it's not specified as an element in the
|
||||||
if (theResourceTypes != null) {
|
* elements filter, specifically because we'll need it in order to automatically add
|
||||||
if (!theResourceTypes.contains(myResDef.getName())) {
|
* the SUBSETTED tag
|
||||||
return true;
|
*/
|
||||||
}
|
|
||||||
}
|
|
||||||
if (theStarPass) {
|
|
||||||
thePathBuilder.append('*');
|
|
||||||
} else {
|
|
||||||
thePathBuilder.append(myResDef.getName());
|
|
||||||
}
|
|
||||||
if (theElements == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return theElements.contains(thePathBuilder.toString());
|
|
||||||
} else if (myParent != null) {
|
|
||||||
boolean parentCheck;
|
|
||||||
if (theCheckingForWhitelist) {
|
|
||||||
parentCheck = myParent.checkIfParentShouldBeEncodedAndBuildPath(thePathBuilder, theStarPass);
|
|
||||||
} else {
|
|
||||||
parentCheck = myParent.checkIfParentShouldNotBeEncodedAndBuildPath(thePathBuilder, theStarPass);
|
|
||||||
}
|
|
||||||
if (parentCheck) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myDef != null) {
|
|
||||||
if (myDef.getMin() > 0) {
|
|
||||||
if (theElements.contains("*.(mandatory)")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thePathBuilder.append('.');
|
|
||||||
thePathBuilder.append(myDef.getElementName());
|
|
||||||
String currentPath = thePathBuilder.toString();
|
|
||||||
boolean retVal = theElements.contains(currentPath);
|
|
||||||
int dotIdx = currentPath.indexOf('.');
|
|
||||||
if (!retVal) {
|
if (!retVal) {
|
||||||
if (dotIdx != -1 && theElements.contains(currentPath.substring(dotIdx + 1))) {
|
if ("meta".equals(myEncodeContext.getLeafResourcePathFirstField()) && shouldAddSubsettedTag(myEncodeContext)) {
|
||||||
if (!myParent.isSubResource()) {
|
// The next element is a child of the <meta> element
|
||||||
return true;
|
retVal = true;
|
||||||
}
|
} else if ("meta".equals(myDef.getElementName()) && shouldAddSubsettedTag(myEncodeContext)) {
|
||||||
|
// The next element is the <meta> element
|
||||||
|
retVal = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkIfParentShouldNotBeEncodedAndBuildPath() {
|
||||||
|
return checkIfPathMatchesForEncoding(myDontEncodeElements, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
private boolean checkIfPathMatchesForEncoding(List<ElementsPath> theElements, boolean theCheckingForEncodeElements) {
|
||||||
|
|
||||||
|
boolean retVal = false;
|
||||||
|
myEncodeContext.pushPath(myDef.getElementName(), false);
|
||||||
|
|
||||||
|
if (theCheckingForEncodeElements && isEncodeElementsAppliesToChildResourcesOnly() && myEncodeContext.getResourcePath().size() < 2) {
|
||||||
|
retVal = true;
|
||||||
|
} else if (theElements == null) {
|
||||||
|
retVal = true;
|
||||||
|
} else {
|
||||||
|
EncodeContextPath currentResourcePath = myEncodeContext.getCurrentResourcePath();
|
||||||
|
ourLog.trace("Current resource path: {}", currentResourcePath);
|
||||||
|
for (ElementsPath next : theElements) {
|
||||||
|
|
||||||
|
if (next.startsWith(currentResourcePath)) {
|
||||||
|
if (theCheckingForEncodeElements || next.getPath().size() == currentResourcePath.getPath().size()) {
|
||||||
|
retVal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next.getPath().get(next.getPath().size() - 1).getName().equals("(mandatory)")) {
|
||||||
|
if (myDef.getMin() > 0) {
|
||||||
|
retVal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (currentResourcePath.getPath().size() > next.getPath().size()) {
|
||||||
|
retVal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myEncodeContext.popPath();
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseRuntimeChildDefinition getDef() {
|
public BaseRuntimeChildDefinition getDef() {
|
||||||
|
@ -1113,38 +1131,189 @@ public abstract class BaseParser implements IParser {
|
||||||
return myParent;
|
return myParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RuntimeResourceDefinition getResDef() {
|
|
||||||
return myResDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSubResource() {
|
|
||||||
return mySubResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldBeEncoded() {
|
public boolean shouldBeEncoded() {
|
||||||
boolean retVal = true;
|
boolean retVal = true;
|
||||||
if (myEncodeElements != null) {
|
if (myEncodeElements != null) {
|
||||||
retVal = checkIfParentShouldBeEncodedAndBuildPath(new StringBuilder(), false);
|
retVal = checkIfParentShouldBeEncodedAndBuildPath();
|
||||||
if (retVal == false && myEncodeElementsIncludesStars) {
|
|
||||||
retVal = checkIfParentShouldBeEncodedAndBuildPath(new StringBuilder(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (retVal && myDontEncodeElements != null) {
|
if (retVal && myDontEncodeElements != null) {
|
||||||
retVal = !checkIfParentShouldNotBeEncodedAndBuildPath(new StringBuilder(), false);
|
retVal = !checkIfParentShouldNotBeEncodedAndBuildPath();
|
||||||
if (retVal && myDontEncodeElementsIncludesStars) {
|
|
||||||
retVal = !checkIfParentShouldNotBeEncodedAndBuildPath(new StringBuilder(), true);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// if (retVal == false && myEncodeElements.contains("*.(mandatory)")) {
|
|
||||||
// if (myDef.getMin() > 0) {
|
|
||||||
// retVal = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected class EncodeContextPath {
|
||||||
|
private final List<EncodeContextPathElement> myPath;
|
||||||
|
|
||||||
|
public EncodeContextPath() {
|
||||||
|
myPath = new ArrayList<>(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodeContextPath(List<EncodeContextPathElement> thePath) {
|
||||||
|
myPath = thePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return myPath.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<EncodeContextPathElement> getPath() {
|
||||||
|
return myPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodeContextPath getCurrentResourcePath() {
|
||||||
|
EncodeContextPath retVal = null;
|
||||||
|
for (int i = myPath.size() - 1; i >= 0; i--) {
|
||||||
|
if (myPath.get(i).isResource()) {
|
||||||
|
retVal = new EncodeContextPath(myPath.subList(i, myPath.size()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Validate.isTrue(retVal != null);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ElementsPath extends EncodeContextPath {
|
||||||
|
|
||||||
|
protected ElementsPath(String thePath) {
|
||||||
|
StringTokenizer tok = new StringTokenizer(thePath, ".");
|
||||||
|
boolean first = true;
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String next = tok.nextToken();
|
||||||
|
if (first && next.equals("*")) {
|
||||||
|
getPath().add(new EncodeContextPathElement("*", true));
|
||||||
|
} else if (isNotBlank(next)) {
|
||||||
|
getPath().add(new EncodeContextPathElement(next, Character.isUpperCase(next.charAt(0))));
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startsWith(EncodeContextPath theCurrentResourcePath) {
|
||||||
|
for (int i = 0; i < getPath().size(); i++) {
|
||||||
|
if (theCurrentResourcePath.getPath().size() == i) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EncodeContextPathElement expected = getPath().get(i);
|
||||||
|
EncodeContextPathElement actual = theCurrentResourcePath.getPath().get(i);
|
||||||
|
if (!expected.matches(actual)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startsWithPath(String thePath) {
|
||||||
|
return startsWith(new ElementsPath(thePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EncodeContext is a shared state object that is passed around the
|
||||||
|
* encode process
|
||||||
|
*/
|
||||||
|
protected class EncodeContext extends EncodeContextPath {
|
||||||
|
private final ArrayList<EncodeContextPathElement> myResourcePath = new ArrayList<>(10);
|
||||||
|
|
||||||
|
protected ArrayList<EncodeContextPathElement> getResourcePath() {
|
||||||
|
return myResourcePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLeafResourcePathFirstField() {
|
||||||
|
String retVal = null;
|
||||||
|
for (int i = getPath().size() - 1; i >= 0; i--) {
|
||||||
|
if (getPath().get(i).isResource()) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
retVal = getPath().get(i).getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an element at the end of the path
|
||||||
|
*/
|
||||||
|
protected void pushPath(String thePathElement, boolean theResource) {
|
||||||
|
assert isNotBlank(thePathElement);
|
||||||
|
assert !thePathElement.contains(".");
|
||||||
|
assert theResource ^ Character.isLowerCase(thePathElement.charAt(0));
|
||||||
|
|
||||||
|
EncodeContextPathElement element = new EncodeContextPathElement(thePathElement, theResource);
|
||||||
|
getPath().add(element);
|
||||||
|
if (theResource) {
|
||||||
|
myResourcePath.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the element at the end of the path
|
||||||
|
*/
|
||||||
|
public void popPath() {
|
||||||
|
EncodeContextPathElement removed = getPath().remove(getPath().size() - 1);
|
||||||
|
if (removed.isResource()) {
|
||||||
|
myResourcePath.remove(myResourcePath.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class EncodeContextPathElement {
|
||||||
|
private final String myName;
|
||||||
|
private final boolean myResource;
|
||||||
|
|
||||||
|
public EncodeContextPathElement(String theName, boolean theResource) {
|
||||||
|
Validate.notBlank(theName);
|
||||||
|
myName = theName;
|
||||||
|
myResource = theResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean matches(EncodeContextPathElement theOther) {
|
||||||
|
if (myResource != theOther.isResource()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (myName.equals(theOther.getName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (myName.equals("*")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37)
|
||||||
|
.append(myName)
|
||||||
|
.append(myResource)
|
||||||
|
.toHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (myResource) {
|
||||||
|
return myName + "(res)";
|
||||||
|
}
|
||||||
|
return myName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return myName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isResource() {
|
||||||
|
return myResource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class ContainedResources {
|
static class ContainedResources {
|
||||||
private long myNextContainedId = 1;
|
private long myNextContainedId = 1;
|
||||||
|
|
||||||
|
@ -1242,7 +1411,6 @@ public abstract class BaseParser implements IParser {
|
||||||
for (IBaseResource nextResource : getResourceList()) {
|
for (IBaseResource nextResource : getResourceList()) {
|
||||||
if (getResourceToIdMap().get(nextResource) != null) {
|
if (getResourceToIdMap().get(nextResource) != null) {
|
||||||
ids.add(getResourceToIdMap().get(nextResource).getValue());
|
ids.add(getResourceToIdMap().get(nextResource).getValue());
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,24 +1442,24 @@ public abstract class BaseParser implements IParser {
|
||||||
return new ArrayList<>(securityLabels);
|
return new ArrayList<>(securityLabels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean hasExtensions(IBase theElement) {
|
static boolean hasNoExtensions(IBase theElement) {
|
||||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||||
if (res.getUndeclaredExtensions().size() > 0 || res.getUndeclaredModifierExtensions().size() > 0) {
|
if (res.getUndeclaredExtensions().size() > 0 || res.getUndeclaredModifierExtensions().size() > 0) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (theElement instanceof IBaseHasExtensions) {
|
if (theElement instanceof IBaseHasExtensions) {
|
||||||
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
|
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
|
||||||
if (res.hasExtension()) {
|
if (res.hasExtension()) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (theElement instanceof IBaseHasModifierExtensions) {
|
if (theElement instanceof IBaseHasModifierExtensions) {
|
||||||
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
|
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
|
||||||
return res.hasModifierExtension();
|
return !res.hasModifierExtension();
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,16 +51,6 @@ public interface IParser {
|
||||||
|
|
||||||
void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
|
void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link #setEncodeElements(Set)}
|
|
||||||
*/
|
|
||||||
Set<String> getEncodeElements();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link #setEncodeElementsAppliesToResourceTypes(Set)}
|
|
||||||
*/
|
|
||||||
Set<String> getEncodeElementsAppliesToResourceTypes();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If not set to null (as is the default) this ID will be used as the ID in any
|
* If not set to null (as is the default) this ID will be used as the ID in any
|
||||||
* resources encoded by this parser
|
* resources encoded by this parser
|
||||||
|
@ -258,14 +248,6 @@ public interface IParser {
|
||||||
*/
|
*/
|
||||||
boolean isEncodeElementsAppliesToChildResourcesOnly();
|
boolean isEncodeElementsAppliesToChildResourcesOnly();
|
||||||
|
|
||||||
/**
|
|
||||||
* If provided, tells the parse which resource types to apply {@link #setEncodeElements(Set) encode elements} to. Any
|
|
||||||
* resource types not specified here will be encoded completely, with no elements excluded.
|
|
||||||
*
|
|
||||||
* @param theEncodeElementsAppliesToResourceTypes
|
|
||||||
*/
|
|
||||||
void setEncodeElementsAppliesToResourceTypes(Set<String> theEncodeElementsAppliesToResourceTypes);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When encoding, force this resource ID to be encoded as the resource ID
|
* When encoding, force this resource ID to be encoded as the resource ID
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -140,21 +140,21 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doEncodeResourceToJsonLikeWriter(IBaseResource theResource, JsonLikeWriter theEventWriter) throws IOException {
|
public void doEncodeResourceToJsonLikeWriter(IBaseResource theResource, JsonLikeWriter theEventWriter, EncodeContext theEncodeContext) throws IOException {
|
||||||
if (myPrettyPrint) {
|
if (myPrettyPrint) {
|
||||||
theEventWriter.setPrettyPrint(myPrettyPrint);
|
theEventWriter.setPrettyPrint(myPrettyPrint);
|
||||||
}
|
}
|
||||||
theEventWriter.init();
|
theEventWriter.init();
|
||||||
|
|
||||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||||
encodeResourceToJsonStreamWriter(resDef, theResource, theEventWriter, null, false, false);
|
encodeResourceToJsonStreamWriter(resDef, theResource, theEventWriter, null, false, theEncodeContext);
|
||||||
theEventWriter.flush();
|
theEventWriter.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException {
|
protected void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter, EncodeContext theEncodeContext) throws IOException {
|
||||||
JsonLikeWriter eventWriter = createJsonWriter(theWriter);
|
JsonLikeWriter eventWriter = createJsonWriter(theWriter);
|
||||||
doEncodeResourceToJsonLikeWriter(theResource, eventWriter);
|
doEncodeResourceToJsonLikeWriter(theResource, eventWriter, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -192,8 +192,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBase theNextValue,
|
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBase theNextValue,
|
||||||
BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theContainedResource, boolean theSubResource, CompositeChildElement theChildElem,
|
BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theContainedResource, CompositeChildElement theChildElem,
|
||||||
boolean theForceEmpty) throws IOException {
|
boolean theForceEmpty, EncodeContext theEncodeContext) throws IOException {
|
||||||
|
|
||||||
switch (theChildDef.getChildType()) {
|
switch (theChildDef.getChildType()) {
|
||||||
case ID_DATATYPE: {
|
case ID_DATATYPE: {
|
||||||
|
@ -265,7 +265,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
} else {
|
} else {
|
||||||
theEventWriter.beginObject();
|
theEventWriter.beginObject();
|
||||||
}
|
}
|
||||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theSubResource, theChildElem);
|
encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theChildElem, theEncodeContext);
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
|
|
||||||
for (IBaseResource next : containedResources) {
|
for (IBaseResource next : containedResources) {
|
||||||
IIdType resourceId = getContainedResources().getResourceId(next);
|
IIdType resourceId = getContainedResources().getResourceId(next);
|
||||||
encodeResourceToJsonStreamWriter(theResDef, next, theEventWriter, null, true, false, fixContainedResourceId(resourceId.getValue()));
|
encodeResourceToJsonStreamWriter(theResDef, next, theEventWriter, null, true, fixContainedResourceId(resourceId.getValue()), theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
|
@ -311,7 +311,11 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
case RESOURCE:
|
case RESOURCE:
|
||||||
IBaseResource resource = (IBaseResource) theNextValue;
|
IBaseResource resource = (IBaseResource) theNextValue;
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
|
||||||
encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, false, true);
|
|
||||||
|
theEncodeContext.pushPath(def.getName(), true);
|
||||||
|
encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, false, theEncodeContext);
|
||||||
|
theEncodeContext.popPath();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case UNDECL_EXT:
|
case UNDECL_EXT:
|
||||||
default:
|
default:
|
||||||
|
@ -321,7 +325,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, JsonLikeWriter theEventWriter,
|
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, JsonLikeWriter theEventWriter,
|
||||||
boolean theContainedResource, boolean theSubResource, CompositeChildElement theParent) throws IOException {
|
boolean theContainedResource, CompositeChildElement theParent, EncodeContext theEncodeContext) throws IOException {
|
||||||
|
|
||||||
{
|
{
|
||||||
String elementId = getCompositeElementId(theElement);
|
String elementId = getCompositeElementId(theElement);
|
||||||
|
@ -331,14 +335,14 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean haveWrittenExtensions = false;
|
boolean haveWrittenExtensions = false;
|
||||||
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theSubResource, theParent)) {
|
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent, theEncodeContext)) {
|
||||||
|
|
||||||
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
||||||
|
|
||||||
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);
|
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, myContext.getElementDefinition(theElement.getClass()), theResDef, theResource, nextChildElem, theParent, theEncodeContext);
|
||||||
haveWrittenExtensions = true;
|
haveWrittenExtensions = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -361,7 +365,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, theSubResource, nextChildElem, false);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, nextChildElem, false, theEncodeContext);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,12 +373,12 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
} else if (nextChild instanceof RuntimeChildContainedResources) {
|
} else if (nextChild instanceof RuntimeChildContainedResources) {
|
||||||
String childName = nextChild.getValidChildNames().iterator().next();
|
String childName = nextChild.getValidChildNames().iterator().next();
|
||||||
BaseRuntimeElementDefinition<?> child = nextChild.getChildByName(childName);
|
BaseRuntimeElementDefinition<?> child = nextChild.getChildByName(childName);
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, null, child, childName, theContainedResource, theSubResource, nextChildElem, false);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, null, child, childName, theContainedResource, nextChildElem, false, theEncodeContext);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
||||||
values = super.preProcessValues(nextChild, theResource, values, nextChildElem);
|
values = super.preProcessValues(nextChild, theResource, values, nextChildElem, theEncodeContext);
|
||||||
|
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -407,6 +411,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
String childName = childNameAndDef.getChildName();
|
String childName = childNameAndDef.getChildName();
|
||||||
|
theEncodeContext.pushPath(childName, false);
|
||||||
|
|
||||||
BaseRuntimeElementDefinition<?> childDef = childNameAndDef.getChildDef();
|
BaseRuntimeElementDefinition<?> childDef = childNameAndDef.getChildDef();
|
||||||
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
|
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
|
||||||
|
|
||||||
|
@ -452,18 +458,19 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
|
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
|
||||||
beginArray(theEventWriter, childName);
|
beginArray(theEventWriter, childName);
|
||||||
inArray = true;
|
inArray = true;
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, theSubResource, nextChildElem, force);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem, force, theEncodeContext);
|
||||||
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
||||||
// suppress narratives from contained resources
|
// suppress narratives from contained resources
|
||||||
} else {
|
} else {
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theContainedResource, theSubResource, nextChildElem, false);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theContainedResource, nextChildElem, false, theEncodeContext);
|
||||||
}
|
}
|
||||||
currentChildName = childName;
|
currentChildName = childName;
|
||||||
} else {
|
} else {
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, theSubResource, nextChildElem, force);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem, force, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
valueIdx++;
|
valueIdx++;
|
||||||
|
theEncodeContext.popPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inArray) {
|
if (inArray) {
|
||||||
|
@ -525,7 +532,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts, theEncodeContext);
|
||||||
if (inArray) {
|
if (inArray) {
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
|
@ -541,11 +548,10 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonLikeWriter theEventWriter, boolean theContainedResource, boolean theSubResource,
|
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonLikeWriter theEventWriter, boolean theContainedResource, CompositeChildElement theParent, EncodeContext theEncodeContext) throws IOException, DataFormatException {
|
||||||
CompositeChildElement theParent) throws IOException, DataFormatException {
|
|
||||||
|
|
||||||
writeCommentsPreAndPost(theNextValue, theEventWriter);
|
writeCommentsPreAndPost(theNextValue, theEventWriter);
|
||||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theSubResource, theParent);
|
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theParent, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -558,27 +564,15 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
"This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not encode a structure for version " + theResource.getStructureFhirVersionEnum());
|
"This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not encode a structure for version " + theResource.getStructureFhirVersionEnum());
|
||||||
}
|
}
|
||||||
|
|
||||||
doEncodeResourceToJsonLikeWriter(theResource, theJsonLikeWriter);
|
EncodeContext encodeContext = new EncodeContext();
|
||||||
|
String resourceName = myContext.getResourceDefinition(theResource).getName();
|
||||||
|
encodeContext.pushPath(resourceName, true);
|
||||||
|
doEncodeResourceToJsonLikeWriter(theResource, theJsonLikeWriter, encodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, String theObjectNameOrNull,
|
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, String theObjectNameOrNull,
|
||||||
boolean theContainedResource, boolean theSubResource) throws IOException {
|
boolean theContainedResource, EncodeContext theEncodeContext) throws IOException {
|
||||||
IIdType resourceId = null;
|
IIdType resourceId = null;
|
||||||
// if (theResource instanceof IResource) {
|
|
||||||
// IResource res = (IResource) theResource;
|
|
||||||
// if (StringUtils.isNotBlank(res.getId().getIdPart())) {
|
|
||||||
// if (theContainedResource) {
|
|
||||||
// resourceId = res.getId().getIdPart();
|
|
||||||
// } else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
|
||||||
// resourceId = res.getId().getIdPart();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (theResource instanceof IAnyResource) {
|
|
||||||
// IAnyResource res = (IAnyResource) theResource;
|
|
||||||
// if (/* theContainedResource && */StringUtils.isNotBlank(res.getIdElement().getIdPart())) {
|
|
||||||
// resourceId = res.getIdElement().getIdPart();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
|
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
|
||||||
resourceId = theResource.getIdElement();
|
resourceId = theResource.getIdElement();
|
||||||
|
@ -588,18 +582,18 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!theContainedResource) {
|
if (!theContainedResource) {
|
||||||
if (super.shouldEncodeResourceId(theResource, theSubResource) == false) {
|
if (!super.shouldEncodeResourceId(theResource, theEncodeContext)) {
|
||||||
resourceId = null;
|
resourceId = null;
|
||||||
} else if (!theSubResource && getEncodeForceResourceId() != null) {
|
} else if (theEncodeContext.getResourcePath().size() == 1 && getEncodeForceResourceId() != null) {
|
||||||
resourceId = getEncodeForceResourceId();
|
resourceId = getEncodeForceResourceId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, theSubResource, resourceId);
|
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, String theObjectNameOrNull,
|
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, String theObjectNameOrNull,
|
||||||
boolean theContainedResource, boolean theSubResource, IIdType theResourceId) throws IOException {
|
boolean theContainedResource, IIdType theResourceId, EncodeContext theEncodeContext) throws IOException {
|
||||||
if (!theContainedResource) {
|
if (!theContainedResource) {
|
||||||
super.containResourcesForEncoding(theResource);
|
super.containResourcesForEncoding(theResource);
|
||||||
}
|
}
|
||||||
|
@ -630,7 +624,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
writeCommentsPreAndPost(theResourceId, theEventWriter);
|
writeCommentsPreAndPost(theResourceId, theEventWriter);
|
||||||
}
|
}
|
||||||
if (haveExtension) {
|
if (haveExtension) {
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
||||||
}
|
}
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
|
@ -644,7 +638,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
||||||
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
||||||
|
|
||||||
TagList tags = getMetaTagsForEncoding(resource);
|
TagList tags = getMetaTagsForEncoding(resource, theEncodeContext);
|
||||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||||
IdDt resourceId = resource.getId();
|
IdDt resourceId = resource.getId();
|
||||||
String versionIdPart = resourceId.getVersionIdPart();
|
String versionIdPart = resourceId.getVersionIdPart();
|
||||||
|
@ -672,7 +666,9 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
beginArray(theEventWriter, "security");
|
beginArray(theEventWriter, "security");
|
||||||
for (BaseCodingDt securityLabel : securityLabels) {
|
for (BaseCodingDt securityLabel : securityLabels) {
|
||||||
theEventWriter.beginObject();
|
theEventWriter.beginObject();
|
||||||
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, theContainedResource, theSubResource, null);
|
theEncodeContext.pushPath("security", false);
|
||||||
|
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, theContainedResource, null, theEncodeContext);
|
||||||
|
theEncodeContext.popPath();
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
|
@ -693,23 +689,23 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
addExtensionMetadata(theResDef, theResource, theContainedResource, theSubResource, extensionMetadataKeys, resDef, theEventWriter);
|
addExtensionMetadata(theResDef, theResource, theContainedResource, extensionMetadataKeys, resDef, theEventWriter, theEncodeContext);
|
||||||
|
|
||||||
theEventWriter.endObject(); // end meta
|
theEventWriter.endObject(); // end meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, theContainedResource, theSubResource, new CompositeChildElement(resDef, theSubResource));
|
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef, theEncodeContext), theEncodeContext);
|
||||||
|
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addExtensionMetadata(RuntimeResourceDefinition theResDef, IBaseResource theResource,
|
private void addExtensionMetadata(RuntimeResourceDefinition theResDef, IBaseResource theResource,
|
||||||
boolean theContainedResource, boolean theSubResource,
|
boolean theContainedResource,
|
||||||
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys,
|
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys,
|
||||||
RuntimeResourceDefinition resDef,
|
RuntimeResourceDefinition resDef,
|
||||||
JsonLikeWriter theEventWriter) throws IOException {
|
JsonLikeWriter theEventWriter, EncodeContext theEncodeContext) throws IOException {
|
||||||
if (extensionMetadataKeys.isEmpty()) {
|
if (extensionMetadataKeys.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -718,7 +714,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : extensionMetadataKeys) {
|
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : extensionMetadataKeys) {
|
||||||
metaResource.addUndeclaredExtension((ExtensionDt) entry.getValue());
|
metaResource.addUndeclaredExtension((ExtensionDt) entry.getValue());
|
||||||
}
|
}
|
||||||
encodeCompositeElementToStreamWriter(theResDef, theResource, metaResource, theEventWriter, theContainedResource, theSubResource, new CompositeChildElement(resDef, theSubResource));
|
encodeCompositeElementToStreamWriter(theResDef, theResource, metaResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef, theEncodeContext), theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -726,7 +722,7 @@ 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) throws IOException {
|
IBaseResource theResource, CompositeChildElement theChildElem, CompositeChildElement theParent, EncodeContext theEncodeContext) 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);
|
||||||
|
|
||||||
|
@ -739,7 +735,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the extensions
|
// Write the extensions
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
@ -1260,18 +1256,18 @@ 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) throws IOException {
|
List<HeldExtension> modifierExtensions, EncodeContext theEncodeContext) throws IOException {
|
||||||
if (extensions.isEmpty() == false) {
|
if (extensions.isEmpty() == false) {
|
||||||
beginArray(theEventWriter, "extension");
|
beginArray(theEventWriter, "extension");
|
||||||
for (HeldExtension next : extensions) {
|
for (HeldExtension next : extensions) {
|
||||||
next.write(resDef, theResource, theEventWriter);
|
next.write(resDef, theResource, theEventWriter, theEncodeContext);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
if (modifierExtensions.isEmpty() == false) {
|
if (modifierExtensions.isEmpty() == false) {
|
||||||
beginArray(theEventWriter, "modifierExtension");
|
beginArray(theEventWriter, "modifierExtension");
|
||||||
for (HeldExtension next : modifierExtensions) {
|
for (HeldExtension next : modifierExtensions) {
|
||||||
next.write(resDef, theResource, theEventWriter);
|
next.write(resDef, theResource, theEventWriter, theEncodeContext);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1330,7 @@ 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) 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) 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);
|
||||||
|
@ -1350,15 +1346,15 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
if (haveContent) {
|
if (haveContent) {
|
||||||
beginObject(theEventWriter, '_' + childName);
|
beginObject(theEventWriter, '_' + childName);
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theEncodeContext);
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter) throws IOException {
|
public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, EncodeContext theEncodeContext) throws IOException {
|
||||||
if (myUndeclaredExtension != null) {
|
if (myUndeclaredExtension != null) {
|
||||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, myUndeclaredExtension);
|
writeUndeclaredExtension(theResDef, theResource, theEventWriter, myUndeclaredExtension, theEncodeContext);
|
||||||
} else {
|
} else {
|
||||||
theEventWriter.beginObject();
|
theEventWriter.beginObject();
|
||||||
|
|
||||||
|
@ -1372,7 +1368,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
*
|
*
|
||||||
* See #327
|
* See #327
|
||||||
*/
|
*/
|
||||||
List<? extends IBase> preProcessedValue = preProcessValues(myDef, theResource, Collections.singletonList(myValue), myChildElem);
|
List<? extends IBase> preProcessedValue = preProcessValues(myDef, theResource, Collections.singletonList(myValue), myChildElem, theEncodeContext);
|
||||||
|
|
||||||
// // Check for undeclared extensions on the declared extension
|
// // Check for undeclared extensions on the declared extension
|
||||||
// // (grrrrrr....)
|
// // (grrrrrr....)
|
||||||
|
@ -1391,18 +1387,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);
|
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, myChildElem, null, theEncodeContext);
|
||||||
} else {
|
} else {
|
||||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, false, myParent, false);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false, theEncodeContext);
|
||||||
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName);
|
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.endObject();
|
theEventWriter.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBaseExtension<?, ?> ext) throws IOException {
|
private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBaseExtension<?, ?> ext, EncodeContext theEncodeContext) throws IOException {
|
||||||
IBase value = ext.getValue();
|
IBase value = ext.getValue();
|
||||||
final String extensionUrl = getExtensionUrl(ext.getUrl());
|
final String extensionUrl = getExtensionUrl(ext.getUrl());
|
||||||
|
|
||||||
|
@ -1429,7 +1425,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Object next : ext.getExtension()) {
|
for (Object next : ext.getExtension()) {
|
||||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next);
|
writeUndeclaredExtension(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next, theEncodeContext);
|
||||||
}
|
}
|
||||||
theEventWriter.endArray();
|
theEventWriter.endArray();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1438,7 +1434,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
* 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
|
||||||
* since we might modify the text
|
* since we might modify the text
|
||||||
*/
|
*/
|
||||||
value = JsonParser.super.preProcessValues(myDef, theResource, Collections.singletonList(value), myChildElem).get(0);
|
value = JsonParser.super.preProcessValues(myDef, theResource, Collections.singletonList(value), myChildElem, theEncodeContext).get(0);
|
||||||
|
|
||||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||||
|
@ -1449,8 +1445,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
if (childDef == null) {
|
if (childDef == null) {
|
||||||
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, true, false, myParent, false);
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, myParent,false, theEncodeContext);
|
||||||
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName);
|
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// theEventWriter.name(myUndeclaredExtension.get);
|
// theEventWriter.name(myUndeclaredExtension.get);
|
||||||
|
|
|
@ -20,28 +20,32 @@ package ca.uhn.fhir.parser;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import ca.uhn.fhir.context.*;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import ca.uhn.fhir.model.api.*;
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import java.io.Reader;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import java.io.StringReader;
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import java.io.Writer;
|
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||||
import java.util.*;
|
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
|
||||||
|
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
||||||
|
import ca.uhn.fhir.util.XmlUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import javax.xml.stream.*;
|
import javax.xml.stream.*;
|
||||||
import javax.xml.stream.events.*;
|
import javax.xml.stream.events.*;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.*;
|
|
||||||
import ca.uhn.fhir.model.api.*;
|
|
||||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.*;
|
|
||||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -52,14 +56,13 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
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 OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
|
|
||||||
static final String RESREF_DISPLAY = "display";
|
static final String RESREF_DISPLAY = "display";
|
||||||
static final String RESREF_REFERENCE = "reference";
|
static final String RESREF_REFERENCE = "reference";
|
||||||
static final String TOMBSTONES_NS = "http://purl.org/atompub/tombstones/1.0";
|
static final String TOMBSTONES_NS = "http://purl.org/atompub/tombstones/1.0";
|
||||||
static final String XHTML_NS = "http://www.w3.org/1999/xhtml";
|
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 Set<String> RESOURCE_NAMESPACES;
|
// private static final Set<String> RESOURCE_NAMESPACES;
|
||||||
|
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private boolean myPrettyPrint;
|
private boolean myPrettyPrint;
|
||||||
|
|
||||||
|
@ -101,12 +104,12 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws DataFormatException {
|
public void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter, EncodeContext theEncodeContext) throws DataFormatException {
|
||||||
XMLStreamWriter eventWriter;
|
XMLStreamWriter eventWriter;
|
||||||
try {
|
try {
|
||||||
eventWriter = createXmlWriter(theWriter);
|
eventWriter = createXmlWriter(theWriter);
|
||||||
|
|
||||||
encodeResourceToXmlStreamWriter(theResource, eventWriter, false, false);
|
encodeResourceToXmlStreamWriter(theResource, eventWriter, false, theEncodeContext);
|
||||||
eventWriter.flush();
|
eventWriter.flush();
|
||||||
} catch (XMLStreamException e) {
|
} catch (XMLStreamException e) {
|
||||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||||
|
@ -123,7 +126,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
ourLog.trace("Entering XML parsing loop with state: {}", parserState);
|
ourLog.trace("Entering XML parsing loop with state: {}", parserState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> heldComments = new ArrayList<String>(1);
|
List<String> heldComments = new ArrayList<>(1);
|
||||||
|
|
||||||
while (streamReader.hasNext()) {
|
while (streamReader.hasNext()) {
|
||||||
XMLEvent nextEvent = streamReader.nextEvent();
|
XMLEvent nextEvent = streamReader.nextEvent();
|
||||||
|
@ -167,10 +170,8 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
heldComments.clear();
|
heldComments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
for (Iterator<Attribute> attributes = elem.getAttributes(); attributes.hasNext(); ) {
|
||||||
Iterator<Attribute> attributes = elem.getAttributes();
|
Attribute next = attributes.next();
|
||||||
for (Iterator<Attribute> iter = attributes; iter.hasNext();) {
|
|
||||||
Attribute next = iter.next();
|
|
||||||
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +216,10 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase theElement, String childName, BaseRuntimeElementDefinition<?> childDef,
|
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase theElement, String childName, BaseRuntimeElementDefinition<?> childDef,
|
||||||
String theExtensionUrl, boolean theIncludedResource, boolean theSubResource, CompositeChildElement theParent) throws XMLStreamException, DataFormatException {
|
String theExtensionUrl, boolean theIncludedResource, CompositeChildElement theParent, EncodeContext theEncodeContext) throws XMLStreamException, DataFormatException {
|
||||||
|
theEncodeContext.pushPath(childName, false);
|
||||||
|
try {
|
||||||
|
|
||||||
if (theElement == null || theElement.isEmpty()) {
|
if (theElement == null || theElement.isEmpty()) {
|
||||||
if (isChildContained(childDef, theIncludedResource)) {
|
if (isChildContained(childDef, theIncludedResource)) {
|
||||||
// We still want to go in..
|
// We still want to go in..
|
||||||
|
@ -230,12 +234,12 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
case ID_DATATYPE: {
|
case ID_DATATYPE: {
|
||||||
IIdType value = IIdType.class.cast(theElement);
|
IIdType value = IIdType.class.cast(theElement);
|
||||||
String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue();
|
String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue();
|
||||||
if (StringUtils.isNotBlank(encodedValue) || super.hasExtensions(value)) {
|
if (StringUtils.isNotBlank(encodedValue) || !super.hasNoExtensions(value)) {
|
||||||
theEventWriter.writeStartElement(childName);
|
theEventWriter.writeStartElement(childName);
|
||||||
if (StringUtils.isNotBlank(encodedValue)) {
|
if (StringUtils.isNotBlank(encodedValue)) {
|
||||||
theEventWriter.writeAttribute("value", encodedValue);
|
theEventWriter.writeAttribute("value", encodedValue);
|
||||||
}
|
}
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource, theSubResource);
|
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -243,7 +247,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
case PRIMITIVE_DATATYPE: {
|
case PRIMITIVE_DATATYPE: {
|
||||||
IPrimitiveType<?> pd = IPrimitiveType.class.cast(theElement);
|
IPrimitiveType<?> pd = IPrimitiveType.class.cast(theElement);
|
||||||
String value = pd.getValueAsString();
|
String value = pd.getValueAsString();
|
||||||
if (value != null || super.hasExtensions(pd)) {
|
if (value != null || !super.hasNoExtensions(pd)) {
|
||||||
theEventWriter.writeStartElement(childName);
|
theEventWriter.writeStartElement(childName);
|
||||||
String elementId = getCompositeElementId(theElement);
|
String elementId = getCompositeElementId(theElement);
|
||||||
if (isNotBlank(elementId)) {
|
if (isNotBlank(elementId)) {
|
||||||
|
@ -252,7 +256,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
theEventWriter.writeAttribute("value", value);
|
theEventWriter.writeAttribute("value", value);
|
||||||
}
|
}
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource,theSubResource);
|
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -267,7 +271,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
if (isNotBlank(theExtensionUrl)) {
|
if (isNotBlank(theExtensionUrl)) {
|
||||||
theEventWriter.writeAttribute("url", theExtensionUrl);
|
theEventWriter.writeAttribute("url", theExtensionUrl);
|
||||||
}
|
}
|
||||||
encodeCompositeElementToStreamWriter(theResource, theElement, theEventWriter, theIncludedResource, theSubResource, theParent);
|
encodeCompositeElementToStreamWriter(theResource, theElement, theEventWriter, theIncludedResource, theParent, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -281,7 +285,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
for (IBaseResource next : getContainedResources().getContainedResources()) {
|
for (IBaseResource next : getContainedResources().getContainedResources()) {
|
||||||
IIdType resourceId = getContainedResources().getResourceId(next);
|
IIdType resourceId = getContainedResources().getResourceId(next);
|
||||||
theEventWriter.writeStartElement("contained");
|
theEventWriter.writeStartElement("contained");
|
||||||
encodeResourceToXmlStreamWriter(next, theEventWriter, true, false, fixContainedResourceId(resourceId.getValue()));
|
encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(resourceId.getValue()), theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -289,7 +293,10 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
case RESOURCE: {
|
case RESOURCE: {
|
||||||
theEventWriter.writeStartElement(childName);
|
theEventWriter.writeStartElement(childName);
|
||||||
IBaseResource resource = (IBaseResource) theElement;
|
IBaseResource resource = (IBaseResource) theElement;
|
||||||
encodeResourceToXmlStreamWriter(resource, theEventWriter, false, true);
|
String resourceName = myContext.getResourceDefinition(resource).getName();
|
||||||
|
theEncodeContext.pushPath(resourceName, true);
|
||||||
|
encodeResourceToXmlStreamWriter(resource, theEventWriter, false, theEncodeContext);
|
||||||
|
theEncodeContext.popPath();
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -318,12 +325,16 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
|
|
||||||
writeCommentsPost(theEventWriter, theElement);
|
writeCommentsPost(theEventWriter, theElement);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
theEncodeContext.popPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, boolean theContainedResource, boolean theSubResource, CompositeChildElement theParent)
|
}
|
||||||
|
|
||||||
|
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement theParent, EncodeContext theEncodeContext)
|
||||||
throws XMLStreamException, DataFormatException {
|
throws XMLStreamException, DataFormatException {
|
||||||
|
|
||||||
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theSubResource, theParent)) {
|
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent, theEncodeContext)) {
|
||||||
|
|
||||||
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
||||||
|
|
||||||
|
@ -353,17 +364,17 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theContainedResource, theSubResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theContainedResource, nextChildElem, theEncodeContext);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextChild instanceof RuntimeChildContainedResources) {
|
if (nextChild instanceof RuntimeChildContainedResources) {
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource, theSubResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource, nextChildElem, theEncodeContext);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
||||||
values = super.preProcessValues(nextChild, theResource, values, nextChildElem);
|
values = super.preProcessValues(nextChild, theResource, values, nextChildElem, theEncodeContext);
|
||||||
|
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -383,7 +394,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
String extensionUrl = getExtensionUrl(nextChild.getExtensionUrl());
|
String extensionUrl = getExtensionUrl(nextChild.getExtensionUrl());
|
||||||
|
|
||||||
if (extensionUrl != null && childName.equals("extension") == false) {
|
if (extensionUrl != null && childName.equals("extension") == false) {
|
||||||
encodeExtension(theResource, theEventWriter, theContainedResource, theSubResource, nextChildElem, nextChild, nextValue, childName, extensionUrl, childDef);
|
encodeExtension(theResource, theEventWriter, theContainedResource, nextChildElem, nextChild, nextValue, childName, extensionUrl, childDef, theEncodeContext);
|
||||||
} else if (nextChild instanceof RuntimeChildExtension) {
|
} else if (nextChild instanceof RuntimeChildExtension) {
|
||||||
IBaseExtension<?, ?> extension = (IBaseExtension<?, ?>) nextValue;
|
IBaseExtension<?, ?> extension = (IBaseExtension<?, ?>) nextValue;
|
||||||
if ((extension.getValue() == null || extension.getValue().isEmpty())) {
|
if ((extension.getValue() == null || extension.getValue().isEmpty())) {
|
||||||
|
@ -391,18 +402,19 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, getExtensionUrl(extension.getUrl()), theContainedResource, theSubResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, getExtensionUrl(extension.getUrl()), theContainedResource, nextChildElem, theEncodeContext);
|
||||||
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
||||||
// suppress narratives from contained resources
|
// suppress narratives from contained resources
|
||||||
} else {
|
} else {
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theContainedResource, theSubResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theContainedResource, nextChildElem, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, boolean theSubResource, CompositeChildElement nextChildElem, BaseRuntimeChildDefinition nextChild, IBase nextValue, String childName, String extensionUrl, BaseRuntimeElementDefinition<?> childDef)
|
private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement nextChildElem, BaseRuntimeChildDefinition nextChild, IBase nextValue, String childName, String extensionUrl, BaseRuntimeElementDefinition<?> childDef, EncodeContext theEncodeContext)
|
||||||
throws XMLStreamException {
|
throws XMLStreamException {
|
||||||
BaseRuntimeDeclaredChildDefinition extDef = (BaseRuntimeDeclaredChildDefinition) nextChild;
|
BaseRuntimeDeclaredChildDefinition extDef = (BaseRuntimeDeclaredChildDefinition) nextChild;
|
||||||
if (extDef.isModifier()) {
|
if (extDef.isModifier()) {
|
||||||
|
@ -417,27 +429,27 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.writeAttribute("url", extensionUrl);
|
theEventWriter.writeAttribute("url", extensionUrl);
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theContainedResource, theSubResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theContainedResource, nextChildElem, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeExtensionsIfPresent(IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource, boolean theSubResource) throws XMLStreamException, DataFormatException {
|
private void encodeExtensionsIfPresent(IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource, EncodeContext theEncodeContext) throws XMLStreamException, DataFormatException {
|
||||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||||
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredExtensions()), "extension", theIncludedResource, theSubResource);
|
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredExtensions()), "extension", theIncludedResource, theEncodeContext);
|
||||||
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredModifierExtensions()), "modifierExtension", theIncludedResource,theSubResource);
|
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredModifierExtensions()), "modifierExtension", theIncludedResource, theEncodeContext);
|
||||||
}
|
}
|
||||||
if (theElement instanceof IBaseHasExtensions) {
|
if (theElement instanceof IBaseHasExtensions) {
|
||||||
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
|
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
|
||||||
encodeUndeclaredExtensions(theResource, theWriter, res.getExtension(), "extension", theIncludedResource,theSubResource);
|
encodeUndeclaredExtensions(theResource, theWriter, res.getExtension(), "extension", theIncludedResource, theEncodeContext);
|
||||||
}
|
}
|
||||||
if (theElement instanceof IBaseHasModifierExtensions) {
|
if (theElement instanceof IBaseHasModifierExtensions) {
|
||||||
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
|
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
|
||||||
encodeUndeclaredExtensions(theResource, theWriter, res.getModifierExtension(), "modifierExtension", theIncludedResource,theSubResource);
|
encodeUndeclaredExtensions(theResource, theWriter, res.getModifierExtension(), "modifierExtension", theIncludedResource, theEncodeContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource) throws XMLStreamException, DataFormatException {
|
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, EncodeContext theEncodeContext) throws XMLStreamException, DataFormatException {
|
||||||
IIdType resourceId = null;
|
IIdType resourceId = null;
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
|
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
|
||||||
|
@ -448,17 +460,17 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!theIncludedResource) {
|
if (!theIncludedResource) {
|
||||||
if (super.shouldEncodeResourceId(theResource, theSubResource) == false) {
|
if (super.shouldEncodeResourceId(theResource, theEncodeContext) == false) {
|
||||||
resourceId = null;
|
resourceId = null;
|
||||||
} else if (theSubResource == false && getEncodeForceResourceId() != null) {
|
} else if (theEncodeContext.getResourcePath().size() == 1 && getEncodeForceResourceId() != null) {
|
||||||
resourceId = getEncodeForceResourceId();
|
resourceId = getEncodeForceResourceId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, theSubResource, resourceId);
|
encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, boolean theSubResource, IIdType theResourceId) throws XMLStreamException {
|
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, IIdType theResourceId, EncodeContext theEncodeContext) throws XMLStreamException {
|
||||||
if (!theContainedResource) {
|
if (!theContainedResource) {
|
||||||
super.containResourcesForEncoding(theResource);
|
super.containResourcesForEncoding(theResource);
|
||||||
}
|
}
|
||||||
|
@ -477,12 +489,12 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
writeCommentsPre(theEventWriter, theResourceId);
|
writeCommentsPre(theEventWriter, theResourceId);
|
||||||
theEventWriter.writeStartElement("id");
|
theEventWriter.writeStartElement("id");
|
||||||
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false, false);
|
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
writeCommentsPost(theEventWriter, theResourceId);
|
writeCommentsPost(theEventWriter, theResourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, theSubResource, new CompositeChildElement(resDef, theSubResource));
|
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef, theEncodeContext), theEncodeContext);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -495,7 +507,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
writeCommentsPost(theEventWriter, theResourceId);*/
|
writeCommentsPost(theEventWriter, theResourceId);*/
|
||||||
theEventWriter.writeStartElement("id");
|
theEventWriter.writeStartElement("id");
|
||||||
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false,false);
|
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
writeCommentsPost(theEventWriter, theResourceId);
|
writeCommentsPost(theEventWriter, theResourceId);
|
||||||
}
|
}
|
||||||
|
@ -510,7 +522,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
||||||
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
||||||
|
|
||||||
TagList tags = getMetaTagsForEncoding((resource));
|
TagList tags = getMetaTagsForEncoding((resource), theEncodeContext);
|
||||||
|
|
||||||
if (super.shouldEncodeResourceMeta(resource) && ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) {
|
if (super.shouldEncodeResourceMeta(resource) && ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) {
|
||||||
theEventWriter.writeStartElement("meta");
|
theEventWriter.writeStartElement("meta");
|
||||||
|
@ -526,7 +538,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
}
|
}
|
||||||
for (BaseCodingDt securityLabel : securityLabels) {
|
for (BaseCodingDt securityLabel : securityLabels) {
|
||||||
theEventWriter.writeStartElement("security");
|
theEventWriter.writeStartElement("security");
|
||||||
encodeCompositeElementToStreamWriter(resource, securityLabel, theEventWriter, theContainedResource, theSubResource, null);
|
encodeCompositeElementToStreamWriter(resource, securityLabel, theEventWriter, theContainedResource, null, theEncodeContext);
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
if (tags != null) {
|
if (tags != null) {
|
||||||
|
@ -549,7 +561,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
||||||
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
||||||
} else {
|
} else {
|
||||||
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, theSubResource, new CompositeChildElement(resDef, theSubResource));
|
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef, theEncodeContext), theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -557,7 +569,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theEventWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource, boolean theSubResource)
|
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theEventWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource, EncodeContext theEncodeContext)
|
||||||
throws XMLStreamException, DataFormatException {
|
throws XMLStreamException, DataFormatException {
|
||||||
for (IBaseExtension<?, ?> next : theExtensions) {
|
for (IBaseExtension<?, ?> next : theExtensions) {
|
||||||
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
|
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
|
||||||
|
@ -593,11 +605,11 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
||||||
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(theResource, theEventWriter, value, childName, childDef, null, theIncludedResource, theSubResource, null);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, value, childName, childDef, null, theIncludedResource, null, theEncodeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// child extensions
|
// child extensions
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, next, theIncludedResource,theSubResource);
|
encodeExtensionsIfPresent(theResource, theEventWriter, next, theIncludedResource, theEncodeContext);
|
||||||
|
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,7 @@ public class Constants {
|
||||||
public static final String PARAM_COUNT = "_count";
|
public static final String PARAM_COUNT = "_count";
|
||||||
public static final String PARAM_DELETE = "_delete";
|
public static final String PARAM_DELETE = "_delete";
|
||||||
public static final String PARAM_ELEMENTS = "_elements";
|
public static final String PARAM_ELEMENTS = "_elements";
|
||||||
|
public static final String PARAM_ELEMENTS_EXCLUDE_MODIFIER = ":exclude";
|
||||||
public static final String PARAM_FORMAT = "_format";
|
public static final String PARAM_FORMAT = "_format";
|
||||||
public static final String PARAM_HAS = "_has";
|
public static final String PARAM_HAS = "_has";
|
||||||
public static final String PARAM_HISTORY = "_history";
|
public static final String PARAM_HISTORY = "_history";
|
||||||
|
|
|
@ -106,6 +106,9 @@ public enum EncodingEnum {
|
||||||
myFormatContentType = theFormatContentType;
|
myFormatContentType = theFormatContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>xml</code> or <code>json</code> as used on the <code>_format</code> search parameter
|
||||||
|
*/
|
||||||
public String getFormatContentType() {
|
public String getFormatContentType() {
|
||||||
return myFormatContentType;
|
return myFormatContentType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.util;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -55,6 +56,24 @@ public class PortUtil {
|
||||||
server = new ServerSocket(0);
|
server = new ServerSocket(0);
|
||||||
server.setReuseAddress(true);
|
server.setReuseAddress(true);
|
||||||
int port = server.getLocalPort();
|
int port = server.getLocalPort();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to connect to the newly allocated port to make sure
|
||||||
|
* it's free
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
try {
|
||||||
|
Socket client = new Socket();
|
||||||
|
client.connect(new InetSocketAddress(port), 1000);
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (i == 9) {
|
||||||
|
throw new InternalErrorException("Can not connect to port: " + port);
|
||||||
|
}
|
||||||
|
Thread.sleep(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
server.close();
|
server.close();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ca.uhn.fhir.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PortUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindFreePort() throws IOException {
|
||||||
|
int port = PortUtil.findFreePort();
|
||||||
|
|
||||||
|
// First bind should succeed, second bind should fail
|
||||||
|
try (ServerSocket ss = new ServerSocket()) {
|
||||||
|
ss.bind(new InetSocketAddress("0.0.0.0", port));
|
||||||
|
|
||||||
|
try (ServerSocket ss2 = new ServerSocket()) {
|
||||||
|
ss2.bind(new InetSocketAddress("0.0.0.0", port));
|
||||||
|
fail();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -84,7 +84,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the server base, including the resource path.
|
* This method returns the server base, including the resource path.
|
||||||
* {@link javax.ws.rs.core.UriInfo#getBaseUri() UriInfo#getBaseUri()}
|
* {@link UriInfo#getBaseUri() UriInfo#getBaseUri()}
|
||||||
*
|
*
|
||||||
* @return the ascii string for the base resource provider path
|
* @return the ascii string for the base resource provider path
|
||||||
*/
|
*/
|
||||||
|
@ -119,6 +119,14 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
||||||
return ETagSupportEnum.DISABLED;
|
return ETagSupportEnum.DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEFAULT = {@link ElementsSupportEnum#STANDARD}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ElementsSupportEnum getElementsSupport() {
|
||||||
|
return ElementsSupportEnum.STANDARD;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FhirContext getFhirContext() {
|
public FhirContext getFhirContext() {
|
||||||
return CTX;
|
return CTX;
|
||||||
|
@ -243,14 +251,6 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DEFAULT = false
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isUseBrowserFriendlyContentTypes() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the headers
|
* Set the headers
|
||||||
*
|
*
|
||||||
|
|
|
@ -150,11 +150,6 @@ public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Pati
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUseBrowserFriendlyContentTypes() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}/$firstVersion")
|
@Path("/{id}/$firstVersion")
|
||||||
public Response operationFirstVersionUsingGet(@PathParam("id") String id) throws IOException {
|
public Response operationFirstVersionUsingGet(@PathParam("id") String id) throws IOException {
|
||||||
|
|
|
@ -151,11 +151,6 @@ public class JaxRsPatientRestProviderDstu3 extends AbstractJaxRsResourceProvider
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUseBrowserFriendlyContentTypes() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}/$firstVersion")
|
@Path("/{id}/$firstVersion")
|
||||||
public Response operationFirstVersionUsingGet(@PathParam("id") String id) throws IOException {
|
public Response operationFirstVersionUsingGet(@PathParam("id") String id) throws IOException {
|
||||||
|
|
|
@ -102,10 +102,10 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc {
|
||||||
|
|
||||||
// Only delete if we don't have results left in this search
|
// Only delete if we don't have results left in this search
|
||||||
if (resultPids.getNumberOfElements() < max) {
|
if (resultPids.getNumberOfElements() < max) {
|
||||||
ourLog.info("Deleting search {}/{} - Created[{}] -- Last returned[{}]", searchToDelete.getId(), searchToDelete.getUuid(), new InstantType(searchToDelete.getCreated()), new InstantType(searchToDelete.getSearchLastReturned()));
|
ourLog.debug("Deleting search {}/{} - Created[{}] -- Last returned[{}]", searchToDelete.getId(), searchToDelete.getUuid(), new InstantType(searchToDelete.getCreated()), new InstantType(searchToDelete.getSearchLastReturned()));
|
||||||
mySearchDao.deleteByPid(searchToDelete.getId());
|
mySearchDao.deleteByPid(searchToDelete.getId());
|
||||||
} else {
|
} else {
|
||||||
ourLog.info("Purged {} search results for deleted search {}/{}", resultPids.getSize(), searchToDelete.getId(), searchToDelete.getUuid());
|
ourLog.debug("Purged {} search results for deleted search {}/{}", resultPids.getSize(), searchToDelete.getId(), searchToDelete.getUuid());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc {
|
||||||
int count = toDelete.getContent().size();
|
int count = toDelete.getContent().size();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
long total = tt.execute(t -> mySearchDao.count());
|
long total = tt.execute(t -> mySearchDao.count());
|
||||||
ourLog.info("Deleted {} searches, {} remaining", count, total);
|
ourLog.debug("Deleted {} searches, {} remaining", count, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
||||||
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
||||||
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ public class EmptyIndexesR4Test extends BaseJpaR4Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
||||||
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +249,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Test
|
@Test
|
||||||
public void testResponseUsesCorrectContentType() throws Exception {
|
public void testResponseUsesCorrectContentType() throws Exception {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||||
|
|
||||||
HttpGet get = new HttpGet(ourServerBase);
|
HttpGet get = new HttpGet(ourServerBase);
|
||||||
|
|
|
@ -51,7 +51,6 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
|
||||||
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
|
||||||
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
myDaoConfig.setMaximumSearchResultCountInTransaction(new DaoConfig().getMaximumSearchResultCountInTransaction());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,7 @@ import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4;
|
||||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
import ca.uhn.fhir.rest.server.*;
|
||||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
|
@ -204,6 +201,11 @@ public class TestRestfulServer extends RestfulServer {
|
||||||
setDefaultPrettyPrint(true);
|
setDefaultPrettyPrint(true);
|
||||||
setDefaultResponseEncoding(EncodingEnum.JSON);
|
setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use extended support for the _elements parameter
|
||||||
|
*/
|
||||||
|
setElementsSupport(ElementsSupportEnum.EXTENDED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The server's base URL (e.g. http://fhirtest.uhn.ca/baseDstu2) is
|
* The server's base URL (e.g. http://fhirtest.uhn.ca/baseDstu2) is
|
||||||
* pulled from a system property, which is helpful if you want to try
|
* pulled from a system property, which is helpful if you want to try
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="http://hapifhir.io/doc_rest_server.html#extended_elements_support">Extended Elements Support</a>
|
||||||
|
*/
|
||||||
|
public enum ElementsSupportEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server will support only the FHIR standard features for the <code>_elements</code>
|
||||||
|
* parameter.
|
||||||
|
*
|
||||||
|
* @see <a href="http://hl7.org/fhir/search.html#elements">http://hl7.org/fhir/search.html#elements</a>
|
||||||
|
*/
|
||||||
|
STANDARD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server will support both the standard features as well as support for elements
|
||||||
|
* exclusion.
|
||||||
|
*/
|
||||||
|
EXTENDED
|
||||||
|
|
||||||
|
}
|
|
@ -49,6 +49,13 @@ public interface IRestfulServerDefaults {
|
||||||
*/
|
*/
|
||||||
ETagSupportEnum getETagSupport();
|
ETagSupportEnum getETagSupport();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the support option for the <code>_elements</code> parameter on search
|
||||||
|
* and read operations.
|
||||||
|
* @see <a href="http://hapifhir.io/doc_rest_server.html#extended_elements_support">Extended Elements Support</a>
|
||||||
|
*/
|
||||||
|
ElementsSupportEnum getElementsSupport();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain
|
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain
|
||||||
* providers should generally use this context if one is needed, as opposed to
|
* providers should generally use this context if one is needed, as opposed to
|
||||||
|
@ -78,12 +85,6 @@ public interface IRestfulServerDefaults {
|
||||||
*/
|
*/
|
||||||
boolean isDefaultPrettyPrint();
|
boolean isDefaultPrettyPrint();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If <code>true</code> the server will use browser friendly content-types (instead of standard FHIR ones)
|
|
||||||
* when it detects that the request is coming from a browser
|
|
||||||
* instead of a FHIR
|
|
||||||
*/
|
|
||||||
boolean isUseBrowserFriendlyContentTypes();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.*;
|
import ca.uhn.fhir.rest.server.exceptions.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.ConformanceMethodBinding;
|
import ca.uhn.fhir.rest.server.method.ConformanceMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
@ -126,10 +125,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
private String myServerVersion = createPoweredByHeaderProductVersion();
|
private String myServerVersion = createPoweredByHeaderProductVersion();
|
||||||
private boolean myStarted;
|
private boolean myStarted;
|
||||||
private boolean myUncompressIncomingContents = true;
|
private boolean myUncompressIncomingContents = true;
|
||||||
private boolean myUseBrowserFriendlyContentTypes;
|
|
||||||
private ITenantIdentificationStrategy myTenantIdentificationStrategy;
|
private ITenantIdentificationStrategy myTenantIdentificationStrategy;
|
||||||
private Date myConformanceDate;
|
private Date myConformanceDate;
|
||||||
private PreferReturnEnum myDefaultPreferReturn = DEFAULT_PREFER_RETURN;
|
private PreferReturnEnum myDefaultPreferReturn = DEFAULT_PREFER_RETURN;
|
||||||
|
private ElementsSupportEnum myElementsSupport = ElementsSupportEnum.EXTENDED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Note that if no {@link FhirContext} is passed in to the server (either through the constructor, or
|
* Constructor. Note that if no {@link FhirContext} is passed in to the server (either through the constructor, or
|
||||||
|
@ -500,6 +499,21 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
return myETagSupport;
|
return myETagSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementsSupportEnum getElementsSupport() {
|
||||||
|
return myElementsSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the elements support mode.
|
||||||
|
*
|
||||||
|
* @see <a href="http://hapifhir.io/doc_rest_server.html#extended_elements_support">Extended Elements Support</a>
|
||||||
|
*/
|
||||||
|
public void setElementsSupport(ElementsSupportEnum theElementsSupport) {
|
||||||
|
Validate.notNull(theElementsSupport, "theElementsSupport must not be null");
|
||||||
|
myElementsSupport = theElementsSupport;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (enables/disables) the server support for ETags. Must not be <code>null</code>. Default is
|
* Sets (enables/disables) the server support for ETags. Must not be <code>null</code>. Default is
|
||||||
* {@link #DEFAULT_ETAG_SUPPORT}
|
* {@link #DEFAULT_ETAG_SUPPORT}
|
||||||
|
@ -1025,6 +1039,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
*/
|
*/
|
||||||
requestDetails.removeParameter(Constants.PARAM_SUMMARY);
|
requestDetails.removeParameter(Constants.PARAM_SUMMARY);
|
||||||
requestDetails.removeParameter(Constants.PARAM_ELEMENTS);
|
requestDetails.removeParameter(Constants.PARAM_ELEMENTS);
|
||||||
|
requestDetails.removeParameter(Constants.PARAM_ELEMENTS + Constants.PARAM_ELEMENTS_EXCLUDE_MODIFIER);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If nobody handles it, default behaviour is to stream back the OperationOutcome to the client.
|
* If nobody handles it, default behaviour is to stream back the OperationOutcome to the client.
|
||||||
|
@ -1251,26 +1266,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
myUncompressIncomingContents = theUncompressIncomingContents;
|
myUncompressIncomingContents = theUncompressIncomingContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated This feature did not work well, and will be removed. Use {@link ResponseHighlighterInterceptor}
|
|
||||||
* instead as an interceptor on your server and it will provide more useful syntax
|
|
||||||
* highlighting. Deprocated in 1.4
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public boolean isUseBrowserFriendlyContentTypes() {
|
|
||||||
return myUseBrowserFriendlyContentTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated This feature did not work well, and will be removed. Use {@link ResponseHighlighterInterceptor}
|
|
||||||
* instead as an interceptor on your server and it will provide more useful syntax
|
|
||||||
* highlighting. Deprocated in 1.4
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
|
|
||||||
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void populateRequestDetailsFromRequestPath(RequestDetails theRequestDetails, String theRequestPath) {
|
public void populateRequestDetailsFromRequestPath(RequestDetails theRequestDetails, String theRequestPath) {
|
||||||
UrlPathTokenizer tok = new UrlPathTokenizer(theRequestPath);
|
UrlPathTokenizer tok = new UrlPathTokenizer(theRequestPath);
|
||||||
|
|
|
@ -46,6 +46,7 @@ import java.io.Writer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
import static org.apache.commons.lang3.StringUtils.*;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public class RestfulServerUtils {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
|
||||||
|
|
||||||
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<String>(Arrays.asList("Bundle", "*.text", "*.(mandatory)"));
|
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<>(Arrays.asList("*.text", "*.id", "*.meta", "*.(mandatory)"));
|
||||||
private static Map<FhirVersionEnum, FhirContext> myFhirContextMap = Collections.synchronizedMap(new HashMap<FhirVersionEnum, FhirContext>());
|
private static Map<FhirVersionEnum, FhirContext> myFhirContextMap = Collections.synchronizedMap(new HashMap<FhirVersionEnum, FhirContext>());
|
||||||
|
|
||||||
private enum NarrativeModeEnum {
|
private enum NarrativeModeEnum {
|
||||||
|
@ -125,13 +126,15 @@ public class RestfulServerUtils {
|
||||||
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequestDetails);
|
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequestDetails);
|
||||||
|
|
||||||
// _elements
|
// _elements
|
||||||
Set<String> elements = ElementsParameter.getElementsValueOrNull(theRequestDetails);
|
Set<String> elements = ElementsParameter.getElementsValueOrNull(theRequestDetails, false);
|
||||||
if (elements != null && summaryMode != null && !summaryMode.equals(Collections.singleton(SummaryEnum.FALSE))) {
|
if (elements != null && summaryMode != null && !summaryMode.equals(Collections.singleton(SummaryEnum.FALSE))) {
|
||||||
throw new InvalidRequestException("Cannot combine the " + Constants.PARAM_SUMMARY + " and " + Constants.PARAM_ELEMENTS + " parameters");
|
throw new InvalidRequestException("Cannot combine the " + Constants.PARAM_SUMMARY + " and " + Constants.PARAM_ELEMENTS + " parameters");
|
||||||
}
|
}
|
||||||
Set<String> elementsAppliesTo = null;
|
|
||||||
if (elements != null && isNotBlank(theRequestDetails.getResourceName())) {
|
// _elements:exclude
|
||||||
elementsAppliesTo = Collections.singleton(theRequestDetails.getResourceName());
|
Set<String> elementsExclude = ElementsParameter.getElementsValueOrNull(theRequestDetails, true);
|
||||||
|
if (elementsExclude != null) {
|
||||||
|
parser.setDontEncodeElements(elementsExclude);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (summaryMode != null) {
|
if (summaryMode != null) {
|
||||||
|
@ -139,15 +142,27 @@ public class RestfulServerUtils {
|
||||||
parser.setEncodeElements(Collections.singleton("Bundle.total"));
|
parser.setEncodeElements(Collections.singleton("Bundle.total"));
|
||||||
} else if (summaryMode.contains(SummaryEnum.TEXT) && summaryMode.size() == 1) {
|
} else if (summaryMode.contains(SummaryEnum.TEXT) && summaryMode.size() == 1) {
|
||||||
parser.setEncodeElements(TEXT_ENCODE_ELEMENTS);
|
parser.setEncodeElements(TEXT_ENCODE_ELEMENTS);
|
||||||
|
parser.setEncodeElementsAppliesToChildResourcesOnly(true);
|
||||||
} else {
|
} else {
|
||||||
parser.setSuppressNarratives(summaryMode.contains(SummaryEnum.DATA));
|
parser.setSuppressNarratives(summaryMode.contains(SummaryEnum.DATA));
|
||||||
parser.setSummaryMode(summaryMode.contains(SummaryEnum.TRUE));
|
parser.setSummaryMode(summaryMode.contains(SummaryEnum.TRUE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (elements != null && elements.size() > 0) {
|
if (elements != null && elements.size() > 0) {
|
||||||
|
String elementsAppliesTo = "*";
|
||||||
|
if (isNotBlank(theRequestDetails.getResourceName())) {
|
||||||
|
elementsAppliesTo = theRequestDetails.getResourceName();
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> newElements = new HashSet<>();
|
Set<String> newElements = new HashSet<>();
|
||||||
for (String next : elements) {
|
for (String next : elements) {
|
||||||
newElements.add("*." + next);
|
if (isNotBlank(next)) {
|
||||||
|
if (Character.isUpperCase(next.charAt(0))) {
|
||||||
|
newElements.add(next);
|
||||||
|
} else {
|
||||||
|
newElements.add(elementsAppliesTo + "." + next);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -158,13 +173,6 @@ public class RestfulServerUtils {
|
||||||
* the client has explicitly scoped the Bundle
|
* the client has explicitly scoped the Bundle
|
||||||
* (i.e. with Bundle.total or something like that)
|
* (i.e. with Bundle.total or something like that)
|
||||||
*/
|
*/
|
||||||
switch (theRequestDetails.getRestOperationType()) {
|
|
||||||
case SEARCH_SYSTEM:
|
|
||||||
case SEARCH_TYPE:
|
|
||||||
case HISTORY_SYSTEM:
|
|
||||||
case HISTORY_TYPE:
|
|
||||||
case HISTORY_INSTANCE:
|
|
||||||
case GET_PAGE:
|
|
||||||
boolean haveExplicitBundleElement = false;
|
boolean haveExplicitBundleElement = false;
|
||||||
for (String next : newElements) {
|
for (String next : newElements) {
|
||||||
if (next.startsWith("Bundle.")) {
|
if (next.startsWith("Bundle.")) {
|
||||||
|
@ -172,6 +180,13 @@ public class RestfulServerUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch (theRequestDetails.getRestOperationType()) {
|
||||||
|
case SEARCH_SYSTEM:
|
||||||
|
case SEARCH_TYPE:
|
||||||
|
case HISTORY_SYSTEM:
|
||||||
|
case HISTORY_TYPE:
|
||||||
|
case HISTORY_INSTANCE:
|
||||||
|
case GET_PAGE:
|
||||||
if (!haveExplicitBundleElement) {
|
if (!haveExplicitBundleElement) {
|
||||||
parser.setEncodeElementsAppliesToChildResourcesOnly(true);
|
parser.setEncodeElementsAppliesToChildResourcesOnly(true);
|
||||||
}
|
}
|
||||||
|
@ -181,26 +196,28 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.setEncodeElements(newElements);
|
parser.setEncodeElements(newElements);
|
||||||
parser.setEncodeElementsAppliesToResourceTypes(elementsAppliesTo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
public static String createPagingLink(Set<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, int theOffset, int theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
||||||
BundleTypeEnum theBundleType) {
|
BundleTypeEnum theBundleType) {
|
||||||
return createPagingLink(theIncludes, theServerBase, theSearchId, theOffset, theCount, theRequestParameters, thePrettyPrint,
|
return createPagingLink(theIncludes, theRequestDetails, theSearchId, theOffset, theCount, theRequestParameters, thePrettyPrint,
|
||||||
theBundleType, null);
|
theBundleType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, String thePageId, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
public static String createPagingLink(Set<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, String thePageId, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
||||||
BundleTypeEnum theBundleType) {
|
BundleTypeEnum theBundleType) {
|
||||||
return createPagingLink(theIncludes, theServerBase, theSearchId, null, null, theRequestParameters, thePrettyPrint,
|
return createPagingLink(theIncludes, theRequestDetails, theSearchId, null, null, theRequestParameters, thePrettyPrint,
|
||||||
theBundleType, thePageId);
|
theBundleType, thePageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, Integer theOffset, Integer theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
private static String createPagingLink(Set<Include> theIncludes, RequestDetails theRequestDetails, String theSearchId, Integer theOffset, Integer theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
||||||
BundleTypeEnum theBundleType, String thePageId) {
|
BundleTypeEnum theBundleType, String thePageId) {
|
||||||
|
|
||||||
|
String serverBase = theRequestDetails.getFhirServerBase();
|
||||||
|
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
b.append(theServerBase);
|
b.append(serverBase);
|
||||||
b.append('?');
|
b.append('?');
|
||||||
b.append(Constants.PARAM_PAGINGACTION);
|
b.append(Constants.PARAM_PAGINGACTION);
|
||||||
b.append('=');
|
b.append('=');
|
||||||
|
@ -258,16 +275,33 @@ public class RestfulServerUtils {
|
||||||
b.append(theBundleType.getCode());
|
b.append(theBundleType.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
String paramName = Constants.PARAM_ELEMENTS;
|
// _elements
|
||||||
String[] params = theRequestParameters.get(paramName);
|
Set<String> elements = ElementsParameter.getElementsValueOrNull(theRequestDetails, false);
|
||||||
if (params != null) {
|
if (elements != null) {
|
||||||
for (String nextValue : params) {
|
|
||||||
if (isNotBlank(nextValue)) {
|
|
||||||
b.append('&');
|
b.append('&');
|
||||||
b.append(paramName);
|
b.append(Constants.PARAM_ELEMENTS);
|
||||||
b.append('=');
|
b.append('=');
|
||||||
b.append(UrlUtil.escapeUrlParam(nextValue));
|
String nextValue = elements
|
||||||
|
.stream()
|
||||||
|
.sorted()
|
||||||
|
.map(UrlUtil::escapeUrlParam)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
b.append(nextValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _elements:exclude
|
||||||
|
if (theRequestDetails.getServer().getElementsSupport() == ElementsSupportEnum.EXTENDED) {
|
||||||
|
Set<String> elementsExclude = ElementsParameter.getElementsValueOrNull(theRequestDetails, true);
|
||||||
|
if (elementsExclude != null) {
|
||||||
|
b.append('&');
|
||||||
|
b.append(Constants.PARAM_ELEMENTS + Constants.PARAM_ELEMENTS_EXCLUDE_MODIFIER);
|
||||||
|
b.append('=');
|
||||||
|
String nextValue = elementsExclude
|
||||||
|
.stream()
|
||||||
|
.sorted()
|
||||||
|
.map(UrlUtil::escapeUrlParam)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
b.append(nextValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,19 +192,19 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
||||||
// We're doing named pages
|
// We're doing named pages
|
||||||
searchId = theResult.getUuid();
|
searchId = theResult.getUuid();
|
||||||
if (isNotBlank(theResult.getNextPageId())) {
|
if (isNotBlank(theResult.getNextPageId())) {
|
||||||
linkNext = RestfulServerUtils.createPagingLink(theIncludes, serverBase, searchId, theResult.getNextPageId(), theRequest.getParameters(), prettyPrint, theBundleType);
|
linkNext = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getNextPageId(), theRequest.getParameters(), prettyPrint, theBundleType);
|
||||||
}
|
}
|
||||||
if (isNotBlank(theResult.getPreviousPageId())) {
|
if (isNotBlank(theResult.getPreviousPageId())) {
|
||||||
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, serverBase, searchId, theResult.getPreviousPageId(), theRequest.getParameters(), prettyPrint, theBundleType);
|
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getPreviousPageId(), theRequest.getParameters(), prettyPrint, theBundleType);
|
||||||
}
|
}
|
||||||
} else if (searchId != null) {
|
} else if (searchId != null) {
|
||||||
// We're doing offset pages
|
// We're doing offset pages
|
||||||
if (numTotalResults == null || theOffset + numToReturn < numTotalResults) {
|
if (numTotalResults == null || theOffset + numToReturn < numTotalResults) {
|
||||||
linkNext = (RestfulServerUtils.createPagingLink(theIncludes, serverBase, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType));
|
linkNext = (RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType));
|
||||||
}
|
}
|
||||||
if (theOffset > 0) {
|
if (theOffset > 0) {
|
||||||
int start = Math.max(0, theOffset - theLimit);
|
int start = Math.max(0, theOffset - theLimit);
|
||||||
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, serverBase, searchId, start, theLimit, theRequest.getParameters(), prettyPrint, theBundleType);
|
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, start, theLimit, theRequest.getParameters(), prettyPrint, theBundleType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,20 +19,24 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.binder.CollectionBinder;
|
import ca.uhn.fhir.rest.param.binder.CollectionBinder;
|
||||||
|
import ca.uhn.fhir.rest.server.ElementsSupportEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
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 org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class ElementsParameter implements IParameter {
|
public class ElementsParameter implements IParameter {
|
||||||
|
|
||||||
|
@ -42,7 +46,7 @@ public class ElementsParameter implements IParameter {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
Set<String> value = getElementsValueOrNull(theRequest);
|
Set<String> value = getElementsValueOrNull(theRequest, false);
|
||||||
if (value == null || value.isEmpty()) {
|
if (value == null || value.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -62,32 +66,6 @@ public class ElementsParameter implements IParameter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> getElementsValueOrNull(RequestDetails theRequest) {
|
|
||||||
String[] summary = theRequest.getParameters().get(Constants.PARAM_ELEMENTS);
|
|
||||||
|
|
||||||
if (summary != null && summary.length > 0) {
|
|
||||||
Set<String> retVal = new HashSet<String>();
|
|
||||||
for (String next : summary) {
|
|
||||||
StringTokenizer tok = new StringTokenizer(next, ",");
|
|
||||||
while (tok.hasMoreTokens()) {
|
|
||||||
String token = tok.nextToken();
|
|
||||||
if (isNotBlank(token)) {
|
|
||||||
retVal.add(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (retVal.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always include the meta element even for subsetted values
|
|
||||||
retVal.add("meta");
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||||
if (theOuterCollectionType != null) {
|
if (theOuterCollectionType != null) {
|
||||||
|
@ -99,4 +77,44 @@ public class ElementsParameter implements IParameter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<String> getElementsValueOrNull(RequestDetails theRequest, boolean theExclude) {
|
||||||
|
boolean standardMode = theRequest.getServer().getElementsSupport() != ElementsSupportEnum.EXTENDED;
|
||||||
|
if (theExclude && standardMode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String paramName = Constants.PARAM_ELEMENTS;
|
||||||
|
if (theExclude) {
|
||||||
|
paramName = Constants.PARAM_ELEMENTS + Constants.PARAM_ELEMENTS_EXCLUDE_MODIFIER;
|
||||||
|
}
|
||||||
|
String[] summary = theRequest.getParameters().get(paramName);
|
||||||
|
|
||||||
|
if (summary != null && summary.length > 0) {
|
||||||
|
Set<String> retVal = new HashSet<String>();
|
||||||
|
for (String next : summary) {
|
||||||
|
StringTokenizer tok = new StringTokenizer(next, ",");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String token = tok.nextToken();
|
||||||
|
if (isNotBlank(token)) {
|
||||||
|
if (token.contains(".") && standardMode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
retVal.add(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retVal.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always include the meta element even for subsetted values
|
||||||
|
if (!theExclude) {
|
||||||
|
retVal.add("meta");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1011,6 +1011,7 @@ public class JsonParserDstu2_1Test {
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
assertThat(out, not(containsString("meta")));
|
||||||
|
assertThat(out, not(containsString("SUBSETTED")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1630,7 +1630,7 @@ public class XmlParserDstu2_1Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
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<>(Arrays.asList("Patient.name")));
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(patient);
|
String out = p.encodeResourceToString(patient);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1639,6 +1639,7 @@ public class XmlParserDstu2_1Test {
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
assertThat(out, not(containsString("meta")));
|
||||||
|
assertThat(out, not(containsString("SUBSETTED")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1667,7 +1668,6 @@ public class XmlParserDstu2_1Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1679,7 +1679,6 @@ public class XmlParserDstu2_1Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -2701,12 +2700,6 @@ public class XmlParserDstu2_1Test {
|
||||||
assertTrue(d.toString(), !d.hasDifferences());
|
assertTrue(d.toString(), !d.hasDifferences());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
IGenericClient c = ourCtx.newRestfulGenericClient("http://fhir-dev.healthintersections.com.au/open");
|
|
||||||
// c.registerInterceptor(new LoggingInterceptor(true));
|
|
||||||
c.read().resource("Patient").withId("324").execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResourceDef(name = "Patient")
|
@ResourceDef(name = "Patient")
|
||||||
public static class TestPatientFor327 extends Patient {
|
public static class TestPatientFor327 extends Patient {
|
||||||
|
|
||||||
|
|
|
@ -1769,7 +1769,7 @@ public class XmlParserDstu2Test {
|
||||||
|
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name", "Bundle.entry")));
|
p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name", "Bundle.entry")));
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1780,8 +1780,7 @@ public class XmlParserDstu2Test {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1792,8 +1791,7 @@ public class XmlParserDstu2Test {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
p.setEncodeElements(new HashSet<>(Arrays.asList("Patient")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1818,7 +1816,7 @@ public class XmlParserDstu2Test {
|
||||||
|
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Bundle.entry", "*.text", "*.(mandatory)")));
|
p.setEncodeElements(new HashSet<>(Arrays.asList("Bundle.entry", "*.text", "*.(mandatory)")));
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
|
||||||
import static org.hamcrest.Matchers.not;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class ElementsParamTest {
|
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
|
||||||
private static Set<String> ourLastElements;
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElementsParamTest.class);
|
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void before() {
|
|
||||||
ourLastElements = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadSummaryData() throws Exception {
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_elements=name,maritalStatus");
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertEquals(Constants.CT_FHIR_XML + Constants.CHARSET_UTF8_CTSUFFIX.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
|
||||||
assertThat(responseContent, not(containsString("<Bundle")));
|
|
||||||
assertThat(responseContent, (containsString("<Patien")));
|
|
||||||
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
|
||||||
assertThat(responseContent, (containsString("family")));
|
|
||||||
assertThat(responseContent, (containsString("maritalStatus")));
|
|
||||||
assertThat(ourLastElements, containsInAnyOrder("meta", "name", "maritalStatus"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadSummaryTrue() throws Exception {
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_elements=name");
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertEquals(Constants.CT_FHIR_XML + Constants.CHARSET_UTF8_CTSUFFIX.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
|
||||||
assertThat(responseContent, not(containsString("<Bundle")));
|
|
||||||
assertThat(responseContent, (containsString("<Patien")));
|
|
||||||
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
|
||||||
assertThat(responseContent, (containsString("family")));
|
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
|
||||||
assertThat(ourLastElements, containsInAnyOrder("meta", "name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchSummaryData() throws Exception {
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_elements=name,maritalStatus");
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, containsString("<Patient"));
|
|
||||||
assertThat(responseContent, not(containsString("THE DIV")));
|
|
||||||
assertThat(responseContent, containsString("family"));
|
|
||||||
assertThat(responseContent, containsString("maritalStatus"));
|
|
||||||
assertThat(ourLastElements, containsInAnyOrder("meta", "name", "maritalStatus"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchSummaryText() throws Exception {
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_elements=text");
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
|
||||||
assertThat(responseContent, (containsString("entry")));
|
|
||||||
assertThat(responseContent, (containsString("THE DIV")));
|
|
||||||
assertThat(responseContent, not(containsString("family")));
|
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
|
||||||
assertThat(ourLastElements, containsInAnyOrder("meta", "text"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
ourServer.stop();
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourPort = PortUtil.findFreePort();
|
|
||||||
ourServer = new Server(ourPort);
|
|
||||||
|
|
||||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
|
||||||
|
|
||||||
servlet.setResourceProviders(patientProvider);
|
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
ourServer.start();
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends IResource> getResourceType() {
|
|
||||||
return Patient.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Read
|
|
||||||
public Patient read(@IdParam IdDt theId, @Elements Set<String> theElements) {
|
|
||||||
ourLastElements = theElements;
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.setId("Patient/1/_history/1");
|
|
||||||
patient.getText().setDiv("<div>THE DIV</div>");
|
|
||||||
patient.addName().addFamily("FAMILY");
|
|
||||||
patient.setMaritalStatus(MaritalStatusCodesEnum.D);
|
|
||||||
return patient;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Search()
|
|
||||||
public Patient search(@Elements Set<String> theElements) {
|
|
||||||
ourLastElements = theElements;
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.setId("Patient/1/_history/1");
|
|
||||||
patient.getText().setDiv("<div>THE DIV</div>");
|
|
||||||
patient.addName().addFamily("FAMILY");
|
|
||||||
patient.setMaritalStatus(MaritalStatusCodesEnum.D);
|
|
||||||
return patient;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1232,6 +1232,7 @@ public class JsonParserDstu3Test {
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
assertThat(out, not(containsString("meta")));
|
||||||
|
assertThat(out, not(containsString("SUBSETTED")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1862,6 +1862,7 @@ public class XmlParserDstu3Test {
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
assertThat(out, not(containsString("meta")));
|
||||||
|
assertThat(out, not(containsString("SUBSETTED")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1890,7 +1891,6 @@ public class XmlParserDstu3Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1902,7 +1902,6 @@ public class XmlParserDstu3Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -252,6 +253,7 @@ public class JsonParserR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
public void testExcludeRootStuff() {
|
public void testExcludeRootStuff() {
|
||||||
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||||
Set<String> excludes = new HashSet<>();
|
Set<String> excludes = new HashSet<>();
|
||||||
|
|
|
@ -0,0 +1,320 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.r4.model.*;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class ElementsParamR4Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElementsParamR4Test.class);
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forR4();
|
||||||
|
private static Set<String> ourLastElements;
|
||||||
|
private static int ourPort;
|
||||||
|
private static Server ourServer;
|
||||||
|
private static Procedure ourNextProcedure;
|
||||||
|
private static RestfulServer ourServlet;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ourLastElements = null;
|
||||||
|
ourNextProcedure = null;
|
||||||
|
ourServlet.setElementsSupport(new RestfulServer().getElementsSupport());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadSummaryData() throws Exception {
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Patient/1?_elements=name,maritalStatus",
|
||||||
|
Patient.class,
|
||||||
|
patient -> {
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
assertThat(responseContent, not(containsString("<Bundle")));
|
||||||
|
assertThat(responseContent, (containsString("<Patient")));
|
||||||
|
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
||||||
|
assertThat(responseContent, (containsString("family")));
|
||||||
|
assertThat(responseContent, (containsString("maritalStatus")));
|
||||||
|
assertThat(ourLastElements, containsInAnyOrder("meta", "name", "maritalStatus"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadSummaryTrue() throws Exception {
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Patient/1?_elements=name",
|
||||||
|
Patient.class,
|
||||||
|
patient -> {
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
||||||
|
assertThat(responseContent, (containsString("family")));
|
||||||
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
|
assertThat(ourLastElements, containsInAnyOrder("meta", "name"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchSummaryData() throws Exception {
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Patient?_elements=name,maritalStatus",
|
||||||
|
bundle -> {
|
||||||
|
assertEquals("1", bundle.getTotalElement().getValueAsString());
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle.getEntry().get(0).getResource());
|
||||||
|
assertThat(responseContent, containsString("<Patient"));
|
||||||
|
assertThat(responseContent, not(containsString("THE DIV")));
|
||||||
|
assertThat(responseContent, containsString("family"));
|
||||||
|
assertThat(responseContent, containsString("maritalStatus"));
|
||||||
|
assertThat(ourLastElements, containsInAnyOrder("meta", "name", "maritalStatus"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchSummaryText() throws Exception {
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Patient?_elements=text&_pretty=true",
|
||||||
|
bundle -> {
|
||||||
|
assertEquals("1", bundle.getTotalElement().getValueAsString());
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle.getEntry().get(0).getResource());
|
||||||
|
assertThat(responseContent, containsString("THE DIV"));
|
||||||
|
assertThat(responseContent, not(containsString("family")));
|
||||||
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
|
assertThat(ourLastElements, containsInAnyOrder("meta", "text"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default the elements apply only to the focal resource in a search
|
||||||
|
* and not any included resources
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testStandardElementsFilter() throws IOException {
|
||||||
|
createProcedureWithLongChain();
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Procedure?_include=*&_elements=reasonCode,status",
|
||||||
|
bundle -> {
|
||||||
|
Procedure procedure = (Procedure) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals("SUBSETTED", procedure.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals("REASON_CODE", procedure.getReasonCode().get(0).getCoding().get(0).getCode());
|
||||||
|
assertEquals(0, procedure.getUsedCode().size());
|
||||||
|
|
||||||
|
DiagnosticReport dr = (DiagnosticReport) bundle.getEntry().get(1).getResource();
|
||||||
|
assertEquals(0, dr.getMeta().getTag().size());
|
||||||
|
assertEquals("Observation/OBSA", dr.getResult().get(0).getReference());
|
||||||
|
|
||||||
|
Observation obs = (Observation ) bundle.getEntry().get(2).getResource();
|
||||||
|
assertEquals(0, obs.getMeta().getTag().size());
|
||||||
|
assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus());
|
||||||
|
assertEquals("1234-5", obs.getCode().getCoding().get(0).getCode());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiResourceElementsFilter() throws IOException {
|
||||||
|
createProcedureWithLongChain();
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Procedure?_include=*&_elements=Procedure.reasonCode,Observation.status,Observation.subject,Observation.value",
|
||||||
|
bundle -> {
|
||||||
|
Procedure procedure = (Procedure) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals("SUBSETTED", procedure.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals("REASON_CODE", procedure.getReasonCode().get(0).getCoding().get(0).getCode());
|
||||||
|
assertEquals(0, procedure.getUsedCode().size());
|
||||||
|
|
||||||
|
DiagnosticReport dr = (DiagnosticReport) bundle.getEntry().get(1).getResource();
|
||||||
|
assertEquals(0, dr.getMeta().getTag().size());
|
||||||
|
|
||||||
|
Observation obs = (Observation ) bundle.getEntry().get(2).getResource();
|
||||||
|
assertEquals("SUBSETTED", obs.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus());
|
||||||
|
assertEquals(0, obs.getCode().getCoding().size());
|
||||||
|
assertEquals("STRING VALUE", obs.getValueStringType().getValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiResourceElementsFilterWithMetadataExcluded() throws IOException {
|
||||||
|
createProcedureWithLongChain();
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Procedure?_include=*&_elements=Procedure.reasonCode,Observation.status,Observation.subject,Observation.value&_elements:exclude=*.meta",
|
||||||
|
bundle -> {
|
||||||
|
Procedure procedure = (Procedure) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(true, procedure.getMeta().isEmpty());
|
||||||
|
assertEquals("REASON_CODE", procedure.getReasonCode().get(0).getCoding().get(0).getCode());
|
||||||
|
assertEquals(0, procedure.getUsedCode().size());
|
||||||
|
|
||||||
|
DiagnosticReport dr = (DiagnosticReport) bundle.getEntry().get(1).getResource();
|
||||||
|
assertEquals(true, dr.getMeta().isEmpty());
|
||||||
|
|
||||||
|
Observation obs = (Observation ) bundle.getEntry().get(2).getResource();
|
||||||
|
assertEquals(true, obs.getMeta().isEmpty());
|
||||||
|
assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus());
|
||||||
|
assertEquals(0, obs.getCode().getCoding().size());
|
||||||
|
assertEquals("STRING VALUE", obs.getValueStringType().getValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testElementsFilterWithComplexPath() throws IOException {
|
||||||
|
createProcedureWithLongChain();
|
||||||
|
verifyXmlAndJson(
|
||||||
|
"http://localhost:" + ourPort + "/Procedure?_elements=Procedure.reasonCode.coding.code",
|
||||||
|
bundle -> {
|
||||||
|
Procedure procedure = (Procedure) bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals("SUBSETTED", procedure.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals("REASON_CODE", procedure.getReasonCode().get(0).getCoding().get(0).getCode());
|
||||||
|
assertEquals(null, procedure.getReasonCode().get(0).getCoding().get(0).getSystem());
|
||||||
|
assertEquals(null, procedure.getReasonCode().get(0).getCoding().get(0).getDisplay());
|
||||||
|
assertEquals(0, procedure.getUsedCode().size());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcedureWithLongChain() {
|
||||||
|
ourNextProcedure = new Procedure();
|
||||||
|
ourNextProcedure.setId("Procedure/PROC");
|
||||||
|
ourNextProcedure.addReasonCode().addCoding().setCode("REASON_CODE").setSystem("REASON_SYSTEM").setDisplay("REASON_DISPLAY");
|
||||||
|
ourNextProcedure.addUsedCode().addCoding().setCode("USED_CODE");
|
||||||
|
|
||||||
|
DiagnosticReport dr = new DiagnosticReport();
|
||||||
|
dr.setId("DiagnosticReport/DRA");
|
||||||
|
ourNextProcedure.addReport().setResource(dr);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setId("Observation/OBSA");
|
||||||
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
|
obs.setSubject(new Reference("Patient/123"));
|
||||||
|
obs.getCode().addCoding().setSystem("http://loinc.org").setCode("1234-5");
|
||||||
|
obs.setValue(new StringType("STRING VALUE"));
|
||||||
|
dr.addResult().setResource(obs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyXmlAndJson(String theUri, Consumer<Bundle> theVerifier) throws IOException {
|
||||||
|
verifyXmlAndJson(theUri, Bundle.class, theVerifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends IBaseResource> void verifyXmlAndJson(String theUri, Class<T> theType, Consumer<T> theVerifier) throws IOException {
|
||||||
|
EncodingEnum encodingEnum;
|
||||||
|
HttpGet httpGet;
|
||||||
|
|
||||||
|
encodingEnum = EncodingEnum.JSON;
|
||||||
|
httpGet = new HttpGet(theUri + "&_pretty=true&_format=" + encodingEnum.getFormatContentType());
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
T response = encodingEnum.newParser(ourCtx).parseResource(theType, responseContent);
|
||||||
|
theVerifier.accept(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
encodingEnum = EncodingEnum.XML;
|
||||||
|
httpGet = new HttpGet(theUri + "&_pretty=true&_format=" + encodingEnum.getFormatContentType());
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
T response = encodingEnum.newParser(ourCtx).parseResource(theType, responseContent);
|
||||||
|
theVerifier.accept(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DummyProcedureResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return Procedure.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public Procedure search(@IncludeParam(allow = {"*"}) Collection<Include> theIncludes) {
|
||||||
|
return ourNextProcedure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read
|
||||||
|
public Patient read(@IdParam IdType theId, @Elements Set<String> theElements) {
|
||||||
|
ourLastElements = theElements;
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId("Patient/1/_history/1");
|
||||||
|
patient.getText().getDiv().setValueAsString("<div>THE DIV</div>");
|
||||||
|
patient.addName().setFamily("FAMILY");
|
||||||
|
patient.getMaritalStatus().addCoding().setCode("D");
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search()
|
||||||
|
public Patient search(@Elements Set<String> theElements) {
|
||||||
|
ourLastElements = theElements;
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId("Patient/1/_history/1");
|
||||||
|
patient.getText().getDiv().setValueAsString("<div>THE DIV</div>");
|
||||||
|
patient.addName().setFamily("FAMILY");
|
||||||
|
patient.getMaritalStatus().addCoding().setCode("D");
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourPort = PortUtil.findFreePort();
|
||||||
|
ourServer = new Server(ourPort);
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
|
|
||||||
|
ourServlet.registerProvider(new DummyPatientResourceProvider());
|
||||||
|
ourServlet.registerProvider(new DummyProcedureResourceProvider());
|
||||||
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
ourServer.start();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -89,36 +89,39 @@ public class SearchR4Test {
|
||||||
String linkSelf;
|
String linkSelf;
|
||||||
|
|
||||||
// Initial search
|
// Initial search
|
||||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_elements=name");
|
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_elements=name&_elements:exclude=birthDate,active");
|
||||||
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
||||||
assertThat(toJson(bundle), not(containsString("active")));
|
assertThat(toJson(bundle), not(containsString("\"active\"")));
|
||||||
linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl();
|
linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl();
|
||||||
assertThat(linkSelf, containsString("_elements=name"));
|
assertThat(linkSelf, containsString("_elements=name"));
|
||||||
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
||||||
assertThat(linkNext, containsString("_elements=name"));
|
assertThat(linkNext, containsString("_elements=meta,name"));
|
||||||
|
|
||||||
ourLog.info(toJson(bundle));
|
ourLog.info(toJson(bundle));
|
||||||
|
|
||||||
// Fetch the next page
|
// Fetch the next page
|
||||||
httpGet = new HttpGet(linkNext);
|
httpGet = new HttpGet(linkNext);
|
||||||
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
||||||
assertThat(toJson(bundle), not(containsString("active")));
|
assertThat(toJson(bundle), not(containsString("\"active\"")));
|
||||||
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
||||||
assertThat(linkNext, containsString("_elements=name"));
|
assertThat(linkNext, containsString("_elements=meta,name"));
|
||||||
|
assertThat(linkNext, containsString("_elements:exclude=active,birthDate"));
|
||||||
|
|
||||||
// Fetch the next page
|
// Fetch the next page
|
||||||
httpGet = new HttpGet(linkNext);
|
httpGet = new HttpGet(linkNext);
|
||||||
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
||||||
assertThat(toJson(bundle), not(containsString("active")));
|
assertThat(toJson(bundle), not(containsString("\"active\"")));
|
||||||
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
||||||
assertThat(linkNext, containsString("_elements=name"));
|
assertThat(linkNext, containsString("_elements=meta,name"));
|
||||||
|
assertThat(linkNext, containsString("_elements:exclude=active,birthDate"));
|
||||||
|
|
||||||
// Fetch the next page
|
// Fetch the next page
|
||||||
httpGet = new HttpGet(linkNext);
|
httpGet = new HttpGet(linkNext);
|
||||||
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
|
||||||
assertThat(toJson(bundle), not(containsString("active")));
|
assertThat(toJson(bundle), not(containsString("\"active\"")));
|
||||||
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
|
||||||
assertThat(linkNext, containsString("_elements=name"));
|
assertThat(linkNext, containsString("_elements=meta,name"));
|
||||||
|
assertThat(linkNext, containsString("_elements:exclude=active,birthDate"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Read;
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
@ -18,18 +20,17 @@ 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.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.hl7.fhir.r4.model.MedicationRequest;
|
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -37,11 +38,11 @@ import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
public class SummaryParamR4Test {
|
public class SummaryParamR4Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SummaryParamR4Test.class);
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
private static FhirContext ourCtx = FhirContext.forR4();
|
||||||
private static SummaryEnum ourLastSummary;
|
private static SummaryEnum ourLastSummary;
|
||||||
private static List<SummaryEnum> ourLastSummaryList;
|
private static List<SummaryEnum> ourLastSummaryList;
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SummaryParamR4Test.class);
|
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
|
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
|
@ -51,16 +52,14 @@ public class SummaryParamR4Test {
|
||||||
ourLastSummary = null;
|
ourLastSummary = null;
|
||||||
ourLastSummaryList = null;
|
ourLastSummaryList = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadSummaryData() throws Exception {
|
public void testReadSummaryData() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.DATA.getCode());
|
verifyXmlAndJson(
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
"http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.DATA.getCode(),
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
Patient.class,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
patient -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertEquals(Constants.CT_FHIR_XML_NEW + Constants.CHARSET_UTF8_CTSUFFIX.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
|
||||||
assertThat(responseContent, not(containsString("<Bundle")));
|
assertThat(responseContent, not(containsString("<Bundle")));
|
||||||
assertThat(responseContent, (containsString("<Patien")));
|
assertThat(responseContent, (containsString("<Patien")));
|
||||||
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
||||||
|
@ -68,15 +67,15 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, (containsString("maritalStatus")));
|
assertThat(responseContent, (containsString("maritalStatus")));
|
||||||
assertEquals(SummaryEnum.DATA, ourLastSummary);
|
assertEquals(SummaryEnum.DATA, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadSummaryText() throws Exception {
|
public void testReadSummaryText() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.TEXT.getCode());
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.TEXT.getCode());
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
@ -87,13 +86,13 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("efer")));
|
assertThat(responseContent, not(containsString("efer")));
|
||||||
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadSummaryTextWithMandatory() throws Exception {
|
public void testReadSummaryTextWithMandatory() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationRequest/1?_summary=" + SummaryEnum.TEXT.getCode());
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationRequest/1?_summary=" + SummaryEnum.TEXT.getCode());
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
@ -104,17 +103,16 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("family")));
|
assertThat(responseContent, not(containsString("family")));
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadSummaryTrue() throws Exception {
|
public void testReadSummaryTrue() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.TRUE.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient/1?_summary=" + SummaryEnum.TRUE.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
Patient.class,
|
||||||
ourLog.info(responseContent);
|
patient -> {
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertEquals(Constants.CT_FHIR_XML_NEW + Constants.CHARSET_UTF8_CTSUFFIX.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
|
||||||
assertThat(responseContent, not(containsString("<Bundle")));
|
assertThat(responseContent, not(containsString("<Bundle")));
|
||||||
assertThat(responseContent, (containsString("<Patien")));
|
assertThat(responseContent, (containsString("<Patien")));
|
||||||
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
assertThat(responseContent, not(containsString("<div>THE DIV</div>")));
|
||||||
|
@ -122,16 +120,17 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
assertEquals(SummaryEnum.TRUE, ourLastSummary);
|
assertEquals(SummaryEnum.TRUE, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryCount() throws Exception {
|
public void testSearchSummaryCount() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_pretty=true&_summary=" + SummaryEnum.COUNT.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_pretty=true&_summary=" + SummaryEnum.COUNT.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||||
assertThat(responseContent, not(containsString("entry")));
|
assertThat(responseContent, not(containsString("entry")));
|
||||||
assertThat(responseContent, not(containsString("THE DIV")));
|
assertThat(responseContent, not(containsString("THE DIV")));
|
||||||
|
@ -139,64 +138,65 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
assertEquals(SummaryEnum.COUNT, ourLastSummary);
|
assertEquals(SummaryEnum.COUNT, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryCountAndData() throws Exception {
|
public void testSearchSummaryCountAndData() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_pretty=true&_summary=" + SummaryEnum.COUNT.getCode() + "," + SummaryEnum.DATA.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_pretty=true&_summary=" + SummaryEnum.COUNT.getCode() + "," + SummaryEnum.DATA.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||||
assertThat(responseContent, (containsString("entry")));
|
assertThat(responseContent, (containsString("entry")));
|
||||||
assertThat(responseContent, not(containsString("THE DIV")));
|
assertThat(responseContent, not(containsString("THE DIV")));
|
||||||
assertThat(responseContent, (containsString("family")));
|
assertThat(responseContent, (containsString("family")));
|
||||||
assertThat(responseContent, (containsString("maritalStatus")));
|
assertThat(responseContent, (containsString("maritalStatus")));
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryData() throws Exception {
|
public void testSearchSummaryData() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.DATA.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.DATA.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, containsString("<Patient"));
|
assertThat(responseContent, containsString("<Patient"));
|
||||||
assertThat(responseContent, not(containsString("THE DIV")));
|
assertThat(responseContent, not(containsString("THE DIV")));
|
||||||
assertThat(responseContent, containsString("family"));
|
assertThat(responseContent, containsString("family"));
|
||||||
assertThat(responseContent, containsString("maritalStatus"));
|
assertThat(responseContent, containsString("maritalStatus"));
|
||||||
assertEquals(SummaryEnum.DATA, ourLastSummary);
|
assertEquals(SummaryEnum.DATA, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryFalse() throws Exception {
|
public void testSearchSummaryFalse() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_summary=false");
|
String url = "http://localhost:" + ourPort + "/Patient?_summary=false";
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, containsString("<Patient"));
|
assertThat(responseContent, containsString("<Patient"));
|
||||||
assertThat(responseContent, containsString("THE DIV"));
|
assertThat(responseContent, containsString("THE DIV"));
|
||||||
assertThat(responseContent, containsString("family"));
|
assertThat(responseContent, containsString("family"));
|
||||||
assertThat(responseContent, containsString("maritalStatus"));
|
assertThat(responseContent, containsString("maritalStatus"));
|
||||||
assertEquals(SummaryEnum.FALSE, ourLastSummary);
|
assertEquals(SummaryEnum.FALSE, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryText() throws Exception {
|
public void testSearchSummaryText() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.TEXT.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.TEXT.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||||
assertThat(responseContent, (containsString("entry")));
|
assertThat(responseContent, (containsString("entry")));
|
||||||
assertThat(responseContent, (containsString("THE DIV")));
|
assertThat(responseContent, (containsString("THE DIV")));
|
||||||
|
@ -204,32 +204,34 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryTextWithMandatory() throws Exception {
|
public void testSearchSummaryTextWithMandatory() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationRequest?_summary=" + SummaryEnum.TEXT.getCode() + "&_pretty=true");
|
String url = "http://localhost:" + ourPort + "/MedicationRequest?_summary=" + SummaryEnum.TEXT.getCode() + "&_pretty=true";
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
assertEquals(0, bundle.getMeta().getTag().size());
|
||||||
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||||
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(containsStringIgnoringCase("note")));
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryTextMulti() throws Exception {
|
public void testSearchSummaryTextMulti() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=multi&_summary=" + SummaryEnum.TEXT.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_query=multi&_summary=" + SummaryEnum.TEXT.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||||
assertThat(responseContent, (containsString("entry")));
|
assertThat(responseContent, (containsString("entry")));
|
||||||
assertThat(responseContent, (containsString("THE DIV")));
|
assertThat(responseContent, (containsString("THE DIV")));
|
||||||
|
@ -237,60 +239,63 @@ public class SummaryParamR4Test {
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
assertThat(ourLastSummaryList, contains(SummaryEnum.TEXT));
|
assertThat(ourLastSummaryList, contains(SummaryEnum.TEXT));
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryTrue() throws Exception {
|
public void testSearchSummaryTrue() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.TRUE.getCode());
|
String url = "http://localhost:" + ourPort + "/Patient?_summary=" + SummaryEnum.TRUE.getCode();
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
verifyXmlAndJson(
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
url,
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
bundle -> {
|
||||||
ourLog.info(responseContent);
|
String responseContent = ourCtx.newXmlParser().encodeResourceToString(bundle);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
|
||||||
assertThat(responseContent, containsString("<Patient"));
|
assertThat(responseContent, containsString("<Patient"));
|
||||||
assertThat(responseContent, not(containsString("THE DIV")));
|
assertThat(responseContent, not(containsString("THE DIV")));
|
||||||
assertThat(responseContent, containsString("family"));
|
assertThat(responseContent, containsString("family"));
|
||||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||||
assertEquals(SummaryEnum.TRUE, ourLastSummary);
|
assertEquals(SummaryEnum.TRUE, ourLastSummary);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchSummaryWithTextAndOthers() throws Exception {
|
public void testSearchSummaryWithTextAndOthers() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_summary=text&_summary=data");
|
String url = "http://localhost:" + ourPort + "/Patient?_summary=text&_summary=data";
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
try (CloseableHttpResponse status = ourClient.execute(new HttpGet(url))) {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
ourLog.info(responseContent);
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
assertThat(responseContent, containsString("Can not combine _summary=text with other values for _summary"));
|
assertThat(responseContent, containsString("Can not combine _summary=text with other values for _summary"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
ourServer.stop();
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
private void verifyXmlAndJson(String theUri, Consumer<Bundle> theVerifier) throws IOException {
|
||||||
public static void beforeClass() throws Exception {
|
verifyXmlAndJson(theUri, Bundle.class, theVerifier);
|
||||||
ourPort = PortUtil.findFreePort();
|
}
|
||||||
ourServer = new Server(ourPort);
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
private <T extends IBaseResource> void verifyXmlAndJson(String theUri, Class<T> theType, Consumer<T> theVerifier) throws IOException {
|
||||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
EncodingEnum encodingEnum;
|
||||||
|
HttpGet httpGet;
|
||||||
|
|
||||||
servlet.setResourceProviders(new DummyPatientResourceProvider(), new DummyMedicationRequestProvider());
|
encodingEnum = EncodingEnum.JSON;
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
httpGet = new HttpGet(theUri + "&_pretty=true&_format=" + encodingEnum.getFormatContentType());
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
ourServer.setHandler(proxyHandler);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourServer.start();
|
ourLog.info(responseContent);
|
||||||
|
T response = encodingEnum.newParser(ourCtx).parseResource(theType, responseContent);
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
theVerifier.accept(response);
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
}
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
|
encodingEnum = EncodingEnum.XML;
|
||||||
|
httpGet = new HttpGet(theUri + "&_pretty=true&_format=" + encodingEnum.getFormatContentType());
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
T response = encodingEnum.newParser(ourCtx).parseResource(theType, responseContent);
|
||||||
|
theVerifier.accept(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DummyMedicationRequestProvider implements IResourceProvider {
|
public static class DummyMedicationRequestProvider implements IResourceProvider {
|
||||||
|
@ -312,7 +317,7 @@ public class SummaryParamR4Test {
|
||||||
|
|
||||||
@Search
|
@Search
|
||||||
public List<MedicationRequest> read() {
|
public List<MedicationRequest> read() {
|
||||||
return Arrays.asList(read(new IdType("999")));
|
return Collections.singletonList(read(new IdType("999")));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -359,4 +364,31 @@ public class SummaryParamR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourPort = PortUtil.findFreePort();
|
||||||
|
ourServer = new Server(ourPort);
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||||
|
|
||||||
|
servlet.setResourceProviders(new DummyPatientResourceProvider(), new DummyMedicationRequestProvider());
|
||||||
|
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
ourServer.start();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -940,7 +940,6 @@ public class JsonParserDstu2_1Test {
|
||||||
assertThat(out, containsString("name"));
|
assertThat(out, containsString("name"));
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1568,7 +1568,6 @@ public class XmlParserDstu2_1Test {
|
||||||
assertThat(out, containsString("name"));
|
assertThat(out, containsString("name"));
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1597,7 +1596,6 @@ public class XmlParserDstu2_1Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1609,7 +1607,6 @@ public class XmlParserDstu2_1Test {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
|
|
@ -1143,7 +1143,6 @@ public class Dstu3JsonParserTest {
|
||||||
assertThat(out, containsString("name"));
|
assertThat(out, containsString("name"));
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1938,7 +1938,6 @@ public class Dstu3XmlParserTest {
|
||||||
assertThat(out, containsString("name"));
|
assertThat(out, containsString("name"));
|
||||||
assertThat(out, containsString("id"));
|
assertThat(out, containsString("id"));
|
||||||
assertThat(out, not(containsString("address")));
|
assertThat(out, not(containsString("address")));
|
||||||
assertThat(out, not(containsString("meta")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1967,7 +1966,6 @@ public class Dstu3XmlParserTest {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
@ -1979,7 +1977,6 @@ public class Dstu3XmlParserTest {
|
||||||
{
|
{
|
||||||
IParser p = ourCtx.newXmlParser();
|
IParser p = ourCtx.newXmlParser();
|
||||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
|
||||||
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
|
|
||||||
p.setPrettyPrint(true);
|
p.setPrettyPrint(true);
|
||||||
String out = p.encodeResourceToString(bundle);
|
String out = p.encodeResourceToString(bundle);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
|
|
|
@ -151,57 +151,6 @@ public class R4JsonParserTest {
|
||||||
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExcludeRootStuff() {
|
|
||||||
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
|
||||||
Set<String> excludes = new HashSet<>();
|
|
||||||
excludes.add("id");
|
|
||||||
excludes.add("meta");
|
|
||||||
parser.setDontEncodeElements(excludes);
|
|
||||||
|
|
||||||
Bundle b = createBundleWithPatient();
|
|
||||||
|
|
||||||
String encoded = parser.encodeResourceToString(b);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
assertThat(encoded, not(containsString("BUNDLEID")));
|
|
||||||
assertThat(encoded, not(containsString("http://FOO")));
|
|
||||||
assertThat(encoded, (containsString("PATIENTID")));
|
|
||||||
assertThat(encoded, (containsString("http://BAR")));
|
|
||||||
assertThat(encoded, containsString("GIVEN"));
|
|
||||||
|
|
||||||
b = parser.parseResource(Bundle.class, encoded);
|
|
||||||
|
|
||||||
assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
|
|
||||||
assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
|
|
||||||
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExcludeStarDotStuff() {
|
|
||||||
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
|
||||||
Set<String> excludes = new HashSet<>();
|
|
||||||
excludes.add("*.id");
|
|
||||||
excludes.add("*.meta");
|
|
||||||
parser.setDontEncodeElements(excludes);
|
|
||||||
|
|
||||||
Bundle b = createBundleWithPatient();
|
|
||||||
|
|
||||||
String encoded = parser.encodeResourceToString(b);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
assertThat(encoded, not(containsString("BUNDLEID")));
|
|
||||||
assertThat(encoded, not(containsString("http://FOO")));
|
|
||||||
assertThat(encoded, not(containsString("PATIENTID")));
|
|
||||||
assertThat(encoded, not(containsString("http://BAR")));
|
|
||||||
assertThat(encoded, containsString("GIVEN"));
|
|
||||||
|
|
||||||
b = parser.parseResource(Bundle.class, encoded);
|
|
||||||
|
|
||||||
assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
|
|
||||||
assertNotEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
|
|
||||||
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that long JSON strings don't get broken up
|
* Test that long JSON strings don't get broken up
|
||||||
|
|
|
@ -106,32 +106,6 @@ public class R4XmlParserTest {
|
||||||
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExcludeRootStuff() {
|
|
||||||
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
|
||||||
Set<String> excludes = new HashSet<>();
|
|
||||||
excludes.add("id");
|
|
||||||
excludes.add("meta");
|
|
||||||
parser.setDontEncodeElements(excludes);
|
|
||||||
|
|
||||||
Bundle b = createBundleWithPatient();
|
|
||||||
|
|
||||||
String encoded = parser.encodeResourceToString(b);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
assertThat(encoded, IsNot.not(containsString("BUNDLEID")));
|
|
||||||
assertThat(encoded, IsNot.not(containsString("http://FOO")));
|
|
||||||
assertThat(encoded, (containsString("PATIENTID")));
|
|
||||||
assertThat(encoded, (containsString("http://BAR")));
|
|
||||||
assertThat(encoded, containsString("GIVEN"));
|
|
||||||
|
|
||||||
b = parser.parseResource(Bundle.class, encoded);
|
|
||||||
|
|
||||||
assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
|
|
||||||
assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
|
|
||||||
assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExcludeStarDotStuff() {
|
public void testExcludeStarDotStuff() {
|
||||||
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
|
|
@ -689,6 +689,55 @@
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section name="Extended Elements Support" id="extended_elements_support">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The HAPI FHIR server may be configured using the
|
||||||
|
<code>RestfulServer#setElementsSupport</code> to enable extended
|
||||||
|
support for the <code>_elements</code> filter.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In standard mode, elements are supported exactly as described in the
|
||||||
|
<a href="http://hl7.org/fhir/search.html#elements">Elements Documentation</a>
|
||||||
|
in the FHIR specification.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In extended mode, HAPI FHIR provides the same behaviour as described in the
|
||||||
|
FHIR specification, but also enabled the following additional options:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Values may be prepended using Resource names in order to apply the
|
||||||
|
elements filter to multiple resources. For example, the following
|
||||||
|
parameter could be used to apply elements filtering to both the
|
||||||
|
DiagnosticReport and Observation resource in a search result:<br/>
|
||||||
|
<code>_elements=DiagnosticReport.subject,DiagnosticReport.result,Observation.value</code>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Values may be prepended with a wildcard star in order to apply them
|
||||||
|
to all resource types. For example, the following parameter could
|
||||||
|
be used to include the <code>subject</code> field in all resource
|
||||||
|
types:<br/>
|
||||||
|
<code>_elements=*.subject</code>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Values may include complex paths. For example, the following parameter could
|
||||||
|
be used to include only the code on a coded element:<br/>
|
||||||
|
<code>_elements=Procedure.reasonCode.coding.code</code>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Elements may be excluded using the <code>:exclude</code> modifier
|
||||||
|
on the elements parameter. For example, the following parameter
|
||||||
|
could be used to remove the resource metadata (meta) element from
|
||||||
|
all resources in the response:<br/>
|
||||||
|
<code>_elements:exclude=*.meta</code><br/>
|
||||||
|
Note that this can be used to suppress the <code>SUBSETTED</code> tag
|
||||||
|
which is automatically added to resources when an <code>_elements</code>
|
||||||
|
parameter is applied.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</document>
|
</document>
|
||||||
|
|
Loading…
Reference in New Issue