Work on HL7.org structs

This commit is contained in:
jamesagnew 2015-04-13 08:32:49 -04:00
parent c5e75ebe60
commit 2edc7eadab
56 changed files with 1765 additions and 640 deletions

View File

@ -183,7 +183,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
}
}
private final class FieldPlainMutator implements IMutator {
protected final class FieldPlainMutator implements IMutator {
@Override
public void addValue(Object theTarget, IBase theValue) {
try {
@ -214,7 +214,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
}
}
private final class FieldListMutator implements IMutator {
protected final class FieldListMutator implements IMutator {
@Override
public void addValue(Object theTarget, IBase theValue) {
try {

View File

@ -158,7 +158,26 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
public abstract ChildTypeEnum getChildType();
public enum ChildTypeEnum {
COMPOSITE_DATATYPE, PRIMITIVE_DATATYPE, RESOURCE, RESOURCE_REF, RESOURCE_BLOCK, PRIMITIVE_XHTML, UNDECL_EXT, EXTENSION_DECLARED, CONTAINED_RESOURCES
COMPOSITE_DATATYPE, PRIMITIVE_DATATYPE, RESOURCE, RESOURCE_REF, RESOURCE_BLOCK,
/**
* HAPI style
*/
PRIMITIVE_XHTML,
UNDECL_EXT, EXTENSION_DECLARED,
/**
* HAPI structure style
*/
CONTAINED_RESOURCES,
ID_DATATYPE,
/**
* HL7.org structure style
*/
CONTAINED_RESOURCE_LIST,
/**
* HL7.org style
*/
PRIMITIVE_XHTML_HL7ORG
}

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.context;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.io.InputStream;
@ -56,9 +56,11 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.IDatatypeElement;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.INarrative;
import org.hl7.fhir.instance.model.api.IReference;
@ -225,6 +227,7 @@ class ModelScanner {
* all of the annotation processing code this method just creates an interface Proxy to simulate the HAPI
* annotations if the HL7.org ones are found instead.
*/
@SuppressWarnings("unchecked")
private <T extends Annotation> T pullAnnotation(AnnotatedElement theTarget, Class<T> theAnnotationType) {
T retVal = theTarget.getAnnotation(theAnnotationType);
@ -493,20 +496,20 @@ class ModelScanner {
Class<?> nextElementType = determineElementType(next);
if (IAnyResource.class.isAssignableFrom(nextElementType) || IResource.class.equals(nextElementType)) {
/*
* Child is a resource as a direct child, as in Bundle.entry.resource
*/
RuntimeChildDirectResource def = new RuntimeChildDirectResource(next, childAnnotation, descriptionAnnotation, elementName);
orderMap.put(order, def);
} else if (BaseContainedDt.class.isAssignableFrom(nextElementType) || (childAnnotation.name().equals("contained") && IDomainResource.class.isAssignableFrom(theClass))) {
if (BaseContainedDt.class.isAssignableFrom(nextElementType) || (childAnnotation.name().equals("contained") && IBaseResource.class.isAssignableFrom(nextElementType))) {
/*
* Child is contained resources
*/
RuntimeChildContainedResources def = new RuntimeChildContainedResources(next, childAnnotation, descriptionAnnotation, elementName);
orderMap.put(order, def);
} else if (IAnyResource.class.isAssignableFrom(nextElementType) || IResource.class.equals(nextElementType)) {
/*
* Child is a resource as a direct child, as in Bundle.entry.resource
*/
RuntimeChildDirectResource def = new RuntimeChildDirectResource(next, childAnnotation, descriptionAnnotation, elementName);
orderMap.put(order, def);
} else if (choiceTypes.size() > 1 && !BaseResourceReferenceDt.class.isAssignableFrom(nextElementType) && !IReference.class.isAssignableFrom(nextElementType)) {
/*
* Child is a choice element
@ -538,8 +541,8 @@ class ModelScanner {
RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et, binder);
orderMap.put(order, def);
if (IElement.class.isAssignableFrom(nextElementType)) {
addScanAlso((Class<? extends IElement>) nextElementType);
if (IBase.class.isAssignableFrom(nextElementType)) {
addScanAlso((Class<? extends IBase>) nextElementType);
}
} else if (BaseResourceReferenceDt.class.isAssignableFrom(nextElementType) || IReference.class.isAssignableFrom(nextElementType)) {
/*
@ -582,17 +585,25 @@ class ModelScanner {
if (nextElementType.equals(BoundCodeDt.class)) {
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
def = new RuntimeChildPrimitiveBoundCodeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder);
} else if (IBaseEnumeration.class.isAssignableFrom(nextElementType)) {
Class<?> binderType = ReflectionUtil.getGenericCollectionTypeOfField(next);
def = new RuntimeChildPrimitiveEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binderType);
} else if (childAnnotation.enumFactory().getSimpleName().equals("NoEnumFactory") == false) {
Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory();
def = new RuntimeChildEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, enumFactory);
// } else if ("id".equals(elementName) && IIdType.class.isAssignableFrom(nextDatatype)) {
// def = new RuntimeChildIdDatatypeDefinition(next, elementName, descriptionAnnotation,
// childAnnotation, nextDatatype);
} else {
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
}
} else if (IBaseXhtml.class.isAssignableFrom(nextElementType)) {
def = new RuntimeChildXhtmlDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
} else {
if (IBoundCodeableConcept.class.isAssignableFrom(nextElementType)) {
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
def = new RuntimeChildCompositeBoundDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder);
} else if (BaseNarrativeDt.class.isAssignableFrom(nextElementType) || INarrative.class.getName().equals(nextElementType.getClass().getName())) {
} else if (BaseNarrativeDt.class.isAssignableFrom(nextElementType) || INarrative.class.isAssignableFrom(nextElementType)) {
def = new RuntimeChildNarrativeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype);
} else {
def = new RuntimeChildCompositeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype);
@ -633,6 +644,12 @@ class ModelScanner {
@SuppressWarnings("unchecked")
Class<XhtmlDt> clazz = (Class<XhtmlDt>) theClass;
resourceDef = new RuntimePrimitiveDatatypeNarrativeDefinition(resourceName, clazz);
} else if (IBaseXhtml.class.isAssignableFrom(theClass)) {
@SuppressWarnings("unchecked")
Class<? extends IBaseXhtml> clazz = (Class<? extends IBaseXhtml>) theClass;
resourceDef = new RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition(resourceName, clazz);
} else if (IIdType.class.isAssignableFrom(theClass)) {
resourceDef = new RuntimeIdDatatypeDefinition(theDatatypeDefinition, theClass);
} else {
resourceDef = new RuntimePrimitiveDatatypeDefinition(theDatatypeDefinition, theClass);
}

View File

@ -21,12 +21,13 @@ package ca.uhn.fhir.context;
*/
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
@ -34,7 +35,7 @@ import ca.uhn.fhir.model.base.composite.BaseContainedDt;
public class RuntimeChildContainedResources extends BaseRuntimeDeclaredChildDefinition {
private RuntimeElemContainedResources myElem;
private BaseRuntimeElementDefinition<?> myElem;
RuntimeChildContainedResources(Field theField, Child theChildAnnotation, Description theDescriptionAnnotation, String theElementName) throws ConfigurationException {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
@ -48,13 +49,13 @@ public class RuntimeChildContainedResources extends BaseRuntimeDeclaredChildDefi
@Override
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theType) {
assert BaseContainedDt.class.isAssignableFrom(theType);
assert BaseContainedDt.class.isAssignableFrom(theType) || List.class.isAssignableFrom(theType);
return myElem;
}
@Override
public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
assert BaseContainedDt.class.isAssignableFrom(theDatatype);
public String getChildNameByDatatype(Class<? extends IBase> theType) {
assert BaseContainedDt.class.isAssignableFrom(theType) || List.class.isAssignableFrom(theType);
return getElementName();
}
@ -70,8 +71,8 @@ public class RuntimeChildContainedResources extends BaseRuntimeDeclaredChildDefi
@SuppressWarnings("unchecked")
Class<? extends BaseContainedDt> type = (Class<? extends BaseContainedDt>) actualType;
myElem = new RuntimeElemContainedResources(type);
} else if (ArrayList.class.isAssignableFrom(actualType)) {
myElem = null;
} else if (List.class.isAssignableFrom(actualType)) {
myElem = new RuntimeElemContainedResourceList(IBaseResource.class);
} else {
throw new ConfigurationException("Fhir Version definition returned invalid contained type: " + actualType);
}

View File

@ -24,22 +24,21 @@ import java.lang.reflect.Field;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildPrimitiveBoundCodeDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
private IValueSetEnumBinder<Enum<?>> myBinder;
private Object myBinder;
public RuntimeChildPrimitiveBoundCodeDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype, IValueSetEnumBinder<Enum<?>> theBinder) {
public RuntimeChildPrimitiveBoundCodeDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype, Object theBinder) {
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
myBinder = theBinder;
}
@Override
public IValueSetEnumBinder<Enum<?>> getInstanceConstructorArguments() {
public Object getInstanceConstructorArguments() {
return myBinder;
}

View File

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

View File

@ -0,0 +1,58 @@
package ca.uhn.fhir.context;
/*
* #%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%
*/
import java.lang.reflect.Field;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildPrimitiveEnumerationDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
private Object myBinder;
private Class<?> myEnumerationType;
public RuntimeChildPrimitiveEnumerationDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype, Class<?> theBinderType) {
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
myEnumerationType = theBinderType;
}
@Override
public Object getInstanceConstructorArguments() {
Object retVal = myBinder;
if (retVal == null) {
Class<?> clazz;
String className = myEnumerationType.getName() + "EnumFactory";
try {
clazz = Class.forName(className);
retVal = clazz.newInstance();
myBinder = retVal;
} catch (Exception e) {
throw new ConfigurationException("Failed to instantiate " + className, e);
}
}
return retVal;
}
}

View File

@ -31,6 +31,7 @@ import java.util.Set;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
@ -43,6 +44,9 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
private List<Class<? extends IBaseResource>> myResourceTypes;
private Set<String> myValidChildNames;
/**
* Constructor
*/
public RuntimeChildResourceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBaseResource>> theResourceTypes) {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
myResourceTypes = theResourceTypes;
@ -56,7 +60,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override
public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) {
if (IReference.class.isAssignableFrom(theDatatype)) {
return getElementName();
}
return null;
@ -64,7 +68,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) {
if (IReference.class.isAssignableFrom(theDatatype)) {
return myRuntimeDef;
}
return null;

View File

@ -0,0 +1,40 @@
package ca.uhn.fhir.context;
/*
* #%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%
*/
import java.lang.reflect.Field;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
/**
* HL7org XHTML type
*/
public class RuntimeChildXhtmlDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
public RuntimeChildXhtmlDatatypeDefinition(Field theField, String theElementName, Description theDescriptionAnnotation, Child theChildAnnotation, Class<? extends IBase> theDatatype) {
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
}
}

View File

@ -0,0 +1,42 @@
package ca.uhn.fhir.context;
/*
* #%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%
*/
import java.util.List;
import org.hl7.fhir.instance.model.IBaseResource;
/**
* HL7org structures use a List for contained instead of a distinct datatype
*/
public class RuntimeElemContainedResourceList extends BaseRuntimeElementDefinition<IBaseResource> {
public RuntimeElemContainedResourceList(Class<IBaseResource> theClass) {
super("contained", theClass);
assert List.class.isAssignableFrom(theClass);
}
@Override
public ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum getChildType() {
return ChildTypeEnum.CONTAINED_RESOURCE_LIST;
}
}

View File

@ -0,0 +1,38 @@
package ca.uhn.fhir.context;
/*
* #%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%
*/
import org.hl7.fhir.instance.model.IPrimitiveType;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
public class RuntimeIdDatatypeDefinition extends RuntimePrimitiveDatatypeDefinition implements IRuntimeDatatypeDefinition {
public RuntimeIdDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType<?>> theImplementingClass) {
super(theDef, theImplementingClass);
}
@Override
public ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum getChildType() {
return ChildTypeEnum.ID_DATATYPE;
}
}

View File

@ -30,11 +30,11 @@ import org.hl7.fhir.instance.model.IPrimitiveType;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
public class RuntimePrimitiveDatatypeDefinition extends BaseRuntimeElementDefinition<IPrimitiveType> implements IRuntimeDatatypeDefinition {
public class RuntimePrimitiveDatatypeDefinition extends BaseRuntimeElementDefinition<IPrimitiveType<?>> implements IRuntimeDatatypeDefinition {
private boolean mySpecialization;
public RuntimePrimitiveDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType> theImplementingClass) {
public RuntimePrimitiveDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType<?>> theImplementingClass) {
super(theDef.name(), theImplementingClass);
String resourceName = theDef.name();

View File

@ -0,0 +1,44 @@
package ca.uhn.fhir.context;
/*
* #%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%
*/
import java.util.Map;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
public class RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition extends BaseRuntimeElementDefinition<IBaseXhtml> {
public RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition(String theName, Class<? extends IBaseXhtml> theImplementingClass) {
super(theName, theImplementingClass);
}
@Override
public ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum getChildType() {
return ChildTypeEnum.PRIMITIVE_XHTML_HL7ORG;
}
@Override
void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
// nothing
}
}

View File

@ -36,6 +36,9 @@ public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementDefini
private final List<Class<? extends IBaseResource>> myResourceTypes;
private HashMap<Class<? extends IBaseResource>, RuntimeResourceDefinition> myResourceTypeToDefinition;
/**
* Constructor
*/
public RuntimeResourceReferenceDefinition(String theName, List<Class<? extends IBaseResource>> theResourceTypes) {
super(theName, BaseResourceReferenceDt.class);
if (theResourceTypes == null || theResourceTypes.isEmpty()) {

View File

@ -28,6 +28,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
@ -38,7 +39,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.client.BaseClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement implements IBaseDatatype {
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement implements IBaseDatatype, IReference {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
private IResource myResource;
@ -114,7 +115,7 @@ public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement im
IParser parser = context.newXmlParser();
Reader responseReader = BaseClient.createReaderFromResponse(response);
myResource = parser.parseResource(responseReader);
myResource = (IResource) parser.parseResource(responseReader);
} finally {
if (response instanceof CloseableHttpResponse) {

View File

@ -30,6 +30,7 @@ import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource;
@ -51,7 +52,7 @@ import ca.uhn.fhir.util.UrlUtil;
* </p>
*/
@DatatypeDef(name = "id")
public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
private String myBaseUrl;
private boolean myHaveComponentParts;
@ -229,6 +230,11 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
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".
*/
public String getIdPart() {
return myUnqualifiedId;
}

View File

@ -20,8 +20,7 @@ package ca.uhn.fhir.parser;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.io.Reader;
@ -43,11 +42,14 @@ import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
@ -57,16 +59,14 @@ import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.IdDt;
public abstract class BaseParser implements IParser {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseParser.class);
private ContainedResources myContainedResources;
private FhirContext myContext;
private boolean mySuppressNarratives;
private String myServerBaseUrl;
private boolean mySuppressNarratives;
public BaseParser(FhirContext theContext) {
myContext = theContext;
@ -95,8 +95,11 @@ public abstract class BaseParser implements IParser {
} else if (theTarget instanceof IDomainResource) {
List<? extends IAnyResource> containedResources = ((IDomainResource) theTarget).getContained();
for (IAnyResource next : containedResources) {
String nextId = next.getId();
String nextId = next.getId().getValue();
if (StringUtils.isNotBlank(nextId)) {
if (!nextId.startsWith("#")) {
nextId = '#' + nextId;
}
allIds.add(nextId);
if (existingIdToContainedResource == null) {
existingIdToContainedResource = new HashMap<String, IBaseResource>();
@ -109,9 +112,9 @@ public abstract class BaseParser implements IParser {
}
{
List<BaseResourceReferenceDt> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class);
for (BaseResourceReferenceDt next : allElements) {
IResource resource = next.getResource();
List<IReference> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IReference.class);
for (IReference next : allElements) {
IBaseResource resource = next.getResource();
if (resource != null) {
if (resource.getId().isEmpty() || resource.getId().isLocal()) {
theContained.addContained(resource);
@ -132,44 +135,21 @@ public abstract class BaseParser implements IParser {
}
}
{
List<IReference> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IReference.class);
for (IReference next : allElements) {
IAnyResource resource = next.getResource();
if (resource != null) {
if (resource.getIdElement().isEmpty() || resource.getId().startsWith("#")) {
theContained.addContained(resource);
} else {
continue;
}
containResourcesForEncoding(theContained, resource, theTarget);
} else if (next.getReference() != null && next.getReference().startsWith("#")) {
if (existingIdToContainedResource != null) {
IBaseResource potentialTarget = existingIdToContainedResource.remove(next.getReference());
if (potentialTarget != null) {
theContained.addContained(potentialTarget);
containResourcesForEncoding(theContained, potentialTarget, theTarget);
}
}
}
}
}
}
protected void containResourcesForEncoding(IBaseResource theResource) {
ContainedResources contained = new ContainedResources();
containResourcesForEncoding(contained, theResource, theResource);
myContainedResources = contained;
}
protected String determineReferenceText(BaseResourceReferenceDt theRef) {
IdDt ref = theRef.getReference();
protected String determineReferenceText(IReference theRef) {
IIdType ref = theRef.getReference();
if (isBlank(ref.getIdPart())) {
String reference = ref.getValue();
if (theRef.getResource() != null) {
IdDt containedId = getContainedResources().getResourceId(theRef.getResource());
IIdType containedId = getContainedResources().getResourceId(theRef.getResource());
if (containedId != null && !containedId.isEmpty()) {
if (containedId.isLocal()) {
reference = containedId.getValue();
@ -192,12 +172,6 @@ public abstract class BaseParser implements IParser {
}
}
@Override
public IParser setServerBaseUrl(String theUrl) {
myServerBaseUrl = isNotBlank(theUrl) ? theUrl : null;
return this;
}
protected String determineResourceBaseUrl(String bundleBaseUrl, BundleEntry theEntry) {
IResource resource = theEntry.getResource();
if (resource == null) {
@ -270,6 +244,10 @@ public abstract class BaseParser implements IParser {
return mySuppressNarratives;
}
protected boolean isChildContained(BaseRuntimeElementDefinition<?> childDef, boolean theIncludedResource) {
return (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES || childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCE_LIST) && getContainedResources().isEmpty() == false && theIncludedResource == false;
}
@Override
public Bundle parseBundle(Reader theReader) {
return parseBundle(null, theReader);
@ -337,12 +315,12 @@ public abstract class BaseParser implements IParser {
}
@Override
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
public IBaseResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
return parseResource(null, theReader);
}
@Override
public IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException {
public IBaseResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException {
return parseResource(null, theMessageString);
}
@ -351,6 +329,12 @@ public abstract class BaseParser implements IParser {
return parseTagList(new StringReader(theString));
}
@Override
public IParser setServerBaseUrl(String theUrl) {
myServerBaseUrl = isNotBlank(theUrl) ? theUrl : null;
return this;
}
@Override
public IParser setSuppressNarratives(boolean theSuppressNarratives) {
mySuppressNarratives = theSuppressNarratives;
@ -385,18 +369,16 @@ public abstract class BaseParser implements IParser {
private long myNextContainedId = 1;
private List<IBaseResource> myResources = new ArrayList<IBaseResource>();
private IdentityHashMap<IBaseResource, IdDt> myResourceToId = new IdentityHashMap<IBaseResource, IdDt>();
private IdentityHashMap<IBaseResource, IIdType> myResourceToId = new IdentityHashMap<IBaseResource, IIdType>();
public void addContained(IBaseResource theResource) {
if (myResourceToId.containsKey(theResource)) {
return;
}
IdDt newId;
if (theResource instanceof IResource && ((IResource) theResource).getId().isLocal()) {
newId = ((IResource) theResource).getId();
} else if (theResource instanceof IAnyResource && ((IAnyResource) theResource).getId() != null && ((IAnyResource) theResource).getId().startsWith("#")) {
newId = new IdDt(((IAnyResource) theResource).getId());
IIdType newId;
if (theResource.getId().isLocal()) {
newId = theResource.getId();
} else {
// TODO: make this configurable between the two below (and something else?)
// newId = new IdDt(UUID.randomUUID().toString());
@ -407,7 +389,7 @@ public abstract class BaseParser implements IParser {
myResources.add(theResource);
}
public void addContained(IdDt theId, IBaseResource theResource) {
public void addContained(IIdType theId, IBaseResource theResource) {
myResourceToId.put(theResource, theId);
myResources.add(theResource);
}
@ -416,7 +398,7 @@ public abstract class BaseParser implements IParser {
return myResources;
}
public IdDt getResourceId(IBaseResource theNext) {
public IIdType getResourceId(IBaseResource theNext) {
return myResourceToId.get(theNext);
}

View File

@ -123,7 +123,7 @@ public interface IParser {
* @throws DataFormatException
* If the resource can not be parsed because the data is not recognized or invalid for any reason
*/
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
IBaseResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
/**
* Parses a resource
@ -134,7 +134,7 @@ public interface IParser {
* @throws DataFormatException
* If the resource can not be parsed because the data is not recognized or invalid for any reason
*/
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
IBaseResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
/**
* Parses a tag list, as defined in the <a href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR Specification</a>.

View File

@ -63,6 +63,7 @@ import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -103,8 +104,8 @@ import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.UrlUtil;
/**
* This class is the FHIR JSON parser/encoder. Users should not interact with this
* class directly, but should use {@link FhirContext#newJsonParser()} to get an instance.
* This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use
* {@link FhirContext#newJsonParser()} to get an instance.
*/
public class JsonParser extends BaseParser implements IParser {
@ -131,7 +132,8 @@ public class JsonParser extends BaseParser implements IParser {
private boolean myPrettyPrint;
/**
* Do not use this constructor, the recommended way to obtain a new instance of the JSON parser is to invoke {@link FhirContext#newJsonParser()}.
* Do not use this constructor, the recommended way to obtain a new instance of the JSON parser is to invoke
* {@link FhirContext#newJsonParser()}.
*/
public JsonParser(FhirContext theContext) {
super(theContext);
@ -323,8 +325,10 @@ public class JsonParser extends BaseParser implements IParser {
// linkStarted = false;
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "self", nextEntry.getLinkSelf(), linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "alternate", nextEntry.getLinkAlternate(), linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "search", nextEntry.getLinkSearch(), linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "alternate", nextEntry.getLinkAlternate(),
// linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "search", nextEntry.getLinkSearch(),
// linkStarted);
// if (linkStarted) {
// theEventWriter.writeEnd();
// }
@ -347,10 +351,21 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd();
}
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue,
BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException {
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException {
switch (theChildDef.getChildType()) {
case ID_DATATYPE: {
IIdType value = (IIdType) theNextValue;
if (isBlank(value.getIdPart())) {
break;
}
if (theChildName != null) {
theWriter.write(theChildName, value.getIdPart());
} else {
theWriter.write(value.getIdPart());
}
break;
}
case PRIMITIVE_DATATYPE: {
IPrimitiveType<?> value = (IPrimitiveType<?>) theNextValue;
if (isBlank(value.getValueAsString())) {
@ -419,17 +434,20 @@ public class JsonParser extends BaseParser implements IParser {
theWriter.writeEnd();
break;
}
case CONTAINED_RESOURCE_LIST:
case CONTAINED_RESOURCES: {
/*
* Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) {
* continue; } encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(next.getId().getValue())); }
* Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next :
* value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; }
* encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true,
* fixContainedResourceId(next.getId().getValue())); }
*/
List<IBaseResource> containedResources = getContainedResources().getContainedResources();
if (containedResources.size() > 0) {
theWriter.writeStartArray(theChildName);
for (IBaseResource next : containedResources) {
IdDt resourceId = getContainedResources().getResourceId(next);
IIdType resourceId = getContainedResources().getResourceId(next);
encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(resourceId.getValue()));
}
@ -437,9 +455,10 @@ public class JsonParser extends BaseParser implements IParser {
}
break;
}
case PRIMITIVE_XHTML_HL7ORG:
case PRIMITIVE_XHTML: {
if (!getSuppressNarratives()) {
XhtmlDt dt = (XhtmlDt) theNextValue;
IPrimitiveType<?> dt = (IPrimitiveType<?>) theNextValue;
if (theChildName != null) {
theWriter.write(theChildName, dt.getValueAsString());
} else {
@ -466,13 +485,12 @@ public class JsonParser extends BaseParser implements IParser {
}
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
for (BaseRuntimeChildDefinition nextChild : theChildren) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue;
}
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
@ -520,7 +538,7 @@ public class JsonParser extends BaseParser implements IParser {
}
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && theIsSubElementWithinResource) {
if ((childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES||childDef.getChildType()==ChildTypeEnum.CONTAINED_RESOURCE_LIST) && theIsSubElementWithinResource) {
continue;
}
@ -624,15 +642,13 @@ public class JsonParser extends BaseParser implements IParser {
}
}
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theIsSubElementWithinResource);
}
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
boolean theContainedResource) throws IOException {
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource) throws IOException {
String resourceId = null;
if (theResource instanceof IResource) {
IResource res = (IResource) theResource;
@ -645,16 +661,15 @@ public class JsonParser extends BaseParser implements IParser {
}
} else if (theResource instanceof IAnyResource) {
IAnyResource res = (IAnyResource) theResource;
if (theContainedResource && StringUtils.isNotBlank(res.getId())) {
resourceId = res.getId();
if (StringUtils.isNotBlank(res.getId().getIdPart())) {
resourceId = res.getId().getIdPart();
}
}
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);
}
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
boolean theContainedResource, String theResourceId) throws IOException {
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource, String theResourceId) throws IOException {
if (!theContainedResource) {
super.containResourcesForEncoding(theResource);
}
@ -688,8 +703,8 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeStartObject("meta");
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart());
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource));
if (profiles != null && profiles.isEmpty()==false) {
if (profiles != null && profiles.isEmpty() == false) {
theEventWriter.writeStartArray("profile");
for (IdDt profile : profiles) {
if (profile != null && isNotBlank(profile.getValue())) {
@ -699,7 +714,7 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd();
}
if (securityLabels.isEmpty()==false) {
if (securityLabels.isEmpty() == false) {
theEventWriter.writeStartArray("security");
for (BaseCodingDt securityLabel : securityLabels) {
theEventWriter.writeStartObject();
@ -709,8 +724,8 @@ public class JsonParser extends BaseParser implements IParser {
}
theEventWriter.writeEnd();
}
if (tags != null && tags.isEmpty()==false) {
if (tags != null && tags.isEmpty() == false) {
theEventWriter.writeStartArray("tag");
for (Tag tag : tags) {
theEventWriter.writeStartObject();
@ -722,7 +737,7 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd();
}
theEventWriter.writeEnd(); //end meta
theEventWriter.writeEnd(); // end meta
}
}
@ -779,10 +794,10 @@ public class JsonParser extends BaseParser implements IParser {
}
/**
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object called _name): resource extensions, and extension extensions
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object
* called _name): resource extensions, and extension extensions
*/
private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
IBaseResource theResource, String theParentExtensionUrl) throws IOException {
private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef, IBaseResource theResource, String theParentExtensionUrl) throws IOException {
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
@ -916,8 +931,7 @@ public class JsonParser extends BaseParser implements IParser {
object = reader.readObject();
} catch (JsonParsingException e) {
if (e.getMessage().startsWith("Unexpected char 39")) {
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage()
+ " - This may indicate that single quotes are being used as JSON escapes where double quotes are required", e);
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage() + " - This may indicate that single quotes are being used as JSON escapes where double quotes are required", e);
}
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage(), e);
}
@ -1154,7 +1168,8 @@ public class JsonParser extends BaseParser implements IParser {
JsonValue jsonVal = nextExt.get(nextKey);
if (jsonVal.getValueType() == ValueType.ARRAY) {
/*
* Extension children which are arrays are sub-extensions. Any other value type should be treated as a value.
* Extension children which are arrays are sub-extensions. Any other value type should be treated as
* a value.
*/
JsonArray arrayValue = (JsonArray) jsonVal;
parseExtensionInDstu2Style(theModifier, theState, extUrl, nextKey, arrayValue);
@ -1278,8 +1293,7 @@ public class JsonParser extends BaseParser implements IParser {
}
}
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
if (extensions.isEmpty() == false) {
theEventWriter.writeStartArray("extension");
for (HeldExtension next : extensions) {

View File

@ -41,6 +41,7 @@ import org.hl7.fhir.instance.model.api.IBaseElement;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
@ -53,6 +54,7 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition;
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.BaseBundle;
@ -1367,6 +1369,37 @@ class ParserState<T> {
}
private class ContainedResourcesStateHl7Org extends PreResourceState {
public ContainedResourcesStateHl7Org(PreResourceState thePreResourcesState) {
super(thePreResourcesState, FhirVersionEnum.DSTU2_HL7ORG);
}
@Override
public void endingElement() throws DataFormatException {
pop();
}
@Override
public void wereBack() {
IBaseResource res = getCurrentElement();
assert res != null;
if (res.getId() == null || res.getId().isEmpty()) {
ourLog.debug("Discarding contained resource with no ID!");
} else {
getPreResourceState().getContainedResources().put(res.getId().getValue(), res);
if (!res.getId().isLocal()) {
res.getId().setValue('#' + res.getId().getIdPart());
}
}
IBaseResource preResCurrentElement = getPreResourceState().getCurrentElement();
RuntimeResourceDefinition def = myContext.getResourceDefinition(preResCurrentElement);
def.getChildByName("contained").getMutator().addValue(preResCurrentElement, res);
}
}
private class DeclaredExtensionState extends BaseState {
private IBase myChildInstance;
@ -1396,7 +1429,7 @@ class ParserState<T> {
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance(myDefinition.getInstanceConstructorArguments());
ICompositeType newChildInstance = (ICompositeType) compositeTarget.newInstance(myDefinition.getInstanceConstructorArguments());
myDefinition.getMutator().addValue(myParentInstance, newChildInstance);
ElementCompositeState newState = new ElementCompositeState(myPreResourceState, compositeTarget, newChildInstance);
push(newState);
@ -1525,6 +1558,7 @@ class ParserState<T> {
push(newState);
return;
}
case ID_DATATYPE:
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance;
@ -1557,6 +1591,14 @@ class ParserState<T> {
push(state);
return;
}
case PRIMITIVE_XHTML_HL7ORG: {
RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition xhtmlTarget = (RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition) target;
IBaseXhtml newDt = xhtmlTarget.newInstance();
child.getMutator().addValue(myInstance, newDt);
XhtmlStateHl7Org state = new XhtmlStateHl7Org(getPreResourceState(), newDt);
push(state);
return;
}
case CONTAINED_RESOURCES: {
List<? extends IBase> values = child.getAccessor().getValues(myInstance);
Object newDt;
@ -1570,6 +1612,11 @@ class ParserState<T> {
push(state);
return;
}
case CONTAINED_RESOURCE_LIST: {
ContainedResourcesStateHl7Org state = new ContainedResourcesStateHl7Org(getPreResourceState());
push(state);
return;
}
case RESOURCE: {
if (myInstance instanceof IResource) {
ParserState<T>.PreResourceStateHapi state = new PreResourceStateHapi(myInstance, child.getMutator(), null);
@ -1650,10 +1697,15 @@ class ParserState<T> {
return;
}
case RESOURCE_REF: {
BaseResourceReferenceDt newChildInstance = (BaseResourceReferenceDt) newResourceReferenceDt(getPreResourceState().myInstance);
ICompositeType newChildInstance = (ICompositeType) newResourceReferenceDt(getPreResourceState().myInstance);
myExtension.setValue(newChildInstance);
ResourceReferenceStateHapi newState = new ResourceReferenceStateHapi(getPreResourceState(), newChildInstance);
push(newState);
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
ParserState<T>.ResourceReferenceStateHl7Org newState = new ResourceReferenceStateHl7Org(getPreResourceState(), (IReference) newChildInstance);
push(newState);
} else {
ResourceReferenceStateHapi newState = new ResourceReferenceStateHapi(getPreResourceState(), (BaseResourceReferenceDt) newChildInstance);
push(newState);
}
return;
}
case PRIMITIVE_XHTML:
@ -2015,6 +2067,19 @@ class ParserState<T> {
}
}
}
}else if (theElement instanceof IReference) {
IReference nextRef = (IReference) theElement;
String ref = nextRef.getReference().getValue();
if (isNotBlank(ref)) {
if (ref.startsWith("#")) {
IBaseResource target = myContainedResources.get(ref.substring(1));
if (target != null) {
nextRef.setResource(target);
} else {
ourLog.warn("Resource contains unknown local ref: " + ref);
}
}
}
}
}
@ -2454,6 +2519,26 @@ class ParserState<T> {
}
private class XhtmlStateHl7Org extends XhtmlState {
private IBaseXhtml myHl7OrgDatatype;
private XhtmlStateHl7Org(PreResourceState thePreResourceState, IBaseXhtml theHl7OrgDatatype) {
super(thePreResourceState, new XhtmlDt(), true);
myHl7OrgDatatype = theHl7OrgDatatype;
}
@Override
public void doPop() {
// TODO: this is not very efficient
String value = getDt().getValueAsString();
myHl7OrgDatatype.setValueAsString(value);
super.doPop();
}
}
private class XhtmlState extends BaseState {
private int myDepth;
private XhtmlDt myDt;
@ -2467,6 +2552,10 @@ class ParserState<T> {
myIncludeOuterEvent = theIncludeOuterEvent;
}
public XhtmlDt getDt() {
return myDt;
}
@Override
public void attributeValue(String theName, String theValue) throws DataFormatException {
if (myJsonMode) {
@ -2476,10 +2565,14 @@ class ParserState<T> {
super.attributeValue(theName, theValue);
}
protected void doPop() {
pop();
}
@Override
public void endingElement() throws DataFormatException {
if (myJsonMode) {
pop();
doPop();
return;
}
super.endingElement();
@ -2507,7 +2600,7 @@ class ParserState<T> {
if (theEvent.isEndElement()) {
if (myDepth == 0) {
myDt.setValue(myEvents);
pop();
doPop();
}
}
}

View File

@ -56,8 +56,11 @@ import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.INarrative;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -66,6 +69,7 @@ import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildContainedResources;
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
@ -93,11 +97,11 @@ import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
import ca.uhn.fhir.util.XmlUtil;
/**
* This class is the FHIR XML parser/encoder. Users should not interact with this
* class directly, but should use {@link FhirContext#newXmlParser()} to get an instance.
* This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use
* {@link FhirContext#newXmlParser()} to get an instance.
*/
public class XmlParser extends BaseParser implements IParser {
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
static final String FHIR_NS = "http://hl7.org/fhir";
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
@ -113,7 +117,8 @@ public class XmlParser extends BaseParser implements IParser {
private boolean myPrettyPrint;
/**
* Do not use this constructor, the recommended way to obtain a new instance of the XML parser is to invoke {@link FhirContext#newXmlParser()}.
* Do not use this constructor, the recommended way to obtain a new instance of the XML parser is to invoke
* {@link FhirContext#newXmlParser()}.
*/
public XmlParser(FhirContext theContext) {
super(theContext);
@ -442,10 +447,9 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.close();
}
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef,
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
if (nextValue.isEmpty()) {
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
if (nextValue == null || nextValue.isEmpty()) {
if (isChildContained(childDef, theIncludedResource)) {
// We still want to go in..
} else {
return;
@ -453,6 +457,17 @@ public class XmlParser extends BaseParser implements IParser {
}
switch (childDef.getChildType()) {
case ID_DATATYPE: {
IIdType pd = (IIdType) nextValue;
String value = pd.getIdPart();
if (value != null) {
theEventWriter.writeStartElement(childName);
theEventWriter.writeAttribute("value", value);
encodeExtensionsIfPresent(theResource, theEventWriter, nextValue, theIncludedResource);
theEventWriter.writeEndElement();
}
break;
}
case PRIMITIVE_DATATYPE: {
IPrimitiveType<?> pd = (IPrimitiveType<?>) nextValue;
String value = pd.getValueAsString();
@ -476,7 +491,7 @@ public class XmlParser extends BaseParser implements IParser {
break;
}
case RESOURCE_REF: {
BaseResourceReferenceDt ref = (BaseResourceReferenceDt) nextValue;
IReference ref = (IReference) nextValue;
if (!ref.isEmpty()) {
theEventWriter.writeStartElement(childName);
encodeResourceReferenceToStreamWriter(theEventWriter, ref);
@ -484,15 +499,16 @@ public class XmlParser extends BaseParser implements IParser {
}
break;
}
case CONTAINED_RESOURCE_LIST:
case CONTAINED_RESOURCES: {
BaseContainedDt value = (BaseContainedDt) nextValue;
/*
* Disable per #103 for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; }
* theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(next.getId().getValue()));
* theEventWriter.writeEndElement(); }
* Disable per #103 for (IResource next : value.getContainedResources()) { if
* (getContainedResources().getResourceId(next) != null) { continue; }
* theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter,
* true, fixContainedResourceId(next.getId().getValue())); theEventWriter.writeEndElement(); }
*/
for (IBaseResource next : getContainedResources().getContainedResources()) {
IdDt resourceId = getContainedResources().getResourceId(next);
IIdType resourceId = getContainedResources().getResourceId(next);
theEventWriter.writeStartElement("contained");
encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(resourceId.getValue()));
theEventWriter.writeEndElement();
@ -513,6 +529,18 @@ public class XmlParser extends BaseParser implements IParser {
}
break;
}
case PRIMITIVE_XHTML_HL7ORG: {
IBaseXhtml dt = (IBaseXhtml) nextValue;
if (dt.isEmpty()) {
break;
} else {
// TODO: this is probably not as efficient as it could be
XhtmlDt hdt = new XhtmlDt();
hdt.setValueAsString(dt.getValueAsString());
encodeXhtml(hdt, theEventWriter);
break;
}
}
case EXTENSION_DECLARED:
case UNDECL_EXT: {
throw new IllegalStateException("state should not happen: " + childDef.getName());
@ -521,12 +549,14 @@ public class XmlParser extends BaseParser implements IParser {
}
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (BaseRuntimeChildDefinition nextChild : children) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue;
}
if (nextChild.getElementName().equals("id")) {
continue;
}
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
@ -544,67 +574,74 @@ public class XmlParser extends BaseParser implements IParser {
continue;
}
} else {
INarrative narr1 = ((IDomainResource) theResource).getText();
BaseNarrativeDt<?> narr2 = null;
if (gen != null && narr1.isEmpty()) {
// TODO: need to implement this
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
gen.generateNarrative(resourceProfile, theResource, null);
}
if (narr2 != null) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
continue;
}
// Narrative generation not currently supported for HL7org structures
// INarrative narr1 = ((IDomainResource) theResource).getText();
// BaseNarrativeDt<?> narr2 = null;
// if (gen != null && narr1.isEmpty()) {
// // TODO: need to implement this
// String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
// gen.generateNarrative(resourceProfile, theResource, null);
// }
// if (narr2 != null) {
// RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
// String childName = nextChild.getChildNameByDatatype(child.getDatatype());
// BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
// encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
// continue;
// }
}
}
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
if (values == null || values.isEmpty()) {
continue;
}
for (IBase nextValue : values) {
if ((nextValue == null || nextValue.isEmpty()) && !(nextValue instanceof BaseContainedDt)) {
if (nextChild instanceof RuntimeChildContainedResources) {
if (!theIncludedResource) {
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theIncludedResource);
}
} else {
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
if (values == null || values.isEmpty()) {
continue;
}
Class<? extends IBase> type = nextValue.getClass();
String childName = nextChild.getChildNameByDatatype(type);
String extensionUrl = nextChild.getExtensionUrl();
BaseRuntimeElementDefinition<?> childDef = nextChild.getChildElementDefinitionByDatatype(type);
if (childDef == null) {
super.throwExceptionForUnknownChildType(nextChild, type);
}
if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
// This is called for the Query resource in DSTU1 only
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
} else if (extensionUrl != null && childName.equals("extension") == false) {
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
if (extDef.isModifier()) {
theEventWriter.writeStartElement("modifierExtension");
} else {
theEventWriter.writeStartElement("extension");
for (IBase nextValue : values) {
if ((nextValue == null || nextValue.isEmpty())) {
continue;
}
Class<? extends IBase> type = nextValue.getClass();
String childName = nextChild.getChildNameByDatatype(type);
String extensionUrl = nextChild.getExtensionUrl();
BaseRuntimeElementDefinition<?> childDef = nextChild.getChildElementDefinitionByDatatype(type);
if (childDef == null) {
super.throwExceptionForUnknownChildType(nextChild, type);
}
theEventWriter.writeAttribute("url", extensionUrl);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
theEventWriter.writeEndElement();
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) {
// suppress narratives from contained resources
} else {
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
// This is called for the Query resource in DSTU1 only
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
} else if (extensionUrl != null && childName.equals("extension") == false) {
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
if (extDef.isModifier()) {
theEventWriter.writeStartElement("modifierExtension");
} else {
theEventWriter.writeStartElement("extension");
}
theEventWriter.writeAttribute("url", extensionUrl);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
theEventWriter.writeEndElement();
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) {
// suppress narratives from contained resources
} else {
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
}
}
}
}
}
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
@ -627,8 +664,9 @@ public class XmlParser extends BaseParser implements IParser {
}
/**
* This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?>> seems to be
* rejected by the compiler some of the time.
* This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to
* java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?>> seems to be rejected by the compiler
* some of the time.
*/
private <Q extends IBaseExtension<?>> List<IBaseExtension<?>> toBaseExtensionList(final List<Q> theList) {
List<IBaseExtension<?>> retVal = new ArrayList<IBaseExtension<?>>(theList.size());
@ -636,7 +674,7 @@ public class XmlParser extends BaseParser implements IParser {
return retVal;
}
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, BaseResourceReferenceDt theRef) throws XMLStreamException {
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, IReference theRef) throws XMLStreamException {
String reference = determineReferenceText(theRef);
if (StringUtils.isNotBlank(reference)) {
@ -651,11 +689,10 @@ public class XmlParser extends BaseParser implements IParser {
}
}
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
/*
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy way to make that happen, but hopefully this won't matter as much once we use the
* HL7 structures
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy
* way to make that happen, but hopefully this won't matter as much once we use the HL7 structures
*/
List<BaseRuntimeChildDefinition> preExtensionChildren = new ArrayList<BaseRuntimeChildDefinition>();
@ -708,14 +745,14 @@ public class XmlParser extends BaseParser implements IParser {
if (theResource instanceof IResource) {
// HAPI structs
IResource iResource = (IResource) theResource;
if (StringUtils.isNotBlank(iResource.getId().getValue())) {
if (StringUtils.isNotBlank(iResource.getId().getIdPart())) {
resourceId = iResource.getId().getIdPart();
}
} else {
// HL7 structs
IAnyResource resource = (IAnyResource) theResource;
if (StringUtils.isNotBlank(resource.getId())) {
resourceId = resource.getId();
if (StringUtils.isNotBlank(resource.getId().getIdPart())) {
resourceId = resource.getId().getIdPart();
}
}
@ -736,8 +773,9 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeDefaultNamespace(FHIR_NS);
if (theResource instanceof IAnyResource) {
// HL7.org Structures
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
} else {
@ -850,8 +888,7 @@ public class XmlParser extends BaseParser implements IParser {
}
}
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource)
throws XMLStreamException, DataFormatException {
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (IBaseExtension<?> next : theExtensions) {
if (next == null) {
continue;

View File

@ -40,6 +40,7 @@ import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -266,7 +267,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return myLastRequest;
}
protected String getPreferredId(IResource theResource, String theId) {
protected String getPreferredId(IBaseResource theResource, String theId) {
if (isNotBlank(theId)) {
return theId;
}
@ -574,7 +575,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return resp;
}
protected IResource parseResourceBody(String theResourceBody) {
protected IBaseResource parseResourceBody(String theResourceBody) {
EncodingEnum encoding = null;
for (int i = 0; i < theResourceBody.length() && encoding == null; i++) {
switch (theResourceBody.charAt(i)) {
@ -625,7 +626,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private CriterionList myCriterionList;
private String myId;
private IResource myResource;
private IBaseResource myResource;
private String myResourceBody;
private String mySearchUrl;
@ -1597,8 +1598,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
private CriterionList myCriterionList;
private IdDt myId;
private IResource myResource;
private IIdType myId;
private IBaseResource myResource;
private String myResourceBody;
private String mySearchUrl;

View File

@ -26,9 +26,13 @@ import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import ca.uhn.fhir.model.api.Include;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.IBaseResource;
@ -36,6 +40,7 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
@ -123,7 +128,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
return myParameters;
}
public Set<Include> getRequestIncludesFromParams(Object[] params) {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Set<Include> getRequestIncludesFromParams(Object[] params) {
if (params == null || params.length == 0)
return null;
int index = 0;
@ -148,7 +154,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
Set includes = new HashSet<Include>();
for (Object o : (Iterable)params[index]) {
if (o instanceof Include) {
includes.add((Include) o);
includes.add(o);
}
}
return includes;
@ -215,7 +221,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
return parser;
}
protected Object[] createParametersForServerRequest(Request theRequest, IResource theResource) {
protected Object[] createParametersForServerRequest(Request theRequest, IBaseResource theResource) {
Object[] params = new Object[getParameters().size()];
for (int i = 0; i < getParameters().size(); i++) {
IParameter param = getParameters().get(i);

View File

@ -37,6 +37,7 @@ import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
@ -143,16 +144,18 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
@Override
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
IResource resource;
IBaseResource resource;
if (requestContainsResource()) {
resource = parseIncomingServerResource(theRequest);
TagList tagList = new TagList();
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
String nextTagComplete = enumeration.nextElement();
MethodUtil.parseTagValue(tagList, nextTagComplete);
}
if (tagList.isEmpty() == false) {
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
if (theServer.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
TagList tagList = new TagList();
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
String nextTagComplete = enumeration.nextElement();
MethodUtil.parseTagValue(tagList, nextTagComplete);
}
if (tagList.isEmpty() == false) {
((IResource)resource).getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
}
}
} else {
resource = null;
@ -268,21 +271,21 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
/**
* @throws IOException
*/
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
IParser parser = encoding.newParser(getContext());
BufferedReader requestReader = theRequest.getServletRequest().getReader();
Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType();
IResource retVal;
IBaseResource retVal;
if (wantedResourceType != null) {
retVal = (IResource) parser.parseResource(wantedResourceType, requestReader);
retVal = parser.parseResource(wantedResourceType, requestReader);
} else {
retVal = parser.parseResource(requestReader);
}
retVal.setId(theRequest.getId());
return retVal;
}
@ -294,10 +297,9 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
protected boolean requestContainsResource() {
return true;
}
/**
* Subclasses may override to provide a specific resource type that this method wants
* as a parameter
* Subclasses may override to provide a specific resource type that this method wants as a parameter
*/
protected Class<? extends IBaseResource> requestContainsResourceType() {
return null;
@ -307,7 +309,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
theResponse.setStatus(theE.getStatusCode());
theServer.addHeadersToResponse(theResponse);
if (theE.getOperationOutcome() != null) {
theResponse.setContentType(theEncodingNotNull.getResourceContentType());
IParser parser = theEncodingNotNull.newParser(theServer.getFhirContext());

View File

@ -94,7 +94,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
}
@Override
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
if (myBinary) {
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
byte[] contents = IOUtils.toByteArray(theRequest.getServletRequest().getInputStream());
@ -103,7 +103,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
binary.setContentType(ct);
binary.setContent(contents);
return (IResource) binary;
return binary;
} else {
return super.parseIncomingServerResource(theRequest);
}

View File

@ -188,7 +188,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
break;
}
case RESOURCE: {
IResource resource;
IBaseResource resource;
if (myResourceType != null) {
resource = parser.parseResource(myResourceType, theResponseReader);
} else {
@ -199,7 +199,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
switch (getMethodReturnType()) {
case BUNDLE:
return Bundle.withSingleResource(resource);
return Bundle.withSingleResource((IResource) resource);
case LIST_OF_RESOURCES:
return Collections.singletonList(resource);
case RESOURCE:

View File

@ -25,6 +25,8 @@ import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
@ -55,8 +57,8 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
}
@Override
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
IResource retVal = super.parseIncomingServerResource(theRequest);
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
IBaseResource retVal = super.parseIncomingServerResource(theRequest);
if (theRequest.getId() != null && theRequest.getId().hasIdPart()) {
retVal.setId(theRequest.getId());

View File

@ -23,13 +23,13 @@ package ca.uhn.fhir.rest.method;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.AbstractHttpEntity;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContents {
public HttpPutClientInvocation(FhirContext theContext, IResource theResource, String theUrlExtension) {
public HttpPutClientInvocation(FhirContext theContext, IBaseResource theResource, String theUrlExtension) {
super(theContext, theResource, theUrlExtension);
}

View File

@ -1,7 +1,6 @@
package ca.uhn.fhir.rest.method;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.io.PushbackReader;
@ -27,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IMetaType;
import ca.uhn.fhir.context.ConfigurationException;
@ -108,12 +108,14 @@ public class MethodUtil {
private static final String SCHEME = "scheme=\"";
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
static void addTagsToPostOrPut(FhirContext theContext, IBaseResource resource, BaseHttpClientInvocation retVal) {
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
TagList list = (TagList) ((IResource)resource).getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
}
}
}
}
@ -123,11 +125,11 @@ public class MethodUtil {
return new HttpGetClientInvocation("metadata");
}
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, FhirContext theContext) {
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, FhirContext theContext) {
return createCreateInvocation(theResource, null, null, theContext);
}
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext) {
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, String theResourceBody, String theId, FhirContext theContext) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
String resourceName = def.getName();
@ -145,26 +147,26 @@ public class MethodUtil {
} else {
retVal = new HttpPostClientInvocation(theContext, theResourceBody, false, urlExtension.toString());
}
addTagsToPostOrPut(theResource, retVal);
addTagsToPostOrPut(theContext, theResource, retVal);
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
return retVal;
}
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, Map<String, List<String>> theIfNoneExistParams) {
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, String theResourceBody, String theId, FhirContext theContext, Map<String, List<String>> theIfNoneExistParams) {
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
retVal.setIfNoneExistParams(theIfNoneExistParams);
return retVal;
}
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, String theIfNoneExistUrl) {
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, String theResourceBody, String theId, FhirContext theContext, String theIfNoneExistUrl) {
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
retVal.setIfNoneExistString(theIfNoneExistUrl);
return retVal;
}
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, String theResourceBody, IdDt theId, FhirContext theContext) {
public static HttpPutClientInvocation createUpdateInvocation(IBaseResource theResource, String theResourceBody, IIdType theId, FhirContext theContext) {
String resourceName = theContext.getResourceDefinition(theResource).getName();
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(resourceName);
@ -194,13 +196,13 @@ public class MethodUtil {
}
}
addTagsToPostOrPut(theResource, retVal);
addTagsToPostOrPut(theContext, theResource, retVal);
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
return retVal;
}
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, Map<String, List<String>> theMatchParams) {
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IBaseResource theResource, String theResourceBody, Map<String, List<String>> theMatchParams) {
StringBuilder b = new StringBuilder();
String resourceType = theContext.getResourceDefinition(theResource).getName();
@ -221,7 +223,6 @@ public class MethodUtil {
}
}
HttpPutClientInvocation retVal;
if (StringUtils.isBlank(theResourceBody)) {
retVal = new HttpPutClientInvocation(theContext, theResource, b.toString());
@ -229,12 +230,12 @@ public class MethodUtil {
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, b.toString());
}
addTagsToPostOrPut(theResource, retVal);
addTagsToPostOrPut(theContext, theResource, retVal);
return retVal;
}
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, String theMatchUrl) {
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IBaseResource theResource, String theResourceBody, String theMatchUrl) {
HttpPutClientInvocation retVal;
if (StringUtils.isBlank(theResourceBody)) {
retVal = new HttpPutClientInvocation(theContext, theResource, theMatchUrl);
@ -242,7 +243,7 @@ public class MethodUtil {
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, theMatchUrl);
}
addTagsToPostOrPut(theResource, retVal);
addTagsToPostOrPut(theContext, theResource, retVal);
return retVal;
}
@ -250,10 +251,10 @@ public class MethodUtil {
public static EncodingEnum detectEncoding(String theBody) {
for (int i = 0; i < theBody.length(); i++) {
switch (theBody.charAt(i)) {
case '<':
return EncodingEnum.XML;
case '{':
return EncodingEnum.JSON;
case '<':
return EncodingEnum.XML;
case '{':
return EncodingEnum.JSON;
}
}
return EncodingEnum.XML;
@ -406,7 +407,7 @@ public class MethodUtil {
param = new ConditionalParamBinder(theRestfulOperationTypeEnum);
} else if (nextAnnotation instanceof OperationParam) {
Operation op = theMethod.getAnnotation(Operation.class);
param = new OperationParamBinder(op.name(), (OperationParam)nextAnnotation);
param = new OperationParamBinder(op.name(), (OperationParam) nextAnnotation);
} else {
continue;
}
@ -519,26 +520,26 @@ public class MethodUtil {
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
QueryParameterAndBinder binder = null;
switch (theParamDef.getParamType()) {
case COMPOSITE:
throw new UnsupportedOperationException();
case DATE:
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case NUMBER:
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case QUANTITY:
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case REFERENCE:
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case STRING:
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case TOKEN:
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
break;
case COMPOSITE:
throw new UnsupportedOperationException();
case DATE:
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
case NUMBER:
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
case QUANTITY:
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
case REFERENCE:
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
case STRING:
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
case TOKEN:
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
break;
}
return binder.parse(theUnqualifiedParamName, theParameters);
@ -657,7 +658,7 @@ public class MethodUtil {
if (reader != null) {
IParser parser = ct.newParser(theContext);
IResource outcome = parser.parseResource(reader);
IBaseResource outcome = parser.parseResource(reader);
if (outcome instanceof BaseOperationOutcome) {
retVal.setOperationOutcome((BaseOperationOutcome) outcome);
}

View File

@ -23,6 +23,8 @@ package ca.uhn.fhir.util;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.ICompositeElement;
import ca.uhn.fhir.model.api.IElement;
@ -41,7 +43,7 @@ public class ElementUtil {
}
} else if (next instanceof String && (!((String)next).isEmpty())) {
return false;
} else if (next != null && !((IElement) next).isEmpty()) {
} else if (next != null && !((IBase) next).isEmpty()) {
return false;
}
}

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
@ -29,6 +30,7 @@ import java.util.TreeSet;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -39,7 +41,6 @@ import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeChildDirectResource;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
@ -56,8 +57,7 @@ public class FhirTerser {
myContext = theContext;
}
private <T extends IBase> void addUndeclaredExtensions(IBase theElement, BaseRuntimeElementDefinition<?> theDefinition, BaseRuntimeChildDefinition theChildDefinition,
IModelVisitor theCallback) {
private void addUndeclaredExtensions(IBase theElement, BaseRuntimeElementDefinition<?> theDefinition, BaseRuntimeChildDefinition theChildDefinition, IModelVisitor theCallback) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
@ -68,14 +68,17 @@ public class FhirTerser {
}
/**
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are either of the exact type specified, or are a subclass of that type.
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are
* either of the exact type specified, or are a subclass of that type.
* <p>
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within the message. Specifying a type of {@link IResource} would return the resource itself, as
* well as any contained resources.
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within the
* message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained
* resources.
* </p>
* <p>
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g.
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource)
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
* resources (e.g. Bundle.entry.resource)
* </p>
*
* @param theResource
@ -102,8 +105,7 @@ public class FhirTerser {
@SuppressWarnings("unchecked")
@Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition,
ExtensionDt theNextExt) {
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
if (theType.isAssignableFrom(theNextExt.getClass())) {
retVal.add((T) theNextExt);
}
@ -115,39 +117,39 @@ public class FhirTerser {
return retVal;
}
public <T extends IBase> List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, new IModelVisitor() {
@SuppressWarnings("unchecked")
@Override
public void acceptElement(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
if (theElement == null || theElement.isEmpty()) {
return;
}
String name = null;
if (theChildDefinition != null) {
name = theChildDefinition.getElementName();
}
if (BaseResourceReferenceDt.class.isAssignableFrom(theElement.getClass())) {
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt)theElement));
}
}
public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, new IModelVisitor() {
@Override
public void acceptElement(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
if (theElement == null || theElement.isEmpty()) {
return;
}
String name = null;
if (theChildDefinition != null) {
name = theChildDefinition.getElementName();
}
if (BaseResourceReferenceDt.class.isAssignableFrom(theElement.getClass())) {
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt) theElement));
}
}
@SuppressWarnings("unchecked")
@Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition,
ExtensionDt theNextExt) {
String name = null;
if (theChildDefinition != null) {
name = theChildDefinition.getElementName();
}
if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) {
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt)theNextExt.getValue()));
}
}
});
return retVal; } private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
@Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
String name = null;
if (theChildDefinition != null) {
name = theChildDefinition.getElementName();
}
if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) {
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt) theNextExt.getValue()));
}
}
});
return retVal;
}
private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));
if (theSubList.size() == 1) {
@ -229,17 +231,16 @@ public class FhirTerser {
// }
switch (theDefinition.getChildType()) {
// case RESOURCE:
// // Don't descend into embedded resources
// break;
case ID_DATATYPE:
case PRIMITIVE_XHTML_HL7ORG:
case PRIMITIVE_XHTML:
case PRIMITIVE_DATATYPE:
// These are primitive types
break;
case RESOURCE_REF:
BaseResourceReferenceDt resRefDt = (BaseResourceReferenceDt) theElement;
IReference resRefDt = (IReference) theElement;
if (resRefDt.getReference().getValue() == null && resRefDt.getResource() != null) {
IResource theResource = resRefDt.getResource();
IBaseResource theResource = resRefDt.getResource();
if (theResource.getId() == null || theResource.getId().isEmpty() || theResource.getId().isLocal()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, theCallback);
@ -248,7 +249,7 @@ public class FhirTerser {
break;
case RESOURCE:
case RESOURCE_BLOCK:
case COMPOSITE_DATATYPE: {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition;
for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) {
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
@ -281,7 +282,7 @@ public class FhirTerser {
}
throw new DataFormatException(b.toString());
}
if (nextChild instanceof RuntimeChildDirectResource) {
// Don't descend into embedded resources
theCallback.acceptElement(nextValue, nextChild, childElementDef);
@ -305,16 +306,147 @@ public class FhirTerser {
case UNDECL_EXT: {
throw new IllegalStateException("state should not happen: " + theDefinition.getChildType());
}
case CONTAINED_RESOURCE_LIST:
if (theElement != null) {
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theElement.getClass());
visit(theElement, null, def, theCallback);
}
break;
}
}
private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor2 theCallback, List<IBase> theContainingElementPath, List<BaseRuntimeChildDefinition> theChildDefinitionPath,
List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath) {
if (theChildDefinition != null) {
theChildDefinitionPath.add(theChildDefinition);
}
theContainingElementPath.add(theElement);
theElementDefinitionPath.add(theDefinition);
theCallback.acceptElement(theElement, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), Collections.unmodifiableList(theElementDefinitionPath));
/*
* Visit undeclared extensions
*/
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
theContainingElementPath.add(nextExt);
theCallback.acceptUndeclaredExtension(nextExt, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath);
theContainingElementPath.remove(theContainingElementPath.size() - 1);
}
}
/*
* Now visit the children of the given element
*/
switch (theDefinition.getChildType()) {
case ID_DATATYPE:
case PRIMITIVE_XHTML_HL7ORG:
case PRIMITIVE_XHTML:
case PRIMITIVE_DATATYPE:
// These are primitive types, so we don't need to visit their children
break;
case RESOURCE_REF:
IReference resRefDt = (IReference) theElement;
if (resRefDt.getReference().getValue() == null && resRefDt.getResource() != null) {
IBaseResource theResource = resRefDt.getResource();
if (theResource.getId() == null || theResource.getId().isEmpty() || theResource.getId().isLocal()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath);
}
}
break;
case RESOURCE:
case RESOURCE_BLOCK:
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition;
for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) {
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
if (values != null) {
for (IBase nextValue : values) {
if (nextValue == null) {
continue;
}
if (nextValue.isEmpty()) {
continue;
}
BaseRuntimeElementDefinition<?> childElementDef;
childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
if (childElementDef == null) {
StringBuilder b = new StringBuilder();
b.append("Found value of type[");
b.append(nextValue.getClass().getSimpleName());
b.append("] which is not valid for field[");
b.append(nextChild.getElementName());
b.append("] in ");
b.append(childDef.getName());
b.append(" - Valid types: ");
for (Iterator<String> iter = new TreeSet<String>(nextChild.getValidChildNames()).iterator(); iter.hasNext();) {
BaseRuntimeElementDefinition<?> childByName = nextChild.getChildByName(iter.next());
b.append(childByName.getImplementingClass().getSimpleName());
if (iter.hasNext()) {
b.append(", ");
}
}
throw new DataFormatException(b.toString());
}
if (nextChild instanceof RuntimeChildDirectResource) {
// Don't descend into embedded resources
theContainingElementPath.add(nextValue);
theChildDefinitionPath.add(nextChild);
theElementDefinitionPath.add(myContext.getElementDefinition(nextValue.getClass()));
theCallback.acceptElement(nextValue, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), Collections.unmodifiableList(theElementDefinitionPath));
theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1);
theContainingElementPath.remove(theContainingElementPath.size() - 1);
theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1);
} else {
visit(nextValue, nextChild, childElementDef, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath);
}
}
}
}
break;
}
case CONTAINED_RESOURCES: {
BaseContainedDt value = (BaseContainedDt) theElement;
for (IResource next : value.getContainedResources()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next);
visit(next, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath);
}
break;
}
case EXTENSION_DECLARED:
case UNDECL_EXT: {
throw new IllegalStateException("state should not happen: " + theDefinition.getChildType());
}
case CONTAINED_RESOURCE_LIST: {
if (theElement != null) {
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theElement.getClass());
visit(theElement, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath);
}
break;
}
}
if (theChildDefinition != null) {
theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1);
}
theContainingElementPath.remove(theContainingElementPath.size() - 1);
theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1);
}
/**
* Visit all elements in a given resource
*
* <p>
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g.
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource)
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
* resources (e.g. Bundle.entry.resource)
* </p>
*
* @param theResource
* The resource to visit
* @param theVisitor
@ -325,15 +457,36 @@ public class FhirTerser {
visit(theResource, null, def, theVisitor);
}
/**
* Visit all elements in a given resource
*
* THIS ALTERNATE METHOD IS STILL EXPERIMENTAL
*
* <p>
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
* resources (e.g. Bundle.entry.resource)
* </p>
*
* @param theResource
* The resource to visit
* @param theVisitor
* The visitor
*/
void visit(IBaseResource theResource, IModelVisitor2 theVisitor) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, theVisitor, new ArrayList<IBase>(), new ArrayList<BaseRuntimeChildDefinition>(), new ArrayList<BaseRuntimeElementDefinition<?>>());
}
public Object getSingleValueOrNull(IBase theTarget, String thePath) {
Validate.notNull(theTarget, "theTarget must not be null");
Validate.notBlank(thePath, "thePath must not be empty");
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theTarget.getClass());
if (!(def instanceof BaseRuntimeElementCompositeDefinition)) {
throw new IllegalArgumentException("Target is not a composite type: " + theTarget.getClass().getName());
}
BaseRuntimeElementCompositeDefinition<?> currentDef = (BaseRuntimeElementCompositeDefinition<?>) def;
Object currentObj = theTarget;

View File

@ -0,0 +1,49 @@
package ca.uhn.fhir.util;
/*
* #%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%
*/
import java.util.List;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
/**
* @see FhirTerser#visit(IBaseResource, IModelVisitor2)
*/
public interface IModelVisitor2 {
/**
* @param theElement The element being visited
* @param theContainingElementPath The elements in the path leading up to the actual element being accepted. The first element in this path will be the outer resource being visited, and the last element will be the saem object as the object passed as <code>theElement</code>
*/
boolean acceptElement(IBase theElement, List<IBase> theContainingElementPath, List<BaseRuntimeChildDefinition> theChildDefinitionPath, List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath);
/**
*/
boolean acceptUndeclaredExtension(IBaseExtension<?> theNextExt, List<IBase> theContainingElementPath, List<BaseRuntimeChildDefinition> theChildDefinitionPath, List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath);
}

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.api.IIdType;
/*
* #%L
* HAPI FHIR - Core Library
@ -29,5 +31,11 @@ package org.hl7.fhir.instance.model;
* <code>ca.uhn.fhir.model.dstu.resource.Patient</code>)
*/
public interface IBaseResource extends IBase {
// nothing here yet
IIdType getId();
IBaseResource setId(String theId);
IBaseResource setId(IIdType theId);
}

View File

@ -24,7 +24,7 @@ import org.hl7.fhir.instance.model.IBaseResource;
public interface IAnyResource extends IBaseResource {
String getId();
IIdType getId();
IAnyResource setId(String theId);

View File

@ -1,4 +1,6 @@
package org.hl7.fhir.instance.model;
package org.hl7.fhir.instance.model.api;
import org.hl7.fhir.instance.model.IPrimitiveType;
/*
* #%L
@ -20,14 +22,8 @@ package org.hl7.fhir.instance.model;
* #L%
*/
/**
* For now, this is a simple marker interface indicating that a class is a resource type.
* There are two concrete types of implementations of this interrface. The first are
* HL7.org's Resource structures (e.g.
* <code>org.hl7.fhir.instance.model.Patient</code>) and
* the second are HAPI's Resource structures, e.g.
* <code>ca.uhn.fhir.model.dstu.resource.Patient</code>)
*/
public interface IBaseResource extends IBase {
// nothing here yet
public interface IBaseEnumeration<T extends Enum<?>> extends IPrimitiveType<T> {
// Marker interface
}

View File

@ -0,0 +1,7 @@
package org.hl7.fhir.instance.model.api;
import org.hl7.fhir.instance.model.IPrimitiveType;
public interface IBaseXhtml extends IPrimitiveType<String> {
}

View File

@ -25,4 +25,34 @@ public interface IIdType {
boolean isEmpty();
boolean isLocal();
/**
* 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();
/**
* 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();
boolean hasIdPart();
String getBaseUrl();
IIdType toUnqualifiedVersionless();
IIdType toVersionless();
IIdType setValue(String theString);
boolean hasVersionIdPart();
String getVersionIdPart();
}

View File

@ -26,4 +26,10 @@ public interface INarrative extends ICompositeType {
boolean isEmpty();
// TODO: use less broad exception type here
public void setDivAsString(String theString) throws Exception;
// TODO: use less broad exception type here
public String getDivAsString() throws Exception;
}

View File

@ -21,16 +21,20 @@ package org.hl7.fhir.instance.model.api;
*/
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
public interface IReference extends IBase {
IAnyResource getResource();
IBaseResource getResource();
void setResource(IAnyResource theResource);
void setResource(IBaseResource theResource);
String getReference();
IIdType getReference();
IReference setReference(String theReference);
IBase setDisplay(String theValue);
IPrimitiveType<String> getDisplayElement();
}

View File

@ -122,12 +122,13 @@ public abstract class BaseResource extends BaseElement implements IResource {
myId = theId;
}
public void setId(String theId) {
public BaseResource setId(String theId) {
if (theId == null) {
myId = null;
} else {
myId = new IdDt(theId);
}
return this;
}
@Override

View File

@ -5,11 +5,15 @@ import static org.junit.Assert.*;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.BeforeClass;
import org.junit.Test;
@ -26,6 +30,7 @@ import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
import ca.uhn.fhir.model.dstu2.composite.DurationDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance;
import ca.uhn.fhir.model.dstu2.resource.Binary;
@ -36,6 +41,7 @@ import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.DocumentReferenceStatusEnum;
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
@ -54,6 +60,204 @@ public class XmlParserDstu2Test {
XMLUnit.setIgnoreWhitespace(true);
}
@Test
public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary();
b.setContent(new byte[] {1,2,3,4});
String output = ourCtx.newXmlParser().encodeResourceToString(b);
ourLog.info(output);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
}
@Test
public void testEncodeNonContained() {
// Create an organization
Organization org = new Organization();
org.setId("Organization/65546");
org.getNameElement().setValue("Contained Test Organization");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getManagingOrganization().setResource(org);
// Create a list containing both resources. In a server method, you might just
// return this list, but here we will create a bundle to encode.
List<IBaseResource> resources = new ArrayList<IBaseResource>();
resources.add(org);
resources.add(patient);
// Create a bundle with both
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
b.addEntry().setResource(org);
b.addEntry().setResource(patient);
// Encode the buntdle
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, not(containsString("<contained>")));
assertThat(encoded, stringContainsInOrder("<Organization", "<id value=\"65546\"/>", "</Organization>"));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
assertThat(encoded, stringContainsInOrder("<Patient", "<id value=\"1333\"/>", "</Patient>"));
encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, not(containsString("<contained>")));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
}
@Test
public void testParseNarrative() throws Exception {
//@formatter:off
String htmlNoNs = "<div>AAA<b>BBB</b>CCC</div>";
String htmlNs = htmlNoNs.replace("<div>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">");
String res= "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <id value=\"1333\"/>\n" +
" <text>\n" +
" " + htmlNs + "\n" +
" </text>\n" +
"</Patient>";
//@formatter:on
Patient p = ourCtx.newXmlParser().parseResource(Patient.class, res);
assertEquals(htmlNoNs, p.getText().getDiv().getValueAsString());
}
/**
* Thanks to Alexander Kley!
*/
@Test
public void testParseContainedBinaryResource() {
byte[] bin = new byte[] { 0, 1, 2, 3, 4 };
final Binary binary = new Binary();
binary.setContentType("PatientConsent").setContent(bin);
// binary.setId(UUID.randomUUID().toString());
ca.uhn.fhir.model.dstu2.resource.DocumentManifest manifest = new ca.uhn.fhir.model.dstu2.resource.DocumentManifest();
// manifest.setId(UUID.randomUUID().toString());
CodeableConceptDt cc = new CodeableConceptDt();
cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
manifest.setType(cc);
manifest.setMasterIdentifier(new IdentifierDt().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
manifest.addContent().setP(new ResourceReferenceDt(binary));
manifest.setStatus(DocumentReferenceStatusEnum.CURRENT);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
ourLog.info(encoded);
assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", "<Binary", "</contained>")));
ca.uhn.fhir.model.dstu2.resource.DocumentManifest actual = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.DocumentManifest.class, encoded);
assertEquals(1, actual.getContained().getContainedResources().size());
assertEquals(1, actual.getContent().size());
assertNotNull(((ResourceReferenceDt)actual.getContent().get(0).getP()).getResource());
}
@Test
public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getNameElement().setValue("Contained Test Organization");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
// Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org);
String encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, containsString("<contained>"));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// Create a bundle with just the patient resource
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
b.addEntry().setResource(patient);
// Encode the bundle
encoded = xmlParser.encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<id value=\"1\"/>", "</contained>")));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<entry>", "</entry>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<entry>", "</entry>", "<entry>"))));
// Re-parse the bundle
patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
assertEquals("#1", patient.getManagingOrganization().getReference().getValue());
assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource();
assertEquals("#1", org.getId().getValue());
assertEquals("Contained Test Organization", org.getName());
// And re-encode a second time
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"1\"/>", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared
patient.getContained().getContainedResources().clear();
patient.getManagingOrganization().setReference((String)null);
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"1\"/>", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared and a manually set local ID
patient.getContained().getContainedResources().clear();
patient.getManagingOrganization().setReference((String)null);
patient.getManagingOrganization().getResource().setId(("#333"));
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"333\"/>", "</Organization", "</contained>", "<reference value=\"#333\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
}
@Test
public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getNameElement().setValue("Contained Test Organization");
org.getText().setDiv("<div>FOOBAR</div>");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getText().setDiv("<div>BARFOO</div>");
patient.getManagingOrganization().setResource(org);
String encoded = parser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Patient", "<text>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">BARFOO</div>", "<contained>", "<Organization", "</Organization"));
assertThat(encoded, not(stringContainsInOrder("<Patient", "<text>", "<contained>", "<Organization", "<text", "</Organization")));
assertThat(encoded, not(containsString("FOOBAR")));
assertThat(encoded, (containsString("BARFOO")));
}
/**
* see #144 and #146
*/

View File

@ -0,0 +1,122 @@
package ca.uhn.fhir.util;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.methods.HttpUriRequest;
import org.hl7.fhir.instance.model.IBase;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
public class FhirTerserDstu2Test {
private static FhirContext ourCtx = new FhirContext();
@Test
public void testGetAllPopulatedChildElementsOfTypeDoesntDescendIntoEmbedded() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Bundle b = new Bundle();
b.addEntry().setResource(p);
b.addLink().setRelation("BUNDLE");
FhirTerser t = ourCtx.newTerser();
List<StringDt> strings = t.getAllPopulatedChildElementsOfType(b, StringDt.class);
assertEquals(1, strings.size());
assertThat(strings, containsInAnyOrder(new StringDt("BUNDLE")));
}
@Test
public void testGetAllPopulatedChildElementsOfTypeDescendsIntoContained() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Organization o = new Organization();
o.getNameElement().setValue("ORGANIZATION");
p.getContained().getContainedResources().add(o);
FhirTerser t = ourCtx.newTerser();
List<StringDt> strings = t.getAllPopulatedChildElementsOfType(p, StringDt.class);
assertEquals(2, strings.size());
assertThat(strings, containsInAnyOrder(new StringDt("PATIENT"), new StringDt("ORGANIZATION")));
}
@Test
public void testVisitWithModelVisitor2() {
IModelVisitor2 visitor = mock(IModelVisitor2.class);
ArgumentCaptor<IBase> element = ArgumentCaptor.forClass(IBase.class);
ArgumentCaptor<List<IBase>> containingElementPath = ArgumentCaptor.forClass(getListClass(IBase.class));
ArgumentCaptor<List<BaseRuntimeChildDefinition>> childDefinitionPath = ArgumentCaptor.forClass(getListClass(BaseRuntimeChildDefinition.class));
ArgumentCaptor<List<BaseRuntimeElementDefinition<?>>> elementDefinitionPath = ArgumentCaptor.forClass(getListClass2());
when(visitor.acceptElement(element.capture(), containingElementPath.capture(), childDefinitionPath.capture(), elementDefinitionPath.capture())).thenReturn(true);
Patient p = new Patient();
p.addLink().getTypeElement().setValue("CODE");
ourCtx.newTerser().visit(p, visitor);
assertEquals(3, element.getAllValues().size());
assertSame(p, element.getAllValues().get(0));
assertSame(p.getLinkFirstRep(), element.getAllValues().get(1));
assertSame(p.getLinkFirstRep().getTypeElement(), element.getAllValues().get(2));
assertEquals(3, containingElementPath.getAllValues().size());
// assertEquals(0, containingElementPath.getAllValues().get(0).size());
// assertEquals(1, containingElementPath.getAllValues().get(1).size());
// assertEquals(2, containingElementPath.getAllValues().get(2).size());
}
/**
* See
* http://stackoverflow.com/questions/182636/how-to-determine-the-class-of-a-generic-type
*/
private static <T> Class<List<T>> getListClass(Class<T> theClass) {
return new ClassGetter<List<T>>() {}.get();
}
/**
* See
* http://stackoverflow.com/questions/182636/how-to-determine-the-class-of-a-generic-type
*/
private static Class<List<BaseRuntimeElementDefinition<?>>> getListClass2() {
return new ClassGetter<List<BaseRuntimeElementDefinition<?>>>() {}.get();
}
/**
* See
* http://stackoverflow.com/questions/182636/how-to-determine-the-class-of-a-generic-type
*/
private static abstract class ClassGetter<T> {
@SuppressWarnings("unchecked")
public final Class<T> get() {
final ParameterizedType superclass = (ParameterizedType)
getClass().getGenericSuperclass();
Type type = superclass.getActualTypeArguments()[0];
if (type instanceof ParameterizedType) {
return (Class<T>) ((ParameterizedType) type).getOwnerType();
}
return (Class<T>)type;
}
}
}

View File

@ -1,55 +0,0 @@
package ca.uhn.fhir.util;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.List;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
public class FhirTerserTest {
private static FhirContext ourCtx = new FhirContext();
@Test
public void testGetAllPopulatedChildElementsOfTypeDoesntDescendIntoEmbedded() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Bundle b = new Bundle();
b.addEntry().setResource(p);
b.addLink().setRelation("BUNDLE");
FhirTerser t = ourCtx.newTerser();
List<StringDt> strings = t.getAllPopulatedChildElementsOfType(b, StringDt.class);
assertEquals(1, strings.size());
assertThat(strings, containsInAnyOrder(new StringDt("BUNDLE")));
}
@Test
public void testGetAllPopulatedChildElementsOfTypeDescendsIntoContained() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Organization o = new Organization();
o.getNameElement().setValue("ORGANIZATION");
p.getContained().getContainedResources().add(o);
FhirTerser t = ourCtx.newTerser();
List<StringDt> strings = t.getAllPopulatedChildElementsOfType(p, StringDt.class);
assertEquals(2, strings.size());
assertThat(strings, containsInAnyOrder(new StringDt("PATIENT"), new StringDt("ORGANIZATION")));
}
}

View File

@ -19,11 +19,11 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -18,7 +18,7 @@
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>0.9-SNAPSHOT</version>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>

View File

@ -40,11 +40,12 @@ import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IDomainResource;
/**
* A resource that includes narrative, extensions, and contained resources.
*/
@ResourceDef(name="DomainResource", profile="http://hl7.org/fhir/Profile/DomainResource")
public abstract class DomainResource extends Resource implements IBaseHasExtensions, IBaseHasModifierExtensions {
public abstract class DomainResource extends Resource implements IBaseHasExtensions, IBaseHasModifierExtensions, IDomainResource {
/**
* A human-readable narrative that contains a summary of the resource, and may be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it "clinically safe" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
/*
Copyright (c) 2011+, HL7, Inc
@ -37,7 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
*
*/
@DatatypeDef(name="enumeration")
public class Enumeration<T extends Enum<?>> extends PrimitiveType<T> {
public class Enumeration<T extends Enum<?>> extends PrimitiveType<T> implements IBaseEnumeration<T> {
private static final long serialVersionUID = 1L;
private EnumFactory<T> myEnumFactory;

View File

@ -28,8 +28,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/
package org.hl7.fhir.instance.model;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.math.BigDecimal;
@ -38,13 +37,9 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.Constants;
@ -545,32 +540,12 @@ public class IdType extends UriType implements IIdType {
return isBlank(getValue());
}
public void applyTo(IBaseResource theResouce) {
if (theResouce == null) {
throw new NullPointerException("theResource can not be null");
} else if (theResouce instanceof IResource) {
((IResource) theResouce).setId(new IdType(getValue()));
} else if (theResouce instanceof IAnyResource) {
((IAnyResource) theResouce).setId(getIdPart());
} else {
throw new IllegalArgumentException("Unknown resource class type, does not implement IResource or extend Resource");
}
@Override
public IdType copy() {
return new IdType(getValue());
}
/**
* Retrieves the ID from the given resource instance
*/
public static IdType of(IBaseResource theResouce) {
if (theResouce == null) {
throw new NullPointerException("theResource can not be null");
} else if (theResouce instanceof IResource) {
return ((IResource) theResouce).getId();
} else if (theResouce instanceof IAnyResource) {
// TODO: implement
throw new UnsupportedOperationException();
} else {
throw new IllegalArgumentException("Unknown resource class type, does not implement IResource or extend Resource");
}
}
}
}

View File

@ -31,17 +31,16 @@ package org.hl7.fhir.instance.model;
// Generated on Wed, Feb 18, 2015 12:09-0500 for FHIR v0.4.0
import java.util.*;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.api.INarrative;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.INarrative;
/**
* A human-readable formatted text, including images.
*/
@ -158,8 +157,8 @@ public class Narrative extends Element implements INarrative {
/**
* The actual narrative content, a stripped down version of XHTML.
*/
// @Child(name="div", type={}, order=1, min=1, max=1)
// @Description(shortDefinition="Limited xhtml content", formalDefinition="The actual narrative content, a stripped down version of XHTML." )
@Child(name="div", type={}, order=1, min=1, max=1)
@Description(shortDefinition="Limited xhtml content", formalDefinition="The actual narrative content, a stripped down version of XHTML." )
protected XhtmlNode div;
private static final long serialVersionUID = 1463852859L;

View File

@ -31,14 +31,15 @@ package org.hl7.fhir.instance.model;
// Generated on Wed, Feb 18, 2015 12:09-0500 for FHIR v0.4.0
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.instance.model.annotations.ResourceDef;
import org.hl7.fhir.instance.model.annotations.SearchParamDefinition;
import org.hl7.fhir.instance.model.annotations.Block;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.annotations.ResourceDef;
import org.hl7.fhir.instance.model.annotations.SearchParamDefinition;
/**
* Demographics and other administrative information about a person or animal receiving care or other health-related services.
*/

View File

@ -65,7 +65,9 @@ public class Reference extends Type implements IReference, ICompositeType {
* Constructor
*/
public Reference(StringType theReference) {
this.reference = theReference;
if (theReference != null) {
this.reference = new IdType(theReference.getValue());
}
}
/**
@ -73,21 +75,21 @@ public class Reference extends Type implements IReference, ICompositeType {
*/
public Reference(String theReference) {
if (StringUtils.isNotBlank(theReference)) {
this.reference = new StringType(theReference);
this.reference = new IdType(theReference);
}
}
/**
* This is not a part of the "wire format" resource, but can be changed/accessed by parsers
*/
private transient IAnyResource resource;
private transient IBaseResource resource;
/**
* Retrieves the actual resource referenced by this reference. Note that the resource itself is not
* a part of the FHIR "wire format" and is never transmitted or receieved inline, but this property
* may be changed/accessed by parsers.
*/
public IAnyResource getResource() {
public IBaseResource getResource() {
return resource;
}
@ -96,7 +98,7 @@ public class Reference extends Type implements IReference, ICompositeType {
* a part of the FHIR "wire format" and is never transmitted or receieved inline, but this property
* may be changed/accessed by parsers.
*/
public void setResource(IAnyResource theResource) {
public void setResource(IBaseResource theResource) {
resource = theResource;
}
@ -105,7 +107,7 @@ public class Reference extends Type implements IReference, ICompositeType {
*/
@Child(name = "reference", type = {StringType.class}, order = 0, min = 0, max = 1)
@Description(shortDefinition="Relative, internal or absolute URL reference", formalDefinition="A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources." )
protected StringType reference;
protected IdType reference;
/**
* Plain text narrative that identifies the resource in addition to the resource reference.
@ -119,12 +121,12 @@ public class Reference extends Type implements IReference, ICompositeType {
/**
* @return {@link #reference} (A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources.). This is the underlying object with id, value and extensions. The accessor "getReference" gives direct access to the value
*/
public StringType getReferenceElement() {
public IdType getReferenceElement() {
if (this.reference == null)
if (Configuration.errorOnAutoCreate())
throw new Error("Attempt to auto-create Reference.reference");
else if (Configuration.doAutoCreate())
this.reference = new StringType(); // bb
this.reference = new IdType(); // bb
return this.reference;
}
@ -139,7 +141,7 @@ public class Reference extends Type implements IReference, ICompositeType {
/**
* @param value {@link #reference} (A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources.). This is the underlying object with id, value and extensions. The accessor "getReference" gives direct access to the value
*/
public Reference setReferenceElement(StringType value) {
public Reference setReferenceElement(IdType value) {
this.reference = value;
return this;
}
@ -147,8 +149,8 @@ public class Reference extends Type implements IReference, ICompositeType {
/**
* @return A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources.
*/
public String getReference() {
return this.reference == null ? null : this.reference.getValue();
public IdType getReference() {
return getReferenceElement();
}
/**
@ -159,7 +161,7 @@ public class Reference extends Type implements IReference, ICompositeType {
this.reference = null;
else {
if (this.reference == null)
this.reference = new StringType();
this.reference = new IdType();
this.reference.setValue(value);
}
return this;
@ -253,7 +255,7 @@ public class Reference extends Type implements IReference, ICompositeType {
}
public boolean isEmpty() {
return super.isEmpty() && (reference == null || reference.isEmpty()) && (display == null || display.isEmpty())
return super.isEmpty() && (reference == null || reference.isEmpty()) && (display == null || display.isEmpty()) && resource == null
;
}

View File

@ -31,15 +31,14 @@ package org.hl7.fhir.instance.model;
// Generated on Wed, Feb 18, 2015 12:09-0500 for FHIR v0.4.0
import java.util.*;
import java.util.List;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.instance.model.annotations.ResourceDef;
import org.hl7.fhir.instance.model.annotations.SearchParamDefinition;
import org.hl7.fhir.instance.model.annotations.Block;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.annotations.ResourceDef;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.Utilities;
/**
* Base Resource for everything.
*/
@ -111,8 +110,8 @@ public abstract class Resource extends Base implements IAnyResource {
/**
* @return The logical id of the resource, as used in the url for the resoure. Once assigned, this value never changes.
*/
public String getId() {
return this.id == null ? null : this.id.getValue();
public IdType getId() {
return getIdElement(); // this.id == null ? null : this.id.getValue();
}
/**
@ -129,6 +128,14 @@ public abstract class Resource extends Base implements IAnyResource {
return this;
}
/**
* @param value The logical id of the resource, as used in the url for the resoure. Once assigned, this value never changes.
*/
public Resource setId(IIdType value) {
this.id = (IdType) value;
return this;
}
/**
* @return {@link #meta} (The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content may not always be associated with version changes to the resource.)
*/

View File

@ -33,8 +33,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
//@DatatypeDef()
public class XhtmlNode {
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
@DatatypeDef(name="xhtml")
public class XhtmlNode implements IBaseXhtml {
public static final String NBSP = Character.toString((char)0xa0);
@ -280,7 +284,40 @@ public class XhtmlNode {
return e1.equalsDeep(e2);
}
public String getValueAsString() throws Exception {
return new XhtmlComposer().compose(this);
public String getValueAsString() {
try {
return new XhtmlComposer().compose(this);
} catch (Exception e) {
// TODO: composer shouldn't throw exception like this
throw new RuntimeException(e);
}
}
@Override
public void setValueAsString(String theValue) throws IllegalArgumentException {
try {
// TODO: this is ugly
XhtmlNode fragment = new XhtmlParser().parseFragment(theValue);
this.Attributes = fragment.Attributes;
this.childNodes = fragment.childNodes;
this.content = fragment.content;
this.name = fragment.name;
this.nodeType= fragment.nodeType;
} catch (Exception e) {
// TODO: composer shouldn't throw exception like this
throw new RuntimeException(e);
}
}
@Override
public String getValue() {
return getValueAsString();
}
@Override
public IPrimitiveType<String> setValue(String theValue) throws IllegalArgumentException {
setValueAsString(theValue);
return this;
}
}

View File

@ -12,6 +12,7 @@ import org.hl7.fhir.instance.model.Coding;
import org.hl7.fhir.instance.model.DecimalType;
import org.hl7.fhir.instance.model.DomainResource;
import org.hl7.fhir.instance.model.Element;
import org.hl7.fhir.instance.model.Enumeration;
import org.hl7.fhir.instance.model.Extension;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.ICompositeType;
@ -36,16 +37,20 @@ import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.ICoding;
import org.hl7.fhir.instance.model.api.IDatatypeElement;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IMetaType;
import org.hl7.fhir.instance.model.api.INarrative;
import org.hl7.fhir.instance.model.api.IReference;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.Test;
public class ModelInheritanceTest {
@ -78,6 +83,11 @@ public class ModelInheritanceTest {
assertTrue(ICompositeType.class.isAssignableFrom(Address.class));
}
@Test
public void testXhtml() {
assertTrue(IBaseXhtml.class.isAssignableFrom(XhtmlNode.class));
}
@Test
public void testBackboneElement() {
assertTrue(IBackboneElement.class.isAssignableFrom(BackboneElement.class));
@ -122,6 +132,7 @@ public class ModelInheritanceTest {
public void testDomainResource() {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(DomainResource.class));
assertTrue(IBaseHasModifierExtensions.class.isAssignableFrom(DomainResource.class));
assertTrue(IDomainResource.class.isAssignableFrom(DomainResource.class));
}
@Test
@ -129,6 +140,11 @@ public class ModelInheritanceTest {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(Element.class));
}
@Test
public void testEnumeration() {
assertTrue(IBaseEnumeration.class.isAssignableFrom(Enumeration.class));
}
/**
* Should be "implements IBaseExtension<Extension>"
*/

View File

@ -77,27 +77,20 @@ public class XmlParserTest {
@BeforeClass
public static void beforeClass2() {
System.setProperty("file.encoding", "ISO-8859-1");
System.setProperty("file.encoding", "ISO-8859-1");
}
@Test
public void testProfileWithBoundCode() throws IOException {
String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/DMIXAuditException.xml"), "UTF-8");
ourCtx.newXmlParser().parseResource(Profile.class, content);
}
@Test
public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary();
b.setContent(new byte[] {1,2,3,4});
b.setContent(new byte[] { 1, 2, 3, 4 });
String output = ourCtx.newXmlParser().encodeResourceToString(b);
ourLog.info(output);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
}
@Test
public void testEncodeNonContained() {
// Create an organization
@ -110,18 +103,18 @@ public class XmlParserTest {
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getManagingOrganization().setResource(org);
// Create a list containing both resources. In a server method, you might just
// return this list, but here we will create a bundle to encode.
List<Resource> resources = new ArrayList<Resource>();
resources.add(org);
resources.add(patient);
resources.add(patient);
// Create a bundle with both
Bundle b = new Bundle();
b.addEntry().setResource(org);
b.addEntry().setResource(patient);
// Encode the buntdle
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
@ -129,13 +122,29 @@ public class XmlParserTest {
assertThat(encoded, stringContainsInOrder("<Organization", "<id value=\"65546\"/>", "</Organization>"));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
assertThat(encoded, stringContainsInOrder("<Patient", "<id value=\"1333\"/>", "</Patient>"));
encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, not(containsString("<contained>")));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
}
@Test
public void testParseNarrative() throws Exception {
//@formatter:off
String htmlNoNs = "<div>AAA<b>BBB</b>CCC</div>";
String htmlNs = htmlNoNs.replace("<div>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">");
String res= "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <id value=\"1333\"/>\n" +
" <text>\n" +
" " + htmlNs + "\n" +
" </text>\n" +
"</Patient>";
//@formatter:on
Patient p = ourCtx.newXmlParser().parseResource(Patient.class, res);
assertEquals(htmlNoNs, p.getText().getDivAsString());
}
@Test
@ -150,22 +159,25 @@ public class XmlParserTest {
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue( "253345");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getText().setDivAsString("<div>BARFOO</div>");
patient.getManagingOrganization().setResource(org);
String encoded = parser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Patient", "<text>", "<div xmlns=\"http://www.w3.org/1999/xhtml\">BARFOO</div>", "<contained>", "<Organization", "</Organization"));
assertThat(encoded, not(stringContainsInOrder("<Patient", "<text>", "<contained>", "<Organization", "<text", "</Organization")));
assertThat(encoded, not(containsString("FOOBAR")));
assertThat(encoded, (containsString("BARFOO")));
}
}
@Test
public void testEncodeContained() {
public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getNameElement().setValue("Contained Test Organization");
@ -174,41 +186,41 @@ public class XmlParserTest {
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
// Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org);
String encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, containsString("<contained>"));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// Create a bundle with just the patient resource
Bundle b = new Bundle();
b.addEntry().setResource(patient);
// Encode the buntdle
// Encode the bundle
encoded = xmlParser.encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>","id=\"1\"", "</contained>")));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<id value=\"1\"/>", "</contained>")));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<entry>", "</entry>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<entry>", "</entry>", "<entry>"))));
// Re-parse the bundle
patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
assertEquals("#1", patient.getManagingOrganization().getReference());
assertEquals("#1", patient.getManagingOrganization().getReference().getValue());
assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource();
assertEquals("#1", org.getId());
assertEquals("#1", org.getId().getValue());
assertEquals("Contained Test Organization", org.getName());
// And re-encode a second time
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"1\"", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"1\"/>", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared
@ -216,8 +228,8 @@ public class XmlParserTest {
patient.getManagingOrganization().setReference(null);
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"1\"", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"1\"/>", "</Organization", "</contained>", "<reference value=\"#1\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared and a manually set local ID
@ -226,59 +238,55 @@ public class XmlParserTest {
patient.getManagingOrganization().getResource().setId(("#333"));
encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"333\"", "</Organization", "</contained>", "<reference value=\"#333\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"333\"/>", "</Organization", "</contained>", "<reference value=\"#333\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
}
/**
* Thanks to Alexander Kley!
*/
@Test
public void testParseContainedBinaryResource() {
byte[] bin = new byte[] {0,1,2,3,4};
final Binary binary = new Binary();
binary.setContentType("PatientConsent").setContent( bin);
// binary.setId(UUID.randomUUID().toString());
DocumentManifest manifest = new DocumentManifest();
// manifest.setId(UUID.randomUUID().toString());
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setSystem("mySystem").setCode( "PatientDocument");
byte[] bin = new byte[] { 0, 1, 2, 3, 4 };
final Binary binary = new Binary();
binary.setContentType("PatientConsent").setContent(bin);
// binary.setId(UUID.randomUUID().toString());
DocumentManifest manifest = new DocumentManifest();
// manifest.setId(UUID.randomUUID().toString());
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
manifest.setType(cc);
manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue( UUID.randomUUID().toString()));
manifest.addContent().setResource(binary);
manifest.setStatus(DocumentReferenceStatus.CURRENT);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
ourLog.info(encoded);
assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>","<Binary", "</contained>")));
DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded);
assertEquals(1, actual.getContained().size());
assertEquals(1, actual.getContent().size());
assertNotNull(actual.getContent().get(0).getResource());
manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
manifest.addContent().setResource(binary);
manifest.setStatus(DocumentReferenceStatus.CURRENT);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
ourLog.info(encoded);
assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", "<Binary", "</contained>")));
DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded);
assertEquals(1, actual.getContained().size());
assertEquals(1, actual.getContent().size());
assertNotNull(actual.getContent().get(0).getResource());
}
@Test
public void testComposition() {
Composition comp = new Composition();
comp.setId("1");
ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp);
// comp.
// comp.
}
@Test
public void testEncodeBinaryResource() {
@ -288,7 +296,7 @@ public class XmlParserTest {
patient.setContent(new byte[] { 1, 2, 3, 4 });
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><contentType value=\"foo\"/><content value=\"AQIDBA==\"/></Binary>", val);
}
@ -310,7 +318,7 @@ public class XmlParserTest {
@Test
public void testEncodeBundle() throws InterruptedException {
Bundle b = new Bundle();
b.getMeta().addTag().setSystem("http://hl7.org/fhir/tag").setCode( "http://hl7.org/fhir/tag/message").setDisplay("Message");
b.getMeta().addTag().setSystem("http://hl7.org/fhir/tag").setCode("http://hl7.org/fhir/tag/message").setDisplay("Message");
InstantType pub = InstantType.withCurrentTime();
b.getMeta().setLastUpdatedElement(pub);
@ -346,7 +354,7 @@ public class XmlParserTest {
Bundle b = new Bundle();
BundleEntryComponent e = b.addEntry();
e.setResource(new Patient());
e.getResource().getMeta().addTag().setSystem("scheme").setCode( "term").setDisplay( "label");
e.getResource().getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("label");
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(val);
@ -363,7 +371,6 @@ public class XmlParserTest {
}
@Test
public void testEncodeEscapedChars() {
@ -409,7 +416,7 @@ public class XmlParserTest {
DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen();
spm.addIdentifier().setSystem("urn").setValue( "123");
spm.addIdentifier().setSystem("urn").setValue("123");
rpt.getText().setDivAsString("AAA");
rpt.addSpecimen().setResource(spm);
@ -472,7 +479,7 @@ public class XmlParserTest {
Patient patient = new Patient();
patient.addAddress().setUse(AddressUse.HOME);
patient.addExtension().setUrl("urn:foo").setValue( new Reference("Organization/123"));
patient.addExtension().setUrl("urn:foo").setValue(new Reference("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
@ -483,7 +490,7 @@ public class XmlParserTest {
List<Extension> ext = actual.getExtension();
assertEquals(1, ext.size());
Reference ref = (Reference) ext.get(0).getValue();
assertEquals("Organization/123", ref.getReference());
assertEquals("Organization/123", ref.getReference().getValue());
}
@ -565,7 +572,6 @@ public class XmlParserTest {
}
@Test
public void testEncodeResourceRef() throws DataFormatException {
@ -618,7 +624,7 @@ public class XmlParserTest {
HumanName name = patient.addName();
name.addFamily("Shmoe");
HumanName given = name.addGiven("Joe");
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello"));
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("Hello"));
given.getExtension().add(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
@ -629,7 +635,7 @@ public class XmlParserTest {
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getName().get(0).getExtension().size());
Extension ext = parsed.getName().get(0).getExtension().get(0);
assertEquals("Hello", ((IPrimitiveType<?>)ext.getValue()).getValue());
assertEquals("Hello", ((IPrimitiveType<?>) ext.getValue()).getValue());
}
@ -642,7 +648,7 @@ public class XmlParserTest {
StringType family = name.addFamilyElement();
family.setValue("Shmoe");
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello"));
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("Hello"));
family.getExtension().add(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
@ -653,7 +659,7 @@ public class XmlParserTest {
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size());
Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0);
assertEquals("Hello", ((IPrimitiveType<?>)ext.getValue()).getValue());
assertEquals("Hello", ((IPrimitiveType<?>) ext.getValue()).getValue());
}
@ -690,7 +696,7 @@ public class XmlParserTest {
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
+ "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>"
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
+ "<gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\" /><code value=\"M\" /></coding></gender>"
+ "<gender value=\"male\"/>"
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
+ "</Patient>";
//@formatter:on
@ -698,11 +704,13 @@ public class XmlParserTest {
Patient patient = ourCtx.newXmlParser().parseResource(Patient.class, msg);
assertEquals(NarrativeStatus.GENERATED, patient.getText().getStatus());
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div>", patient.getText().getDiv().getValueAsString());
assertEquals("<div>John Cardinal: 444333333 </div>", patient.getText().getDiv().getValueAsString());
assertEquals("PRP1660", patient.getIdentifier().get(0).getValue());
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
Diff d = new Diff(new StringReader(msg), new StringReader(encoded));
assertTrue(d.toString(), d.identical());
@ -801,12 +809,12 @@ public class XmlParserTest {
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel());
assertEquals("Foo1Value", ((IPrimitiveType<?>)resource.getExtension().get(0).getValue()).getValueAsString());
assertEquals("Foo1Value2", ((IPrimitiveType<?>)resource.getExtension().get(1).getValue()).getValueAsString());
assertEquals("Foo2Value1", ((IPrimitiveType<?>)resource.getModifierExtension().get(0).getValue()).getValueAsString());
assertEquals("Foo1Value", ((IPrimitiveType<?>) resource.getExtension().get(0).getValue()).getValueAsString());
assertEquals("Foo1Value2", ((IPrimitiveType<?>) resource.getExtension().get(1).getValue()).getValueAsString());
assertEquals("Foo2Value1", ((IPrimitiveType<?>) resource.getModifierExtension().get(0).getValue()).getValueAsString());
assertEquals("2013-01-01", ((IPrimitiveType<?>)resource.getExtension().get(2).getExtension().get(0).getValue()).getValueAsString());
assertEquals("2013-01-02", ((IPrimitiveType<?>)resource.getExtension().get(2).getExtension().get(1).getExtension().get(0).getValue()).getValueAsString());
assertEquals("2013-01-01", ((IPrimitiveType<?>) resource.getExtension().get(2).getExtension().get(0).getValue()).getValueAsString());
assertEquals("2013-01-02", ((IPrimitiveType<?>) resource.getExtension().get(2).getExtension().get(1).getExtension().get(0).getValue()).getValueAsString());
String encoded = p.encodeResourceToString(resource);
ourLog.info(encoded);
@ -815,51 +823,9 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical());
}
@Test
public void testLoadObservation() throws ConfigurationException, DataFormatException, IOException {
IParser p = ourCtx.newXmlParser();
String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/observation-example-eeg.xml"), Charset.forName("UTF-8"));
IBaseResource resource = p.parseResource(string);
String result = p.encodeResourceToString(resource);
ourLog.info(result);
}
@Test
public void testLoadPatient() throws ConfigurationException, DataFormatException, IOException {
IParser p = ourCtx.newXmlParser();
String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/patient-example-dicom.xml"), Charset.forName("UTF-8"));
IBaseResource resource = p.parseResource(string);
String result = p.encodeResourceToString(resource);
ourLog.info(result);
// Nothing
string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/patient-example-us-extensions.xml"), Charset.forName("UTF-8"));
resource = p.parseResource(string);
result = p.encodeResourceToString(resource);
ourLog.info(result);
}
@Test
public void testLoadQuestionnaire() throws ConfigurationException, DataFormatException, IOException {
IParser p = ourCtx.newXmlParser();
String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/questionnaire-example.xml"), Charset.forName("UTF-8"));
IBaseResource resource = p.parseResource(string);
String result = p.encodeResourceToString(resource);
ourLog.info(result);
}
@Test
public void testReEncode() throws SAXException, IOException {
@ -920,12 +886,10 @@ public class XmlParserTest {
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(
enc,
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
*/
@ -964,7 +928,8 @@ public class XmlParserTest {
}
@Test
// Narrative generation not currently supported for HL7org structures
public void testNarrativeGeneration() throws DataFormatException, IOException {
Patient patient = new Patient();
@ -998,8 +963,9 @@ public class XmlParserTest {
@Override
public void setFhirContext(FhirContext theFhirContext) {
// nothing
}};
}
};
FhirContext context = new FhirContext();
context.setNarrativeGenerator(gen);
IParser p = context.newXmlParser();
@ -1075,7 +1041,6 @@ public class XmlParserTest {
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
@ -1141,7 +1106,6 @@ public class XmlParserTest {
assertEquals("zh-CN", pt.getLanguage());
}
@Test
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
@ -1217,7 +1181,6 @@ public class XmlParserTest {
}
@BeforeClass
public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true);

View File

@ -0,0 +1,149 @@
{
"resourceType":"Patient",
"extension":[
{
"url":"urn:patientext:att",
"valueAttachment":{
"contentType":"aaaa",
"data":"AAAA"
}
},
{
"url":"urn:patientext:moreext",
"extension":[
{
"url":"urn:patientext:moreext:1",
"valueString":"str1"
},
{
"url":"urn:patientext:moreext:2",
"valueString":"str2"
}
]
}
],
"modifierExtension":[
{
"url":"urn:modext",
"valueDate":"2011-01-02"
}
],
"text":{
"status":"generated",
"div":"<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <table>\n <tbody>\n <tr>\n <td>Name</td>\n <td>Peter James <b>Chalmers</b> (\"Jim\")</td>\n </tr>\n <tr>\n <td>Address</td>\n <td>534 Erewhon, Pleasantville, Vic, 3999</td>\n </tr>\n <tr>\n <td>Contacts</td>\n <td>Home: unknown. Work: (03) 5555 6473</td>\n </tr>\n <tr>\n <td>Id</td>\n <td>MRN: 12345 (Acme Healthcare)</td>\n </tr>\n </tbody>\n </table>\n </div>"
},
"identifier":[
{
"use":"usual",
"label":"MRN",
"system":"urn:oid:1.2.36.146.595.217.0.1",
"value":"12345",
"period":{
"start":"2001-05-06"
},
"assigner":{
"display":"Acme Healthcare"
}
}
],
"name":[
{
"use":"official",
"family":[
"Chalmers"
],
"given":[
"Peter",
"James"
]
},
{
"use":"usual",
"given":[
"Jim"
]
}
],
"telecom":[
{
"use":"home"
},
{
"system":"phone",
"value":"(03) 5555 6473",
"use":"work"
}
],
"gender":{
"coding":[
{
"system":"http://hl7.org/fhir/v3/AdministrativeGender",
"code":"M",
"display":"Male"
}
]
},
"birthDate":"1974-12-25",
"deceasedBoolean":false,
"address":[
{
"use":"home",
"line":[
"534 Erewhon St"
],
"city":"PleasantVille",
"state":"Vic",
"zip":"3999"
},
{
"use":"old",
"line":[
"SecondAddress"
]
}
],
"contact":[
{
"relationship":[
{
"coding":[
{
"system":"http://hl7.org/fhir/patient-contact-relationship",
"code":"partner"
}
]
}
],
"name":{
"family":[
"du",
"Marché"
],
"_family":[
{
"extension":[
{
"url":"http://hl7.org/fhir/Profile/iso-21090#qualifier",
"valueCode":"VV"
}
]
},
null
],
"given":[
"Bénédicte"
]
},
"telecom":[
{
"system":"phone",
"value":"+33 (237) 998327"
}
]
}
],
"managingOrganization":{
"reference":"Organization/1"
},
"active":true
}