Merge branch 'hl7org_structs' of github.com:jamesagnew/hapi-fhir into hl7org_structs

This commit is contained in:
James Agnew 2015-04-14 11:59:53 -04:00
commit 4c82e1f87b
56 changed files with 1760 additions and 642 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 @Override
public void addValue(Object theTarget, IBase theValue) { public void addValue(Object theTarget, IBase theValue) {
try { try {
@ -214,7 +214,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
} }
} }
private final class FieldListMutator implements IMutator { protected final class FieldListMutator implements IMutator {
@Override @Override
public void addValue(Object theTarget, IBase theValue) { public void addValue(Object theTarget, IBase theValue) {
try { try {

View File

@ -158,7 +158,26 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
public abstract ChildTypeEnum getChildType(); public abstract ChildTypeEnum getChildType();
public enum ChildTypeEnum { 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% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; 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.IBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory; 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.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.IDatatypeElement; 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.INarrative;
import org.hl7.fhir.instance.model.api.IReference; 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 * 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. * annotations if the HL7.org ones are found instead.
*/ */
@SuppressWarnings("unchecked")
private <T extends Annotation> T pullAnnotation(AnnotatedElement theTarget, Class<T> theAnnotationType) { private <T extends Annotation> T pullAnnotation(AnnotatedElement theTarget, Class<T> theAnnotationType) {
T retVal = theTarget.getAnnotation(theAnnotationType); T retVal = theTarget.getAnnotation(theAnnotationType);
@ -493,20 +496,20 @@ class ModelScanner {
Class<?> nextElementType = determineElementType(next); Class<?> nextElementType = determineElementType(next);
if (IAnyResource.class.isAssignableFrom(nextElementType) || IResource.class.equals(nextElementType)) { if (BaseContainedDt.class.isAssignableFrom(nextElementType) || (childAnnotation.name().equals("contained") && IBaseResource.class.isAssignableFrom(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))) {
/* /*
* Child is contained resources * Child is contained resources
*/ */
RuntimeChildContainedResources def = new RuntimeChildContainedResources(next, childAnnotation, descriptionAnnotation, elementName); RuntimeChildContainedResources def = new RuntimeChildContainedResources(next, childAnnotation, descriptionAnnotation, elementName);
orderMap.put(order, def); 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)) { } else if (choiceTypes.size() > 1 && !BaseResourceReferenceDt.class.isAssignableFrom(nextElementType) && !IReference.class.isAssignableFrom(nextElementType)) {
/* /*
* Child is a choice element * Child is a choice element
@ -538,8 +541,8 @@ class ModelScanner {
RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et, binder); RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et, binder);
orderMap.put(order, def); orderMap.put(order, def);
if (IElement.class.isAssignableFrom(nextElementType)) { if (IBase.class.isAssignableFrom(nextElementType)) {
addScanAlso((Class<? extends IElement>) nextElementType); addScanAlso((Class<? extends IBase>) nextElementType);
} }
} else if (BaseResourceReferenceDt.class.isAssignableFrom(nextElementType) || IReference.class.isAssignableFrom(nextElementType)) { } else if (BaseResourceReferenceDt.class.isAssignableFrom(nextElementType) || IReference.class.isAssignableFrom(nextElementType)) {
/* /*
@ -582,17 +585,25 @@ class ModelScanner {
if (nextElementType.equals(BoundCodeDt.class)) { if (nextElementType.equals(BoundCodeDt.class)) {
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next); IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
def = new RuntimeChildPrimitiveBoundCodeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder); 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) { } else if (childAnnotation.enumFactory().getSimpleName().equals("NoEnumFactory") == false) {
Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory(); Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory();
def = new RuntimeChildEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, 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 { } else {
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype); def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
} }
} else if (IBaseXhtml.class.isAssignableFrom(nextElementType)) {
def = new RuntimeChildXhtmlDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
} else { } else {
if (IBoundCodeableConcept.class.isAssignableFrom(nextElementType)) { if (IBoundCodeableConcept.class.isAssignableFrom(nextElementType)) {
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next); IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
def = new RuntimeChildCompositeBoundDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder); 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); def = new RuntimeChildNarrativeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype);
} else { } else {
def = new RuntimeChildCompositeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype); def = new RuntimeChildCompositeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype);
@ -633,6 +644,12 @@ class ModelScanner {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<XhtmlDt> clazz = (Class<XhtmlDt>) theClass; Class<XhtmlDt> clazz = (Class<XhtmlDt>) theClass;
resourceDef = new RuntimePrimitiveDatatypeNarrativeDefinition(resourceName, clazz); 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 { } else {
resourceDef = new RuntimePrimitiveDatatypeDefinition(theDatatypeDefinition, theClass); resourceDef = new RuntimePrimitiveDatatypeDefinition(theDatatypeDefinition, theClass);
} }

View File

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

View File

@ -28,10 +28,47 @@ import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildPrimitiveDatatypeDefinition extends BaseRuntimeChildDatatypeDefinition { 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) { public RuntimeChildPrimitiveDatatypeDefinition(Field theField, String theElementName, Description theDescriptionAnnotation, Child theChildAnnotation, Class<? extends IBase> theDatatype) {
super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation, 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.IBase;
import org.hl7.fhir.instance.model.IBaseResource; 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.IResource;
import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.Child;
@ -43,6 +44,9 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
private List<Class<? extends IBaseResource>> myResourceTypes; private List<Class<? extends IBaseResource>> myResourceTypes;
private Set<String> myValidChildNames; private Set<String> myValidChildNames;
/**
* Constructor
*/
public RuntimeChildResourceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBaseResource>> theResourceTypes) { public RuntimeChildResourceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBaseResource>> theResourceTypes) {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName); super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
myResourceTypes = theResourceTypes; myResourceTypes = theResourceTypes;
@ -56,7 +60,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override @Override
public String getChildNameByDatatype(Class<? extends IBase> theDatatype) { public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) { if (IReference.class.isAssignableFrom(theDatatype)) {
return getElementName(); return getElementName();
} }
return null; return null;
@ -64,7 +68,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
@Override @Override
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) { public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theDatatype) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theDatatype)) { if (IReference.class.isAssignableFrom(theDatatype)) {
return myRuntimeDef; return myRuntimeDef;
} }
return null; 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.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.ResourceDef; 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; private boolean mySpecialization;
public RuntimePrimitiveDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType> theImplementingClass) { public RuntimePrimitiveDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType<?>> theImplementingClass) {
super(theDef.name(), theImplementingClass); super(theDef.name(), theImplementingClass);
String resourceName = theDef.name(); 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 final List<Class<? extends IBaseResource>> myResourceTypes;
private HashMap<Class<? extends IBaseResource>, RuntimeResourceDefinition> myResourceTypeToDefinition; private HashMap<Class<? extends IBaseResource>, RuntimeResourceDefinition> myResourceTypeToDefinition;
/**
* Constructor
*/
public RuntimeResourceReferenceDefinition(String theName, List<Class<? extends IBaseResource>> theResourceTypes) { public RuntimeResourceReferenceDefinition(String theName, List<Class<? extends IBaseResource>> theResourceTypes) {
super(theName, BaseResourceReferenceDt.class); super(theName, BaseResourceReferenceDt.class);
if (theResourceTypes == null || theResourceTypes.isEmpty()) { 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.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.hl7.fhir.instance.model.api.IBaseDatatype; 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.context.FhirContext;
import ca.uhn.fhir.model.api.BaseIdentifiableElement; 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.BaseClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient; 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 static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
private IResource myResource; private IResource myResource;
@ -114,7 +115,7 @@ public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement im
IParser parser = context.newXmlParser(); IParser parser = context.newXmlParser();
Reader responseReader = BaseClient.createReaderFromResponse(response); Reader responseReader = BaseClient.createReaderFromResponse(response);
myResource = parser.parseResource(responseReader); myResource = (IResource) parser.parseResource(responseReader);
} finally { } finally {
if (response instanceof CloseableHttpResponse) { 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.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.IBaseResource; import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IAnyResource; 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.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
@ -51,7 +52,7 @@ import ca.uhn.fhir.util.UrlUtil;
* </p> * </p>
*/ */
@DatatypeDef(name = "id") @DatatypeDef(name = "id")
public class IdDt extends UriDt implements IPrimitiveDatatype<String> { public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
private String myBaseUrl; private String myBaseUrl;
private boolean myHaveComponentParts; private boolean myHaveComponentParts;
@ -229,6 +230,11 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
return myBaseUrl; 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() { public String getIdPart() {
return myUnqualifiedId; return myUnqualifiedId;
} }

View File

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

View File

@ -123,7 +123,7 @@ public interface IParser {
* @throws DataFormatException * @throws DataFormatException
* If the resource can not be parsed because the data is not recognized or invalid for any reason * 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 * Parses a resource
@ -134,7 +134,7 @@ public interface IParser {
* @throws DataFormatException * @throws DataFormatException
* If the resource can not be parsed because the data is not recognized or invalid for any reason * 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>. * 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.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype; 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.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -103,8 +104,8 @@ import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
/** /**
* This class is the FHIR JSON parser/encoder. Users should not interact with this * This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use
* class directly, but should use {@link FhirContext#newJsonParser()} to get an instance. * {@link FhirContext#newJsonParser()} to get an instance.
*/ */
public class JsonParser extends BaseParser implements IParser { public class JsonParser extends BaseParser implements IParser {
@ -131,7 +132,8 @@ public class JsonParser extends BaseParser implements IParser {
private boolean myPrettyPrint; 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) { public JsonParser(FhirContext theContext) {
super(theContext); super(theContext);
@ -323,8 +325,10 @@ public class JsonParser extends BaseParser implements IParser {
// linkStarted = false; // linkStarted = false;
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "self", nextEntry.getLinkSelf(), linkStarted); // linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "self", nextEntry.getLinkSelf(), linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "alternate", nextEntry.getLinkAlternate(), linkStarted); // linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "alternate", nextEntry.getLinkAlternate(),
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "search", nextEntry.getLinkSearch(), linkStarted); // linkStarted);
// linkStarted = writeAtomLinkInDstu1Format(theEventWriter, "search", nextEntry.getLinkSearch(),
// linkStarted);
// if (linkStarted) { // if (linkStarted) {
// theEventWriter.writeEnd(); // theEventWriter.writeEnd();
// } // }
@ -347,10 +351,21 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd(); theEventWriter.writeEnd();
} }
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException {
BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException {
switch (theChildDef.getChildType()) { 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: { case PRIMITIVE_DATATYPE: {
IPrimitiveType<?> value = (IPrimitiveType<?>) theNextValue; IPrimitiveType<?> value = (IPrimitiveType<?>) theNextValue;
if (isBlank(value.getValueAsString())) { if (isBlank(value.getValueAsString())) {
@ -419,17 +434,20 @@ public class JsonParser extends BaseParser implements IParser {
theWriter.writeEnd(); theWriter.writeEnd();
break; break;
} }
case CONTAINED_RESOURCE_LIST:
case CONTAINED_RESOURCES: { case CONTAINED_RESOURCES: {
/* /*
* Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { * Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next :
* continue; } encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(next.getId().getValue())); } * value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; }
* encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true,
* fixContainedResourceId(next.getId().getValue())); }
*/ */
List<IBaseResource> containedResources = getContainedResources().getContainedResources(); List<IBaseResource> containedResources = getContainedResources().getContainedResources();
if (containedResources.size() > 0) { if (containedResources.size() > 0) {
theWriter.writeStartArray(theChildName); theWriter.writeStartArray(theChildName);
for (IBaseResource next : containedResources) { for (IBaseResource next : containedResources) {
IdDt resourceId = getContainedResources().getResourceId(next); IIdType resourceId = getContainedResources().getResourceId(next);
encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(resourceId.getValue())); encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(resourceId.getValue()));
} }
@ -437,9 +455,10 @@ public class JsonParser extends BaseParser implements IParser {
} }
break; break;
} }
case PRIMITIVE_XHTML_HL7ORG:
case PRIMITIVE_XHTML: { case PRIMITIVE_XHTML: {
if (!getSuppressNarratives()) { if (!getSuppressNarratives()) {
XhtmlDt dt = (XhtmlDt) theNextValue; IPrimitiveType<?> dt = (IPrimitiveType<?>) theNextValue;
if (theChildName != null) { if (theChildName != null) {
theWriter.write(theChildName, dt.getValueAsString()); theWriter.write(theChildName, dt.getValueAsString());
} else { } else {
@ -466,13 +485,12 @@ public class JsonParser extends BaseParser implements IParser {
} }
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
for (BaseRuntimeChildDefinition nextChild : theChildren) { for (BaseRuntimeChildDefinition nextChild : theChildren) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) { if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue; continue;
} }
if (nextChild instanceof RuntimeChildNarrativeDefinition) { if (nextChild instanceof RuntimeChildNarrativeDefinition) {
INarrativeGenerator gen = myContext.getNarrativeGenerator(); INarrativeGenerator gen = myContext.getNarrativeGenerator();
@ -520,7 +538,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE; 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; continue;
} }
@ -624,15 +642,13 @@ public class JsonParser extends BaseParser implements IParser {
} }
} }
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null); extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource); encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theIsSubElementWithinResource); encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theIsSubElementWithinResource);
} }
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource) throws IOException {
boolean theContainedResource) throws IOException {
String resourceId = null; String resourceId = null;
if (theResource instanceof IResource) { if (theResource instanceof IResource) {
IResource res = (IResource) theResource; IResource res = (IResource) theResource;
@ -645,16 +661,15 @@ public class JsonParser extends BaseParser implements IParser {
} }
} else if (theResource instanceof IAnyResource) { } else if (theResource instanceof IAnyResource) {
IAnyResource res = (IAnyResource) theResource; IAnyResource res = (IAnyResource) theResource;
if (theContainedResource && StringUtils.isNotBlank(res.getId())) { if (StringUtils.isNotBlank(res.getId().getIdPart())) {
resourceId = res.getId(); resourceId = res.getId().getIdPart();
} }
} }
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId); encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);
} }
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource, String theResourceId) throws IOException {
boolean theContainedResource, String theResourceId) throws IOException {
if (!theContainedResource) { if (!theContainedResource) {
super.containResourcesForEncoding(theResource); super.containResourcesForEncoding(theResource);
} }
@ -688,8 +703,8 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeStartObject("meta"); theEventWriter.writeStartObject("meta");
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart()); writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart());
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource)); writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource));
if (profiles != null && profiles.isEmpty()==false) { if (profiles != null && profiles.isEmpty() == false) {
theEventWriter.writeStartArray("profile"); theEventWriter.writeStartArray("profile");
for (IdDt profile : profiles) { for (IdDt profile : profiles) {
if (profile != null && isNotBlank(profile.getValue())) { if (profile != null && isNotBlank(profile.getValue())) {
@ -699,7 +714,7 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd(); theEventWriter.writeEnd();
} }
if (securityLabels.isEmpty()==false) { if (securityLabels.isEmpty() == false) {
theEventWriter.writeStartArray("security"); theEventWriter.writeStartArray("security");
for (BaseCodingDt securityLabel : securityLabels) { for (BaseCodingDt securityLabel : securityLabels) {
theEventWriter.writeStartObject(); theEventWriter.writeStartObject();
@ -709,8 +724,8 @@ public class JsonParser extends BaseParser implements IParser {
} }
theEventWriter.writeEnd(); theEventWriter.writeEnd();
} }
if (tags != null && tags.isEmpty()==false) { if (tags != null && tags.isEmpty() == false) {
theEventWriter.writeStartArray("tag"); theEventWriter.writeStartArray("tag");
for (Tag tag : tags) { for (Tag tag : tags) {
theEventWriter.writeStartObject(); theEventWriter.writeStartObject();
@ -722,7 +737,7 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd(); 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, private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef, IBaseResource theResource, String theParentExtensionUrl) throws IOException {
IBaseResource theResource, String theParentExtensionUrl) throws IOException {
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0); List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
List<HeldExtension> modifierExtensions = 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(); object = reader.readObject();
} catch (JsonParsingException e) { } catch (JsonParsingException e) {
if (e.getMessage().startsWith("Unexpected char 39")) { if (e.getMessage().startsWith("Unexpected char 39")) {
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage() 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);
+ " - 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); 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); JsonValue jsonVal = nextExt.get(nextKey);
if (jsonVal.getValueType() == ValueType.ARRAY) { 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; JsonArray arrayValue = (JsonArray) jsonVal;
parseExtensionInDstu2Style(theModifier, theState, extUrl, nextKey, arrayValue); 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, private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
if (extensions.isEmpty() == false) { if (extensions.isEmpty() == false) {
theEventWriter.writeStartArray("extension"); theEventWriter.writeStartArray("extension");
for (HeldExtension next : extensions) { 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.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; 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 org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 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.RuntimeChildDeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition; import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition; import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition;
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition; import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.BaseBundle; 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 class DeclaredExtensionState extends BaseState {
private IBase myChildInstance; private IBase myChildInstance;
@ -1396,7 +1429,7 @@ class ParserState<T> {
switch (target.getChildType()) { switch (target.getChildType()) {
case COMPOSITE_DATATYPE: { case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target; BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance(myDefinition.getInstanceConstructorArguments()); ICompositeType newChildInstance = (ICompositeType) compositeTarget.newInstance(myDefinition.getInstanceConstructorArguments());
myDefinition.getMutator().addValue(myParentInstance, newChildInstance); myDefinition.getMutator().addValue(myParentInstance, newChildInstance);
ElementCompositeState newState = new ElementCompositeState(myPreResourceState, compositeTarget, newChildInstance); ElementCompositeState newState = new ElementCompositeState(myPreResourceState, compositeTarget, newChildInstance);
push(newState); push(newState);
@ -1525,6 +1558,7 @@ class ParserState<T> {
push(newState); push(newState);
return; return;
} }
case ID_DATATYPE:
case PRIMITIVE_DATATYPE: { case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target; RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance; IPrimitiveType<?> newChildInstance;
@ -1557,6 +1591,14 @@ class ParserState<T> {
push(state); push(state);
return; 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: { case CONTAINED_RESOURCES: {
List<? extends IBase> values = child.getAccessor().getValues(myInstance); List<? extends IBase> values = child.getAccessor().getValues(myInstance);
Object newDt; Object newDt;
@ -1570,6 +1612,11 @@ class ParserState<T> {
push(state); push(state);
return; return;
} }
case CONTAINED_RESOURCE_LIST: {
ContainedResourcesStateHl7Org state = new ContainedResourcesStateHl7Org(getPreResourceState());
push(state);
return;
}
case RESOURCE: { case RESOURCE: {
if (myInstance instanceof IResource) { if (myInstance instanceof IResource) {
ParserState<T>.PreResourceStateHapi state = new PreResourceStateHapi(myInstance, child.getMutator(), null); ParserState<T>.PreResourceStateHapi state = new PreResourceStateHapi(myInstance, child.getMutator(), null);
@ -1650,10 +1697,15 @@ class ParserState<T> {
return; return;
} }
case RESOURCE_REF: { case RESOURCE_REF: {
BaseResourceReferenceDt newChildInstance = (BaseResourceReferenceDt) newResourceReferenceDt(getPreResourceState().myInstance); ICompositeType newChildInstance = (ICompositeType) newResourceReferenceDt(getPreResourceState().myInstance);
myExtension.setValue(newChildInstance); myExtension.setValue(newChildInstance);
ResourceReferenceStateHapi newState = new ResourceReferenceStateHapi(getPreResourceState(), newChildInstance); if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
push(newState); ParserState<T>.ResourceReferenceStateHl7Org newState = new ResourceReferenceStateHl7Org(getPreResourceState(), (IReference) newChildInstance);
push(newState);
} else {
ResourceReferenceStateHapi newState = new ResourceReferenceStateHapi(getPreResourceState(), (BaseResourceReferenceDt) newChildInstance);
push(newState);
}
return; return;
} }
case PRIMITIVE_XHTML: 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 class XhtmlState extends BaseState {
private int myDepth; private int myDepth;
private XhtmlDt myDt; private XhtmlDt myDt;
@ -2467,6 +2552,10 @@ class ParserState<T> {
myIncludeOuterEvent = theIncludeOuterEvent; myIncludeOuterEvent = theIncludeOuterEvent;
} }
public XhtmlDt getDt() {
return myDt;
}
@Override @Override
public void attributeValue(String theName, String theValue) throws DataFormatException { public void attributeValue(String theName, String theValue) throws DataFormatException {
if (myJsonMode) { if (myJsonMode) {
@ -2476,10 +2565,14 @@ class ParserState<T> {
super.attributeValue(theName, theValue); super.attributeValue(theName, theValue);
} }
protected void doPop() {
pop();
}
@Override @Override
public void endingElement() throws DataFormatException { public void endingElement() throws DataFormatException {
if (myJsonMode) { if (myJsonMode) {
pop(); doPop();
return; return;
} }
super.endingElement(); super.endingElement();
@ -2507,7 +2600,7 @@ class ParserState<T> {
if (theEvent.isEndElement()) { if (theEvent.isEndElement()) {
if (myDepth == 0) { if (myDepth == 0) {
myDt.setValue(myEvents); 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.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; 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.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.INarrative; 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.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 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.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildContainedResources;
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition; import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition; import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
@ -93,11 +97,11 @@ import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
import ca.uhn.fhir.util.XmlUtil; import ca.uhn.fhir.util.XmlUtil;
/** /**
* This class is the FHIR XML parser/encoder. Users should not interact with this * This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use
* class directly, but should use {@link FhirContext#newXmlParser()} to get an instance. * {@link FhirContext#newXmlParser()} to get an instance.
*/ */
public class XmlParser extends BaseParser implements IParser { public class XmlParser extends BaseParser implements IParser {
static final String ATOM_NS = "http://www.w3.org/2005/Atom"; static final String ATOM_NS = "http://www.w3.org/2005/Atom";
static final String FHIR_NS = "http://hl7.org/fhir"; static final String FHIR_NS = "http://hl7.org/fhir";
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/"; static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
@ -113,7 +117,8 @@ public class XmlParser extends BaseParser implements IParser {
private boolean myPrettyPrint; 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) { public XmlParser(FhirContext theContext) {
super(theContext); super(theContext);
@ -442,10 +447,9 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.close(); theEventWriter.close();
} }
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException { if (nextValue == null || nextValue.isEmpty()) {
if (nextValue.isEmpty()) { if (isChildContained(childDef, theIncludedResource)) {
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
// We still want to go in.. // We still want to go in..
} else { } else {
return; return;
@ -453,6 +457,17 @@ public class XmlParser extends BaseParser implements IParser {
} }
switch (childDef.getChildType()) { 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: { case PRIMITIVE_DATATYPE: {
IPrimitiveType<?> pd = (IPrimitiveType<?>) nextValue; IPrimitiveType<?> pd = (IPrimitiveType<?>) nextValue;
String value = pd.getValueAsString(); String value = pd.getValueAsString();
@ -476,7 +491,7 @@ public class XmlParser extends BaseParser implements IParser {
break; break;
} }
case RESOURCE_REF: { case RESOURCE_REF: {
BaseResourceReferenceDt ref = (BaseResourceReferenceDt) nextValue; IReference ref = (IReference) nextValue;
if (!ref.isEmpty()) { if (!ref.isEmpty()) {
theEventWriter.writeStartElement(childName); theEventWriter.writeStartElement(childName);
encodeResourceReferenceToStreamWriter(theEventWriter, ref); encodeResourceReferenceToStreamWriter(theEventWriter, ref);
@ -484,15 +499,16 @@ public class XmlParser extends BaseParser implements IParser {
} }
break; break;
} }
case CONTAINED_RESOURCE_LIST:
case CONTAINED_RESOURCES: { case CONTAINED_RESOURCES: {
BaseContainedDt value = (BaseContainedDt) nextValue;
/* /*
* Disable per #103 for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; } * Disable per #103 for (IResource next : value.getContainedResources()) { if
* theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(next.getId().getValue())); * (getContainedResources().getResourceId(next) != null) { continue; }
* theEventWriter.writeEndElement(); } * theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter,
* true, fixContainedResourceId(next.getId().getValue())); theEventWriter.writeEndElement(); }
*/ */
for (IBaseResource next : getContainedResources().getContainedResources()) { for (IBaseResource next : getContainedResources().getContainedResources()) {
IdDt resourceId = getContainedResources().getResourceId(next); IIdType resourceId = getContainedResources().getResourceId(next);
theEventWriter.writeStartElement("contained"); theEventWriter.writeStartElement("contained");
encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(resourceId.getValue())); encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(resourceId.getValue()));
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
@ -513,6 +529,18 @@ public class XmlParser extends BaseParser implements IParser {
} }
break; 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 EXTENSION_DECLARED:
case UNDECL_EXT: { case UNDECL_EXT: {
throw new IllegalStateException("state should not happen: " + childDef.getName()); 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, private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (BaseRuntimeChildDefinition nextChild : children) { for (BaseRuntimeChildDefinition nextChild : children) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) { if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue; continue;
} }
if (nextChild.getElementName().equals("id")) {
continue;
}
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) { if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
INarrativeGenerator gen = myContext.getNarrativeGenerator(); INarrativeGenerator gen = myContext.getNarrativeGenerator();
@ -544,67 +574,74 @@ public class XmlParser extends BaseParser implements IParser {
continue; continue;
} }
} else { } else {
INarrative narr1 = ((IDomainResource) theResource).getText(); // Narrative generation not currently supported for HL7org structures
BaseNarrativeDt<?> narr2 = null; // INarrative narr1 = ((IDomainResource) theResource).getText();
if (gen != null && narr1.isEmpty()) { // BaseNarrativeDt<?> narr2 = null;
// TODO: need to implement this // if (gen != null && narr1.isEmpty()) {
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile(); // // TODO: need to implement this
gen.generateNarrative(resourceProfile, theResource, null); // String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
} // gen.generateNarrative(resourceProfile, theResource, null);
if (narr2 != null) { // }
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild; // if (narr2 != null) {
String childName = nextChild.getChildNameByDatatype(child.getDatatype()); // RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName); // String childName = nextChild.getChildNameByDatatype(child.getDatatype());
encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource); // BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
continue; // 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 (nextChild instanceof RuntimeChildContainedResources) {
if ((nextValue == null || nextValue.isEmpty()) && !(nextValue instanceof BaseContainedDt)) { 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; continue;
} }
Class<? extends IBase> type = nextValue.getClass(); for (IBase nextValue : values) {
String childName = nextChild.getChildNameByDatatype(type); if ((nextValue == null || nextValue.isEmpty())) {
String extensionUrl = nextChild.getExtensionUrl(); continue;
BaseRuntimeElementDefinition<?> childDef = nextChild.getChildElementDefinitionByDatatype(type); }
if (childDef == null) { Class<? extends IBase> type = nextValue.getClass();
super.throwExceptionForUnknownChildType(nextChild, type); String childName = nextChild.getChildNameByDatatype(type);
} String extensionUrl = nextChild.getExtensionUrl();
BaseRuntimeElementDefinition<?> childDef = nextChild.getChildElementDefinitionByDatatype(type);
if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) { if (childDef == null) {
// This is called for the Query resource in DSTU1 only super.throwExceptionForUnknownChildType(nextChild, type);
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); if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource); // This is called for the Query resource in DSTU1 only
theEventWriter.writeEndElement(); extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) { encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
// suppress narratives from contained resources
} else { } else if (extensionUrl != null && childName.equals("extension") == false) {
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource); 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, private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource); encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), 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 * This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to
* rejected by the compiler some of the time. * 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) { private <Q extends IBaseExtension<?>> List<IBaseExtension<?>> toBaseExtensionList(final List<Q> theList) {
List<IBaseExtension<?>> retVal = new ArrayList<IBaseExtension<?>>(theList.size()); List<IBaseExtension<?>> retVal = new ArrayList<IBaseExtension<?>>(theList.size());
@ -636,7 +674,7 @@ public class XmlParser extends BaseParser implements IParser {
return retVal; return retVal;
} }
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, BaseResourceReferenceDt theRef) throws XMLStreamException { private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, IReference theRef) throws XMLStreamException {
String reference = determineReferenceText(theRef); String reference = determineReferenceText(theRef);
if (StringUtils.isNotBlank(reference)) { 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, private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
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 * DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy
* HL7 structures * 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>(); List<BaseRuntimeChildDefinition> preExtensionChildren = new ArrayList<BaseRuntimeChildDefinition>();
@ -708,14 +745,14 @@ public class XmlParser extends BaseParser implements IParser {
if (theResource instanceof IResource) { if (theResource instanceof IResource) {
// HAPI structs // HAPI structs
IResource iResource = (IResource) theResource; IResource iResource = (IResource) theResource;
if (StringUtils.isNotBlank(iResource.getId().getValue())) { if (StringUtils.isNotBlank(iResource.getId().getIdPart())) {
resourceId = iResource.getId().getIdPart(); resourceId = iResource.getId().getIdPart();
} }
} else { } else {
// HL7 structs // HL7 structs
IAnyResource resource = (IAnyResource) theResource; IAnyResource resource = (IAnyResource) theResource;
if (StringUtils.isNotBlank(resource.getId())) { if (StringUtils.isNotBlank(resource.getId().getIdPart())) {
resourceId = resource.getId(); resourceId = resource.getId().getIdPart();
} }
} }
@ -736,8 +773,9 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeDefaultNamespace(FHIR_NS); theEventWriter.writeDefaultNamespace(FHIR_NS);
if (theResource instanceof IAnyResource) { if (theResource instanceof IAnyResource) {
// HL7.org Structures // HL7.org Structures
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource); encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
} else { } 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) private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
throws XMLStreamException, DataFormatException {
for (IBaseExtension<?> next : theExtensions) { for (IBaseExtension<?> next : theExtensions) {
if (next == null) { if (next == null) {
continue; 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.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseParameters; 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.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
@ -266,7 +267,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return myLastRequest; return myLastRequest;
} }
protected String getPreferredId(IResource theResource, String theId) { protected String getPreferredId(IBaseResource theResource, String theId) {
if (isNotBlank(theId)) { if (isNotBlank(theId)) {
return theId; return theId;
} }
@ -574,7 +575,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return resp; return resp;
} }
protected IResource parseResourceBody(String theResourceBody) { protected IBaseResource parseResourceBody(String theResourceBody) {
EncodingEnum encoding = null; EncodingEnum encoding = null;
for (int i = 0; i < theResourceBody.length() && encoding == null; i++) { for (int i = 0; i < theResourceBody.length() && encoding == null; i++) {
switch (theResourceBody.charAt(i)) { switch (theResourceBody.charAt(i)) {
@ -625,7 +626,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private CriterionList myCriterionList; private CriterionList myCriterionList;
private String myId; private String myId;
private IResource myResource; private IBaseResource myResource;
private String myResourceBody; private String myResourceBody;
private String mySearchUrl; 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 class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
private CriterionList myCriterionList; private CriterionList myCriterionList;
private IdDt myId; private IIdType myId;
private IResource myResource; private IBaseResource myResource;
private String myResourceBody; private String myResourceBody;
private String mySearchUrl; private String mySearchUrl;

View File

@ -26,9 +26,13 @@ import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; 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.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.IBaseResource; 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.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource; 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.api.TagList;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum; import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
@ -123,7 +128,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
return myParameters; return myParameters;
} }
public Set<Include> getRequestIncludesFromParams(Object[] params) { @SuppressWarnings({ "unchecked", "rawtypes" })
public Set<Include> getRequestIncludesFromParams(Object[] params) {
if (params == null || params.length == 0) if (params == null || params.length == 0)
return null; return null;
int index = 0; int index = 0;
@ -148,7 +154,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
Set includes = new HashSet<Include>(); Set includes = new HashSet<Include>();
for (Object o : (Iterable)params[index]) { for (Object o : (Iterable)params[index]) {
if (o instanceof Include) { if (o instanceof Include) {
includes.add((Include) o); includes.add(o);
} }
} }
return includes; return includes;
@ -215,7 +221,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
return parser; return parser;
} }
protected Object[] createParametersForServerRequest(Request theRequest, IResource theResource) { protected Object[] createParametersForServerRequest(Request theRequest, IBaseResource theResource) {
Object[] params = new Object[getParameters().size()]; Object[] params = new Object[getParameters().size()];
for (int i = 0; i < getParameters().size(); i++) { for (int i = 0; i < getParameters().size(); i++) {
IParameter param = getParameters().get(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.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; 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.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
@ -143,16 +144,18 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
@Override @Override
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException { public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
IResource resource; IBaseResource resource;
if (requestContainsResource()) { if (requestContainsResource()) {
resource = parseIncomingServerResource(theRequest); resource = parseIncomingServerResource(theRequest);
TagList tagList = new TagList(); if (theServer.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) { TagList tagList = new TagList();
String nextTagComplete = enumeration.nextElement(); for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
MethodUtil.parseTagValue(tagList, nextTagComplete); String nextTagComplete = enumeration.nextElement();
} MethodUtil.parseTagValue(tagList, nextTagComplete);
if (tagList.isEmpty() == false) { }
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList); if (tagList.isEmpty() == false) {
((IResource)resource).getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
}
} }
} else { } else {
resource = null; resource = null;
@ -268,21 +271,21 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
/** /**
* @throws IOException * @throws IOException
*/ */
protected IResource parseIncomingServerResource(Request theRequest) throws IOException { protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest); EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
IParser parser = encoding.newParser(getContext()); IParser parser = encoding.newParser(getContext());
BufferedReader requestReader = theRequest.getServletRequest().getReader(); BufferedReader requestReader = theRequest.getServletRequest().getReader();
Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType(); Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType();
IResource retVal; IBaseResource retVal;
if (wantedResourceType != null) { if (wantedResourceType != null) {
retVal = (IResource) parser.parseResource(wantedResourceType, requestReader); retVal = parser.parseResource(wantedResourceType, requestReader);
} else { } else {
retVal = parser.parseResource(requestReader); retVal = parser.parseResource(requestReader);
} }
retVal.setId(theRequest.getId()); retVal.setId(theRequest.getId());
return retVal; return retVal;
} }
@ -294,10 +297,9 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
protected boolean requestContainsResource() { protected boolean requestContainsResource() {
return true; return true;
} }
/** /**
* Subclasses may override to provide a specific resource type that this method wants * Subclasses may override to provide a specific resource type that this method wants as a parameter
* as a parameter
*/ */
protected Class<? extends IBaseResource> requestContainsResourceType() { protected Class<? extends IBaseResource> requestContainsResourceType() {
return null; return null;
@ -307,7 +309,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
theResponse.setStatus(theE.getStatusCode()); theResponse.setStatus(theE.getStatusCode());
theServer.addHeadersToResponse(theResponse); theServer.addHeadersToResponse(theResponse);
if (theE.getOperationOutcome() != null) { if (theE.getOperationOutcome() != null) {
theResponse.setContentType(theEncodingNotNull.getResourceContentType()); theResponse.setContentType(theEncodingNotNull.getResourceContentType());
IParser parser = theEncodingNotNull.newParser(theServer.getFhirContext()); IParser parser = theEncodingNotNull.newParser(theServer.getFhirContext());

View File

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

View File

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

View File

@ -25,6 +25,8 @@ import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum; import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
@ -55,8 +57,8 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
} }
@Override @Override
protected IResource parseIncomingServerResource(Request theRequest) throws IOException { protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
IResource retVal = super.parseIncomingServerResource(theRequest); IBaseResource retVal = super.parseIncomingServerResource(theRequest);
if (theRequest.getId() != null && theRequest.getId().hasIdPart()) { if (theRequest.getId() != null && theRequest.getId().hasIdPart()) {
retVal.setId(theRequest.getId()); 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.HttpPut;
import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.AbstractHttpEntity;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContents { 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); super(theContext, theResource, theUrlExtension);
} }

View File

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

View File

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

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.TreeSet; import java.util.TreeSet;
@ -29,6 +30,7 @@ import java.util.TreeSet;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.IBase; import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource; 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.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 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.RuntimeChildDirectResource;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt; 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.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions; import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.base.composite.BaseContainedDt; import ca.uhn.fhir.model.base.composite.BaseContainedDt;
@ -56,8 +57,7 @@ public class FhirTerser {
myContext = theContext; myContext = theContext;
} }
private <T extends IBase> void addUndeclaredExtensions(IBase theElement, BaseRuntimeElementDefinition<?> theDefinition, BaseRuntimeChildDefinition theChildDefinition, private void addUndeclaredExtensions(IBase theElement, BaseRuntimeElementDefinition<?> theDefinition, BaseRuntimeChildDefinition theChildDefinition, IModelVisitor theCallback) {
IModelVisitor theCallback) {
if (theElement instanceof ISupportsUndeclaredExtensions) { if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement; ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) { 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> * <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 * For example, specifying a type of {@link StringDt} would return all non-empty string instances within the
* well as any contained resources. * message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained
* resources.
* </p> * </p>
* <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. * Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource) * but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
* resources (e.g. Bundle.entry.resource)
* </p> * </p>
* *
* @param theResource * @param theResource
@ -102,8 +105,7 @@ public class FhirTerser {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
ExtensionDt theNextExt) {
if (theType.isAssignableFrom(theNextExt.getClass())) { if (theType.isAssignableFrom(theNextExt.getClass())) {
retVal.add((T) theNextExt); retVal.add((T) theNextExt);
} }
@ -115,39 +117,39 @@ public class FhirTerser {
return retVal; return retVal;
} }
public <T extends IBase> List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) { public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>(); final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, new IModelVisitor() { visit(theResource, null, def, new IModelVisitor() {
@SuppressWarnings("unchecked") @Override
@Override public void acceptElement(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
public void acceptElement(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) { if (theElement == null || theElement.isEmpty()) {
if (theElement == null || theElement.isEmpty()) { return;
return; }
} String name = null;
String name = null; if (theChildDefinition != null) {
if (theChildDefinition != null) { name = theChildDefinition.getElementName();
name = theChildDefinition.getElementName(); }
} if (BaseResourceReferenceDt.class.isAssignableFrom(theElement.getClass())) {
if (BaseResourceReferenceDt.class.isAssignableFrom(theElement.getClass())) { retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt) theElement));
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt)theElement)); }
} }
}
@SuppressWarnings("unchecked") @Override
@Override public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, String name = null;
ExtensionDt theNextExt) { if (theChildDefinition != null) {
String name = null; name = theChildDefinition.getElementName();
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()));
if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) { }
retVal.add(new ResourceReferenceInfo(theResource, name, (BaseResourceReferenceDt)theNextExt.getValue())); }
} });
} return retVal;
}); }
return retVal; } private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0)); BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));
if (theSubList.size() == 1) { if (theSubList.size() == 1) {
@ -229,17 +231,16 @@ public class FhirTerser {
// } // }
switch (theDefinition.getChildType()) { switch (theDefinition.getChildType()) {
// case RESOURCE: case ID_DATATYPE:
// // Don't descend into embedded resources case PRIMITIVE_XHTML_HL7ORG:
// break;
case PRIMITIVE_XHTML: case PRIMITIVE_XHTML:
case PRIMITIVE_DATATYPE: case PRIMITIVE_DATATYPE:
// These are primitive types // These are primitive types
break; break;
case RESOURCE_REF: case RESOURCE_REF:
BaseResourceReferenceDt resRefDt = (BaseResourceReferenceDt) theElement; IReference resRefDt = (IReference) theElement;
if (resRefDt.getReference().getValue() == null && resRefDt.getResource() != null) { 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()) { if (theResource.getId() == null || theResource.getId().isEmpty() || theResource.getId().isLocal()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, theCallback); visit(theResource, null, def, theCallback);
@ -248,7 +249,7 @@ public class FhirTerser {
break; break;
case RESOURCE: case RESOURCE:
case RESOURCE_BLOCK: case RESOURCE_BLOCK:
case COMPOSITE_DATATYPE: { case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition; BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition;
for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) {
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement); List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
@ -281,7 +282,7 @@ public class FhirTerser {
} }
throw new DataFormatException(b.toString()); throw new DataFormatException(b.toString());
} }
if (nextChild instanceof RuntimeChildDirectResource) { if (nextChild instanceof RuntimeChildDirectResource) {
// Don't descend into embedded resources // Don't descend into embedded resources
theCallback.acceptElement(nextValue, nextChild, childElementDef); theCallback.acceptElement(nextValue, nextChild, childElementDef);
@ -305,16 +306,147 @@ public class FhirTerser {
case UNDECL_EXT: { case UNDECL_EXT: {
throw new IllegalStateException("state should not happen: " + theDefinition.getChildType()); 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 * Visit all elements in a given resource
* *
* <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. * Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource) * but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
* resources (e.g. Bundle.entry.resource)
* </p> * </p>
*
* @param theResource * @param theResource
* The resource to visit * The resource to visit
* @param theVisitor * @param theVisitor
@ -325,15 +457,36 @@ public class FhirTerser {
visit(theResource, null, def, theVisitor); 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) { public Object getSingleValueOrNull(IBase theTarget, String thePath) {
Validate.notNull(theTarget, "theTarget must not be null"); Validate.notNull(theTarget, "theTarget must not be null");
Validate.notBlank(thePath, "thePath must not be empty"); Validate.notBlank(thePath, "thePath must not be empty");
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theTarget.getClass()); BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theTarget.getClass());
if (!(def instanceof BaseRuntimeElementCompositeDefinition)) { if (!(def instanceof BaseRuntimeElementCompositeDefinition)) {
throw new IllegalArgumentException("Target is not a composite type: " + theTarget.getClass().getName()); throw new IllegalArgumentException("Target is not a composite type: " + theTarget.getClass().getName());
} }
BaseRuntimeElementCompositeDefinition<?> currentDef = (BaseRuntimeElementCompositeDefinition<?>) def; BaseRuntimeElementCompositeDefinition<?> currentDef = (BaseRuntimeElementCompositeDefinition<?>) def;
Object currentObj = theTarget; 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; package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.api.IIdType;
/* /*
* #%L * #%L
* HAPI FHIR - Core Library * HAPI FHIR - Core Library
@ -29,5 +31,11 @@ package org.hl7.fhir.instance.model;
* <code>ca.uhn.fhir.model.dstu.resource.Patient</code>) * <code>ca.uhn.fhir.model.dstu.resource.Patient</code>)
*/ */
public interface IBaseResource extends IBase { 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 { public interface IAnyResource extends IBaseResource {
String getId(); IIdType getId();
IAnyResource setId(String theId); 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 * #%L
@ -20,16 +22,8 @@ package org.hl7.fhir.instance.model;
* #L% * #L%
*/ */
/** public interface IBaseEnumeration<T extends Enum<?>> extends IPrimitiveType<T> {
* 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 {
IIdType // 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 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(); 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.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
public interface IReference extends IBase { 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); IReference setReference(String theReference);
IBase setDisplay(String theValue); IBase setDisplay(String theValue);
IPrimitiveType<String> getDisplayElement();
} }

View File

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

View File

@ -5,11 +5,15 @@ import static org.junit.Assert.*;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit; import org.custommonkey.xmlunit.XMLUnit;
import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; 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.ContainedDt;
import ca.uhn.fhir.model.dstu2.composite.DurationDt; import ca.uhn.fhir.model.dstu2.composite.DurationDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt; 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.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance; import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance;
import ca.uhn.fhir.model.dstu2.resource.Binary; 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.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient; 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.dstu2.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
@ -54,6 +60,204 @@ public class XmlParserDstu2Test {
XMLUnit.setIgnoreWhitespace(true); 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 * 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"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -18,7 +18,7 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId> <artifactId>hapi-fhir-base</artifactId>
<version>0.9-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<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.annotations.Description;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; 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. * A resource that includes narrative, extensions, and contained resources.
*/ */
@ResourceDef(name="DomainResource", profile="http://hl7.org/fhir/Profile/DomainResource") @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. * 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.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory; import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
/* /*
Copyright (c) 2011+, HL7, Inc Copyright (c) 2011+, HL7, Inc
@ -37,7 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
@DatatypeDef(name="enumeration") @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 static final long serialVersionUID = 1L;
private EnumFactory<T> myEnumFactory; private EnumFactory<T> myEnumFactory;

View File

@ -28,8 +28,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.hl7.fhir.instance.model; package org.hl7.fhir.instance.model;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.math.BigDecimal; 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.Validate;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.annotations.DatatypeDef; 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 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.api.annotation.SimpleSetter;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
@ -545,37 +540,12 @@ public class IdType extends UriType implements IIdType {
return isBlank(getValue()); 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");
}
}
/**
* 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 ((IBaseResource) theResouce).getIdElement();
} 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");
}
}
@Override @Override
public IdType copy() { public IdType copy() {
return new IdType(getValue()); return new IdType(getValue());
} }
}
}

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 // 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.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.XhtmlComposer;
import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.XhtmlParser; 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. * 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. * The actual narrative content, a stripped down version of XHTML.
*/ */
// @Child(name="div", type={}, order=1, min=1, max=1) @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." ) @Description(shortDefinition="Limited xhtml content", formalDefinition="The actual narrative content, a stripped down version of XHTML." )
protected XhtmlNode div; protected XhtmlNode div;
private static final long serialVersionUID = 1463852859L; 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 // 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.Block;
import org.hl7.fhir.instance.model.annotations.Child; import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description; 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. * 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 * Constructor
*/ */
public Reference(StringType theReference) { 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) { public Reference(String theReference) {
if (StringUtils.isNotBlank(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 * 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 * 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 * a part of the FHIR "wire format" and is never transmitted or receieved inline, but this property
* may be changed/accessed by parsers. * may be changed/accessed by parsers.
*/ */
public IAnyResource getResource() { public IBaseResource getResource() {
return resource; 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 * a part of the FHIR "wire format" and is never transmitted or receieved inline, but this property
* may be changed/accessed by parsers. * may be changed/accessed by parsers.
*/ */
public void setResource(IAnyResource theResource) { public void setResource(IBaseResource theResource) {
resource = 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) @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." ) @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. * 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 * @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 (this.reference == null)
if (Configuration.errorOnAutoCreate()) if (Configuration.errorOnAutoCreate())
throw new Error("Attempt to auto-create Reference.reference"); throw new Error("Attempt to auto-create Reference.reference");
else if (Configuration.doAutoCreate()) else if (Configuration.doAutoCreate())
this.reference = new StringType(); // bb this.reference = new IdType(); // bb
return this.reference; 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 * @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; this.reference = value;
return this; 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. * @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() { public IdType getReference() {
return this.reference == null ? null : this.reference.getValue(); return getReferenceElement();
} }
/** /**
@ -159,7 +161,7 @@ public class Reference extends Type implements IReference, ICompositeType {
this.reference = null; this.reference = null;
else { else {
if (this.reference == null) if (this.reference == null)
this.reference = new StringType(); this.reference = new IdType();
this.reference.setValue(value); this.reference.setValue(value);
} }
return this; return this;
@ -253,7 +255,7 @@ public class Reference extends Type implements IReference, ICompositeType {
} }
public boolean isEmpty() { 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 // 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.Child;
import org.hl7.fhir.instance.model.annotations.Description; 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.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.utilities.Utilities;
/** /**
* Base Resource for everything. * 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. * @return The logical id of the resource, as used in the url for the resoure. Once assigned, this value never changes.
*/ */
public String getId() { public IdType getId() {
return this.id == null ? null : this.id.getValue(); return getIdElement(); // this.id == null ? null : this.id.getValue();
} }
/** /**
@ -129,6 +128,14 @@ public abstract class Resource extends Base implements IAnyResource {
return this; 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.) * @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.List;
import java.util.Map; import java.util.Map;
//@DatatypeDef() import org.hl7.fhir.instance.model.IPrimitiveType;
public class XhtmlNode { 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); public static final String NBSP = Character.toString((char)0xa0);
@ -280,7 +284,40 @@ public class XhtmlNode {
return e1.equalsDeep(e2); return e1.equalsDeep(e2);
} }
public String getValueAsString() throws Exception { public String getValueAsString() {
return new XhtmlComposer().compose(this); 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.DecimalType;
import org.hl7.fhir.instance.model.DomainResource; import org.hl7.fhir.instance.model.DomainResource;
import org.hl7.fhir.instance.model.Element; 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.Extension;
import org.hl7.fhir.instance.model.IBase; import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.ICompositeType; 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.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype; 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.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype; 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.ICoding;
import org.hl7.fhir.instance.model.api.IDatatypeElement; 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.IIdType;
import org.hl7.fhir.instance.model.api.IMetaType; import org.hl7.fhir.instance.model.api.IMetaType;
import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.INarrative;
import org.hl7.fhir.instance.model.api.IReference; import org.hl7.fhir.instance.model.api.IReference;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.Test; import org.junit.Test;
public class ModelInheritanceTest { public class ModelInheritanceTest {
@ -78,6 +83,11 @@ public class ModelInheritanceTest {
assertTrue(ICompositeType.class.isAssignableFrom(Address.class)); assertTrue(ICompositeType.class.isAssignableFrom(Address.class));
} }
@Test
public void testXhtml() {
assertTrue(IBaseXhtml.class.isAssignableFrom(XhtmlNode.class));
}
@Test @Test
public void testBackboneElement() { public void testBackboneElement() {
assertTrue(IBackboneElement.class.isAssignableFrom(BackboneElement.class)); assertTrue(IBackboneElement.class.isAssignableFrom(BackboneElement.class));
@ -122,6 +132,7 @@ public class ModelInheritanceTest {
public void testDomainResource() { public void testDomainResource() {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(DomainResource.class)); assertTrue(IBaseHasExtensions.class.isAssignableFrom(DomainResource.class));
assertTrue(IBaseHasModifierExtensions.class.isAssignableFrom(DomainResource.class)); assertTrue(IBaseHasModifierExtensions.class.isAssignableFrom(DomainResource.class));
assertTrue(IDomainResource.class.isAssignableFrom(DomainResource.class));
} }
@Test @Test
@ -129,6 +140,11 @@ public class ModelInheritanceTest {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(Element.class)); assertTrue(IBaseHasExtensions.class.isAssignableFrom(Element.class));
} }
@Test
public void testEnumeration() {
assertTrue(IBaseEnumeration.class.isAssignableFrom(Enumeration.class));
}
/** /**
* Should be "implements IBaseExtension<Extension>" * Should be "implements IBaseExtension<Extension>"
*/ */

View File

@ -77,27 +77,20 @@ public class XmlParserTest {
@BeforeClass @BeforeClass
public static void beforeClass2() { 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 @Test
public void testEncodeBinaryWithNoContentType() { public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary(); 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); String output = ourCtx.newXmlParser().encodeResourceToString(b);
ourLog.info(output); ourLog.info(output);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output); assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
} }
@Test @Test
public void testEncodeNonContained() { public void testEncodeNonContained() {
// Create an organization // Create an organization
@ -110,18 +103,18 @@ public class XmlParserTest {
patient.setId("Patient/1333"); patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getManagingOrganization().setResource(org); patient.getManagingOrganization().setResource(org);
// Create a list containing both resources. In a server method, you might just // 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. // return this list, but here we will create a bundle to encode.
List<Resource> resources = new ArrayList<Resource>(); List<Resource> resources = new ArrayList<Resource>();
resources.add(org); resources.add(org);
resources.add(patient); resources.add(patient);
// Create a bundle with both // Create a bundle with both
Bundle b = new Bundle(); Bundle b = new Bundle();
b.addEntry().setResource(org); b.addEntry().setResource(org);
b.addEntry().setResource(patient); b.addEntry().setResource(patient);
// Encode the buntdle // Encode the buntdle
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded); ourLog.info(encoded);
@ -129,13 +122,29 @@ public class XmlParserTest {
assertThat(encoded, stringContainsInOrder("<Organization", "<id value=\"65546\"/>", "</Organization>")); assertThat(encoded, stringContainsInOrder("<Organization", "<id value=\"65546\"/>", "</Organization>"));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>")); assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
assertThat(encoded, stringContainsInOrder("<Patient", "<id value=\"1333\"/>", "</Patient>")); assertThat(encoded, stringContainsInOrder("<Patient", "<id value=\"1333\"/>", "</Patient>"));
encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, not(containsString("<contained>"))); assertThat(encoded, not(containsString("<contained>")));
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>")); 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 @Test
@ -150,22 +159,25 @@ public class XmlParserTest {
// Create a patient // Create a patient
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("Patient/1333"); 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.getText().setDivAsString("<div>BARFOO</div>");
patient.getManagingOrganization().setResource(org); patient.getManagingOrganization().setResource(org);
String encoded = parser.encodeResourceToString(patient); String encoded = parser.encodeResourceToString(patient);
ourLog.info(encoded); 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, not(containsString("FOOBAR")));
assertThat(encoded, (containsString("BARFOO"))); assertThat(encoded, (containsString("BARFOO")));
}
}
@Test @Test
public void testEncodeContained() { public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID // Create an organization, note that the organization does not have an ID
Organization org = new Organization(); Organization org = new Organization();
org.getNameElement().setValue("Contained Test Organization"); org.getNameElement().setValue("Contained Test Organization");
@ -174,41 +186,41 @@ public class XmlParserTest {
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("Patient/1333"); patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
// Put the organization as a reference in the patient resource // Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org); patient.getManagingOrganization().setResource(org);
String encoded = xmlParser.encodeResourceToString(patient); String encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, containsString("<contained>")); assertThat(encoded, containsString("<contained>"));
assertThat(encoded, containsString("<reference value=\"#1\"/>")); assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// Create a bundle with just the patient resource // Create a bundle with just the patient resource
Bundle b = new Bundle(); Bundle b = new Bundle();
b.addEntry().setResource(patient); b.addEntry().setResource(patient);
// Encode the buntdle // Encode the bundle
encoded = xmlParser.encodeResourceToString(b); encoded = xmlParser.encodeResourceToString(b);
ourLog.info(encoded); 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, containsString("<reference value=\"#1\"/>"));
assertThat(encoded, stringContainsInOrder(Arrays.asList("<entry>", "</entry>"))); assertThat(encoded, stringContainsInOrder(Arrays.asList("<entry>", "</entry>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<entry>", "</entry>", "<entry>")))); assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<entry>", "</entry>", "<entry>"))));
// Re-parse the bundle // Re-parse the bundle
patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
assertEquals("#1", patient.getManagingOrganization().getReference()); assertEquals("#1", patient.getManagingOrganization().getReference().getValue());
assertNotNull(patient.getManagingOrganization().getResource()); assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource(); org = (Organization) patient.getManagingOrganization().getResource();
assertEquals("#1", org.getId()); assertEquals("#1", org.getId().getValue());
assertEquals("Contained Test Organization", org.getName()); assertEquals("Contained Test Organization", org.getName());
// And re-encode a second time // And re-encode a second time
encoded = xmlParser.encodeResourceToString(patient); encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"1\"", "</Organization", "</contained>", "<reference value=\"#1\"/>"))); 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, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>")); assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared // And re-encode once more, with the references cleared
@ -216,8 +228,8 @@ public class XmlParserTest {
patient.getManagingOrganization().setReference(null); patient.getManagingOrganization().setReference(null);
encoded = xmlParser.encodeResourceToString(patient); encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"1\"", "</Organization", "</contained>", "<reference value=\"#1\"/>"))); 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, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
assertThat(encoded, containsString("<reference value=\"#1\"/>")); assertThat(encoded, containsString("<reference value=\"#1\"/>"));
// And re-encode once more, with the references cleared and a manually set local ID // 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")); patient.getManagingOrganization().getResource().setId(("#333"));
encoded = xmlParser.encodeResourceToString(patient); encoded = xmlParser.encodeResourceToString(patient);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "id=\"333\"", "</Organization", "</contained>", "<reference value=\"#333\"/>"))); assertThat(encoded, stringContainsInOrder(Arrays.asList("<contained>", "<Organization ", "<id value=\"333\"/>", "</Organization", "</contained>", "<reference value=\"#333\"/>")));
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>")))); assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
} }
/** /**
* Thanks to Alexander Kley! * Thanks to Alexander Kley!
*/ */
@Test @Test
public void testParseContainedBinaryResource() { public void testParseContainedBinaryResource() {
byte[] bin = new byte[] {0,1,2,3,4}; byte[] bin = new byte[] { 0, 1, 2, 3, 4 };
final Binary binary = new Binary(); final Binary binary = new Binary();
binary.setContentType("PatientConsent").setContent( bin); binary.setContentType("PatientConsent").setContent(bin);
// binary.setId(UUID.randomUUID().toString()); // binary.setId(UUID.randomUUID().toString());
DocumentManifest manifest = new DocumentManifest(); DocumentManifest manifest = new DocumentManifest();
// manifest.setId(UUID.randomUUID().toString()); // manifest.setId(UUID.randomUUID().toString());
CodeableConcept cc = new CodeableConcept(); CodeableConcept cc = new CodeableConcept();
cc.addCoding().setSystem("mySystem").setCode( "PatientDocument"); cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
manifest.setType(cc); manifest.setType(cc);
manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue( UUID.randomUUID().toString())); manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
manifest.addContent().setResource(binary); manifest.addContent().setResource(binary);
manifest.setStatus(DocumentReferenceStatus.CURRENT); manifest.setStatus(DocumentReferenceStatus.CURRENT);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest); String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
ourLog.info(encoded); ourLog.info(encoded);
assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>","<Binary", "</contained>"))); assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", "<Binary", "</contained>")));
DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded); DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded);
assertEquals(1, actual.getContained().size()); assertEquals(1, actual.getContained().size());
assertEquals(1, actual.getContent().size()); assertEquals(1, actual.getContent().size());
assertNotNull(actual.getContent().get(0).getResource()); assertNotNull(actual.getContent().get(0).getResource());
} }
@Test @Test
public void testComposition() { public void testComposition() {
Composition comp = new Composition(); Composition comp = new Composition();
comp.setId("1"); comp.setId("1");
ourCtx.newXmlParser().encodeResourceToString(comp); ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp); ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp); ourCtx.newXmlParser().encodeResourceToString(comp);
ourCtx.newXmlParser().encodeResourceToString(comp); ourCtx.newXmlParser().encodeResourceToString(comp);
// comp. // comp.
} }
@Test @Test
public void testEncodeBinaryResource() { public void testEncodeBinaryResource() {
@ -288,7 +296,7 @@ public class XmlParserTest {
patient.setContent(new byte[] { 1, 2, 3, 4 }); patient.setContent(new byte[] { 1, 2, 3, 4 });
String val = ourCtx.newXmlParser().encodeResourceToString(patient); 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 @Test
public void testEncodeBundle() throws InterruptedException { public void testEncodeBundle() throws InterruptedException {
Bundle b = new Bundle(); 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(); InstantType pub = InstantType.withCurrentTime();
b.getMeta().setLastUpdatedElement(pub); b.getMeta().setLastUpdatedElement(pub);
@ -346,7 +354,7 @@ public class XmlParserTest {
Bundle b = new Bundle(); Bundle b = new Bundle();
BundleEntryComponent e = b.addEntry(); BundleEntryComponent e = b.addEntry();
e.setResource(new Patient()); 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); String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(val); ourLog.info(val);
@ -363,7 +371,6 @@ public class XmlParserTest {
} }
@Test @Test
public void testEncodeEscapedChars() { public void testEncodeEscapedChars() {
@ -409,7 +416,7 @@ public class XmlParserTest {
DiagnosticReport rpt = new DiagnosticReport(); DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen(); Specimen spm = new Specimen();
spm.addIdentifier().setSystem("urn").setValue( "123"); spm.addIdentifier().setSystem("urn").setValue("123");
rpt.getText().setDivAsString("AAA"); rpt.getText().setDivAsString("AAA");
rpt.addSpecimen().setResource(spm); rpt.addSpecimen().setResource(spm);
@ -472,7 +479,7 @@ public class XmlParserTest {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addAddress().setUse(AddressUse.HOME); 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); String val = parser.encodeResourceToString(patient);
ourLog.info(val); ourLog.info(val);
@ -483,7 +490,7 @@ public class XmlParserTest {
List<Extension> ext = actual.getExtension(); List<Extension> ext = actual.getExtension();
assertEquals(1, ext.size()); assertEquals(1, ext.size());
Reference ref = (Reference) ext.get(0).getValue(); 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 @Test
public void testEncodeResourceRef() throws DataFormatException { public void testEncodeResourceRef() throws DataFormatException {
@ -618,7 +624,7 @@ public class XmlParserTest {
HumanName name = patient.addName(); HumanName name = patient.addName();
name.addFamily("Shmoe"); name.addFamily("Shmoe");
HumanName given = name.addGiven("Joe"); 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); given.getExtension().add(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output); ourLog.info(output);
@ -629,7 +635,7 @@ public class XmlParserTest {
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc)); Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getName().get(0).getExtension().size()); assertEquals(1, parsed.getName().get(0).getExtension().size());
Extension ext = parsed.getName().get(0).getExtension().get(0); 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(); StringType family = name.addFamilyElement();
family.setValue("Shmoe"); 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); family.getExtension().add(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output); ourLog.info(output);
@ -653,7 +659,7 @@ public class XmlParserTest {
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc)); Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size()); assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size());
Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0); 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><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
+ "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>" + "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>"
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>" + "<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\" />" + "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
+ "</Patient>"; + "</Patient>";
//@formatter:on //@formatter:on
@ -698,11 +704,13 @@ public class XmlParserTest {
Patient patient = ourCtx.newXmlParser().parseResource(Patient.class, msg); Patient patient = ourCtx.newXmlParser().parseResource(Patient.class, msg);
assertEquals(NarrativeStatus.GENERATED, patient.getText().getStatus()); 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()); assertEquals("PRP1660", patient.getIdentifier().get(0).getValue());
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient); String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
Diff d = new Diff(new StringReader(msg), new StringReader(encoded)); Diff d = new Diff(new StringReader(msg), new StringReader(encoded));
assertTrue(d.toString(), d.identical()); assertTrue(d.toString(), d.identical());
@ -801,12 +809,12 @@ public class XmlParserTest {
Patient resource = (Patient) p.parseResource(msg); Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel()); assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel());
assertEquals("Foo1Value", ((IPrimitiveType<?>)resource.getExtension().get(0).getValue()).getValueAsString()); assertEquals("Foo1Value", ((IPrimitiveType<?>) resource.getExtension().get(0).getValue()).getValueAsString());
assertEquals("Foo1Value2", ((IPrimitiveType<?>)resource.getExtension().get(1).getValue()).getValueAsString()); assertEquals("Foo1Value2", ((IPrimitiveType<?>) resource.getExtension().get(1).getValue()).getValueAsString());
assertEquals("Foo2Value1", ((IPrimitiveType<?>)resource.getModifierExtension().get(0).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-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-02", ((IPrimitiveType<?>) resource.getExtension().get(2).getExtension().get(1).getExtension().get(0).getValue()).getValueAsString());
String encoded = p.encodeResourceToString(resource); String encoded = p.encodeResourceToString(resource);
ourLog.info(encoded); ourLog.info(encoded);
@ -815,51 +823,9 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical()); 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 @Test
public void testReEncode() throws SAXException, IOException { public void testReEncode() throws SAXException, IOException {
@ -920,12 +886,10 @@ public class XmlParserTest {
String enc = ourCtx.newXmlParser().encodeResourceToString(patient); 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("<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("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat( 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>"));
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=\"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>")); 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 * 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 { public void testNarrativeGeneration() throws DataFormatException, IOException {
Patient patient = new Patient(); Patient patient = new Patient();
@ -998,8 +963,9 @@ public class XmlParserTest {
@Override @Override
public void setFhirContext(FhirContext theFhirContext) { public void setFhirContext(FhirContext theFhirContext) {
// nothing // nothing
}}; }
};
FhirContext context = new FhirContext(); FhirContext context = new FhirContext();
context.setNarrativeGenerator(gen); context.setNarrativeGenerator(gen);
IParser p = context.newXmlParser(); IParser p = context.newXmlParser();
@ -1075,7 +1041,6 @@ public class XmlParserTest {
} }
@Test @Test
public void testParseBundleWithMixedReturnTypes() { public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml")); InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
@ -1141,7 +1106,6 @@ public class XmlParserTest {
assertEquals("zh-CN", pt.getLanguage()); assertEquals("zh-CN", pt.getLanguage());
} }
@Test @Test
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException { public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser(); IParser p = ourCtx.newXmlParser();
@ -1217,7 +1181,6 @@ public class XmlParserTest {
} }
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true); 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
}