Merge branch 'hapi3_refactor' of github.com:jamesagnew/hapi-fhir into hapi3_refactor
This commit is contained in:
commit
95a607d155
|
@ -140,6 +140,11 @@ public enum FhirVersionEnum {
|
|||
String provideVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class attempts to read the FHIR version from the actual model
|
||||
* classes in order to supply an accurate version string even over time
|
||||
*
|
||||
*/
|
||||
private static class Dstu3Version implements IVersionProvider {
|
||||
|
||||
public Dstu3Version() {
|
||||
|
@ -147,7 +152,7 @@ public enum FhirVersionEnum {
|
|||
Class<?> c = Class.forName("org.hl7.fhir.dstu3.model.Constants");
|
||||
myVersion = (String) c.getDeclaredField("VERSION").get(null);
|
||||
} catch (Exception e) {
|
||||
myVersion = "UNKNOWN";
|
||||
myVersion = "3.0.1";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,7 +172,7 @@ public enum FhirVersionEnum {
|
|||
Class<?> c = Class.forName("org.hl7.fhir.r4.model.Constants");
|
||||
myVersion = (String) c.getDeclaredField("VERSION").get(null);
|
||||
} catch (Exception e) {
|
||||
myVersion = "UNKNOWN";
|
||||
myVersion = "4.0.0";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -301,11 +301,16 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype<String>, */IIdTy
|
|||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
if (b.length() > 0 && isNotBlank(myUnqualifiedId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedId)) {
|
||||
b.append(myUnqualifiedId);
|
||||
} else if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append(Constants.PARAM_HISTORY);
|
||||
|
@ -381,7 +386,7 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype<String>, */IIdTy
|
|||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isBlank(getValue());
|
||||
return super.isBaseEmpty() && isBlank(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -522,8 +527,22 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype<String>, */IIdTy
|
|||
int typeIndex = theValue.lastIndexOf('/', idIndex - 1);
|
||||
if (typeIndex == -1) {
|
||||
myResourceType = theValue.substring(0, idIndex);
|
||||
} else {
|
||||
if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) {
|
||||
typeIndex = theValue.indexOf('/', typeIndex + 1);
|
||||
}
|
||||
if (typeIndex >= idIndex) {
|
||||
// e.g. http://example.org/foo
|
||||
// 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id.
|
||||
// Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly
|
||||
// recreate the url
|
||||
myResourceType = myUnqualifiedId;
|
||||
myUnqualifiedId = null;
|
||||
super.setValue(null);
|
||||
myHaveComponentParts = true;
|
||||
} else {
|
||||
myResourceType = theValue.substring(typeIndex + 1, idIndex);
|
||||
}
|
||||
|
||||
if (typeIndex > 4) {
|
||||
myBaseUrl = theValue.substring(0, typeIndex);
|
||||
|
|
|
@ -47,6 +47,8 @@ import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType;
|
|||
import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.ID_DATATYPE;
|
||||
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.PRIMITIVE_DATATYPE;
|
||||
|
||||
/**
|
||||
* This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use
|
||||
|
@ -612,9 +614,23 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
write(theEventWriter, "resourceType", resDef.getName());
|
||||
if (theResourceId != null && theResourceId.hasIdPart()) {
|
||||
write(theEventWriter, "id", theResourceId.getIdPart());
|
||||
if (theResourceId.hasFormatComment()) {
|
||||
final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
||||
final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
||||
// Undeclared extensions
|
||||
extractUndeclaredExtensions(theResourceId, extensions, modifierExtensions, null, null);
|
||||
boolean haveExtension = false;
|
||||
if (!extensions.isEmpty()) {
|
||||
haveExtension = true;
|
||||
}
|
||||
|
||||
if (theResourceId.hasFormatComment() || haveExtension) {
|
||||
beginObject(theEventWriter, "_id");
|
||||
if (theResourceId.hasFormatComment()) {
|
||||
writeCommentsPreAndPost(theResourceId, theEventWriter);
|
||||
}
|
||||
if (haveExtension) {
|
||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
||||
}
|
||||
theEventWriter.endObject();
|
||||
}
|
||||
}
|
||||
|
@ -1014,6 +1030,9 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
}
|
||||
|
||||
private void parseExtension(ParserState<?> theState, JsonLikeArray theValues, boolean theIsModifier) {
|
||||
int allUnderscoreNames = 0;
|
||||
int handledUnderscoreNames = 0;
|
||||
|
||||
for (int i = 0; i < theValues.size(); i++) {
|
||||
JsonLikeObject nextExtObj = JsonLikeValue.asObject(theValues.get(i));
|
||||
JsonLikeValue jsonElement = nextExtObj.get("url");
|
||||
|
@ -1040,9 +1059,43 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
} else if ("modifierExtension".equals(next)) {
|
||||
JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next));
|
||||
parseExtension(theState, jsonVal, true);
|
||||
} else if (next.charAt(0) == '_') {
|
||||
allUnderscoreNames++;
|
||||
continue;
|
||||
} else {
|
||||
JsonLikeValue jsonVal = nextExtObj.get(next);
|
||||
parseChildren(theState, next, jsonVal, null, null, false);
|
||||
String alternateName = '_' + next;
|
||||
JsonLikeValue alternateVal = nextExtObj.get(alternateName);
|
||||
if (alternateVal != null) {
|
||||
handledUnderscoreNames++;
|
||||
}
|
||||
parseChildren(theState, next, jsonVal, alternateVal, alternateName, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This happens if an element has an extension but no actual value. I.e.
|
||||
* if a resource has a "_status" element but no corresponding "status"
|
||||
* element. This could be used to handle a null value with an extension
|
||||
* for example.
|
||||
*/
|
||||
if (allUnderscoreNames > handledUnderscoreNames) {
|
||||
for (String alternateName : nextExtObj.keySet()) {
|
||||
if (alternateName.startsWith("_") && alternateName.length() > 1) {
|
||||
JsonLikeValue nextValue = nextExtObj.get(alternateName);
|
||||
if (nextValue != null) {
|
||||
if (nextValue.isObject()) {
|
||||
String nextName = alternateName.substring(1);
|
||||
if (nextExtObj.get(nextName) == null) {
|
||||
theState.enteringNewElement(null, nextName);
|
||||
parseAlternates(nextValue, theState, alternateName, alternateName);
|
||||
theState.endingElement();
|
||||
}
|
||||
} else {
|
||||
getErrorHandler().incorrectJsonType(null, alternateName, ValueType.OBJECT, null, nextValue.getJsonType(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
theState.endingElement();
|
||||
|
@ -1314,6 +1367,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
} else {
|
||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false);
|
||||
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName);
|
||||
}
|
||||
|
||||
theEventWriter.endObject();
|
||||
|
@ -1368,6 +1422,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, myParent, false);
|
||||
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
@ -1375,6 +1430,26 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
theEventWriter.endObject();
|
||||
}
|
||||
|
||||
private void managePrimitiveExtension(final IBase theValue, final RuntimeResourceDefinition theResDef, final IBaseResource theResource, final JsonLikeWriter theEventWriter, final BaseRuntimeElementDefinition<?> def, final String childName) throws IOException {
|
||||
if (def.getChildType().equals(ID_DATATYPE) || def.getChildType().equals(PRIMITIVE_DATATYPE)) {
|
||||
final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
||||
final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
||||
// Undeclared extensions
|
||||
extractUndeclaredExtensions(theValue, extensions, modifierExtensions, myParent, null);
|
||||
// Declared extensions
|
||||
if (def != null) {
|
||||
extractDeclaredExtensions(theValue, def, extensions, modifierExtensions, myParent);
|
||||
}
|
||||
boolean haveContent = false;
|
||||
if (!extensions.isEmpty() || !modifierExtensions.isEmpty()) {
|
||||
haveContent = true;
|
||||
}
|
||||
if (haveContent) {
|
||||
beginObject(theEventWriter, '_' + childName);
|
||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
||||
theEventWriter.endObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -422,6 +422,7 @@ class ParserState<T> {
|
|||
push(newState);
|
||||
return;
|
||||
}
|
||||
case ID_DATATYPE:
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
|
||||
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance(myDefinition.getInstanceConstructorArguments());
|
||||
|
@ -1158,10 +1159,16 @@ class ParserState<T> {
|
|||
// if (isNotBlank(entryBaseUrl)) {
|
||||
// nextResource.setId(new IdDt(entryBaseUrl, resourceName, bundleIdPart, version));
|
||||
// } else {
|
||||
IdDt previousId = nextResource.getId();
|
||||
nextResource.setId(new IdDt(null, resourceName, bundleIdPart, version));
|
||||
// Copy extensions
|
||||
if (!previousId.getAllUndeclaredExtensions().isEmpty()) {
|
||||
for (final ExtensionDt ext : previousId.getAllUndeclaredExtensions()) {
|
||||
nextResource.getId().addUndeclaredExtension(ext);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -184,9 +184,9 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
heldComments.clear();
|
||||
}
|
||||
parserState.endingElement();
|
||||
// if (parserState.isComplete()) {
|
||||
// return parserState.getObject();
|
||||
// }
|
||||
// if (parserState.isComplete()) {
|
||||
// return parserState.getObject();
|
||||
// }
|
||||
break;
|
||||
}
|
||||
case XMLStreamConstants.CHARACTERS: {
|
||||
|
@ -229,10 +229,14 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
case ID_DATATYPE: {
|
||||
IIdType value = IIdType.class.cast(theElement);
|
||||
String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue();
|
||||
if (StringUtils.isNotBlank(encodedValue) || super.hasExtensions(value)) {
|
||||
theEventWriter.writeStartElement(childName);
|
||||
if (StringUtils.isNotBlank(encodedValue)) {
|
||||
theEventWriter.writeAttribute("value", encodedValue);
|
||||
}
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
|
@ -354,8 +358,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
}
|
||||
|
||||
if (nextChild instanceof RuntimeChildContainedResources) {
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource,
|
||||
nextChildElem);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource, nextChildElem);
|
||||
} else {
|
||||
|
||||
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
||||
|
@ -398,8 +401,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, 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)
|
||||
throws XMLStreamException {
|
||||
BaseRuntimeDeclaredChildDefinition extDef = (BaseRuntimeDeclaredChildDefinition) nextChild;
|
||||
if (extDef.isModifier()) {
|
||||
|
@ -434,8 +436,7 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource) throws XMLStreamException, DataFormatException {
|
||||
IIdType resourceId = null;
|
||||
|
||||
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
|
||||
|
@ -470,11 +471,13 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
if (theResource instanceof IAnyResource) {
|
||||
|
||||
// HL7.org Structures
|
||||
if (theResourceId != null) {
|
||||
writeCommentsPre(theEventWriter, theResourceId);
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart());
|
||||
theEventWriter.writeStartElement("id");
|
||||
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false);
|
||||
theEventWriter.writeEndElement();
|
||||
writeCommentsPost(theEventWriter, theResourceId);
|
||||
}
|
||||
|
||||
|
@ -486,8 +489,13 @@ public class XmlParser extends BaseParser /* implements IParser */ {
|
|||
|
||||
IResource resource = (IResource) theResource;
|
||||
if (theResourceId != null) {
|
||||
writeCommentsPre(theEventWriter, theResourceId);
|
||||
/* writeCommentsPre(theEventWriter, theResourceId);
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart());
|
||||
writeCommentsPost(theEventWriter, theResourceId);*/
|
||||
theEventWriter.writeStartElement("id");
|
||||
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false);
|
||||
theEventWriter.writeEndElement();
|
||||
writeCommentsPost(theEventWriter, theResourceId);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,20 +28,20 @@ public interface IBaseBundle extends IBaseResource {
|
|||
* link.type field to indicate that the given link is for
|
||||
* the next page of results.
|
||||
*/
|
||||
public static final String LINK_NEXT = "next";
|
||||
String LINK_NEXT = "next";
|
||||
|
||||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* link.type field to indicate that the given link is for
|
||||
* the previous page of results.
|
||||
*/
|
||||
public static final String LINK_PREV = "previous";
|
||||
String LINK_PREV = "previous";
|
||||
|
||||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* link.type field to indicate that the given link is for
|
||||
* this bundle.
|
||||
*/
|
||||
public static final String LINK_SELF = "self";
|
||||
String LINK_SELF = "self";
|
||||
|
||||
}
|
||||
|
|
|
@ -1755,11 +1755,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
}
|
||||
|
||||
if (myReturnBundleType == null && myContext.getVersion().getVersion().isRi()) {
|
||||
throw new IllegalArgumentException("When using the client with HL7.org structures, you must specify "
|
||||
+ "the bundle return type for the client by adding \".returnBundle(org.hl7.fhir.instance.model.Bundle.class)\" to your search method call before the \".execute()\" method");
|
||||
}
|
||||
|
||||
IClientResponseHandler<? extends IBase> binding;
|
||||
binding = new ResourceResponseHandler(myReturnBundleType, getPreferResponseTypes(myResourceType));
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
|
||||
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
private FhirContext myContext;
|
||||
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory>();
|
||||
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<>();
|
||||
private ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE;
|
||||
private int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT;
|
||||
private String myProxyUsername;
|
||||
|
@ -82,9 +82,6 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
|
||||
/**
|
||||
* Return the proxy username to authenticate with the HTTP proxy
|
||||
*
|
||||
* @param The
|
||||
* proxy username
|
||||
*/
|
||||
protected String getProxyUsername() {
|
||||
return myProxyUsername;
|
||||
|
@ -92,9 +89,6 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
|
||||
/**
|
||||
* Return the proxy password to authenticate with the HTTP proxy
|
||||
*
|
||||
* @param The
|
||||
* proxy password
|
||||
*/
|
||||
protected String getProxyPassword() {
|
||||
return myProxyPassword;
|
||||
|
@ -128,8 +122,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
|
||||
T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
|
||||
return proxy;
|
||||
return (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,9 +155,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
myInvocationHandlers.put(theClientType, invocationHandler);
|
||||
}
|
||||
|
||||
T proxy = instantiateProxy(theClientType, invocationHandler.newInvocationHandler(this));
|
||||
|
||||
return proxy;
|
||||
return instantiateProxy(theClientType, invocationHandler.newInvocationHandler(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,13 +322,14 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
FhirVersionEnum serverFhirVersionEnum = null;
|
||||
if (StringUtils.isBlank(serverFhirVersionString)) {
|
||||
// we'll be lenient and accept this
|
||||
ourLog.debug("Server conformance statement does not indicate the FHIR version");
|
||||
} else {
|
||||
if (serverFhirVersionString.startsWith("0.4") || serverFhirVersionString.startsWith("0.5") || serverFhirVersionString.startsWith("1.0.")) {
|
||||
if (serverFhirVersionString.equals(FhirVersionEnum.DSTU2.getFhirVersionString())) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
|
||||
} else if (serverFhirVersionString.startsWith("3.0.")) {
|
||||
} else if (serverFhirVersionString.equals(FhirVersionEnum.DSTU2_1.getFhirVersionString())) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU2_1;
|
||||
} else if (serverFhirVersionString.equals(FhirVersionEnum.DSTU3.getFhirVersionString())) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU3;
|
||||
} else if (serverFhirVersionString.startsWith("3.1.")) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.R4;
|
||||
} else {
|
||||
// we'll be lenient and accept this
|
||||
ourLog.debug("Server conformance statement indicates unknown FHIR version: {}", serverFhirVersionString);
|
||||
|
|
|
@ -264,6 +264,10 @@
|
|||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
|
|
|
@ -197,7 +197,15 @@ public class ResourceLink implements Serializable {
|
|||
public void setTargetResourceUrl(IIdType theTargetResourceUrl) {
|
||||
Validate.isTrue(theTargetResourceUrl.hasBaseUrl());
|
||||
Validate.isTrue(theTargetResourceUrl.hasResourceType());
|
||||
Validate.isTrue(theTargetResourceUrl.hasIdPart());
|
||||
|
||||
if (theTargetResourceUrl.hasIdPart()) {
|
||||
// do nothing
|
||||
} else {
|
||||
// Must have set an url like http://example.org/something
|
||||
// We treat 'something' as the resource type because of fix for #659. Prior to #659 fix, 'something' was
|
||||
// treated as the id and 'example.org' was treated as the resource type
|
||||
// TODO: log a warning?
|
||||
}
|
||||
|
||||
myTargetResourceType = theTargetResourceUrl.getResourceType();
|
||||
myTargetResourceUrl = theTargetResourceUrl.getValue();
|
||||
|
|
|
@ -80,7 +80,8 @@ public class RestHookSubscriptionDstu2Interceptor extends BaseRestHookSubscripti
|
|||
*/
|
||||
private void checkSubscriptions(IIdType idType, String resourceType, RestOperationTypeEnum theOperation) {
|
||||
//avoid a ConcurrentModificationException by copying to an array
|
||||
for (Object object : myRestHookSubscriptions.toArray()) {
|
||||
Object[] subscriptions = myRestHookSubscriptions.toArray();
|
||||
for (Object object : subscriptions) {
|
||||
if (object == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -330,8 +331,9 @@ public class RestHookSubscriptionDstu2Interceptor extends BaseRestHookSubscripti
|
|||
Subscription subscription = (Subscription) theResource;
|
||||
if (subscription.getChannel() != null
|
||||
&& subscription.getChannel().getTypeElement().getValueAsEnum() == SubscriptionChannelTypeEnum.REST_HOOK
|
||||
&& subscription.getStatusElement().getValueAsEnum() == SubscriptionStatusEnum.ACTIVE) {
|
||||
&& subscription.getStatusElement().getValueAsEnum() == SubscriptionStatusEnum.REQUESTED) {
|
||||
removeLocalSubscription(subscription.getIdElement().getIdPart());
|
||||
subscription.setStatus(SubscriptionStatusEnum.ACTIVE);
|
||||
myRestHookSubscriptions.add(subscription);
|
||||
ourLog.info("Subscription was added. Id: " + subscription.getId());
|
||||
}
|
||||
|
|
|
@ -319,8 +319,9 @@ public class RestHookSubscriptionDstu3Interceptor extends BaseRestHookSubscripti
|
|||
Subscription subscription = (Subscription) theResource;
|
||||
if (subscription.getChannel() != null
|
||||
&& subscription.getChannel().getType() == Subscription.SubscriptionChannelType.RESTHOOK
|
||||
&& subscription.getStatus() == Subscription.SubscriptionStatus.ACTIVE) {
|
||||
&& subscription.getStatus() == Subscription.SubscriptionStatus.REQUESTED) {
|
||||
removeLocalSubscription(subscription.getIdElement().getIdPart());
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE);
|
||||
myRestHookSubscriptions.add(subscription);
|
||||
ourLog.info("Subscription was added, id: {} - Have {}", subscription.getIdElement().getIdPart(), myRestHookSubscriptions.size());
|
||||
}
|
||||
|
|
|
@ -58,10 +58,10 @@ public class RestHookSubscriptionR4Interceptor extends BaseRestHookSubscriptionI
|
|||
private final static int MAX_THREADS = 1;
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(RestHookSubscriptionR4Interceptor.class);
|
||||
|
||||
private final List<Subscription> myRestHookSubscriptions = new ArrayList<>();
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
private final List<Subscription> myRestHookSubscriptions = new ArrayList<Subscription>();
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mySubscriptionDaoR4")
|
||||
|
@ -314,9 +314,10 @@ public class RestHookSubscriptionR4Interceptor extends BaseRestHookSubscriptionI
|
|||
Subscription subscription = (Subscription) theResource;
|
||||
if (subscription.getChannel() != null
|
||||
&& subscription.getChannel().getType() == Subscription.SubscriptionChannelType.RESTHOOK
|
||||
&& subscription.getStatus() == Subscription.SubscriptionStatus.ACTIVE) {
|
||||
&& subscription.getStatus() == Subscription.SubscriptionStatus.REQUESTED) {
|
||||
removeLocalSubscription(subscription.getIdElement().getIdPart());
|
||||
myRestHookSubscriptions.add(subscription);
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE);
|
||||
ourLog.info("Subscription was added, id: {} - Have {}", subscription.getIdElement().getIdPart(), myRestHookSubscriptions.size());
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.messaging.support.ExecutorSubscribableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public abstract class BaseSubscriptionInterceptor extends ServerOperationInterceptorAdapter {
|
||||
|
||||
private static final Integer MAX_SUBSCRIPTION_RESULTS = 1000;
|
||||
private SubscribableChannel myProcessingChannel;
|
||||
private ExecutorService myExecutor;
|
||||
private boolean myAutoActivateSubscriptions = true;
|
||||
private int myExecutorThreadCount = 1;
|
||||
private MessageHandler mySubscriptionActivatingSubscriber;
|
||||
private MessageHandler mySubscriptionCheckingSubscriber;
|
||||
private ConcurrentHashMap<String, IBaseResource> myIdToSubscription = new ConcurrentHashMap<>();
|
||||
private Subscription.SubscriptionChannelType myChannelType = Subscription.SubscriptionChannelType.RESTHOOK;
|
||||
private Logger ourLog = LoggerFactory.getLogger(BaseSubscriptionInterceptor.class);
|
||||
|
||||
protected abstract IFhirResourceDao<?> getSubscriptionDao();
|
||||
|
||||
/**
|
||||
* Read the existing subscriptions from the database
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Scheduled(fixedDelay = 10000)
|
||||
public void initSubscriptions() {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Subscription.SP_TYPE, new TokenParam(null, myChannelType.toCode()));
|
||||
map.add(Subscription.SP_STATUS, new TokenParam(null, Subscription.SubscriptionStatus.ACTIVE.toCode()));
|
||||
map.setLoadSynchronousUpTo(MAX_SUBSCRIPTION_RESULTS);
|
||||
|
||||
RequestDetails req = new ServletSubRequestDetails();
|
||||
req.setSubRequest(true);
|
||||
|
||||
IBundleProvider subscriptionBundleList = getSubscriptionDao().search(map, req);
|
||||
if (subscriptionBundleList.size() >= MAX_SUBSCRIPTION_RESULTS) {
|
||||
ourLog.error("Currently over " + MAX_SUBSCRIPTION_RESULTS + " subscriptions. Some subscriptions have not been loaded.");
|
||||
}
|
||||
|
||||
List<IBaseResource> resourceList = subscriptionBundleList.getResources(0, subscriptionBundleList.size());
|
||||
|
||||
Set<String> allIds = new HashSet<>();
|
||||
for (IBaseResource resource : resourceList) {
|
||||
String nextId = resource.getIdElement().getIdPart();
|
||||
allIds.add(nextId);
|
||||
myIdToSubscription.put(nextId, resource);
|
||||
}
|
||||
|
||||
for (String next : myIdToSubscription.keySet()) {
|
||||
if (!allIds.contains(next)) {
|
||||
myIdToSubscription.remove(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
|
||||
ThreadFactory threadFactory = new BasicThreadFactory.Builder()
|
||||
.namingPattern("subscription-%d")
|
||||
.daemon(false)
|
||||
.priority(Thread.NORM_PRIORITY)
|
||||
.build();
|
||||
myExecutor = new ThreadPoolExecutor(
|
||||
myExecutorThreadCount,
|
||||
myExecutorThreadCount,
|
||||
0L,
|
||||
TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(1000),
|
||||
threadFactory,
|
||||
rejectedExecutionHandler);
|
||||
|
||||
|
||||
if (myProcessingChannel == null) {
|
||||
myProcessingChannel = new ExecutorSubscribableChannel(myExecutor);
|
||||
}
|
||||
|
||||
if (myAutoActivateSubscriptions) {
|
||||
if (mySubscriptionActivatingSubscriber == null) {
|
||||
mySubscriptionActivatingSubscriber = new SubscriptionActivatingSubscriber(getSubscriptionDao(), myIdToSubscription, myChannelType, myProcessingChannel);
|
||||
}
|
||||
myProcessingChannel.subscribe(mySubscriptionActivatingSubscriber);
|
||||
}
|
||||
|
||||
if (mySubscriptionCheckingSubscriber == null) {
|
||||
mySubscriptionCheckingSubscriber = new SubscriptionCheckingSubscriber(getSubscriptionDao(), myIdToSubscription, myChannelType, myProcessingChannel);
|
||||
}
|
||||
myProcessingChannel.subscribe(mySubscriptionCheckingSubscriber);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@PreDestroy
|
||||
public void preDestroy() {
|
||||
if (myAutoActivateSubscriptions) {
|
||||
myProcessingChannel.unsubscribe(mySubscriptionActivatingSubscriber);
|
||||
}
|
||||
myProcessingChannel.unsubscribe(mySubscriptionCheckingSubscriber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage();
|
||||
msg.setId(theResource.getIdElement());
|
||||
msg.setOperationType(RestOperationTypeEnum.CREATE);
|
||||
msg.setNewPayload(theResource);
|
||||
submitResourceModified(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceDeleted(RequestDetails theRequest, IBaseResource theResource) {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage();
|
||||
msg.setId(theResource.getIdElement());
|
||||
msg.setOperationType(RestOperationTypeEnum.DELETE);
|
||||
submitResourceModified(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage();
|
||||
msg.setId(theNewResource.getIdElement());
|
||||
msg.setOperationType(RestOperationTypeEnum.UPDATE);
|
||||
msg.setNewPayload(theNewResource);
|
||||
submitResourceModified(msg);
|
||||
}
|
||||
|
||||
private void submitResourceModified(ResourceModifiedMessage theMsg) {
|
||||
myProcessingChannel.send(new GenericMessage<>(theMsg));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class BaseSubscriptionSubscriber implements MessageHandler {
|
||||
static final String SUBSCRIPTION_STATUS = "Subscription.status";
|
||||
private static final String SUBSCRIPTION_TYPE = "Subscription.channel.type";
|
||||
private final IFhirResourceDao mySubscriptionDao;
|
||||
private final ConcurrentHashMap<String, IBaseResource> myIdToSubscription;
|
||||
private final Subscription.SubscriptionChannelType myChannelType;
|
||||
private final SubscribableChannel myProcessingChannel;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public BaseSubscriptionSubscriber(IFhirResourceDao<? extends IBaseResource> theSubscriptionDao, ConcurrentHashMap<String, IBaseResource> theIdToSubscription, Subscription.SubscriptionChannelType theChannelType, SubscribableChannel theProcessingChannel) {
|
||||
mySubscriptionDao = theSubscriptionDao;
|
||||
myIdToSubscription = theIdToSubscription;
|
||||
myChannelType = theChannelType;
|
||||
myProcessingChannel = theProcessingChannel;
|
||||
}
|
||||
|
||||
public Subscription.SubscriptionChannelType getChannelType() {
|
||||
return myChannelType;
|
||||
}
|
||||
|
||||
public FhirContext getContext() {
|
||||
return getSubscriptionDao().getContext();
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, IBaseResource> getIdToSubscription() {
|
||||
return myIdToSubscription;
|
||||
}
|
||||
|
||||
public SubscribableChannel getProcessingChannel() {
|
||||
return myProcessingChannel;
|
||||
}
|
||||
|
||||
public IFhirResourceDao getSubscriptionDao() {
|
||||
return mySubscriptionDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this subscription type (e.g. rest hook, websocket, etc) apply to this interceptor?
|
||||
*/
|
||||
protected boolean subscriptionTypeApplies(ResourceModifiedMessage theMsg) {
|
||||
FhirContext ctx = mySubscriptionDao.getContext();
|
||||
IBaseResource subscription = theMsg.getNewPayload();
|
||||
return subscriptionTypeApplies(ctx, subscription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this subscription type (e.g. rest hook, websocket, etc) apply to this interceptor?
|
||||
*/
|
||||
protected boolean subscriptionTypeApplies(FhirContext theCtx, IBaseResource theSubscription) {
|
||||
IPrimitiveType<?> status = theCtx.newTerser().getSingleValueOrNull(theSubscription, SUBSCRIPTION_TYPE, IPrimitiveType.class);
|
||||
boolean subscriptionTypeApplies = false;
|
||||
if (getChannelType().toCode().equals(status.getValueAsString())) {
|
||||
subscriptionTypeApplies = true;
|
||||
}
|
||||
return subscriptionTypeApplies;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ResourceDeliveryMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private IBaseResource mySubscription;
|
||||
private IBaseResource myPayoad;
|
||||
private RestOperationTypeEnum myOperationType;
|
||||
|
||||
public RestOperationTypeEnum getOperationType() {
|
||||
return myOperationType;
|
||||
}
|
||||
|
||||
public void setOperationType(RestOperationTypeEnum theOperationType) {
|
||||
myOperationType = theOperationType;
|
||||
}
|
||||
|
||||
public IBaseResource getPayoad() {
|
||||
return myPayoad;
|
||||
}
|
||||
|
||||
public void setPayoad(IBaseResource thePayoad) {
|
||||
myPayoad = thePayoad;
|
||||
}
|
||||
|
||||
public IBaseResource getSubscription() {
|
||||
return mySubscription;
|
||||
}
|
||||
|
||||
public void setSubscription(IBaseResource theSubscription) {
|
||||
mySubscription = theSubscription;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ResourceModifiedMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private IIdType myId;
|
||||
private RestOperationTypeEnum myOperationType;
|
||||
private IBaseResource myNewPayload;
|
||||
|
||||
public IIdType getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public void setId(IIdType theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
|
||||
public RestOperationTypeEnum getOperationType() {
|
||||
return myOperationType;
|
||||
}
|
||||
|
||||
public void setOperationType(RestOperationTypeEnum theOperationType) {
|
||||
myOperationType = theOperationType;
|
||||
}
|
||||
|
||||
public IBaseResource getNewPayload() {
|
||||
return myNewPayload;
|
||||
}
|
||||
|
||||
public void setNewPayload(IBaseResource theNewPayload) {
|
||||
myNewPayload = theNewPayload;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SubscriptionActivatingSubscriber extends BaseSubscriptionSubscriber {
|
||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SubscriptionActivatingSubscriber(IFhirResourceDao<? extends IBaseResource> theSubscriptionDao, ConcurrentHashMap<String, IBaseResource> theIdToSubscription, Subscription.SubscriptionChannelType theChannelType, SubscribableChannel theProcessingChannel) {
|
||||
super(theSubscriptionDao, theIdToSubscription, theChannelType, theProcessingChannel);
|
||||
}
|
||||
|
||||
private void handleCreate(ResourceModifiedMessage theMsg) {
|
||||
if (!theMsg.getId().getResourceType().equals("Subscription")) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean subscriptionTypeApplies = subscriptionTypeApplies(theMsg);
|
||||
if (subscriptionTypeApplies == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
FhirContext ctx = getSubscriptionDao().getContext();
|
||||
IBaseResource subscription = theMsg.getNewPayload();
|
||||
IPrimitiveType<?> status = ctx.newTerser().getSingleValueOrNull(subscription, SUBSCRIPTION_STATUS, IPrimitiveType.class);
|
||||
String statusString = status.getValueAsString();
|
||||
|
||||
String oldStatus = Subscription.SubscriptionStatus.REQUESTED.toCode();
|
||||
if (oldStatus.equals(statusString)) {
|
||||
String newStatus = Subscription.SubscriptionStatus.ACTIVE.toCode();
|
||||
status.setValueAsString(newStatus);
|
||||
ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualifiedVersionless().getValue(), oldStatus, newStatus);
|
||||
getSubscriptionDao().update(subscription);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message<?> theMessage) throws MessagingException {
|
||||
|
||||
if (!(theMessage.getPayload() instanceof ResourceModifiedMessage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceModifiedMessage msg = (ResourceModifiedMessage) theMessage.getPayload();
|
||||
IIdType id = msg.getId();
|
||||
|
||||
switch (msg.getOperationType()) {
|
||||
case DELETE:
|
||||
getIdToSubscription().remove(id.getIdPart());
|
||||
return;
|
||||
case CREATE:
|
||||
handleCreate(msg);
|
||||
break;
|
||||
case UPDATE:
|
||||
handleUpdate(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleUpdate(ResourceModifiedMessage theMsg) {
|
||||
if (!theMsg.getId().getResourceType().equals("Subscription")) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean subscriptionTypeApplies = subscriptionTypeApplies(theMsg);
|
||||
if (subscriptionTypeApplies == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
FhirContext ctx = getSubscriptionDao().getContext();
|
||||
IBaseResource subscription = theMsg.getNewPayload();
|
||||
IPrimitiveType<?> status = ctx.newTerser().getSingleValueOrNull(subscription, SUBSCRIPTION_STATUS, IPrimitiveType.class);
|
||||
String statusString = status.getValueAsString();
|
||||
|
||||
if (Subscription.SubscriptionStatus.ACTIVE.toCode().equals(statusString)) {
|
||||
getIdToSubscription().put(theMsg.getId().getIdPart(), theMsg.getNewPayload());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber {
|
||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionCheckingSubscriber.class);
|
||||
|
||||
public SubscriptionCheckingSubscriber(IFhirResourceDao theSubscriptionDao, ConcurrentHashMap<String, IBaseResource> theIdToSubscription, Subscription.SubscriptionChannelType theChannelType, SubscribableChannel theProcessingChannel) {
|
||||
super(theSubscriptionDao, theIdToSubscription, theChannelType, theProcessingChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message<?> theMessage) throws MessagingException {
|
||||
if (!(theMessage.getPayload() instanceof ResourceModifiedMessage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceModifiedMessage msg = (ResourceModifiedMessage) theMessage.getPayload();
|
||||
switch (msg.getOperationType()) {
|
||||
case CREATE:
|
||||
case UPDATE:
|
||||
break;
|
||||
default:
|
||||
// ignore anything else
|
||||
return;
|
||||
}
|
||||
|
||||
String resourceType = msg.getId().getResourceType();
|
||||
String resourceId = msg.getId().getIdPart();
|
||||
|
||||
for (IBaseResource nextSubscription : getIdToSubscription().values()) {
|
||||
|
||||
String nextSubscriptionId = nextSubscription.getIdElement().toUnqualifiedVersionless().getValue();
|
||||
IPrimitiveType<?> nextCriteria = getContext().newTerser().getSingleValueOrNull(nextSubscription, "Subscription.criteria", IPrimitiveType.class);
|
||||
String nextCriteriaString = nextCriteria != null ? nextCriteria.getValueAsString() : null;
|
||||
|
||||
if (StringUtils.isBlank(nextCriteriaString)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// see if the criteria matches the created object
|
||||
ourLog.info("Checking subscription {} for {} with criteria {}", nextSubscriptionId, resourceType, nextCriteriaString);
|
||||
|
||||
String criteriaResource = nextCriteriaString;
|
||||
int index = criteriaResource.indexOf("?");
|
||||
if (index != -1) {
|
||||
criteriaResource = criteriaResource.substring(0, criteriaResource.indexOf("?"));
|
||||
}
|
||||
|
||||
if (resourceType != null && nextCriteriaString != null && !criteriaResource.equals(resourceType)) {
|
||||
ourLog.info("Skipping subscription search for {} because it does not match the criteria {}", resourceType, nextCriteriaString);
|
||||
continue;
|
||||
}
|
||||
|
||||
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
||||
String criteria = nextCriteriaString;
|
||||
criteria += "&_id=" + resourceType + "/" + resourceId;
|
||||
criteria = massageCriteria(criteria);
|
||||
|
||||
IBundleProvider results = performSearch(criteria);
|
||||
if (results.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// should just be one resource as it was filtered by the id
|
||||
for (IBaseResource nextBase : results.getResources(0, results.size())) {
|
||||
IAnyResource next = (IAnyResource) nextBase;
|
||||
ourLog.info("Found match: queueing rest-hook notification for resource: {}", next.getIdElement());
|
||||
|
||||
ResourceDeliveryMessage deliveryMsg = new ResourceDeliveryMessage();
|
||||
deliveryMsg.setPayoad(next);
|
||||
deliveryMsg.setSubscription(nextSubscription);
|
||||
deliveryMsg.setOperationType(msg.getOperationType());
|
||||
|
||||
getProcessingChannel().send(new GenericMessage<>(deliveryMsg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
protected String massageCriteria(String theCriteria) {
|
||||
return theCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search based on a query criteria
|
||||
*/
|
||||
protected IBundleProvider performSearch(String theCriteria) {
|
||||
RuntimeResourceDefinition responseResourceDef = getSubscriptionDao().validateCriteriaAndReturnResourceDefinition(theCriteria);
|
||||
SearchParameterMap responseCriteriaUrl = BaseHapiFhirDao.translateMatchUrl(getSubscriptionDao(), getSubscriptionDao().getContext(), theCriteria, responseResourceDef);
|
||||
|
||||
RequestDetails req = new ServletSubRequestDetails();
|
||||
req.setSubRequest(true);
|
||||
|
||||
IFhirResourceDao<? extends IBaseResource> responseDao = getSubscriptionDao().getDao(responseResourceDef.getImplementingClass());
|
||||
responseCriteriaUrl.setLoadSynchronousUpTo(1);
|
||||
|
||||
IBundleProvider responseResults = responseDao.search(responseCriteriaUrl, req);
|
||||
return responseResults;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionSubscriber {
|
||||
|
||||
public SubscriptionDeliveringRestHookSubscriber(IFhirResourceDao theSubscriptionDao, ConcurrentHashMap<String, IBaseResource> theIdToSubscription, Subscription.SubscriptionChannelType theChannelType, SubscribableChannel theProcessingChannel) {
|
||||
super(theSubscriptionDao, theIdToSubscription, theChannelType, theProcessingChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message<?> theMessage) throws MessagingException {
|
||||
if (!(theMessage.getPayload() instanceof ResourceDeliveryMessage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceDeliveryMessage msg = (ResourceDeliveryMessage) theMessage.getPayload();
|
||||
|
||||
if (!subscriptionTypeApplies(getContext(), msg.getSubscription())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -57,11 +57,8 @@ public class SubscriptionWebsocketHandlerR4 extends TextWebSocketHandler impleme
|
|||
private static IFhirResourceDaoSubscription<Subscription> ourSubscriptionDao;
|
||||
|
||||
private ScheduledFuture<?> myScheduleFuture;
|
||||
|
||||
private IState myState = new InitialState();
|
||||
|
||||
private IIdType mySubscriptionId;
|
||||
|
||||
private Long mySubscriptionPid;
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -116,7 +116,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
server.start();
|
||||
|
||||
ourClient = myFhirCtx.newRestfulGenericClient(ourServerBase);
|
||||
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
||||
ourClient.registerInterceptor(new LoggingInterceptor());
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.entity.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.*;
|
||||
|
@ -2059,7 +2060,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
Observation o = new Observation();
|
||||
o.getCode().setText("testSearchWithInvalidSort");
|
||||
myObservationDao.create(o, mySrd);
|
||||
ourClient
|
||||
IBaseBundle bundle = ourClient
|
||||
.search()
|
||||
.forResource(Observation.class)
|
||||
.sort().ascending(Observation.CODE_VALUE_QUANTITY) // composite sort not supported yet
|
||||
|
|
|
@ -151,7 +151,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000);
|
||||
ourClient = myFhirCtx.newRestfulGenericClient(ourServerBase);
|
||||
if (shouldLogClient()) {
|
||||
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
||||
ourClient.registerInterceptor(new LoggingInterceptor());
|
||||
}
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
|
|
|
@ -1,23 +1,6 @@
|
|||
|
||||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderDstu2Test;
|
||||
|
@ -38,6 +21,19 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
|||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test the rest-hook subscriptions
|
||||
|
@ -51,12 +47,19 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
private static String ourListenerServerBase;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu2Test.class);
|
||||
private static List<Observation> ourUpdatedObservations = Lists.newArrayList();
|
||||
private List<IIdType> mySubscriptionIds = new ArrayList<IIdType>();
|
||||
|
||||
@After
|
||||
public void afterUnregisterRestHookListener() {
|
||||
for (IIdType next : mySubscriptionIds){
|
||||
ourClient.delete().resourceById(next).execute();
|
||||
}
|
||||
mySubscriptionIds.clear();
|
||||
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
ourLog.info("Deleting all subscriptions");
|
||||
ourClient.delete().resourceConditionalByUrl("Subscription?status=active").execute();
|
||||
ourClient.delete().resourceConditionalByUrl("Observation?code:missing=false").execute();
|
||||
ourLog.info("Done deleting all subscriptions");
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
|
||||
|
@ -77,7 +80,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
private Subscription createSubscription(String criteria, String payload, String endpoint) {
|
||||
Subscription subscription = new Subscription();
|
||||
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
||||
subscription.setStatus(SubscriptionStatusEnum.ACTIVE);
|
||||
subscription.setStatus(SubscriptionStatusEnum.REQUESTED);
|
||||
subscription.setCriteria(criteria);
|
||||
|
||||
Channel channel = new Channel();
|
||||
|
@ -88,6 +91,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute();
|
||||
subscription.setId(methodOutcome.getId().getIdPart());
|
||||
mySubscriptionIds.add(methodOutcome.getId());
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
@ -136,9 +140,9 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription/" + subscription2.getId())).execute();
|
||||
|
@ -147,7 +151,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -160,7 +164,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -174,7 +178,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
@ -222,9 +226,9 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(ourCreatedObservations.toString(), 2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription/" + subscription2.getId())).execute();
|
||||
|
@ -233,7 +237,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -246,7 +250,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -260,7 +264,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
|
|
@ -1,54 +1,60 @@
|
|||
|
||||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.*;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test the rest-hook subscriptions
|
||||
*/
|
||||
public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
||||
|
||||
private static List<String> ourContentTypes = new ArrayList<String>();
|
||||
private static List<Observation> ourCreatedObservations = Lists.newArrayList();
|
||||
private static int ourListenerPort;
|
||||
private static RestfulServer ourListenerRestServer;
|
||||
private static Server ourListenerServer;
|
||||
private static String ourListenerServerBase;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu3Test.class);
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu2Test.class);
|
||||
private static List<Observation> ourUpdatedObservations = Lists.newArrayList();
|
||||
private List<IIdType> mySubscriptionIds = new ArrayList<>();
|
||||
private static List<String> ourContentTypes = new ArrayList<>();
|
||||
|
||||
@After
|
||||
public void afterUnregisterRestHookListener() {
|
||||
for (IIdType next : mySubscriptionIds){
|
||||
ourClient.delete().resourceById(next).execute();
|
||||
}
|
||||
mySubscriptionIds.clear();
|
||||
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
ourLog.info("Deleting all subscriptions");
|
||||
ourClient.delete().resourceConditionalByUrl("Subscription?status=active").execute();
|
||||
ourClient.delete().resourceConditionalByUrl("Observation?code:missing=false").execute();
|
||||
ourLog.info("Done deleting all subscriptions");
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
|
||||
|
@ -85,7 +91,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint) {
|
||||
Subscription subscription = new Subscription();
|
||||
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE);
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED);
|
||||
subscription.setCriteria(theCriteria);
|
||||
|
||||
Subscription.SubscriptionChannelComponent channel = new Subscription.SubscriptionChannelComponent();
|
||||
|
@ -96,6 +102,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute();
|
||||
subscription.setId(methodOutcome.getId().getIdPart());
|
||||
mySubscriptionIds.add(methodOutcome.getId());
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
@ -163,21 +170,20 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
subscriptionTemp.setCriteria(criteria1);
|
||||
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
|
||||
|
||||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute();
|
||||
ourClient.delete().resourceById(new IdType("Subscription/" + subscription2.getId())).execute();
|
||||
|
||||
Observation observationTemp3 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -190,7 +196,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -204,7 +210,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
@ -232,7 +238,6 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
assertEquals(Constants.CT_FHIR_XML_NEW, ourContentTypes.get(0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRestHookSubscriptionApplicationXml() throws Exception {
|
||||
String payload = "application/xml";
|
||||
|
@ -258,21 +263,20 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
subscriptionTemp.setCriteria(criteria1);
|
||||
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
|
||||
|
||||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(ourCreatedObservations.toString(), 2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute();
|
||||
ourClient.delete().resourceById(new IdType("Subscription/" + subscription2.getId())).execute();
|
||||
|
||||
Observation observationTemp3 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -285,7 +289,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -299,7 +303,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
@ -309,7 +313,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
@BeforeClass
|
||||
public static void startListenerServer() throws Exception {
|
||||
ourListenerPort = RandomServerPortProvider.findFreePort();
|
||||
ourListenerPort = PortUtil.findFreePort();
|
||||
ourListenerRestServer = new RestfulServer(FhirContext.forDstu3());
|
||||
ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context";
|
||||
|
||||
|
|
|
@ -1,54 +1,60 @@
|
|||
|
||||
package ca.uhn.fhir.jpa.subscription.r4;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.*;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.jpa.subscription.RestHookTestDstu2Test;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.junit.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test the rest-hook subscriptions
|
||||
*/
|
||||
public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
||||
|
||||
private static List<String> ourContentTypes = new ArrayList<String>();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu2Test.class);
|
||||
private static List<Observation> ourCreatedObservations = Lists.newArrayList();
|
||||
private static int ourListenerPort;
|
||||
private static RestfulServer ourListenerRestServer;
|
||||
private static Server ourListenerServer;
|
||||
private static String ourListenerServerBase;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestR4Test.class);
|
||||
|
||||
private static List<Observation> ourUpdatedObservations = Lists.newArrayList();
|
||||
private static List<String> ourContentTypes = new ArrayList<>();
|
||||
private List<IIdType> mySubscriptionIds = new ArrayList<>();
|
||||
|
||||
@After
|
||||
public void afterUnregisterRestHookListener() {
|
||||
for (IIdType next : mySubscriptionIds) {
|
||||
ourClient.delete().resourceById(next).execute();
|
||||
}
|
||||
mySubscriptionIds.clear();
|
||||
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
ourLog.info("Deleting all subscriptions");
|
||||
ourClient.delete().resourceConditionalByUrl("Subscription?status=active").execute();
|
||||
ourClient.delete().resourceConditionalByUrl("Observation?code:missing=false").execute();
|
||||
ourLog.info("Done deleting all subscriptions");
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
|
||||
|
@ -81,11 +87,10 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint) {
|
||||
Subscription subscription = new Subscription();
|
||||
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE);
|
||||
subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED);
|
||||
subscription.setCriteria(theCriteria);
|
||||
|
||||
Subscription.SubscriptionChannelComponent channel = new Subscription.SubscriptionChannelComponent();
|
||||
|
@ -96,6 +101,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute();
|
||||
subscription.setId(methodOutcome.getId().getIdPart());
|
||||
mySubscriptionIds.add(methodOutcome.getId());
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
@ -163,21 +169,20 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
subscriptionTemp.setCriteria(criteria1);
|
||||
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
|
||||
|
||||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute();
|
||||
ourClient.delete().resourceById(new IdType("Subscription/" + subscription2.getId())).execute();
|
||||
|
||||
Observation observationTemp3 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -190,7 +195,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -204,7 +209,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
@ -232,7 +237,6 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
assertEquals(Constants.CT_FHIR_XML_NEW, ourContentTypes.get(0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRestHookSubscriptionApplicationXml() throws Exception {
|
||||
String payload = "application/xml";
|
||||
|
@ -258,21 +262,20 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
subscriptionTemp.setCriteria(criteria1);
|
||||
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
|
||||
|
||||
|
||||
Observation observation2 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see two subscription notifications
|
||||
// Should see one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(ourCreatedObservations.toString(), 2, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute();
|
||||
ourClient.delete().resourceById(new IdType("Subscription/" + subscription2.getId())).execute();
|
||||
|
||||
Observation observationTemp3 = sendObservation(code, "SNOMED-CT");
|
||||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -285,7 +288,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
// Should see no subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(0, ourUpdatedObservations.size());
|
||||
|
||||
Observation observation3a = ourClient.read(Observation.class, observationTemp3.getId());
|
||||
|
@ -299,7 +302,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
// Should see only one subscription notification
|
||||
Thread.sleep(500);
|
||||
assertEquals(4, ourCreatedObservations.size());
|
||||
assertEquals(3, ourCreatedObservations.size());
|
||||
assertEquals(1, ourUpdatedObservations.size());
|
||||
|
||||
Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
|
||||
|
@ -309,7 +312,7 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
@BeforeClass
|
||||
public static void startListenerServer() throws Exception {
|
||||
ourListenerPort = RandomServerPortProvider.findFreePort();
|
||||
ourListenerPort = PortUtil.findFreePort();
|
||||
ourListenerRestServer = new RestfulServer(FhirContext.forR4());
|
||||
ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context";
|
||||
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
package ca.uhn.fhir.jpa.z;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ResourceMinimizerMojo {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceMinimizerMojo.class);
|
||||
|
||||
private String fhirVersion;
|
||||
private long myByteCount;
|
||||
private FhirContext myCtx;
|
||||
private int myFileCount;
|
||||
private File targetDirectory;
|
||||
|
||||
public void execute() throws Exception {
|
||||
ourLog.info("Starting resource minimizer");
|
||||
|
||||
if (myCtx != null) {
|
||||
// nothing
|
||||
} else if ("DSTU2".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forDstu2();
|
||||
} else if ("HL7ORG_DSTU2".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forDstu2Hl7Org();
|
||||
} else if ("DSTU2_1".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forDstu2_1();
|
||||
} else if ("DSTU3".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forDstu3();
|
||||
} else if ("R4".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forR4();
|
||||
} else {
|
||||
throw new Exception("Unknown version: " + fhirVersion);
|
||||
}
|
||||
|
||||
ourLog.info("Looking for files in directory: {}", targetDirectory.getAbsolutePath());
|
||||
|
||||
Collection<File> files = FileUtils.listFiles(targetDirectory, new String[]{"xml", "json"}, true);
|
||||
for (File nextFile : files) {
|
||||
ourLog.debug("Checking file: {}", nextFile);
|
||||
|
||||
String inputString;
|
||||
try {
|
||||
inputString = IOUtils.toString(new FileInputStream(nextFile), "UTF-8");
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Failed to read file: " + nextFile, e);
|
||||
}
|
||||
|
||||
IParser parser = EncodingEnum.detectEncoding(inputString).newParser(myCtx);
|
||||
IBaseResource input = parser.parseResource(inputString);
|
||||
|
||||
if (input instanceof IResource) {
|
||||
((IResource) input).getText().getDiv().setValueAsString((String) null);
|
||||
((IResource) input).getText().getStatus().setValueAsString((String) null);
|
||||
if (input instanceof Bundle) {
|
||||
for (Entry nextEntry : ((Bundle) input).getEntry()) {
|
||||
if (nextEntry.getResource() != null) {
|
||||
nextEntry.getResource().getText().getDiv().setValueAsString((String) null);
|
||||
nextEntry.getResource().getText().getStatus().setValueAsString((String) null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
minimizeResource((IBaseResource) input);
|
||||
}
|
||||
|
||||
String outputString = parser.setPrettyPrint(true).encodeResourceToString(input);
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (String nextLine : outputString.split("\\n")) {
|
||||
int i;
|
||||
for (i = 0; i < nextLine.length(); i++) {
|
||||
if (nextLine.charAt(i) != ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
b.append(StringUtils.leftPad("", i / 3, ' '));
|
||||
b.append(nextLine.substring(i));
|
||||
b.append("\n");
|
||||
}
|
||||
outputString = b.toString();
|
||||
|
||||
if (!inputString.equals(outputString)) {
|
||||
ourLog.info("Trimming contents of resource: {} - From {} to {}", nextFile, FileUtils.byteCountToDisplaySize(inputString.length()), FileUtils.byteCountToDisplaySize(outputString.length()));
|
||||
myByteCount += (inputString.length() - outputString.length());
|
||||
myFileCount++;
|
||||
try {
|
||||
String f = nextFile.getAbsolutePath();
|
||||
Writer w = new OutputStreamWriter(new FileOutputStream(f, false), "UTF-8");
|
||||
w = new BufferedWriter(w);
|
||||
w.append(outputString);
|
||||
w.close();
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Failed to write " + nextFile, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void minimizeResource(IBaseResource theInput) {
|
||||
if (theInput instanceof IBaseBundle) {
|
||||
for (IBaseResource next : BundleUtil.toListOfResources(myCtx, (IBaseBundle) theInput)) {
|
||||
minimizeResource(next);
|
||||
}
|
||||
}
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> element = (BaseRuntimeElementCompositeDefinition) myCtx.getElementDefinition(theInput.getClass());
|
||||
BaseRuntimeChildDefinition textElement = element.getChildByName("text");
|
||||
if (textElement != null) {
|
||||
textElement.getMutator().setValue(theInput, null);
|
||||
}
|
||||
}
|
||||
|
||||
public long getByteCount() {
|
||||
return myByteCount;
|
||||
}
|
||||
|
||||
public int getFileCount() {
|
||||
return myFileCount;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
FhirContext ctxDstu2 = FhirContext.forDstu2();
|
||||
// FhirContext ctxDstu2_1 = FhirContext.forDstu2_1();
|
||||
FhirContext ctxDstu3 = FhirContext.forDstu3();
|
||||
FhirContext ctxR4 = FhirContext.forR4();
|
||||
|
||||
LoggerContext loggerContext = ((ch.qos.logback.classic.Logger) ourLog).getLoggerContext();
|
||||
URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(loggerContext);
|
||||
System.out.println(mainURL);
|
||||
// or even
|
||||
ourLog.info("Logback used '{}' as the configuration file.", mainURL);
|
||||
|
||||
int fileCount = 0;
|
||||
long byteCount = 0;
|
||||
|
||||
ResourceMinimizerMojo m = new ResourceMinimizerMojo();
|
||||
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("./hapi-tinder-plugin/src/main/resources/vs/dstu2");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/valueset");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/profile");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu3;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/profile");
|
||||
m.fhirVersion = "DSTU3";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu3;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/valueset");
|
||||
m.fhirVersion = "DSTU3";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2_1;
|
||||
// m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/profile");
|
||||
// m.fhirVersion = "DSTU2_1";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
//
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2_1;
|
||||
// m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/valueset");
|
||||
// m.fhirVersion = "DSTU2_1";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxR4;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-r4/src/main/resources/org/hl7/fhir/r4/model/profile");
|
||||
m.fhirVersion = "R4";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxR4;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-r4/src/main/resources/org/hl7/fhir/r4/model/valueset");
|
||||
m.fhirVersion = "R4";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
ourLog.info("Trimmed {} files", fileCount);
|
||||
ourLog.info("Trimmed {} bytes", FileUtils.byteCountToDisplaySize(byteCount));
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.util.*;
|
|||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -98,7 +99,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
|
||||
retVal.setPublisher(myPublisher);
|
||||
retVal.setDate(conformanceDate());
|
||||
retVal.setFhirVersion("0.0.82-3059"); // TODO: pull from model
|
||||
retVal.setFhirVersion(FhirVersionEnum.DSTU1.getFhirVersionString());
|
||||
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser needs to be modified to actually allow it
|
||||
|
||||
retVal.getImplementation().setDescription(myServerConfiguration.getImplementationDescription());
|
||||
|
|
|
@ -84,6 +84,37 @@ public class IdDtTest {
|
|||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo1() {
|
||||
IdDt id = new IdDt("http://my.org/foo");
|
||||
assertEquals("http://my.org/foo", id.getValueAsString());
|
||||
assertEquals(null, id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("foo", id.getResourceType());
|
||||
assertEquals("http://my.org", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo2() {
|
||||
IdDt id = new IdDt("http://my.org/a/b/c/foo");
|
||||
assertEquals("http://my.org/a/b/c/foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("c/foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("c", id.getResourceType());
|
||||
assertEquals("http://my.org/a/b", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectIsIdPartValid() {
|
||||
|
|
|
@ -358,11 +358,16 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
if (b.length() > 0 && isNotBlank(myUnqualifiedId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedId)) {
|
||||
b.append(myUnqualifiedId);
|
||||
} else if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append("_history");
|
||||
|
@ -553,8 +558,22 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
int typeIndex = theValue.lastIndexOf('/', idIndex - 1);
|
||||
if (typeIndex == -1) {
|
||||
myResourceType = theValue.substring(0, idIndex);
|
||||
} else {
|
||||
if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) {
|
||||
typeIndex = theValue.indexOf('/', typeIndex + 1);
|
||||
}
|
||||
if (typeIndex >= idIndex) {
|
||||
// e.g. http://example.org/foo
|
||||
// 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id.
|
||||
// Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly
|
||||
// recreate the url
|
||||
myResourceType = myUnqualifiedId;
|
||||
myUnqualifiedId = null;
|
||||
super.setValue(null);
|
||||
myHaveComponentParts = true;
|
||||
} else {
|
||||
myResourceType = theValue.substring(typeIndex + 1, idIndex);
|
||||
}
|
||||
|
||||
if (typeIndex > 4) {
|
||||
myBaseUrl = theValue.substring(0, typeIndex);
|
||||
|
|
|
@ -92,6 +92,37 @@ public class IdTypeDstu2_1Test {
|
|||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo1() {
|
||||
IdType id = new IdType("http://my.org/foo");
|
||||
assertEquals("http://my.org/foo", id.getValueAsString());
|
||||
assertEquals(null, id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("foo", id.getResourceType());
|
||||
assertEquals("http://my.org", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo2() {
|
||||
IdType id = new IdType("http://my.org/a/b/c/foo");
|
||||
assertEquals("http://my.org/a/b/c/foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("c/foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("c", id.getResourceType());
|
||||
assertEquals("http://my.org/a/b", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectLocal() {
|
||||
|
|
|
@ -1873,6 +1873,26 @@ public class JsonParserDstu2_1Test {
|
|||
Assert.assertThat(message, containsString("contained"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newJsonParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@AfterClass
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.parser.FooMessageHeaderWithExplicitField.FooMessageSourceComponent;
|
||||
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
|
||||
import ca.uhn.fhir.parser.PatientWithCustomCompositeExtension.FooParentExtension;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.collection.IsEmptyCollection;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hamcrest.text.StringContainsInOrder;
|
||||
import org.hl7.fhir.dstu2016may.model.*;
|
||||
import org.hl7.fhir.dstu2016may.model.Address.AddressUse;
|
||||
import org.hl7.fhir.dstu2016may.model.*;
|
||||
import org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu2016may.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu2016may.model.ContactPoint.ContactPointSystem;
|
||||
|
@ -32,20 +33,20 @@ import org.junit.*;
|
|||
import org.mockito.ArgumentCaptor;
|
||||
import org.xmlunit.builder.DiffBuilder;
|
||||
import org.xmlunit.builder.Input;
|
||||
import org.xmlunit.diff.*;
|
||||
import org.xmlunit.diff.ComparisonControllers;
|
||||
import org.xmlunit.diff.DefaultNodeMatcher;
|
||||
import org.xmlunit.diff.Diff;
|
||||
import org.xmlunit.diff.ElementSelectors;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.parser.FooMessageHeaderWithExplicitField.FooMessageSourceComponent;
|
||||
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
|
||||
import ca.uhn.fhir.parser.PatientWithCustomCompositeExtension.FooParentExtension;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class XmlParserDstu2_1Test {
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||
|
@ -2662,6 +2663,26 @@ public class XmlParserDstu2_1Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newXmlParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map.Entry;
|
|||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -162,7 +163,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
|
||||
retVal.setPublisher(myPublisher);
|
||||
retVal.setDate(conformanceDate());
|
||||
retVal.setFhirVersion("1.0.2"); // TODO: pull from model
|
||||
retVal.setFhirVersion(FhirVersionEnum.DSTU2.getFhirVersionString());
|
||||
retVal.setAcceptUnknown(UnknownContentCodeEnum.UNKNOWN_EXTENSIONS); // TODO: make this configurable - this is a fairly big effort since the parser
|
||||
// needs to be modified to actually allow it
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public class BaseResourceReferenceDtTest {
|
|||
new ResourceReferenceDt("http://foo/123123").loadResource(client);
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Unknown resource name \"foo\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage());
|
||||
assertEquals("Unknown resource name \"123123\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Created by Sébastien Rivière 12/04/2017
|
||||
|
@ -16,7 +17,7 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
public class ElementWithExtensionDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu2Test.class);
|
||||
private static FhirContext ctx = FhirContext.forDstu2();
|
||||
private final FhirContext ctx = FhirContext.forDstu2();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
|
@ -24,13 +25,42 @@ public class ElementWithExtensionDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testExtensionOnPrimitiveExtensionJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final HumanNameDt name = patient.getNameFirstRep();
|
||||
name.addFamily(new StringDt("family"));
|
||||
name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
|
||||
|
||||
final StringDt stringExt = new StringDt();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
|
||||
final ExtensionDt ext = new ExtensionDt();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addUndeclaredExtension(ext);
|
||||
|
||||
|
||||
patient.setPetName(new StringDt("myPet"));
|
||||
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyFirstRep().getUndeclaredExtensions().size());
|
||||
assertEquals(1, ((StringDt) patient.getUndeclaredExtensionsByUrl("/myExt").get(0).getValue()).getUndeclaredExtensions().size());
|
||||
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnPrimitiveExtensionWithNullValueJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
@ -39,13 +69,44 @@ public class ElementWithExtensionDstu2Test {
|
|||
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExtensionOnPrimitiveExtensionXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
|
||||
final HumanNameDt name = patient.getNameFirstRep();
|
||||
name.addFamily(new StringDt("family"));
|
||||
name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
|
||||
|
||||
final StringDt stringExt = new StringDt();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
|
||||
final ExtensionDt ext = new ExtensionDt();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addUndeclaredExtension(ext);
|
||||
|
||||
|
||||
patient.setPetName(new StringDt("myPet"));
|
||||
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyFirstRep().getUndeclaredExtensions().size());
|
||||
assertEquals(1, ((StringDt) patient.getUndeclaredExtensionsByUrl("/myExt").get(0).getValue()).getUndeclaredExtensions().size());
|
||||
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnPrimitiveExtensionWithNullValueXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
@ -55,13 +116,11 @@ public class ElementWithExtensionDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testExtensionOnIDDatatypeJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
@ -70,14 +129,14 @@ public class ElementWithExtensionDstu2Test {
|
|||
assertEquals(1, patient.getId().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testExtensionOnIDDatatypeXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
@ -87,13 +146,26 @@ public class ElementWithExtensionDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testExtensionOnIDDatatypeExtensionJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.setCustomId(new IdDt("3"));
|
||||
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnIDDatatypeExtensionNullValueJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
@ -103,13 +175,26 @@ public class ElementWithExtensionDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testExtensionOnIDDatatypeExtensionXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.setCustomId(new IdDt("4"));
|
||||
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnIDDatatypeExtensionNullValueXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
parser.setServerBaseUrl("http://foo");
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
|
|
@ -1948,4 +1948,24 @@ public class JsonParserDstu2Test {
|
|||
assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addUndeclaredExtension(false, "x1").setValue(new ResourceReferenceDt(refVal));
|
||||
|
||||
IParser parser = ourCtx.newJsonParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<ExtensionDt> extlst = fhirPat.getUndeclaredExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((ResourceReferenceDt) extlst.get(0).getValue()).getReference().getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hamcrest.text.StringContainsInOrder;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
@ -2790,6 +2791,26 @@ public class XmlParserDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addUndeclaredExtension(false, "x1").setValue(new ResourceReferenceDt(refVal));
|
||||
|
||||
IParser parser = ourCtx.newXmlParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<ExtensionDt> extlst = fhirPat.getUndeclaredExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((ResourceReferenceDt) extlst.get(0).getValue()).getReference().getValue());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -68,7 +68,7 @@ public class ClientServerValidationDstu2Test {
|
|||
@Test
|
||||
public void testClientUsesInterceptors() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.5.0");
|
||||
conf.setFhirVersion("1.0.2");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -110,7 +110,7 @@ public class ClientServerValidationDstu2Test {
|
|||
@Test
|
||||
public void testForceConformanceCheck() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.5.0");
|
||||
conf.setFhirVersion("1.0.2");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -254,6 +254,44 @@ public class ClientServerValidationDstu2Test {
|
|||
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("1.0.2");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
if (myFirstResponse) {
|
||||
myFirstResponse = false;
|
||||
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
|
||||
} else {
|
||||
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
// don't load the conformance until the first time the client is actually used
|
||||
assertTrue(myFirstResponse);
|
||||
client.read(new UriDt("http://foo/Patient/123"));
|
||||
assertFalse(myFirstResponse);
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
|
||||
|
||||
// Conformance only loaded once, then 3 reads
|
||||
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsWrongVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
|
|
|
@ -351,11 +351,16 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
if (b.length() > 0 && isNotBlank(myUnqualifiedId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedId)) {
|
||||
b.append(myUnqualifiedId);
|
||||
} else if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append("_history");
|
||||
|
@ -431,7 +436,7 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isBlank(getValue());
|
||||
return super.isEmpty() && isBlank(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -546,8 +551,22 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
int typeIndex = theValue.lastIndexOf('/', idIndex - 1);
|
||||
if (typeIndex == -1) {
|
||||
myResourceType = theValue.substring(0, idIndex);
|
||||
} else {
|
||||
if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) {
|
||||
typeIndex = theValue.indexOf('/', typeIndex + 1);
|
||||
}
|
||||
if (typeIndex >= idIndex) {
|
||||
// e.g. http://example.org/foo
|
||||
// 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id.
|
||||
// Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly
|
||||
// recreate the url
|
||||
myResourceType = myUnqualifiedId;
|
||||
myUnqualifiedId = null;
|
||||
super.setValue(null);
|
||||
myHaveComponentParts = true;
|
||||
} else {
|
||||
myResourceType = theValue.substring(typeIndex + 1, idIndex);
|
||||
}
|
||||
|
||||
if (typeIndex > 4) {
|
||||
myBaseUrl = theValue.substring(0, typeIndex);
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.DomainResource;
|
||||
import org.hl7.fhir.dstu3.model.Narrative;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.junit.AfterClass;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class MinimizeResources {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MinimizeResources.class);
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
|
||||
Collection<File> xml = FileUtils.listFiles(new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/profile"), new String[] {"xml"}, false);
|
||||
for (File next : xml) {
|
||||
ourLog.info("Checking: {}", next.getAbsoluteFile());
|
||||
|
||||
String inputFile = IOUtils.toString(new FileReader(next));
|
||||
Bundle bundle = (Bundle) ourCtx.newXmlParser().parseResource(inputFile);
|
||||
for (BundleEntryComponent nextEntry : bundle.getEntry()) {
|
||||
Resource resource;
|
||||
resource = nextEntry.getResource();
|
||||
if (resource instanceof DomainResource) {
|
||||
((DomainResource) resource).setText(new Narrative());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(bundle);
|
||||
if (!output.equals(inputFile)) {
|
||||
ourLog.info("Rewriting {}", next.getAbsolutePath());
|
||||
|
||||
FileWriter writer = new FileWriter(next, false);
|
||||
writer.append(output);
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -92,6 +92,38 @@ public class IdTypeDstu3Test {
|
|||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo1() {
|
||||
IdType id = new IdType("http://my.org/foo");
|
||||
assertEquals("http://my.org/foo", id.getValueAsString());
|
||||
assertEquals(null, id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("foo", id.getResourceType());
|
||||
assertEquals("http://my.org", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo2() {
|
||||
IdType id = new IdType("http://my.org/a/b/c/foo");
|
||||
assertEquals("http://my.org/a/b/c/foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("c/foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("c", id.getResourceType());
|
||||
assertEquals("http://my.org/a/b", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectLocal() {
|
||||
IdType id;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Created by Sébastien Rivière 12/04/2017
|
||||
|
@ -16,7 +16,7 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
public class ElementWithExtensionDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu3Test.class);
|
||||
private static final FhirContext ctx = FhirContext.forDstu3();
|
||||
private final FhirContext ctx = FhirContext.forDstu3();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
|
@ -24,11 +24,43 @@ public class ElementWithExtensionDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorPrimitiveExtensionJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final HumanName name = patient.getNameFirstRep();
|
||||
name.setFamily("family");
|
||||
name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
patient.setPetName(new StringType("myPet"));
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final StringType stringExt = new StringType();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final Extension ext = new Extension();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addExtension(ext);
|
||||
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
|
||||
assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionNullValueJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
|
@ -39,11 +71,45 @@ public class ElementWithExtensionDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorPrimitiveExtensionXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final HumanName name = patient.getNameFirstRep();
|
||||
name.setFamily("family");
|
||||
name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
patient.setPetName(new StringType("myPet"));
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final StringType stringExt = new StringType();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final Extension ext = new Extension();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addExtension(ext);
|
||||
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
|
||||
assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionNullValueXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
|
@ -53,8 +119,8 @@ public class ElementWithExtensionDstu3Test {
|
|||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorIDDatatypeJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
|
@ -69,7 +135,6 @@ public class ElementWithExtensionDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorIDDatatypeXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
|
@ -84,10 +149,10 @@ public class ElementWithExtensionDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorExtensionIDDatatypeJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.setCustomId(new IdType(("4")));
|
||||
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
@ -99,12 +164,13 @@ public class ElementWithExtensionDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullFlavorExtensionIDDatatypeXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
|
||||
patient.setCustomId(new IdType(("4")));
|
||||
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
@ -112,5 +178,48 @@ public class ElementWithExtensionDstu3Test {
|
|||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getCustomId().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnResourceIdXml(){
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.getIdElement().setValue("123");
|
||||
p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO"));
|
||||
|
||||
IParser parser = ctx.newXmlParser();
|
||||
String encoded = parser.encodeResourceToString(p);
|
||||
assertThat(encoded, containsString("http://foo"));
|
||||
assertThat(encoded, containsString("FOO"));
|
||||
|
||||
p = (Patient) parser.parseResource(encoded);
|
||||
assertEquals("Patient/123", p.getId());
|
||||
Extension ex = p.getIdElement().getExtension().get(0);
|
||||
assertEquals("http://foo", ex.getUrl());
|
||||
assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnResourceIdJson(){
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.getIdElement().setValue("123");
|
||||
p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO"));
|
||||
|
||||
IParser parser = ctx.newJsonParser();
|
||||
String encoded = parser.encodeResourceToString(p);
|
||||
assertThat(encoded, containsString("http://foo"));
|
||||
assertThat(encoded, containsString("FOO"));
|
||||
|
||||
p = (Patient) parser.parseResource(encoded);
|
||||
assertEquals("Patient/123", p.getId());
|
||||
Extension ex = p.getIdElement().getExtension().get(0);
|
||||
assertEquals("http://foo", ex.getUrl());
|
||||
assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2414,6 +2414,26 @@ public class JsonParserDstu3Test {
|
|||
assertTrue(result.isSuccessful());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newJsonParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -36,7 +36,7 @@ public class MyPatientWithCustomUrlExtension extends Patient {
|
|||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return super.isEmpty() && myPetName.isEmpty();
|
||||
return super.isEmpty() && getCustomId().isEmpty() && getPetName().isEmpty();
|
||||
}
|
||||
|
||||
public IdType getCustomId() {
|
||||
|
|
|
@ -3334,6 +3334,26 @@ public class XmlParserDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newXmlParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtensionsByUrl("x1");
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.jar.Manifest;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.*;
|
||||
import org.hl7.fhir.instance.model.Conformance.*;
|
||||
|
@ -158,7 +159,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
|
||||
retVal.setPublisher(myPublisher);
|
||||
retVal.setDate(conformanceDate());
|
||||
retVal.setFhirVersion("1.0.2"); // TODO: pull from model
|
||||
retVal.setFhirVersion(FhirVersionEnum.DSTU2_HL7ORG.getFhirVersionString());
|
||||
retVal.setAcceptUnknown(UnknownContentCode.EXTENSIONS); // TODO: make this configurable - this is a fairly big effort since the parser
|
||||
// needs to be modified to actually allow it
|
||||
|
||||
|
|
|
@ -380,11 +380,16 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
if (b.length() > 0 && isNotBlank(myUnqualifiedId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedId)) {
|
||||
b.append(myUnqualifiedId);
|
||||
} else if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append("_history");
|
||||
|
@ -570,8 +575,22 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||
int typeIndex = theValue.lastIndexOf('/', idIndex - 1);
|
||||
if (typeIndex == -1) {
|
||||
myResourceType = theValue.substring(0, idIndex);
|
||||
} else {
|
||||
if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) {
|
||||
typeIndex = theValue.indexOf('/', typeIndex + 1);
|
||||
}
|
||||
if (typeIndex >= idIndex) {
|
||||
// e.g. http://example.org/foo
|
||||
// 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id.
|
||||
// Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly
|
||||
// recreate the url
|
||||
myResourceType = myUnqualifiedId;
|
||||
myUnqualifiedId = null;
|
||||
super.setValue(null);
|
||||
myHaveComponentParts = true;
|
||||
} else {
|
||||
myResourceType = theValue.substring(typeIndex + 1, idIndex);
|
||||
}
|
||||
|
||||
if (typeIndex > 4) {
|
||||
myBaseUrl = theValue.substring(0, typeIndex);
|
||||
|
|
|
@ -84,6 +84,54 @@ public class IdTypeTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormal() {
|
||||
IdType id = new IdType("foo");
|
||||
assertEquals("foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals(null, id.getResourceType());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo1() {
|
||||
IdType id = new IdType("http://my.org/foo");
|
||||
assertEquals("http://my.org/foo", id.getValueAsString());
|
||||
assertEquals(null, id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("foo", id.getResourceType());
|
||||
assertEquals("http://my.org", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo2() {
|
||||
IdType id = new IdType("http://my.org/a/b/c/foo");
|
||||
assertEquals("http://my.org/a/b/c/foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("c/foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("c", id.getResourceType());
|
||||
assertEquals("http://my.org/a/b", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetermineBase() {
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import net.sf.json.JSON;
|
||||
import net.sf.json.JSONSerializer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.core.IsNot;
|
||||
import org.hamcrest.core.StringContains;
|
||||
|
@ -22,19 +22,23 @@ import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
|
|||
import org.hl7.fhir.instance.model.Patient.ContactComponent;
|
||||
import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.instance.model.ValueSet.ValueSetCodeSystemComponent;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.INarrative;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.junit.*;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import net.sf.json.JSON;
|
||||
import net.sf.json.JSONSerializer;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class JsonParserHl7OrgDstu2Test {
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
|
||||
|
@ -1274,6 +1278,26 @@ public class JsonParserHl7OrgDstu2Test {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newJsonParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtension();
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
@ResourceDef(name = "Patient")
|
||||
public static class MyPatientWithOneDeclaredAddressExtension extends Patient {
|
||||
|
||||
|
|
|
@ -21,6 +21,24 @@ import org.hl7.fhir.instance.model.Identifier.IdentifierUse;
|
|||
import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.junit.*;
|
||||
import org.hl7.fhir.instance.model.Observation;
|
||||
import org.hl7.fhir.instance.model.Organization;
|
||||
import org.hl7.fhir.instance.model.Patient;
|
||||
import org.hl7.fhir.instance.model.PrimitiveType;
|
||||
import org.hl7.fhir.instance.model.Reference;
|
||||
import org.hl7.fhir.instance.model.Resource;
|
||||
import org.hl7.fhir.instance.model.SimpleQuantity;
|
||||
import org.hl7.fhir.instance.model.Specimen;
|
||||
import org.hl7.fhir.instance.model.StringType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.INarrative;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xmlunit.builder.DiffBuilder;
|
||||
import org.xmlunit.builder.Input;
|
||||
|
@ -1738,6 +1756,26 @@ public class XmlParserHl7OrgDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
|
||||
String refVal = "http://my.org/FooBar";
|
||||
|
||||
Patient fhirPat = new Patient();
|
||||
fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
|
||||
|
||||
IParser parser = ourCtx.newXmlParser();
|
||||
|
||||
String output = parser.encodeResourceToString(fhirPat);
|
||||
System.out.println("output: " + output);
|
||||
|
||||
// Deserialize then check that valueReference value is still correct
|
||||
fhirPat = parser.parseResource(Patient.class, output);
|
||||
|
||||
List<Extension> extlst = fhirPat.getExtension();
|
||||
Assert.assertEquals(1, extlst.size());
|
||||
Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu2Hl7Org();
|
||||
|
|
|
@ -57,46 +57,9 @@ public class ClientServerValidationTestHl7OrgDstu2 {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
|
||||
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.5.0");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
if (myFirstResponse) {
|
||||
myFirstResponse=false;
|
||||
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
|
||||
} else {
|
||||
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
|
||||
}
|
||||
}});
|
||||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
// don't load the conformance until the first time the client is actually used
|
||||
assertTrue(myFirstResponse);
|
||||
client.read(new UriDt("http://foo/Patient/123"));
|
||||
assertFalse(myFirstResponse);
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
|
||||
|
||||
// Conformance only loaded once, then 3 reads
|
||||
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsAppropriateVersionForDstu2_050() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.5.0");
|
||||
conf.setFhirVersion("1.0.2");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -133,7 +96,7 @@ public class ClientServerValidationTestHl7OrgDstu2 {
|
|||
@Test
|
||||
public void testServerReturnsWrongVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.80");
|
||||
conf.setFhirVersion("0.0.82");
|
||||
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -150,7 +113,7 @@ public class ClientServerValidationTestHl7OrgDstu2 {
|
|||
fail();
|
||||
} catch (FhirClientInappropriateForServerException e) {
|
||||
String out = e.toString();
|
||||
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.80\" which corresponds to DSTU1, but this client is configured to use DSTU2_HL7ORG (via the FhirContext)";
|
||||
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.0.82\" which corresponds to DSTU1, but this client is configured to use DSTU2_HL7ORG (via the FhirContext)";
|
||||
ourLog.info(out);
|
||||
ourLog.info(want);
|
||||
assertThat(out, containsString(want));
|
||||
|
|
|
@ -70,89 +70,89 @@ import org.hl7.fhir.instance.model.api.*;
|
|||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/**
|
||||
* This class represents the logical identity for a resource, or as much of that
|
||||
* identity is known. In FHIR, every resource must have a "logical ID" which is
|
||||
* defined by the FHIR specification as:
|
||||
* <p>
|
||||
* <code>A whole number in the range 0 to 2^64-1 (optionally represented in hex),
|
||||
* a uuid, an oid, or any other combination of lowercase letters, numerals, "-"
|
||||
* and ".", with a length limit of 36 characters</code>
|
||||
* </p>
|
||||
* <p>
|
||||
* This class contains that logical ID, and can optionally also contain a
|
||||
* relative or absolute URL representing the resource identity. For example, the
|
||||
* following are all valid values for IdType, and all might represent the same
|
||||
* resource:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li><code>123</code> (just a resource's ID)</li>
|
||||
* <li><code>Patient/123</code> (a relative identity)</li>
|
||||
* <li><code>http://example.com/Patient/123 (an absolute identity)</code></li>
|
||||
* <li>
|
||||
* <code>http://example.com/Patient/123/_history/1 (an absolute identity with a version id)</code>
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>Patient/123/_history/1 (a relative identity with a version id)</code>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In most situations, you only need to populate the resource's ID (e.g.
|
||||
* <code>123</code>) in resources you are constructing and the encoder will
|
||||
* infer the rest from the context in which the object is being used. On the
|
||||
* other hand, the parser will always try to populate the complete absolute
|
||||
* identity on objects it creates as a convenience.
|
||||
* </p>
|
||||
* <p>
|
||||
* Regex for ID: [a-z0-9\-\.]{1,36}
|
||||
* </p>
|
||||
*/
|
||||
@DatatypeDef(name = "id", profileOf=StringType.class)
|
||||
* This class represents the logical identity for a resource, or as much of that
|
||||
* identity is known. In FHIR, every resource must have a "logical ID" which is
|
||||
* defined by the FHIR specification as:
|
||||
* <p>
|
||||
* <code>A whole number in the range 0 to 2^64-1 (optionally represented in hex),
|
||||
* a uuid, an oid, or any other combination of lowercase letters, numerals, "-"
|
||||
* and ".", with a length limit of 36 characters</code>
|
||||
* </p>
|
||||
* <p>
|
||||
* This class contains that logical ID, and can optionally also contain a
|
||||
* relative or absolute URL representing the resource identity. For example, the
|
||||
* following are all valid values for IdType, and all might represent the same
|
||||
* resource:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li><code>123</code> (just a resource's ID)</li>
|
||||
* <li><code>Patient/123</code> (a relative identity)</li>
|
||||
* <li><code>http://example.com/Patient/123 (an absolute identity)</code></li>
|
||||
* <li>
|
||||
* <code>http://example.com/Patient/123/_history/1 (an absolute identity with a version id)</code>
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>Patient/123/_history/1 (a relative identity with a version id)</code>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In most situations, you only need to populate the resource's ID (e.g.
|
||||
* <code>123</code>) in resources you are constructing and the encoder will
|
||||
* infer the rest from the context in which the object is being used. On the
|
||||
* other hand, the parser will always try to populate the complete absolute
|
||||
* identity on objects it creates as a convenience.
|
||||
* </p>
|
||||
* <p>
|
||||
* Regex for ID: [a-z0-9\-\.]{1,36}
|
||||
* </p>
|
||||
*/
|
||||
@DatatypeDef(name = "id", profileOf = StringType.class)
|
||||
public final class IdType extends UriType implements IPrimitiveType<String>, IIdType {
|
||||
public static final String URN_PREFIX = "urn:";
|
||||
public static final String URN_PREFIX = "urn:";
|
||||
|
||||
/**
|
||||
/**
|
||||
* This is the maximum length for the ID
|
||||
*/
|
||||
public static final int MAX_LENGTH = 64; // maximum length
|
||||
public static final int MAX_LENGTH = 64; // maximum length
|
||||
|
||||
private static final long serialVersionUID = 2L;
|
||||
private String myBaseUrl;
|
||||
private boolean myHaveComponentParts;
|
||||
private String myResourceType;
|
||||
private String myUnqualifiedId;
|
||||
private String myUnqualifiedVersionId;
|
||||
private static final long serialVersionUID = 2L;
|
||||
private String myBaseUrl;
|
||||
private boolean myHaveComponentParts;
|
||||
private String myResourceType;
|
||||
private String myUnqualifiedId;
|
||||
private String myUnqualifiedVersionId;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Create a new empty ID
|
||||
*/
|
||||
public IdType() {
|
||||
public IdType() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Create a new ID, using a BigDecimal input. Uses
|
||||
* {@link BigDecimal#toPlainString()} to generate the string representation.
|
||||
*/
|
||||
public IdType(BigDecimal thePid) {
|
||||
public IdType(BigDecimal thePid) {
|
||||
if (thePid != null) {
|
||||
setValue(toPlainStringWithNpeThrowIfNeeded(thePid));
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Create a new ID using a long
|
||||
*/
|
||||
public IdType(long theId) {
|
||||
public IdType(long theId) {
|
||||
setValue(Long.toString(theId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Create a new ID using a string. This String may contain a simple ID (e.g.
|
||||
* "1234") or it may contain a complete URL
|
||||
* (http://example.com/fhir/Patient/1234).
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally
|
||||
* represented in hex), a uuid, an oid, or any other combination of lowercase
|
||||
|
@ -162,73 +162,60 @@ public IdType(long theId) {
|
|||
* regex: [a-z0-9\-\.]{1,36}
|
||||
* </p>
|
||||
*/
|
||||
public IdType(String theValue) {
|
||||
public IdType(String theValue) {
|
||||
setValue(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theIdPart
|
||||
* The ID (e.g. "123")
|
||||
* @param theResourceType The resource type (e.g. "Patient")
|
||||
* @param theIdPart The ID (e.g. "123")
|
||||
*/
|
||||
public IdType(String theResourceType, BigDecimal theIdPart) {
|
||||
public IdType(String theResourceType, BigDecimal theIdPart) {
|
||||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theIdPart
|
||||
* The ID (e.g. "123")
|
||||
* @param theResourceType The resource type (e.g. "Patient")
|
||||
* @param theIdPart The ID (e.g. "123")
|
||||
*/
|
||||
public IdType(String theResourceType, Long theIdPart) {
|
||||
public IdType(String theResourceType, Long theIdPart) {
|
||||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theId
|
||||
* The ID (e.g. "123")
|
||||
* @param theResourceType The resource type (e.g. "Patient")
|
||||
* @param theId The ID (e.g. "123")
|
||||
*/
|
||||
public IdType(String theResourceType, String theId) {
|
||||
public IdType(String theResourceType, String theId) {
|
||||
this(theResourceType, theId, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theId
|
||||
* The ID (e.g. "123")
|
||||
* @param theVersionId
|
||||
* The version ID ("e.g. "456")
|
||||
* @param theResourceType The resource type (e.g. "Patient")
|
||||
* @param theId The ID (e.g. "123")
|
||||
* @param theVersionId The version ID ("e.g. "456")
|
||||
*/
|
||||
public IdType(String theResourceType, String theId, String theVersionId) {
|
||||
public IdType(String theResourceType, String theId, String theVersionId) {
|
||||
this(null, theResourceType, theId, theVersionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theBaseUrl
|
||||
* The server base URL (e.g. "http://example.com/fhir")
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theId
|
||||
* The ID (e.g. "123")
|
||||
* @param theVersionId
|
||||
* The version ID ("e.g. "456")
|
||||
* @param theBaseUrl The server base URL (e.g. "http://example.com/fhir")
|
||||
* @param theResourceType The resource type (e.g. "Patient")
|
||||
* @param theId The ID (e.g. "123")
|
||||
* @param theVersionId The version ID ("e.g. "456")
|
||||
*/
|
||||
public IdType(String theBaseUrl, String theResourceType, String theId, String theVersionId) {
|
||||
public IdType(String theBaseUrl, String theResourceType, String theId, String theVersionId) {
|
||||
myBaseUrl = theBaseUrl;
|
||||
myResourceType = theResourceType;
|
||||
myUnqualifiedId = theId;
|
||||
|
@ -237,51 +224,51 @@ public IdType(String theBaseUrl, String theResourceType, String theId, String th
|
|||
if (isBlank(myBaseUrl) && isBlank(myResourceType) && isBlank(myUnqualifiedId) && isBlank(myUnqualifiedVersionId)) {
|
||||
myHaveComponentParts = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates an ID based on a given URL
|
||||
*/
|
||||
public IdType(UriType theUrl) {
|
||||
public IdType(UriType theUrl) {
|
||||
setValue(theUrl.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public void applyTo(IBaseResource theResouce) {
|
||||
public void applyTo(IBaseResource theResouce) {
|
||||
if (theResouce == null) {
|
||||
throw new NullPointerException("theResource can not be null");
|
||||
} else {
|
||||
theResouce.setId(new IdType(getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead (this method was
|
||||
* deprocated because its name is ambiguous)
|
||||
*/
|
||||
@Deprecated
|
||||
public BigDecimal asBigDecimal() {
|
||||
@Deprecated
|
||||
public BigDecimal asBigDecimal() {
|
||||
return getIdPartAsBigDecimal();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdType copy() {
|
||||
@Override
|
||||
public IdType copy() {
|
||||
return new IdType(getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theArg0) {
|
||||
@Override
|
||||
public boolean equals(Object theArg0) {
|
||||
if (!(theArg0 instanceof IdType)) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.equals(getValueAsString(), ((IdType)theArg0).getValueAsString());
|
||||
}
|
||||
return StringUtils.equals(getValueAsString(), ((IdType) theArg0).getValueAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns true if this IdType matches the given IdType in terms of resource
|
||||
* type and ID, but ignores the URL base
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean equalsIgnoreBase(IdType theId) {
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean equalsIgnoreBase(IdType theId) {
|
||||
if (theId == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -291,9 +278,9 @@ public boolean equalsIgnoreBase(IdType theId) {
|
|||
return ObjectUtils.equals(getResourceType(), theId.getResourceType())
|
||||
&& ObjectUtils.equals(getIdPart(), theId.getIdPart())
|
||||
&& ObjectUtils.equals(getVersionIdPart(), theId.getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the portion of this resource ID which corresponds to the server
|
||||
* base URL. For example given the resource ID
|
||||
* <code>http://example.com/fhir/Patient/123</code> the base URL would be
|
||||
|
@ -302,66 +289,64 @@ public boolean equalsIgnoreBase(IdType theId) {
|
|||
* This method may return null if the ID contains no base (e.g. "Patient/123")
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
return myBaseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns only the logical ID part of this ID. For example, given the ID
|
||||
* "http://example,.com/fhir/Patient/123/_history/456", this method would
|
||||
* return "123".
|
||||
*/
|
||||
@Override
|
||||
public String getIdPart() {
|
||||
@Override
|
||||
public String getIdPart() {
|
||||
return myUnqualifiedId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the unqualified portion of this ID as a big decimal, or
|
||||
* <code>null</code> if the value is null
|
||||
*
|
||||
* @throws NumberFormatException
|
||||
* If the value is not a valid BigDecimal
|
||||
* @throws NumberFormatException If the value is not a valid BigDecimal
|
||||
*/
|
||||
public BigDecimal getIdPartAsBigDecimal() {
|
||||
public BigDecimal getIdPartAsBigDecimal() {
|
||||
String val = getIdPart();
|
||||
if (isBlank(val)) {
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the unqualified portion of this ID as a {@link Long}, or
|
||||
* <code>null</code> if the value is null
|
||||
*
|
||||
* @throws NumberFormatException
|
||||
* If the value is not a valid Long
|
||||
* @throws NumberFormatException If the value is not a valid Long
|
||||
*/
|
||||
@Override
|
||||
public Long getIdPartAsLong() {
|
||||
@Override
|
||||
public Long getIdPartAsLong() {
|
||||
String val = getIdPart();
|
||||
if (isBlank(val)) {
|
||||
return null;
|
||||
}
|
||||
return Long.parseLong(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceType() {
|
||||
@Override
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the value of this ID. Note that this value may be a fully qualified
|
||||
* URL, a relative/partial URL, or a simple ID. Use {@link #getIdPart()} to
|
||||
* get just the ID portion.
|
||||
*
|
||||
* @see #getIdPart()
|
||||
*/
|
||||
@Override
|
||||
public String getValue() {
|
||||
@Override
|
||||
public String getValue() {
|
||||
String retVal = super.getValue();
|
||||
if (retVal == null && myHaveComponentParts) {
|
||||
|
||||
|
@ -381,11 +366,16 @@ public String getValue() {
|
|||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
if (b.length() > 0 && isNotBlank(myUnqualifiedId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedId)) {
|
||||
b.append(myUnqualifiedId);
|
||||
} else if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append("_history");
|
||||
|
@ -396,76 +386,76 @@ public String getValue() {
|
|||
super.setValue(retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsString() {
|
||||
@Override
|
||||
public String getValueAsString() {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersionIdPart() {
|
||||
@Override
|
||||
public String getVersionIdPart() {
|
||||
return myUnqualifiedVersionId;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getVersionIdPartAsLong() {
|
||||
public Long getVersionIdPartAsLong() {
|
||||
if (!hasVersionIdPart()) {
|
||||
return null;
|
||||
} else {
|
||||
return Long.parseLong(getVersionIdPart());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns true if this ID has a base url
|
||||
*
|
||||
* @see #getBaseUrl()
|
||||
*/
|
||||
public boolean hasBaseUrl() {
|
||||
public boolean hasBaseUrl() {
|
||||
return isNotBlank(myBaseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
HashCodeBuilder b = new HashCodeBuilder();
|
||||
b.append(getValueAsString());
|
||||
return b.toHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIdPart() {
|
||||
@Override
|
||||
public boolean hasIdPart() {
|
||||
return isNotBlank(getIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasResourceType() {
|
||||
@Override
|
||||
public boolean hasResourceType() {
|
||||
return isNotBlank(myResourceType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVersionIdPart() {
|
||||
@Override
|
||||
public boolean hasVersionIdPart() {
|
||||
return isNotBlank(getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an absolute URL (in other
|
||||
* words, a URL starting with "http://" or "https://"
|
||||
*/
|
||||
@Override
|
||||
public boolean isAbsolute() {
|
||||
@Override
|
||||
public boolean isAbsolute() {
|
||||
if (StringUtils.isBlank(getValue())) {
|
||||
return false;
|
||||
}
|
||||
return isUrlAbsolute(getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isBlank(getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdPartValid() {
|
||||
@Override
|
||||
public boolean isIdPartValid() {
|
||||
String id = getIdPart();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
return false;
|
||||
|
@ -490,38 +480,38 @@ public boolean isIdPartValid() {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the unqualified ID is a valid {@link Long}
|
||||
* value (in other words, it consists only of digits)
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdPartValidLong() {
|
||||
@Override
|
||||
public boolean isIdPartValidLong() {
|
||||
return isValidLong(getIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns <code>true</code> if the ID is a local reference (in other words,
|
||||
* it begins with the '#' character)
|
||||
*/
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return defaultString(myUnqualifiedId).startsWith("#");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUrn() {
|
||||
public boolean isUrn() {
|
||||
return defaultString(myUnqualifiedId).startsWith(URN_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionIdPartValidLong() {
|
||||
@Override
|
||||
public boolean isVersionIdPartValidLong() {
|
||||
return isValidLong(getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the value
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally
|
||||
* represented in hex), a uuid, an oid, or any other combination of lowercase
|
||||
|
@ -531,8 +521,8 @@ public boolean isVersionIdPartValidLong() {
|
|||
* regex: [a-z0-9\-\.]{1,36}
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public IdType setValue(String theValue) {
|
||||
@Override
|
||||
public IdType setValue(String theValue) {
|
||||
// TODO: add validation
|
||||
super.setValue(theValue);
|
||||
myHaveComponentParts = false;
|
||||
|
@ -576,8 +566,22 @@ public IdType setValue(String theValue) {
|
|||
int typeIndex = theValue.lastIndexOf('/', idIndex - 1);
|
||||
if (typeIndex == -1) {
|
||||
myResourceType = theValue.substring(0, idIndex);
|
||||
} else {
|
||||
if (typeIndex > 0 && '/' == theValue.charAt(typeIndex - 1)) {
|
||||
typeIndex = theValue.indexOf('/', typeIndex + 1);
|
||||
}
|
||||
if (typeIndex >= idIndex) {
|
||||
// e.g. http://example.org/foo
|
||||
// 'foo' was the id but we're making that the resource type. Nullify the id part because we don't have an id.
|
||||
// Also set null value to the super.setValue() and enable myHaveComponentParts so it forces getValue() to properly
|
||||
// recreate the url
|
||||
myResourceType = myUnqualifiedId;
|
||||
myUnqualifiedId = null;
|
||||
super.setValue(null);
|
||||
myHaveComponentParts = true;
|
||||
} else {
|
||||
myResourceType = theValue.substring(typeIndex + 1, idIndex);
|
||||
}
|
||||
|
||||
if (typeIndex > 4) {
|
||||
myBaseUrl = theValue.substring(0, typeIndex);
|
||||
|
@ -588,11 +592,11 @@ public IdType setValue(String theValue) {
|
|||
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the value
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally
|
||||
* represented in hex), a uuid, an oid, or any other combination of lowercase
|
||||
|
@ -602,87 +606,84 @@ public IdType setValue(String theValue) {
|
|||
* regex: [a-z0-9\-\.]{1,36}
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsString(String theValue) {
|
||||
@Override
|
||||
public void setValueAsString(String theValue) {
|
||||
setValue(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns a new IdType containing this IdType's values but with no server
|
||||
* base URL if one is present in this IdType. For example, if this IdType
|
||||
* contains the ID "http://foo/Patient/1", this method will return a new
|
||||
* IdType containing ID "Patient/1".
|
||||
*/
|
||||
@Override
|
||||
public IdType toUnqualified() {
|
||||
@Override
|
||||
public IdType toUnqualified() {
|
||||
if (isLocal() || isUrn()) {
|
||||
return new IdType(getValueAsString());
|
||||
}
|
||||
return new IdType(getResourceType(), getIdPart(), getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdType toUnqualifiedVersionless() {
|
||||
@Override
|
||||
public IdType toUnqualifiedVersionless() {
|
||||
if (isLocal() || isUrn()) {
|
||||
return new IdType(getValueAsString());
|
||||
}
|
||||
return new IdType(getResourceType(), getIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdType toVersionless() {
|
||||
@Override
|
||||
public IdType toVersionless() {
|
||||
if (isLocal() || isUrn()) {
|
||||
return new IdType(getValueAsString());
|
||||
}
|
||||
return new IdType(getBaseUrl(), getResourceType(), getIdPart(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdType withResourceType(String theResourceName) {
|
||||
@Override
|
||||
public IdType withResourceType(String theResourceName) {
|
||||
if (isLocal() || isUrn()) {
|
||||
return new IdType(getValueAsString());
|
||||
}
|
||||
return new IdType(theResourceName, getIdPart(), getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns a view of this ID as a fully qualified URL, given a server base and
|
||||
* resource name (which will only be used if the ID does not already contain
|
||||
* those respective parts). Essentially, because IdType can contain either a
|
||||
* complete URL or a partial one (or even jut a simple ID), this method may be
|
||||
* used to translate into a complete URL.
|
||||
*
|
||||
* @param theServerBase
|
||||
* The server base (e.g. "http://example.com/fhir")
|
||||
* @param theResourceType
|
||||
* The resource name (e.g. "Patient")
|
||||
* @param theServerBase The server base (e.g. "http://example.com/fhir")
|
||||
* @param theResourceType The resource name (e.g. "Patient")
|
||||
* @return A fully qualified URL for this ID (e.g.
|
||||
* "http://example.com/fhir/Patient/1")
|
||||
*/
|
||||
@Override
|
||||
public IdType withServerBase(String theServerBase, String theResourceType) {
|
||||
@Override
|
||||
public IdType withServerBase(String theServerBase, String theResourceType) {
|
||||
if (isLocal() || isUrn()) {
|
||||
return new IdType(getValueAsString());
|
||||
}
|
||||
return new IdType(theServerBase, theResourceType, getIdPart(), getVersionIdPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a new instance of this ID which is identical, but refers to the
|
||||
* specific version of this resource ID noted by theVersion.
|
||||
*
|
||||
* @param theVersion
|
||||
* The actual version string, e.g. "1"
|
||||
* @param theVersion The actual version string, e.g. "1"
|
||||
* @return A new instance of IdType which is identical, but refers to the
|
||||
* specific version of this resource ID noted by theVersion.
|
||||
*/
|
||||
@Override
|
||||
public IdType withVersion(String theVersion) {
|
||||
@Override
|
||||
public IdType withVersion(String theVersion) {
|
||||
Validate.notBlank(theVersion, "Version may not be null or empty");
|
||||
|
||||
if (isLocal() || isUrn()) {
|
||||
|
@ -700,14 +701,14 @@ public IdType withVersion(String theVersion) {
|
|||
}
|
||||
|
||||
return new IdType(value + '/' + "_history" + '/' + theVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isUrlAbsolute(String theValue) {
|
||||
private static boolean isUrlAbsolute(String theValue) {
|
||||
String value = theValue.toLowerCase();
|
||||
return value.startsWith("http://") || value.startsWith("https://");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidLong(String id) {
|
||||
private static boolean isValidLong(String id) {
|
||||
if (StringUtils.isBlank(id)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -717,20 +718,20 @@ private static boolean isValidLong(String id) {
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Construct a new ID with with form "urn:uuid:[UUID]" where [UUID] is a new,
|
||||
* randomly created UUID generated by {@link UUID#randomUUID()}
|
||||
*/
|
||||
public static IdType newRandomUuid() {
|
||||
public static IdType newRandomUuid() {
|
||||
return new IdType("urn:uuid:" + UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Retrieves the ID from the given resource instance
|
||||
*/
|
||||
public static IdType of(IBaseResource theResouce) {
|
||||
public static IdType of(IBaseResource theResouce) {
|
||||
if (theResouce == null) {
|
||||
throw new NullPointerException("theResource can not be null");
|
||||
} else {
|
||||
|
@ -743,21 +744,21 @@ public static IdType of(IBaseResource theResouce) {
|
|||
return new IdType(retVal.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(BigDecimal theIdPart) {
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(BigDecimal theIdPart) {
|
||||
if (theIdPart == null) {
|
||||
throw new NullPointerException("BigDecimal ID can not be null");
|
||||
}
|
||||
return theIdPart.toPlainString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(Long theIdPart) {
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(Long theIdPart) {
|
||||
if (theIdPart == null) {
|
||||
throw new NullPointerException("Long ID can not be null");
|
||||
}
|
||||
return theIdPart.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String fhirType() {
|
||||
return "id";
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
package org.hl7.fhir.r4.model.api;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base interface for ID datatype.
|
||||
*
|
||||
* <p>
|
||||
* <b>Concrete Implementations:</b> This interface is often returned and/or accepted by methods in HAPI's API
|
||||
* where either {@link ca.uhn.fhir.model.primitive.IdDt} (the HAPI structure ID type) or
|
||||
* <code>org.hl7.fhir.instance.model.IdType</code> (the RI structure ID type) will be used, depending on
|
||||
* which version of the strctures your application is using.
|
||||
* </p>
|
||||
*/
|
||||
public interface IIdType {
|
||||
|
||||
void applyTo(IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* Returns the server base URL if this ID contains one. For example, the base URL is
|
||||
* the 'http://example.com/fhir' in the following ID: <code>http://example.com/fhir/Patient/123/_history/55</code>
|
||||
*/
|
||||
String getBaseUrl();
|
||||
|
||||
/**
|
||||
* Returns only the logical ID part of this ID. For example, given the ID
|
||||
* "http://example,.com/fhir/Patient/123/_history/456", this method would
|
||||
* return "123".
|
||||
*/
|
||||
String getIdPart();
|
||||
|
||||
/**
|
||||
* Returns the ID part of this ID (e.g. in the ID http://example.com/Patient/123/_history/456 this would be the
|
||||
* part "123") parsed as a {@link Long}.
|
||||
*
|
||||
* @throws NumberFormatException If the value can't be parsed as a long
|
||||
*/
|
||||
Long getIdPartAsLong();
|
||||
|
||||
String getResourceType();
|
||||
|
||||
/**
|
||||
* Returns the value of this ID. Note that this value may be a fully qualified URL, a relative/partial URL, or a simple ID. Use {@link #getIdPart()} to get just the ID portion.
|
||||
*
|
||||
* @see #getIdPart()
|
||||
*/
|
||||
String getValue();
|
||||
|
||||
String getVersionIdPart();
|
||||
|
||||
/**
|
||||
* Returns the version ID part of this ID (e.g. in the ID http://example.com/Patient/123/_history/456 this would be the
|
||||
* part "456") parsed as a {@link Long}.
|
||||
*
|
||||
* @throws NumberFormatException If the value can't be parsed as a long
|
||||
*/
|
||||
Long getVersionIdPartAsLong();
|
||||
|
||||
boolean hasBaseUrl();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an actual ID part. For example, the ID part is
|
||||
* the '123' in the following ID: <code>http://example.com/fhir/Patient/123/_history/55</code>
|
||||
*/
|
||||
boolean hasIdPart();
|
||||
|
||||
boolean hasResourceType();
|
||||
|
||||
boolean hasVersionIdPart();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an absolute URL (in other words, a URL starting with "http://" or "https://"
|
||||
*/
|
||||
boolean isAbsolute();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} is valid according to the FHIR rules for valid IDs.
|
||||
* <p>
|
||||
* The FHIR specification states:
|
||||
* <code>Any combination of upper or lower case ASCII letters ('A'..'Z', and 'a'..'z', numerals ('0'..'9'), '-' and '.', with a length limit of 64 characters. (This might be an integer, an un-prefixed OID, UUID or any other identifier pattern that meets these constraints.) regex: [A-Za-z0-9\-\.]{1,64}</code>
|
||||
* </p>
|
||||
*/
|
||||
boolean isIdPartValid();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} contains
|
||||
* only numbers
|
||||
*/
|
||||
boolean isIdPartValidLong();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the ID is a local reference (in other words, it begins with the '#' character)
|
||||
*/
|
||||
boolean isLocal();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getVersionIdPart() version ID part of this object} contains
|
||||
* only numbers
|
||||
*/
|
||||
boolean isVersionIdPartValidLong();
|
||||
|
||||
IIdType setValue(String theString);
|
||||
|
||||
IIdType toUnqualified();
|
||||
|
||||
IIdType toUnqualifiedVersionless();
|
||||
|
||||
IIdType toVersionless();
|
||||
|
||||
IIdType withResourceType(String theResName);
|
||||
|
||||
IIdType withServerBase(String theServerBase, String theResourceName);
|
||||
|
||||
IIdType withVersion(String theVersion);
|
||||
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Created by Sébastien Rivière 12/04/2017
|
||||
*/
|
||||
public class ElementWithExtensionR4Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElementWithExtensionR4Test.class);
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final HumanName name = patient.getNameFirstRep();
|
||||
name.setFamily("family");
|
||||
name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
patient.setPetName(new StringType("myPet"));
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final StringType stringExt = new StringType();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final Extension ext = new Extension();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addExtension(ext);
|
||||
|
||||
final IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
|
||||
assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionNullValueJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final HumanName name = patient.getNameFirstRep();
|
||||
name.setFamily("family");
|
||||
name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
patient.setPetName(new StringType("myPet"));
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final StringType stringExt = new StringType();
|
||||
stringExt.setValue("myStringExt");
|
||||
stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final Extension ext = new Extension();
|
||||
ext.setValue(stringExt);
|
||||
ext.setUrl("/myExt");
|
||||
patient.addExtension(ext);
|
||||
|
||||
final IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
|
||||
assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullFlavorPrimitiveExtensionNullValueXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
|
||||
patient.getExtensionsByUrl("/petname");
|
||||
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getPetName().getExtension().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullFlavorIDDatatypeJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getIdElement().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorIDDatatypeXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getIdElement().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorExtensionIDDatatypeJson() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
patient.setCustomId(new IdType(("4")));
|
||||
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
final IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
|
||||
final String json = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(json);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
|
||||
assertEquals(1, patient.getCustomId().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFlavorExtensionIDDatatypeXml() throws Exception {
|
||||
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
|
||||
patient.setId("1");
|
||||
final IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
patient.setCustomId(new IdType(("4")));
|
||||
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
|
||||
|
||||
final String xml = parser.encodeResourceToString(patient);
|
||||
|
||||
ourLog.info(xml);
|
||||
|
||||
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
|
||||
assertEquals(1, patient.getCustomId().getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnResourceIdXml(){
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.getIdElement().setValue("123");
|
||||
p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO"));
|
||||
|
||||
IParser parser = ourCtx.newXmlParser();
|
||||
String encoded = parser.encodeResourceToString(p);
|
||||
assertThat(encoded, containsString("http://foo"));
|
||||
assertThat(encoded, containsString("FOO"));
|
||||
|
||||
p = (Patient) parser.parseResource(encoded);
|
||||
assertEquals("Patient/123", p.getId());
|
||||
Extension ex = p.getIdElement().getExtension().get(0);
|
||||
assertEquals("http://foo", ex.getUrl());
|
||||
assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionOnResourceIdJson(){
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.getIdElement().setValue("123");
|
||||
p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO"));
|
||||
|
||||
IParser parser = ourCtx.newJsonParser();
|
||||
String encoded = parser.encodeResourceToString(p);
|
||||
assertThat(encoded, containsString("http://foo"));
|
||||
assertThat(encoded, containsString("FOO"));
|
||||
|
||||
p = (Patient) parser.parseResource(encoded);
|
||||
assertEquals("Patient/123", p.getId());
|
||||
Extension ex = p.getIdElement().getExtension().get(0);
|
||||
assertEquals("http://foo", ex.getUrl());
|
||||
assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
|
||||
@ResourceDef()
|
||||
public class MyPatientWithCustomUrlExtension extends Patient {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Child(name = "petName")
|
||||
@Extension(url = "/petname", definedLocally = false, isModifier = false)
|
||||
@Description(shortDefinition = "The name of the patient's favourite pet")
|
||||
private StringType myPetName;
|
||||
|
||||
@Child(name = "customid")
|
||||
@Extension(url = "/customid", definedLocally = false, isModifier = false)
|
||||
@Description(shortDefinition = "The customid of the patient's ")
|
||||
private IdType myCustomId;
|
||||
|
||||
public StringType getPetName() {
|
||||
if (myPetName == null) {
|
||||
myPetName = new StringType();
|
||||
}
|
||||
return myPetName;
|
||||
}
|
||||
|
||||
public void setPetName(final StringType thePetName) {
|
||||
myPetName = thePetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return super.isEmpty() && getCustomId().isEmpty() && getPetName().isEmpty();
|
||||
}
|
||||
|
||||
public IdType getCustomId() {
|
||||
if (myCustomId == null) {
|
||||
myCustomId = new IdType();
|
||||
}
|
||||
return myCustomId;
|
||||
}
|
||||
|
||||
public void setCustomId(final IdType myCustomId) {
|
||||
this.myCustomId = myCustomId;
|
||||
}
|
||||
}
|
|
@ -1216,7 +1216,7 @@ public class ClientR4Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
private static String getPatientFeedWithOneResult() {
|
||||
static String getPatientFeedWithOneResult() {
|
||||
return getPatientFeedWithOneResult(ourCtx);
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ public class ClientServerValidationDstu1Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testServerReturnsWrongVersionDstu() throws Exception {
|
||||
CapabilityStatement conf = new CapabilityStatement();
|
||||
conf.setFhirVersion("0.4.0");
|
||||
|
|
|
@ -108,6 +108,30 @@ public class GenericClientR4Test {
|
|||
return capt;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithNoExplicitBundleReturnType() throws Exception {
|
||||
|
||||
String msg = ClientR4Test.getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
// httpResponse = new BasicHttpResponse(statusline, catalog, locale)
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://foo");
|
||||
Bundle response = (Bundle) client.search().forResource(Patient.class).execute();
|
||||
|
||||
assertEquals("http://foo/Patient", capt.getValue().getURI().toString());
|
||||
Patient patient = (Patient) response.getEntry().get(0).getResource();
|
||||
assertEquals("PRP1660", patient.getIdentifier().get(0).getValueElement().getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAcceptHeaderWithEncodingSpecified() throws Exception {
|
||||
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
package org.hl7.fhir.r4.model;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class IdTypeR4Test {
|
||||
|
||||
private static FhirContext ourCtx;
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeR4Test.class);
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo1() {
|
||||
IdType id = new IdType("http://my.org/foo");
|
||||
assertEquals("http://my.org/foo", id.getValueAsString());
|
||||
assertEquals(null, id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("foo", id.getResourceType());
|
||||
assertEquals("http://my.org", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/foo//_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBaseUrlFoo2() {
|
||||
IdType id = new IdType("http://my.org/a/b/c/foo");
|
||||
assertEquals("http://my.org/a/b/c/foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("c/foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("c/foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals("c", id.getResourceType());
|
||||
assertEquals("http://my.org/a/b", id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUuid() {
|
||||
IdType id = new IdType("urn:uuid:1234-5678");
|
||||
assertEquals("urn:uuid:1234-5678", id.getValueAsString());
|
||||
assertEquals("urn:uuid:1234-5678", id.getIdPart());
|
||||
assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
|
||||
assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals(null, id.getResourceType());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
|
||||
assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
|
||||
assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOid() {
|
||||
IdType id = new IdType("urn:oid:1.2.3.4");
|
||||
assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
|
||||
assertEquals("urn:oid:1.2.3.4", id.getIdPart());
|
||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
|
||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals(null, id.getResourceType());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
|
||||
assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
|
||||
assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocal() {
|
||||
IdType id = new IdType("#foo");
|
||||
assertEquals("#foo", id.getValueAsString());
|
||||
assertEquals("#foo", id.getIdPart());
|
||||
assertEquals("#foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("#foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals(null, id.getResourceType());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
|
||||
assertEquals("#foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("#foo", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormal() {
|
||||
IdType id = new IdType("foo");
|
||||
assertEquals("foo", id.getValueAsString());
|
||||
assertEquals("foo", id.getIdPart());
|
||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||
assertEquals(null, id.getVersionIdPart());
|
||||
assertEquals(null, id.getResourceType());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
|
||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectLocal() {
|
||||
IdType id;
|
||||
|
||||
id = new IdType("#123");
|
||||
assertEquals("#123", id.getValue());
|
||||
assertTrue(id.isLocal());
|
||||
|
||||
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
||||
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
|
||||
assertTrue(id.isLocal());
|
||||
|
||||
id = new IdType("http://example.com/Patient/33#123");
|
||||
assertEquals("http://example.com/Patient/33#123", id.getValue());
|
||||
assertFalse(id.isLocal());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorsWithNullArguments() {
|
||||
IdType id = new IdType(null, null, null);
|
||||
assertEquals(null, id.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectLocalBase() {
|
||||
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
|
||||
assertEquals(null, new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
||||
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
||||
|
||||
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
|
||||
assertEquals(null, new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
||||
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
||||
|
||||
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
|
||||
assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
||||
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #67
|
||||
*/
|
||||
@Test
|
||||
public void testComplicatedLocal() {
|
||||
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||
assertTrue(id.isLocal());
|
||||
assertEquals(null, id.getBaseUrl());
|
||||
assertNull(id.getResourceType());
|
||||
assertNull(id.getVersionIdPart());
|
||||
assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
|
||||
|
||||
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||
assertEquals(id, id2);
|
||||
|
||||
id2 = id2.toUnqualified();
|
||||
assertTrue(id2.isLocal());
|
||||
assertNull(id2.getBaseUrl());
|
||||
assertNull(id2.getResourceType());
|
||||
assertNull(id2.getVersionIdPart());
|
||||
assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetermineBase() {
|
||||
|
||||
IdType rr;
|
||||
|
||||
rr = new IdType("http://foo/fhir/Organization/123");
|
||||
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
||||
|
||||
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
|
||||
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
||||
|
||||
rr = new IdType("Organization/123/_history/123");
|
||||
assertEquals(null, rr.getBaseUrl());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueAbsolute() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("http://foo/fhir/Organization/123");
|
||||
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals("Organization", ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigDecimalIds() {
|
||||
|
||||
IdType id = new IdType(new BigDecimal("123"));
|
||||
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueAbsoluteWithVersion() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("http://foo/fhir/Organization/123/_history/999");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals("Organization", ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testViewMethods() {
|
||||
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
|
||||
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
|
||||
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
|
||||
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueWithVersion() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("/123/_history/999");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals(null, ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueMissingType1() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("/123");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals(null, ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueMissingType2() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("123");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals(null, ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueRelative1() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("Organization/123");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals("Organization", ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeParts() {
|
||||
IdType id = new IdType("http://foo", "Patient", "123", "456");
|
||||
assertEquals("http://foo/Patient/123/_history/456", id.getValue());
|
||||
assertEquals("http://foo/Patient/123/_history/9", id.withVersion("9").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseValueRelative2() {
|
||||
Patient patient = new Patient();
|
||||
IdType rr = new IdType();
|
||||
rr.setValue("/Organization/123");
|
||||
patient.setManagingOrganization(new Reference(rr));
|
||||
|
||||
Patient actual = parseAndEncode(patient);
|
||||
Reference ref = actual.getManagingOrganization();
|
||||
assertEquals("Organization", ref.getReferenceElement().getResourceType());
|
||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
private Patient parseAndEncode(Patient patient) {
|
||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||
ourLog.info("\n" + encoded);
|
||||
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forR4();
|
||||
}
|
||||
|
||||
}
|
|
@ -70,14 +70,88 @@ function addSearchControls(theConformance, theSearchParamType, theSearchParamNam
|
|||
)
|
||||
);
|
||||
} else if (theSearchParamType == 'token') {
|
||||
|
||||
var tokenQualifiers = new Array();
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[0].name='Matches';
|
||||
tokenQualifiers[0].value='';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[1].name='Text';
|
||||
tokenQualifiers[1].value=':text';
|
||||
tokenQualifiers[1].description='The search parameter is processed as a string that searches text associated with the code/value.';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[2].name='Not';
|
||||
tokenQualifiers[2].value=':not';
|
||||
tokenQualifiers[2].description='Reverse the code matching described in the paragraph above. Note that this includes resources that have no value for the parameter.';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[3].name='Above';
|
||||
tokenQualifiers[3].value=':above';
|
||||
tokenQualifiers[3].description='The search parameter is a concept with the form [system]|[code], and the search parameter tests whether the coding in a resource subsumes the specified search code. For example, the search concept has an is-a relationship with the coding in the resource, and this includes the coding itself.';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[4].name='Below';
|
||||
tokenQualifiers[4].value=':below';
|
||||
tokenQualifiers[4].description='The search parameter is a concept with the form [system]|[code], and the search parameter tests whether the coding in a resource is subsumed by the specified search code. For example, the coding in the resource has an is-a relationship with the search concept, and this includes the coding itself.';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[5].name='In';
|
||||
tokenQualifiers[5].value=':in';
|
||||
tokenQualifiers[5].description='The search parameter is a URI (relative or absolute) that identifies a value set, and the search parameter tests whether the coding is in the specified value set. The reference may be literal (to an address where the value set can be found) or logical (a reference to ValueSet.url). If the server can treat the reference as a literal URL, it does, else it tries to match known logical ValueSet.url values.';
|
||||
|
||||
tokenQualifiers.push(new Object());
|
||||
tokenQualifiers[6].name='Not-in';
|
||||
tokenQualifiers[6].value=':not-in';
|
||||
tokenQualifiers[6].description='The search parameter is a URI (relative or absolute) that identifies a value set, and the search parameter tests whether the coding is not in the specified value set.';
|
||||
|
||||
|
||||
var tokenQualifierInput = $('<input />', { id: 'param.' + theRowNum + '.qualifier', type: 'hidden' });
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<div />', { 'class': 'col-sm-3' }).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.0', placeholder: 'system/namespace', type: 'text', 'class': 'form-control' })
|
||||
tokenQualifierInput
|
||||
);
|
||||
|
||||
function clickTokenFunction(value, name){
|
||||
return function(){
|
||||
tokenQualifierInput.val(value);
|
||||
tokenQualifierLabel.text(name);
|
||||
}
|
||||
};
|
||||
var tokenQualifierLabel = $('<span>' + tokenQualifiers[0].name + '</span>');
|
||||
var tokenQualifierDropdown = $('<ul />', {'class':'dropdown-menu', role:'menu'});
|
||||
for (var i = 0; i < tokenQualifiers.length; i++) {
|
||||
var qualName = tokenQualifiers[i].name;
|
||||
var nextValue = tokenQualifiers[i].value;
|
||||
var nextLink = $('<a>' + tokenQualifiers[i].name+'</a>');
|
||||
tokenQualifierDropdown.append($('<li />').append(nextLink));
|
||||
nextLink.click(clickTokenFunction(nextValue, qualName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<div />', { 'class': 'col-sm-6' }).append(
|
||||
$('<div />', { 'class':'input-group'}).append(
|
||||
$('<div />', {'class':'input-group-btn'}).append(
|
||||
$('<button />', {'class':'btn btn-default dropdown-toggle', 'data-toggle':'dropdown'}).append(
|
||||
tokenQualifierLabel,
|
||||
$('<span class="caret" style="margin-left: 5px;"></span>')
|
||||
),
|
||||
$('<div />', { 'class': 'col-sm-3' }).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.1', placeholder: 'value', type: 'text', 'class': 'form-control' })
|
||||
tokenQualifierDropdown
|
||||
),
|
||||
$('<div />', { 'class':'input-group-addon', 'style':'padding:6px;'} ).append(
|
||||
$('<span>System</span>')
|
||||
),
|
||||
$('<input />', { type:'text', 'class':'form-control', id: 'param.' + theRowNum + '.0', placeholder: "(opt)" }),
|
||||
$('<div />', { 'class':'input-group-addon', 'style':'padding:6px;'} ).append(
|
||||
$('<span>Code</span>')
|
||||
),
|
||||
$('<input />', { type:'text', 'class':'form-control', id: 'param.' + theRowNum + '.1', placeholder: "(opt)" })
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
} else if (theSearchParamType == 'string') {
|
||||
var placeholderText = 'value';
|
||||
var qualifiers = new Array();
|
||||
|
@ -93,17 +167,23 @@ function addSearchControls(theConformance, theSearchParamType, theSearchParamNam
|
|||
qualifierInput
|
||||
);
|
||||
|
||||
|
||||
var matchesLabel = $('<span>' + qualifiers[0].name + '</span>');
|
||||
var qualifierDropdown = $('<ul />', {'class':'dropdown-menu', role:'menu'});
|
||||
|
||||
function clickFunction(value, name){
|
||||
return function(){
|
||||
qualifierInput.val(value);
|
||||
matchesLabel.text(name);
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < qualifiers.length; i++) {
|
||||
var nextLink = $('<a>' + qualifiers[i].name+'</a>');
|
||||
var qualName = qualifiers[i].name;
|
||||
var nextValue = qualifiers[i].value;
|
||||
qualifierDropdown.append($('<li />').append(nextLink));
|
||||
nextLink.click(function(){
|
||||
qualifierInput.val(nextValue);
|
||||
matchesLabel.text(qualName);
|
||||
});
|
||||
nextLink.click(clickFunction(nextValue, qualName));
|
||||
}
|
||||
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -99,8 +99,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -97,8 +97,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[^\s]+([\s][^\s]+)*"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[^\s]+([\s][^\s]+)*"/>
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1]))?)?"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1]))?)?"/>
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?([0]|([1-9][0-9]*))(\.[0-9]+)?"/>
|
||||
|
@ -102,8 +102,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?([0]|([1-9][0-9]*))(\.[0-9]+)?"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[A-Za-z0-9\-\.]{1,64}"/>
|
||||
|
@ -102,8 +102,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[A-Za-z0-9\-\.]{1,64}"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -99,8 +99,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?([0]|([1-9][0-9]*))"/>
|
||||
|
@ -104,8 +104,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="-?([0]|([1-9][0-9]*))"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -99,8 +99,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="urn:oid:(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*"/>
|
||||
|
@ -102,8 +102,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="urn:oid:(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*"/>
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[1-9][0-9]*"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[1-9][0-9]*"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?"/>
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[0]|([1-9][0-9]*)"/>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="[0]|([1-9][0-9]*)"/>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
@ -99,8 +99,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<code>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type">
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<max value="1"/>
|
||||
</base>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"/>
|
||||
|
@ -102,8 +102,8 @@
|
|||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<!-- Note: primitive values do not have an assigned type
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
e.g. this is compiler magic
|
||||
XML and JSON types provided by extension -->
|
||||
<type>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-regex">
|
||||
<valueString value="urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"/>
|
||||
|
|
|
@ -56749,14 +56749,14 @@
|
|||
<contained>
|
||||
<ConceptMap xmlns="http://hl7.org/fhir">
|
||||
<id value="map"/>
|
||||
<name value="NHIN / V3 Mapping"/>
|
||||
<status value="draft"/>
|
||||
<sourceReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/nhin-purposeofuse"/>
|
||||
</sourceReference>
|
||||
<targetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/v3-PurposeOfUse"/>
|
||||
</targetReference>
|
||||
<name value="NHIN / V3 Mapping"/>
|
||||
<status value="draft"/>
|
||||
<group>
|
||||
<source value="http://healthit.gov/nhin/purposeofuse"/>
|
||||
<target value="http://hl7.org/fhir/v3/ActReason"/>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,10 @@ import java.io.*;
|
|||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -11,6 +15,7 @@ import org.apache.maven.plugin.*;
|
|||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
@ -51,6 +56,8 @@ public class ResourceMinimizerMojo extends AbstractMojo {
|
|||
myCtx = FhirContext.forDstu2_1();
|
||||
} else if ("DSTU3".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forDstu3();
|
||||
} else if ("R4".equals(fhirVersion)) {
|
||||
myCtx = FhirContext.forR4();
|
||||
} else {
|
||||
throw new MojoFailureException("Unknown version: " + fhirVersion);
|
||||
}
|
||||
|
@ -82,30 +89,8 @@ public class ResourceMinimizerMojo extends AbstractMojo {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (input instanceof org.hl7.fhir.dstu3.model.Bundle) {
|
||||
for (org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent nextEntry : ((org.hl7.fhir.dstu3.model.Bundle) input).getEntry()) {
|
||||
if (nextEntry.getResource() instanceof org.hl7.fhir.dstu3.model.DomainResource) {
|
||||
((org.hl7.fhir.dstu3.model.DomainResource) nextEntry.getResource()).getText().getDiv().setValueAsString((String) null);
|
||||
((org.hl7.fhir.dstu3.model.DomainResource) nextEntry.getResource()).getText().getStatusElement().setValueAsString((String) null);
|
||||
}
|
||||
}
|
||||
} else if (input instanceof org.hl7.fhir.dstu2016may.model.Bundle) {
|
||||
for (org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent nextEntry : ((org.hl7.fhir.dstu2016may.model.Bundle) input).getEntry()) {
|
||||
if (nextEntry.getResource() instanceof org.hl7.fhir.dstu2016may.model.DomainResource) {
|
||||
((org.hl7.fhir.dstu2016may.model.DomainResource) nextEntry.getResource()).getText().getDiv().setValueAsString((String) null);
|
||||
((org.hl7.fhir.dstu2016may.model.DomainResource) nextEntry.getResource()).getText().getStatusElement().setValueAsString((String) null);
|
||||
}
|
||||
}
|
||||
} else if (input instanceof org.hl7.fhir.dstu3.model.DomainResource) {
|
||||
try {
|
||||
((org.hl7.fhir.dstu3.model.DomainResource) input).getText().setDivAsString(null);
|
||||
((org.hl7.fhir.dstu3.model.DomainResource) input).getText().getStatusElement().setValueAsString(null);
|
||||
} catch (Exception e) {
|
||||
ourLog.error("Failed to clear narrative", e);
|
||||
}
|
||||
} else {
|
||||
ourLog.info("Ignoring type: " + input.getClass());
|
||||
continue;
|
||||
minimizeResource((IBaseResource)input);
|
||||
}
|
||||
|
||||
String outputString = parser.setPrettyPrint(true).encodeResourceToString(input);
|
||||
|
@ -143,6 +128,20 @@ public class ResourceMinimizerMojo extends AbstractMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void minimizeResource(IBaseResource theInput) {
|
||||
if (theInput instanceof IBaseBundle) {
|
||||
for (IBaseResource next : BundleUtil.toListOfResources(myCtx, (IBaseBundle) theInput)) {
|
||||
minimizeResource(next);
|
||||
}
|
||||
}
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> element = (BaseRuntimeElementCompositeDefinition) myCtx.getElementDefinition(theInput.getClass());
|
||||
BaseRuntimeChildDefinition textElement = element.getChildByName("text");
|
||||
if (textElement != null) {
|
||||
textElement.getMutator().setValue(theInput, null);
|
||||
}
|
||||
}
|
||||
|
||||
public long getByteCount() {
|
||||
return myByteCount;
|
||||
}
|
||||
|
@ -153,8 +152,9 @@ public class ResourceMinimizerMojo extends AbstractMojo {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
FhirContext ctxDstu2 = FhirContext.forDstu2();
|
||||
// FhirContext ctxDstu2_1 = FhirContext.forDstu2_1();
|
||||
// FhirContext ctxDstu3 = FhirContext.forDstu3();
|
||||
FhirContext ctxDstu2_1 = FhirContext.forDstu2_1();
|
||||
FhirContext ctxDstu3 = FhirContext.forDstu3();
|
||||
FhirContext ctxR4 = FhirContext.forR4();
|
||||
|
||||
LoggerContext loggerContext = ((ch.qos.logback.classic.Logger) ourLog).getLoggerContext();
|
||||
URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(loggerContext);
|
||||
|
@ -166,59 +166,76 @@ public class ResourceMinimizerMojo extends AbstractMojo {
|
|||
long byteCount = 0;
|
||||
|
||||
ResourceMinimizerMojo m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2;
|
||||
// m.targetDirectory = new File("../hapi-tinder-plugin/src/main/resources/vs/dstu2");
|
||||
// m.fhirVersion = "DSTU2";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
//
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2;
|
||||
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/valueset");
|
||||
// m.fhirVersion = "DSTU2";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
//
|
||||
m = new ResourceMinimizerMojo();
|
||||
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/profile");
|
||||
m.targetDirectory = new File("./hapi-tinder-plugin/src/main/resources/vs/dstu2");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu3;
|
||||
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/profile");
|
||||
// m.fhirVersion = "DSTU3";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/valueset");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu3;
|
||||
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/valueset");
|
||||
// m.fhirVersion = "DSTU3";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/profile");
|
||||
m.fhirVersion = "DSTU2";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2_1;
|
||||
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/profile");
|
||||
// m.fhirVersion = "DSTU2_1";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
//
|
||||
// m = new ResourceMinimizerMojo();
|
||||
// m.myCtx = ctxDstu2_1;
|
||||
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/valueset");
|
||||
// m.fhirVersion = "DSTU2_1";
|
||||
// m.execute();
|
||||
// byteCount += m.getByteCount();
|
||||
// fileCount += m.getFileCount();
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu3;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/profile");
|
||||
m.fhirVersion = "DSTU3";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu3;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/valueset");
|
||||
m.fhirVersion = "DSTU3";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2_1;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/profile");
|
||||
m.fhirVersion = "DSTU2_1";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2_1;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/model/valueset");
|
||||
m.fhirVersion = "DSTU2_1";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2_1;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-r4/src/main/resources/org/hl7/fhir/r4/model/profile");
|
||||
m.fhirVersion = "R4";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
m = new ResourceMinimizerMojo();
|
||||
m.myCtx = ctxDstu2_1;
|
||||
m.targetDirectory = new File("./hapi-fhir-validation-resources-r4/src/main/resources/org/hl7/fhir/r4/model/valueset");
|
||||
m.fhirVersion = "R4";
|
||||
m.execute();
|
||||
byteCount += m.getByteCount();
|
||||
fileCount += m.getFileCount();
|
||||
|
||||
ourLog.info("Trimmed {} files", fileCount);
|
||||
ourLog.info("Trimmed {} bytes", FileUtils.byteCountToDisplaySize(byteCount));
|
||||
|
|
12
pom.xml
12
pom.xml
|
@ -346,6 +346,18 @@
|
|||
<id>SarenCurrie</id>
|
||||
<name>Saren Currie</name>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>dconlan</id>
|
||||
<name>dconlan</name>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>psbrandt</id>
|
||||
<name>Pascal Brandt</name>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>InfiniteLoop90</id>
|
||||
<name>Clayton Bodendein</name>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
|
|
|
@ -269,6 +269,33 @@
|
|||
correctly validated if the element contained only a profiled extension. Thanks
|
||||
to Sébastien Rivière for the pull request!
|
||||
</action>
|
||||
<action type="add" issue="701">
|
||||
Testing UI now has a dropdown for modifiers on token search. Thanks
|
||||
to GitHub user @dconlan for the pull request!
|
||||
</action>
|
||||
<action type="add" issue="688">
|
||||
When parsing an incomplete ID with the form <![CDATA[<code>http://my.org/Foo</code>]]> into
|
||||
IdDt and IdType objects, the Foo portion will now be treated as the resource type.
|
||||
Previously my.org was treated as the resource type and Foo was treated as the ID. Thanks
|
||||
to GitHub user @CarthageKing for the pull request!
|
||||
</action>
|
||||
<action type="fix" issue="695">
|
||||
Extensions on ID datatypes were not parsed or serialized correctly. Thanks to
|
||||
Stephen Rivière for the pull request!
|
||||
</action>
|
||||
<action type="fix" issue="710">
|
||||
Fix a bug in REST Hook Subscription interceptors which prevented subscriptions
|
||||
from being activated. Thanks to Jeff Chung for the pull request!
|
||||
</action>
|
||||
<action type="fix" issue="708">
|
||||
Fix broken links in usage pattern diagram on website. Thanks to
|
||||
Pascal Brandt for the pull request!
|
||||
</action>
|
||||
<action type="fix" issue="706">
|
||||
Fix incorrect FHIR Version Strings that were being outputted and verified in the
|
||||
client for some versions of FHIR. Thanks to Clayton Bodendein for the
|
||||
pull request!
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.5" date="2017-06-08">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue