diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java b/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java index 7ff77978357..c8f76b62d58 100644 --- a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java +++ b/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java @@ -54,18 +54,17 @@ public class MultiVersionXmlParserTest { String res = ourCtxDstu1.newXmlParser().encodeResourceToString(p); - { - ca.uhn.fhir.model.dstu2.resource.Patient parsed = ourCtxDstu1.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Patient.class, res); - assertEquals("RR Display", parsed.getManagingOrganization().getDisplayElement().getValue()); - assertEquals(1, parsed.getContained().getContainedResources().size()); - assertEquals("
DIV
", p.getText().getDiv().getValueAsString()); - + try { + ourCtxDstu1.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Patient.class, res); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("This parser is for FHIR version DSTU1 - Can not parse a structure for version DSTU2", e.getMessage()); } - { - ca.uhn.fhir.model.dstu.resource.Patient parsed = ourCtxDstu2.newXmlParser().parseResource(ca.uhn.fhir.model.dstu.resource.Patient.class, res); - assertEquals("RR Display", parsed.getManagingOrganization().getDisplayElement().getValue()); - assertEquals(1, parsed.getContained().getContainedResources().size()); - assertEquals("
DIV
", p.getText().getDiv().getValueAsString()); + try { + ourCtxDstu2.newXmlParser().parseResource(ca.uhn.fhir.model.dstu.resource.Patient.class, res); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("This parser is for FHIR version DSTU2 - Can not parse a structure for version DSTU1", e.getMessage()); } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java index 1b79716b93d..02dd7227aac 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java @@ -23,8 +23,10 @@ package ca.uhn.fhir.context; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseReference; public abstract class BaseRuntimeChildDefinition { @@ -73,6 +75,17 @@ public abstract class BaseRuntimeChildDefinition { void setValue(Object theTarget, IBase theValue); } + BaseRuntimeElementDefinition findResourceReferenceDefinition(Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { + for (Entry, BaseRuntimeElementDefinition> next : theClassToElementDefinitions.entrySet()) { + if (IBaseReference.class.isAssignableFrom(next.getKey())) { + return next.getValue(); + } + } + + // Shouldn't happen + throw new IllegalStateException("Unable to find reference type"); + } + // public String getExtensionUrl() { // return null; // } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java index a0ae1eb9acf..4009ee6d30d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java @@ -40,9 +40,9 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil private final int myMin; private boolean myModifier; private final IMutator myMutator; + private final String myShortDefinition; private boolean mySummary; - BaseRuntimeDeclaredChildDefinition(Field theField, Child theChildAnnotation, Description theDescriptionAnnotation, String theElementName) throws ConfigurationException { super(); Validate.notNull(theField, "No field speficied"); @@ -124,10 +124,15 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil return myModifier; } + @Override public boolean isSummary() { return mySummary; } + protected void setModifier(boolean theModifier) { + myModifier = theModifier; + } + private final class FieldListAccessor implements IAccessor { @SuppressWarnings("unchecked") @Override diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java index a480fbb8a24..52281e0387a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.TreeSet; @@ -51,6 +52,11 @@ public abstract class BaseRuntimeElementCompositeDefinition ext myChildren.add(theNext); } + public BaseRuntimeChildDefinition getChildByName(String theName){ + BaseRuntimeChildDefinition retVal = myNameToChild.get(theName); + return retVal; + } + public BaseRuntimeChildDefinition getChildByNameOrThrowDataFormatException(String theName) throws DataFormatException { BaseRuntimeChildDefinition retVal = myNameToChild.get(theName); if (retVal == null) { @@ -59,11 +65,6 @@ public abstract class BaseRuntimeElementCompositeDefinition ext return retVal; } - public BaseRuntimeChildDefinition getChildByName(String theName){ - BaseRuntimeChildDefinition retVal = myNameToChild.get(theName); - return retVal; - } - public List getChildren() { return myChildren; } @@ -72,8 +73,8 @@ public abstract class BaseRuntimeElementCompositeDefinition ext return myChildrenAndExtensions; } - @Override - public void sealAndInitialize(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { + @Override + void sealAndInitialize(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { super.sealAndInitialize(theContext, theClassToElementDefinitions); for (BaseRuntimeChildDefinition next : myChildren) { @@ -100,9 +101,25 @@ public abstract class BaseRuntimeElementCompositeDefinition ext List children = new ArrayList(); children.addAll(myChildren); - children.addAll(getExtensionsModifier()); - children.addAll(getExtensionsNonModifier()); + if (getExtensionsNonModifier().isEmpty() == false) { + children.addAll(findIndex(children, "extension"), getExtensionsNonModifier()); + } + if (getExtensionsModifier().isEmpty() == false) { + children.addAll(findIndex(children, "modifierExtension"), getExtensionsModifier()); + } + myChildrenAndExtensions=Collections.unmodifiableList(children); } + private static int findIndex(List theChildren, String theName) { + int index = theChildren.size(); + for (ListIterator iter = theChildren.listIterator(); iter.hasNext(); ) { + if (iter.next().getElementName().equals(theName)) { + index = iter.previousIndex(); + break; + } + } + return index; + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index c0a5c1bc469..461abc41be1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -478,7 +478,13 @@ class ModelScanner { Class nextElementType = determineElementType(next); - if (BaseContainedDt.class.isAssignableFrom(nextElementType) || (childAnnotation.name().equals("contained") && IBaseResource.class.isAssignableFrom(nextElementType))) { + if (childAnnotation.name().equals("extension") && IBaseExtension.class.isAssignableFrom(nextElementType)) { + RuntimeChildExtension def = new RuntimeChildExtension(next, childAnnotation.name(), childAnnotation, descriptionAnnotation); + orderMap.put(order, def); + } else if (childAnnotation.name().equals("modifierExtension") && IBaseExtension.class.isAssignableFrom(nextElementType)) { + RuntimeChildExtension def = new RuntimeChildExtension(next, childAnnotation.name(), childAnnotation, descriptionAnnotation); + orderMap.put(order, def); + } else if (BaseContainedDt.class.isAssignableFrom(nextElementType) || (childAnnotation.name().equals("contained") && IBaseResource.class.isAssignableFrom(nextElementType))) { /* * Child is contained resources */ diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java index 442bb157fb4..fe7835b31dd 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang3.StringUtils; @@ -101,8 +102,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini elementName = getElementName() + StringUtils.capitalize(next.getSimpleName()); List> types = new ArrayList>(); types.add((Class) next); - nextDef = new RuntimeResourceReferenceDefinition(elementName, types, false); - nextDef.sealAndInitialize(theContext, theClassToElementDefinitions); + nextDef = findResourceReferenceDefinition(theClassToElementDefinitions); myNameToChildDefinition.put(getElementName() + "Reference", nextDef); myNameToChildDefinition.put(getElementName() + "Resource", nextDef); @@ -169,6 +169,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini } + @Override public String getChildNameByDatatype(Class theDatatype) { String retVal = myDatatypeToElementName.get(theDatatype); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildDeclaredExtensionDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildDeclaredExtensionDefinition.java index 60a27860439..9d89d339d69 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildDeclaredExtensionDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildDeclaredExtensionDefinition.java @@ -138,6 +138,7 @@ public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclared return myDefinedLocally; } + @Override public boolean isModifier() { return myModifier; } @@ -164,7 +165,7 @@ public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclared myDatatypeChildName = "valueResource"; List> types = new ArrayList>(); types.add(IResource.class); - myChildDef = new RuntimeResourceReferenceDefinition("valueResource", types, false); + myChildDef = findResourceReferenceDefinition(theClassToElementDefinitions); } else { myChildDef = elementDef; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildExtension.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildExtension.java new file mode 100644 index 00000000000..c36196749fe --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildExtension.java @@ -0,0 +1,51 @@ +package ca.uhn.fhir.context; + +import static org.hamcrest.Matchers.emptyCollectionOf; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseExtension; + +import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; + +public class RuntimeChildExtension extends RuntimeChildAny { + + private RuntimeChildUndeclaredExtensionDefinition myExtensionElement; + + public RuntimeChildExtension(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation) { + super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation); + } + + @Override + public String getChildNameByDatatype(Class theDatatype) { + return getElementName(); + } + + @Override + public Set getValidChildNames() { + return Collections.singleton(getElementName()); + } + +// @Override +// public BaseRuntimeElementDefinition getChildElementDefinitionByDatatype(Class theDatatype) { +// if (IBaseExtension.class.isAssignableFrom(theDatatype)) { +// return myExtensionElement; +// } +// return super.getChildElementDefinitionByDatatype(theDatatype); +// } +// +// @Override +// void sealAndInitialize(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { +// super.sealAndInitialize(theContext, theClassToElementDefinitions); +// +// myExtensionElement = theContext.getRuntimeChildUndeclaredExtensionDefinition(); +// } + + +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildResourceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildResourceDefinition.java index a474a44e8ee..9b5bad37fb8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildResourceDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildResourceDefinition.java @@ -83,8 +83,7 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi @Override void sealAndInitialize(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { - myRuntimeDef = new RuntimeResourceReferenceDefinition(getElementName(), myResourceTypes, false); - myRuntimeDef.sealAndInitialize(theContext, theClassToElementDefinitions); + myRuntimeDef = findResourceReferenceDefinition(theClassToElementDefinitions); myValidChildNames = new HashSet(); myValidChildNames.add(getElementName()); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java index 22d1351fb2f..92e96703fe0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java @@ -50,8 +50,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD private void addReferenceBinding(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions, String value) { List> types = new ArrayList>(); types.add(IBaseResource.class); - RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition(value, types, false); - def.sealAndInitialize(theContext, theClassToElementDefinitions); + BaseRuntimeElementDefinition def = findResourceReferenceDefinition(theClassToElementDefinitions); myAttributeNameToDefinition.put(value, def); /* diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceReferenceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceReferenceDefinition.java index 8079e96a7fe..939ba806760 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceReferenceDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceReferenceDefinition.java @@ -1,70 +1,20 @@ package ca.uhn.fhir.context; -/* - * #%L - * HAPI FHIR - Core Library - * %% - * Copyright (C) 2014 - 2016 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.HashMap; -import java.util.List; import java.util.Map; -import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBase; -import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IBaseReference; -import ca.uhn.fhir.model.api.IResource; -import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt; +public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementCompositeDefinition { -public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementDefinition { - private final List> myResourceTypes; - private HashMap, RuntimeResourceDefinition> myResourceTypeToDefinition; - - /** - * Constructor - * @param theStandardType - */ - public RuntimeResourceReferenceDefinition(String theName, List> theResourceTypes, boolean theStandardType) { - super(theName, BaseResourceReferenceDt.class, theStandardType); - if (theResourceTypes == null || theResourceTypes.isEmpty()) { - throw new ConfigurationException("Element '" + theName + "' has no resource types noted"); - } - myResourceTypes = theResourceTypes; - } - - public List> getResourceTypes() { - return myResourceTypes; + public RuntimeResourceReferenceDefinition(String theName, Class theImplementingClass, boolean theStandardType) { + super(theName, theImplementingClass, theStandardType); } @Override void sealAndInitialize(FhirContext theContext, Map, BaseRuntimeElementDefinition> theClassToElementDefinitions) { - myResourceTypeToDefinition = new HashMap, RuntimeResourceDefinition>(); - for (Class next : myResourceTypes) { - if (next.equals(IResource.class) || next.equals(IAnyResource.class) || next.equals(IBaseResource.class)) { - continue; - } - RuntimeResourceDefinition definition = (RuntimeResourceDefinition) theClassToElementDefinitions.get(next); - if (definition == null) { - throw new ConfigurationException("Couldn't find definition for: " + next.getCanonicalName()); - } - myResourceTypeToDefinition.put(next, definition); - } + super.sealAndInitialize(theContext, theClassToElementDefinitions); } @Override @@ -72,12 +22,4 @@ public class RuntimeResourceReferenceDefinition extends BaseRuntimeElementDefini return ChildTypeEnum.RESOURCE_REF; } - public RuntimeResourceDefinition getDefinitionForResourceType(Class theType) { - RuntimeResourceDefinition retVal = myResourceTypeToDefinition.get(theType); - if (retVal == null) { - throw new ConfigurationException("Unknown type: " + theType.getCanonicalName()); - } - return retVal; - } - } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java index 736215ee926..af35ef65c24 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java @@ -27,11 +27,23 @@ import java.util.List; import org.apache.commons.lang3.Validate; import org.hl7.fhir.instance.model.api.IBaseDatatype; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; + public abstract class BaseElement implements IElement, ISupportsUndeclaredExtensions { private List myFormatCommentsPost; private List myFormatCommentsPre; + + @Child(name = "extension", type = {ExtensionDt.class}, order=0, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=false) + @Description(shortDefinition="Additional Content defined by implementations", formalDefinition="May be used to represent additional information that is not part of the basic definition of the resource. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension." ) private List myUndeclaredExtensions; + + /** + * May be used to represent additional information that is not part of the basic definition of the resource, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. + */ + @Child(name = "modifierExtension", type = {ExtensionDt.class}, order=1, min=0, max=Child.MAX_UNLIMITED, modifier=true, summary=false) + @Description(shortDefinition="Extensions that cannot be ignored", formalDefinition="May be used to represent additional information that is not part of the basic definition of the resource, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions." ) private List myUndeclaredModifierExtensions; @Override diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ExtensionDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ExtensionDt.java index 87500a0547c..787c3ee229d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ExtensionDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ExtensionDt.java @@ -24,6 +24,8 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseExtension; @@ -153,4 +155,14 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa return getAllUndeclaredExtensions(); } + @Override + public String toString() { + ToStringBuilder retVal = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); + retVal.append("url", getUrl()); + retVal.append("value", getValue()); + return retVal.build(); + } + + + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java index 06babd9cb06..1746bfb63c7 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.model.view; import java.util.List; import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseExtension; import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; @@ -70,6 +71,8 @@ public class ViewGenerator { private void copyChildren(BaseRuntimeElementCompositeDefinition theSourceDef, BaseElement theSource, BaseRuntimeElementCompositeDefinition theTargetDef, BaseElement theTarget) { if (!theSource.isEmpty()) { List targetChildren = theTargetDef.getChildren(); + List targetExts = theTargetDef.getExtensions(); + for (BaseRuntimeChildDefinition nextChild : targetChildren) { String elementName = nextChild.getElementName(); @@ -84,35 +87,50 @@ public class ViewGenerator { List sourceValues = sourceChildEquivalent.getAccessor().getValues(theSource); for (IBase nextElement : sourceValues) { - nextChild.getMutator().addValue(theTarget, nextElement); + boolean handled = false; + if (nextElement instanceof IBaseExtension) { + String url = ((IBaseExtension) nextElement).getUrl(); + for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { + String nextTargetUrl = nextExt.getExtensionUrl(); + if (!nextTargetUrl.equals(url)) { + continue; + } + addExtension(theSourceDef, theSource, theTarget, nextExt, url); + handled = true; + } + } + if (!handled) { + nextChild.getMutator().addValue(theTarget, nextElement); + } } } - List targetExts = theTargetDef.getExtensions(); for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { String url = nextExt.getExtensionUrl(); - - RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url); - if (sourceDeclaredExt == null) { - - for (ExtensionDt next : theSource.getAllUndeclaredExtensions()) { - if (next.getUrlAsString().equals(url)) { - nextExt.getMutator().addValue(theTarget, next.getValue()); - } - } - - } else { - - List values = sourceDeclaredExt.getAccessor().getValues(theSource); - for (IBase nextElement : values) { - nextExt.getMutator().addValue(theTarget, nextElement); - } - - } - + addExtension(theSourceDef, theSource, theTarget, nextExt, url); } } } + + private void addExtension(BaseRuntimeElementCompositeDefinition theSourceDef, BaseElement theSource, BaseElement theTarget, RuntimeChildDeclaredExtensionDefinition nextExt, String url) { + RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url); + if (sourceDeclaredExt == null) { + + for (ExtensionDt next : theSource.getAllUndeclaredExtensions()) { + if (next.getUrlAsString().equals(url)) { + nextExt.getMutator().addValue(theTarget, next.getValue()); + } + } + + } else { + + List values = sourceDeclaredExt.getAccessor().getValues(theSource); + for (IBase nextElement : values) { + nextExt.getMutator().addValue(theTarget, nextElement); + } + + } + } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java index c26b473f388..fdbf9f7d40b 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java @@ -104,7 +104,11 @@ public abstract class BaseParser implements IParser { myErrorHandler = theParserErrorHandler; } - protected Iterable compositeChildIterator(final List theChildren, final boolean theContainedResource, final CompositeChildElement theParent) { + protected Iterable compositeChildIterator(IBase theCompositeElement, final boolean theContainedResource, final CompositeChildElement theParent) { + + BaseRuntimeElementCompositeDefinition elementDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(theCompositeElement.getClass()); + final List children = elementDef.getChildrenAndExtension(); + return new Iterable() { @Override public Iterator iterator() { @@ -118,7 +122,7 @@ public abstract class BaseParser implements IParser { * Constructor */ { - myChildrenIter = theChildren.iterator(); + myChildrenIter = children.iterator(); } @Override @@ -139,9 +143,10 @@ public abstract class BaseParser implements IParser { /* * There are lots of reasons we might skip encoding a particular child */ - if (myNext.getDef().getElementName().equals("extension") || myNext.getDef().getElementName().equals("modifierExtension")) { - myNext = null; - } else if (myNext.getDef().getElementName().equals("id")) { +// if (myNext.getDef().getElementName().equals("extension") || myNext.getDef().getElementName().equals("modifierExtension")) { +// myNext = null; +// } else + if (myNext.getDef().getElementName().equals("id")) { myNext = null; } else if (!myNext.shouldBeEncoded()) { myNext = null; @@ -261,7 +266,7 @@ public abstract class BaseParser implements IParser { myContainedResources = contained; } - protected String determineReferenceText(IBaseReference theRef) { + private String determineReferenceText(IBaseReference theRef) { IIdType ref = theRef.getReferenceElement(); if (isBlank(ref.getIdPart())) { String reference = ref.getValue(); @@ -396,11 +401,14 @@ public abstract class BaseParser implements IParser { } } - protected IdDt fixContainedResourceId(String theValue) { + protected IIdType fixContainedResourceId(String theValue) { + IIdType retVal = (IIdType) myContext.getElementDefinition("id").newInstance(); if (StringUtils.isNotBlank(theValue) && theValue.charAt(0) == '#') { - return new IdDt(theValue.substring(1)); + retVal.setValue(theValue.substring(1)); + } else { + retVal.setValue(theValue); } - return new IdDt(theValue); + return retVal; } ContainedResources getContainedResources() { @@ -544,6 +552,14 @@ public abstract class BaseParser implements IParser { @Override public T parseResource(Class theResourceType, Reader theReader) throws DataFormatException { + + if (theResourceType != null) { + RuntimeResourceDefinition def = myContext.getResourceDefinition(theResourceType); + if (def.getStructureVersion() != myContext.getVersion().getVersion()) { + throw new IllegalArgumentException("This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not parse a structure for version " + def.getStructureVersion()); + } + } + T retVal = doParseResource(theResourceType, theReader); RuntimeResourceDefinition def = myContext.getResourceDefinition(retVal); @@ -666,7 +682,35 @@ public abstract class BaseParser implements IParser { } } - return theValues; + @SuppressWarnings("unchecked") + List retVal = (List) theValues; + + for (int i = 0; i < retVal.size(); i++) { + IBase next = retVal.get(i); + + /* + * If we have automatically contained any resources via + * their references, this ensures that we output the new + * local reference + */ + if (next instanceof IBaseReference) { + IBaseReference nextRef = (IBaseReference)next; + String refText = determineReferenceText(nextRef); + if (!StringUtils.equals(refText, nextRef.getReferenceElement().getValue())) { + + if (retVal == theValues) { + retVal = new ArrayList(theValues); + } + IBaseReference newRef = (IBaseReference) myContext.getElementDefinition(nextRef.getClass()).newInstance(); + myContext.newTerser().cloneInto(nextRef, newRef, true); + newRef.setReference(refText); + retVal.set(i, newRef); + + } + } + } + + return retVal; } @Override diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index 5363224bf6f..a3a5c9897ce 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -51,16 +51,15 @@ import javax.json.stream.JsonGeneratorFactory; import javax.json.stream.JsonParsingException; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseBinary; import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype; -import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype; import org.hl7.fhir.instance.model.api.IBaseExtension; import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype; -import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IDomainResource; import org.hl7.fhir.instance.model.api.IIdType; @@ -68,7 +67,6 @@ import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.IPrimitiveType; import ca.uhn.fhir.context.BaseRuntimeChildDefinition; -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; @@ -142,6 +140,19 @@ public class JsonParser extends BaseParser implements IParser { myContext = theContext; } + private void addToHeldComments(int valueIdx, List theCommentsToAdd, ArrayList> theListToAddTo) { + if (theCommentsToAdd.size() > 0) { + theListToAddTo.ensureCapacity(valueIdx); + while (theListToAddTo.size() <= valueIdx) { + theListToAddTo.add(null); + } + if (theListToAddTo.get(valueIdx) == null) { + theListToAddTo.set(valueIdx, new ArrayList()); + } + theListToAddTo.get(valueIdx).addAll(theCommentsToAdd); + } + } + private void addToHeldExtensions(int valueIdx, List> ext, ArrayList> list, boolean theIsModifier) { if (ext.size() > 0) { list.ensureCapacity(valueIdx); @@ -157,19 +168,6 @@ public class JsonParser extends BaseParser implements IParser { } } - private void addToHeldComments(int valueIdx, List theCommentsToAdd, ArrayList> theListToAddTo) { - if (theCommentsToAdd.size() > 0) { - theListToAddTo.ensureCapacity(valueIdx); - while (theListToAddTo.size() <= valueIdx) { - theListToAddTo.add(null); - } - if (theListToAddTo.get(valueIdx) == null) { - theListToAddTo.set(valueIdx, new ArrayList()); - } - theListToAddTo.get(valueIdx).addAll(theCommentsToAdd); - } - } - private void assertObjectOfType(JsonValue theResourceTypeObj, ValueType theValueType, String thePosition) { if (theResourceTypeObj == null) { throw new DataFormatException("Invalid JSON content detected, missing required element: '" + thePosition + "'"); @@ -462,37 +460,15 @@ public class JsonParser extends BaseParser implements IParser { } break; } + case RESOURCE_REF: case RESOURCE_BLOCK: case COMPOSITE_DATATYPE: { - BaseRuntimeElementCompositeDefinition childCompositeDef = (BaseRuntimeElementCompositeDefinition) theChildDef; if (theChildName != null) { theWriter.writeStartObject(theChildName); } else { theWriter.writeStartObject(); } - if (theNextValue instanceof IBaseExtension) { - theWriter.write("url", ((IBaseExtension) theNextValue).getUrl()); - } - encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theWriter, childCompositeDef, theContainedResource, theChildElem); - theWriter.writeEnd(); - break; - } - case RESOURCE_REF: { - IBaseReference referenceDt = (IBaseReference) theNextValue; - if (theChildName != null) { - theWriter.writeStartObject(theChildName); - } else { - theWriter.writeStartObject(); - } - - String reference = determineReferenceText(referenceDt); - - if (StringUtils.isNotBlank(reference)) { - theWriter.write(XmlParser.RESREF_REFERENCE, reference); - } - if (referenceDt.getDisplayElement().isEmpty() == false) { - theWriter.write(XmlParser.RESREF_DISPLAY, referenceDt.getDisplayElement().getValueAsString()); - } + encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theWriter, theContainedResource, theChildElem); theWriter.writeEnd(); break; } @@ -547,12 +523,22 @@ public class JsonParser extends BaseParser implements IParser { } - private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, List theChildren, boolean theContainedResource, CompositeChildElement theParent) + private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent) throws IOException { - for (CompositeChildElement nextChildElem : super.compositeChildIterator(theChildren, theContainedResource, theParent)) { + boolean haveWrittenExtensions = false; + for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent)) { BaseRuntimeChildDefinition nextChild = nextChildElem.getDef(); + + if (nextChildElem.getDef().getElementName().equals("extension") || nextChildElem.getDef().getElementName().equals("modifierExtension") || nextChild instanceof RuntimeChildDeclaredExtensionDefinition) { + if (!haveWrittenExtensions) { + extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, myContext.getElementDefinition(theElement.getClass()), theResDef, theResource); + haveWrittenExtensions = true; + } + continue; + } + if (nextChild instanceof RuntimeChildNarrativeDefinition) { INarrativeGenerator gen = myContext.getNarrativeGenerator(); if (gen != null) { @@ -582,7 +568,7 @@ public class JsonParser extends BaseParser implements IParser { continue; } - List values = nextChild.getAccessor().getValues(theNextValue); + List values = nextChild.getAccessor().getValues(theElement); values = super.preProcessValues(nextChild, theResource, values); if (values == null || values.isEmpty()) { @@ -610,9 +596,13 @@ public class JsonParser extends BaseParser implements IParser { } Class type = nextValue.getClass(); + String childName = nextChild.getChildNameByDatatype(type); BaseRuntimeElementDefinition childDef = nextChild.getChildElementDefinitionByDatatype(type); if (childDef == null) { +// if (IBaseExtension.class.isAssignableFrom(type)) { +// continue; +// } super.throwExceptionForUnknownChildType(nextChild, type); } boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE; @@ -621,16 +611,10 @@ public class JsonParser extends BaseParser implements IParser { continue; } - if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) { - // Don't encode extensions - // RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) - // nextChild; - // if (extDef.isModifier()) { - // addToHeldExtensions(valueIdx, modifierExtensions, extDef, nextValue); - // } else { - // addToHeldExtensions(valueIdx, extensions, extDef, nextValue); - // } - } else { +// if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) { +// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild; +// new HeldExtension(extDef, nextValue).write(theResDef, theResource, theEventWriter); +// } else { if (currentChildName == null || !currentChildName.equals(childName)) { if (inArray) { @@ -675,7 +659,7 @@ public class JsonParser extends BaseParser implements IParser { } } - } +// } valueIdx++; } @@ -730,7 +714,7 @@ public class JsonParser extends BaseParser implements IParser { } theEventWriter.writeEnd(); } - writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts, null); + writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, heldExts, heldModExts); if (inArray) { theEventWriter.writeEnd(); } @@ -742,33 +726,11 @@ public class JsonParser extends BaseParser implements IParser { } } - private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition resDef, boolean theContainedResource, CompositeChildElement theParent) + private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent) throws IOException, DataFormatException { writeCommentsPreAndPost(theNextValue, theEventWriter); - - extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null); - encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theContainedResource, theParent); - encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theContainedResource, theParent); - } - - private void writeCommentsPreAndPost(IBase theNextValue, JsonGenerator theEventWriter) { - if (theNextValue.hasFormatComment()) { - theEventWriter.writeStartArray("fhir_comments"); - List pre = theNextValue.getFormatCommentsPre(); - if (pre.isEmpty() == false) { - for (String next : pre) { - theEventWriter.write(next); - } - } - List post = theNextValue.getFormatCommentsPost(); - if (post.isEmpty() == false) { - for (String next : post) { - theEventWriter.write(next); - } - } - theEventWriter.writeEnd(); - } + encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theParent); } private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource) throws IOException { @@ -868,8 +830,7 @@ public class JsonParser extends BaseParser implements IParser { theEventWriter.writeStartArray("security"); for (BaseCodingDt securityLabel : securityLabels) { theEventWriter.writeStartObject(); - BaseRuntimeElementCompositeDefinition def = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(securityLabel.getClass()); - encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource, null); + encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, theContainedResource, null); theEventWriter.writeEnd(); } theEventWriter.writeEnd(); @@ -905,7 +866,7 @@ public class JsonParser extends BaseParser implements IParser { theEventWriter.write("content", contentAsBase64); } } else { - encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theContainedResource, new CompositeChildElement(resDef)); + encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); } theEventWriter.writeEnd(); @@ -945,7 +906,7 @@ 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 */ - private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition theElementDef, RuntimeResourceDefinition theResDef, IBaseResource theResource, String theParentExtensionUrl) throws IOException { + private void extractAndWriteExtensionsAsDirectChild(IBase theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition theElementDef, RuntimeResourceDefinition theResDef, IBaseResource theResource) throws IOException { List extensions = new ArrayList(0); List modifierExtensions = new ArrayList(0); @@ -958,7 +919,7 @@ public class JsonParser extends BaseParser implements IParser { } // Write the extensions - writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions, theParentExtensionUrl); + writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions); } private void extractDeclaredExtensions(IBase theResource, BaseRuntimeElementDefinition resDef, List extensions, List modifierExtensions) { @@ -1031,6 +992,17 @@ public class JsonParser extends BaseParser implements IParser { return EncodingEnum.JSON; } + private JsonArray grabJsonArray(JsonObject theObject, String nextName, String thePosition) { + JsonValue object = theObject.get(nextName); + if (object == null) { + return null; + } + if (object.getValueType() != ValueType.ARRAY) { + throw new DataFormatException("Syntax error parsing JSON FHIR structure: Expected ARRAY at element '" + thePosition + "', found '" + object.getValueType().name() + "'"); + } + return (JsonArray) object; + } + private void parseAlternates(JsonValue theAlternateVal, ParserState theState, String theElementName) { if (theAlternateVal == null || theAlternateVal.getValueType() == ValueType.NULL) { return; @@ -1275,30 +1247,6 @@ public class JsonParser extends BaseParser implements IParser { } - private void parseFhirComments(JsonValue theObject, ParserState theState) { - if (theObject.getValueType() == ValueType.ARRAY) { - for (JsonValue nextComment : ((JsonArray) theObject)) { - if (nextComment.getValueType() == ValueType.STRING) { - String commentText = ((JsonString) nextComment).getString(); - if (commentText != null) { - theState.commentPre(commentText); - } - } - } - } - } - - private JsonArray grabJsonArray(JsonObject theObject, String nextName, String thePosition) { - JsonValue object = theObject.get(nextName); - if (object == null) { - return null; - } - if (object.getValueType() != ValueType.ARRAY) { - throw new DataFormatException("Syntax error parsing JSON FHIR structure: Expected ARRAY at element '" + thePosition + "', found '" + object.getValueType().name() + "'"); - } - return (JsonArray) object; - } - private void parseChildren(ParserState theState, String theName, JsonValue theJsonVal, JsonValue theAlternateVal, String theAlternateName) { switch (theJsonVal.getValueType()) { case ARRAY: { @@ -1385,6 +1333,38 @@ public class JsonParser extends BaseParser implements IParser { } } + private void parseFhirComments(JsonValue theObject, ParserState theState) { + if (theObject.getValueType() == ValueType.ARRAY) { + for (JsonValue nextComment : ((JsonArray) theObject)) { + if (nextComment.getValueType() == ValueType.STRING) { + String commentText = ((JsonString) nextComment).getString(); + if (commentText != null) { + theState.commentPre(commentText); + } + } + } + } + } + + @Override + public TagList parseTagList(Reader theReader) { + JsonReader reader = Json.createReader(theReader); + JsonObject object = reader.readObject(); + + JsonValue resourceTypeObj = object.get("resourceType"); + assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType"); + String resourceType = ((JsonString) resourceTypeObj).getString(); + + ParserState state = ParserState.getPreTagListInstance(this, myContext, true, getErrorHandler()); + state.enteringNewElement(null, resourceType); + + parseChildren(object, state); + + state.endingElement(); + + return state.getObject(); + } + // private void parseExtensionInDstu2Style(boolean theModifier, ParserState theState, String // theParentExtensionUrl, String theExtensionUrl, JsonArray theValues) { // String extUrl = UrlUtil.constructAbsoluteUrl(theParentExtensionUrl, theExtensionUrl); @@ -1411,25 +1391,6 @@ public class JsonParser extends BaseParser implements IParser { // theState.endingElement(); // } - @Override - public TagList parseTagList(Reader theReader) { - JsonReader reader = Json.createReader(theReader); - JsonObject object = reader.readObject(); - - JsonValue resourceTypeObj = object.get("resourceType"); - assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType"); - String resourceType = ((JsonString) resourceTypeObj).getString(); - - ParserState state = ParserState.getPreTagListInstance(this, myContext, true, getErrorHandler()); - state.enteringNewElement(null, resourceType); - - parseChildren(object, state); - - state.endingElement(); - - return state.getObject(); - } - @Override public IParser setPrettyPrint(boolean thePrettyPrint) { myPrettyPrint = thePrettyPrint; @@ -1493,7 +1454,26 @@ public class JsonParser extends BaseParser implements IParser { } } - private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List extensions, List modifierExtensions, String theParentExtensionUrl) throws IOException { + private void writeCommentsPreAndPost(IBase theNextValue, JsonGenerator theEventWriter) { + if (theNextValue.hasFormatComment()) { + theEventWriter.writeStartArray("fhir_comments"); + List pre = theNextValue.getFormatCommentsPre(); + if (pre.isEmpty() == false) { + for (String next : pre) { + theEventWriter.write(next); + } + } + List post = theNextValue.getFormatCommentsPost(); + if (post.isEmpty() == false) { + for (String next : post) { + theEventWriter.write(next); + } + } + theEventWriter.writeEnd(); + } + } + + private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List extensions, List modifierExtensions) throws IOException { if (extensions.isEmpty() == false) { theEventWriter.writeStartArray("extension"); for (HeldExtension next : extensions) { @@ -1594,7 +1574,7 @@ public class JsonParser extends BaseParser implements IParser { BaseRuntimeElementDefinition def = myDef.getChildElementDefinitionByDatatype(myValue.getClass()); if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) { - extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, myDef.getExtensionUrl()); + extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource); } else { String childName = myDef.getChildNameByDatatype(myValue.getClass()); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, null); @@ -1605,7 +1585,7 @@ public class JsonParser extends BaseParser implements IParser { } private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, IBaseExtension ext) throws IOException { - IBaseDatatype value = ext.getValue(); + IBase value = ext.getValue(); String extensionUrl = ext.getUrl(); theEventWriter.writeStartObject(); @@ -1630,10 +1610,17 @@ public class JsonParser extends BaseParser implements IParser { } theEventWriter.writeEnd(); } else { + + /* + * Pre-process value - This is called in case the value is a reference + * since we might modify the text + */ + value = JsonParser.super.preProcessValues(myDef, theResource, Collections.singletonList(value)).get(0); + RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition(); String childName = extDef.getChildNameByDatatype(value.getClass()); if (childName == null) { - childName = "value" + myContext.getElementDefinition(value.getClass()).getName(); + childName = "value" + WordUtils.capitalize(myContext.getElementDefinition(value.getClass()).getName()); } BaseRuntimeElementDefinition childDef = extDef.getChildElementDefinitionByDatatype(value.getClass()); if (childDef == null) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index 6d522b8e235..3ab3b69b512 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -1420,6 +1420,11 @@ class ParserState { pop(); } + @Override + protected void populateTarget() { + // nothing + } + @Override public void wereBack() { super.wereBack(); @@ -1442,11 +1447,6 @@ class ParserState { } - @Override - protected void populateTarget() { - // nothing - } - } private class ContainedResourcesStateHl7Org extends PreResourceState { @@ -1460,6 +1460,11 @@ class ParserState { pop(); } + @Override + protected void populateTarget() { + // nothing + } + @Override public void wereBack() { super.wereBack(); @@ -1480,11 +1485,6 @@ class ParserState { def.getChildByName("contained").getMutator().addValue(preResCurrentElement, res); } - @Override - protected void populateTarget() { - // nothing - } - } private class DeclaredExtensionState extends BaseState { @@ -1974,7 +1974,7 @@ class ParserState { private abstract class PreResourceState extends BaseState { - private Map myContainedResources = new HashMap(); + private Map myContainedResources; private IBaseResource myInstance; private FhirVersionEnum myParentVersion; private boolean myRequireResourceType = true; @@ -1983,6 +1983,7 @@ class ParserState { public PreResourceState(Class theResourceType) { super(null); myResourceType = theResourceType; + myContainedResources = new HashMap(); if (theResourceType != null) { myParentVersion = myContext.getResourceDefinition(theResourceType).getStructureVersion(); } else { @@ -1990,12 +1991,11 @@ class ParserState { } } - protected abstract void populateTarget(); - public PreResourceState(PreResourceState thePreResourcesState, FhirVersionEnum theParentVersion) { super(thePreResourcesState); Validate.notNull(theParentVersion); myParentVersion = theParentVersion; + myContainedResources = thePreResourcesState.getContainedResources(); } @Override @@ -2070,6 +2070,8 @@ class ParserState { return true; } + protected abstract void populateTarget(); + public ParserState.PreResourceState setRequireResourceType(boolean theRequireResourceType) { myRequireResourceType = theRequireResourceType; return this; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java index 45e18fe214c..662833b4378 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java @@ -50,6 +50,7 @@ import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseBinary; import org.hl7.fhir.instance.model.api.IBaseDatatype; +import org.hl7.fhir.instance.model.api.IBaseElement; import org.hl7.fhir.instance.model.api.IBaseExtension; import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; @@ -62,6 +63,7 @@ import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.IPrimitiveType; import ca.uhn.fhir.context.BaseRuntimeChildDefinition; +import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition; import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; import ca.uhn.fhir.context.BaseRuntimeElementDefinition; import ca.uhn.fhir.context.ConfigurationException; @@ -69,6 +71,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.RuntimeChildContainedResources; import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; +import ca.uhn.fhir.context.RuntimeChildExtension; import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition; import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition; @@ -523,6 +526,7 @@ public class XmlParser extends BaseParser implements IParser { } break; } + case RESOURCE_REF: case RESOURCE_BLOCK: case COMPOSITE_DATATYPE: { theEventWriter.writeStartElement(childName); @@ -530,19 +534,10 @@ public class XmlParser extends BaseParser implements IParser { theEventWriter.writeAttribute("url", theExtensionUrl); } BaseRuntimeElementCompositeDefinition childCompositeDef = (BaseRuntimeElementCompositeDefinition) childDef; - encodeCompositeElementToStreamWriter(theResource, theElement, theEventWriter, childCompositeDef, theIncludedResource, theParent); + encodeCompositeElementToStreamWriter(theResource, theElement, theEventWriter, theIncludedResource, theParent); theEventWriter.writeEndElement(); break; } - case RESOURCE_REF: { - IBaseReference ref = (IBaseReference) theElement; - if (!ref.isEmpty()) { - theEventWriter.writeStartElement(childName); - encodeResourceReferenceToStreamWriter(theEventWriter, ref, theResource, theIncludedResource); - theEventWriter.writeEndElement(); - } - break; - } case CONTAINED_RESOURCE_LIST: case CONTAINED_RESOURCES: { /* @@ -594,31 +589,20 @@ public class XmlParser extends BaseParser implements IParser { } - private void writeCommentsPre(XMLStreamWriter theEventWriter, IBase theElement) throws XMLStreamException { - if (theElement != null && theElement.hasFormatComment()) { - for (String next : theElement.getFormatCommentsPre()) { - if (isNotBlank(next)) { - theEventWriter.writeComment(next); - } - } - } - } - - private void writeCommentsPost(XMLStreamWriter theEventWriter, IBase theElement) throws XMLStreamException { - if (theElement != null && theElement.hasFormatComment()) { - for (String next : theElement.getFormatCommentsPost()) { - if (isNotBlank(next)) { - theEventWriter.writeComment(next); - } - } - } - } - - private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List theChildren, boolean theContainedResource, CompositeChildElement theParent) + @SuppressWarnings("rawtypes") + private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement theParent) throws XMLStreamException, DataFormatException { - for (CompositeChildElement nextChildElem : super.compositeChildIterator(theChildren, theContainedResource, theParent)) { + for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent)) { BaseRuntimeChildDefinition nextChild = nextChildElem.getDef(); + + if (nextChild.getElementName().equals("url") && theElement instanceof IBaseExtension) { + /* + * XML encoding is a one-off for extensions. The URL element goes in an attribute + * instead of being encoded as a normal element, only for XML encoding + */ + continue; + } if (nextChild instanceof RuntimeChildNarrativeDefinition) { INarrativeGenerator gen = myContext.getNarrativeGenerator(); @@ -656,12 +640,31 @@ public class XmlParser extends BaseParser implements IParser { if ((nextValue == null || nextValue.isEmpty())) { continue; } + Class type = nextValue.getClass(); String childName = nextChild.getChildNameByDatatype(type); String extensionUrl = nextChild.getExtensionUrl(); BaseRuntimeElementDefinition childDef = nextChild.getChildElementDefinitionByDatatype(type); if (childDef == null) { - super.throwExceptionForUnknownChildType(nextChild, type); + if (nextValue instanceof IBaseExtension) { + continue; + } + + /* + * For RI structures Enumeration class, this replaces the child def + * with the "code" one. This is messy, and presumably there is a better + * way.. + */ + BaseRuntimeElementDefinition elementDef = myContext.getElementDefinition(type); + if (elementDef.getName().equals("code")) { + Class type2 = myContext.getElementDefinition("code").getImplementingClass(); + childDef = nextChild.getChildElementDefinitionByDatatype(type2); + childName = nextChild.getChildNameByDatatype(type2); + } + + if (childDef == null) { + super.throwExceptionForUnknownChildType(nextChild, type); + } } if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) { @@ -670,16 +673,15 @@ public class XmlParser extends BaseParser implements IParser { encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theContainedResource, nextChildElem); } else if (extensionUrl != null && childName.equals("extension") == false) { - RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild; - if (extDef.isModifier()) { - theEventWriter.writeStartElement("modifierExtension"); - } else { - theEventWriter.writeStartElement("extension"); + encodeExtension(theResource, theEventWriter, theContainedResource, nextChildElem, nextChild, nextValue, childName, extensionUrl, childDef); + } else if (nextChild instanceof RuntimeChildExtension) { + IBaseExtension extension = (IBaseExtension) nextValue; + if ((extension.getValue() == null || extension.getValue().isEmpty())) { + if (extension.getExtension().isEmpty()) { + continue; + } } - - theEventWriter.writeAttribute("url", extensionUrl); - encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theContainedResource, nextChildElem); - theEventWriter.writeEndElement(); + encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extension.getUrl(), theContainedResource, nextChildElem); } else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) { // suppress narratives from contained resources } else { @@ -690,11 +692,18 @@ public class XmlParser extends BaseParser implements IParser { } } - private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition theElementDefinition, boolean theIncludedResource, CompositeChildElement theParent) - throws XMLStreamException, DataFormatException { - encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); - encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource, theParent); - encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource, theParent); + private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement nextChildElem, BaseRuntimeChildDefinition nextChild, IBase nextValue, String childName, String extensionUrl, BaseRuntimeElementDefinition childDef) + throws XMLStreamException { + BaseRuntimeDeclaredChildDefinition extDef = (BaseRuntimeDeclaredChildDefinition) nextChild; + if (extDef.isModifier()) { + theEventWriter.writeStartElement("modifierExtension"); + } else { + theEventWriter.writeStartElement("extension"); + } + + theEventWriter.writeAttribute("url", extensionUrl); + encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theContainedResource, nextChildElem); + theEventWriter.writeEndElement(); } private void encodeExtensionsIfPresent(IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException { @@ -713,54 +722,6 @@ public class XmlParser extends BaseParser implements IParser { } } - private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, IBaseReference theRef, IBaseResource theResource, boolean theIncludedResource) throws XMLStreamException { - String reference = determineReferenceText(theRef); - - encodeExtensionsIfPresent(theResource, theEventWriter, theRef, theIncludedResource); - - if (StringUtils.isNotBlank(reference)) { - theEventWriter.writeStartElement(RESREF_REFERENCE); - theEventWriter.writeAttribute("value", reference); - theEventWriter.writeEndElement(); - } - if (!(theRef.getDisplayElement().isEmpty())) { - theEventWriter.writeStartElement(RESREF_DISPLAY); - theEventWriter.writeAttribute("value", theRef.getDisplayElement().getValue()); - theEventWriter.writeEndElement(); - } - } - - private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException { - /* - * DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy way - * to make that happen, but hopefully this won't matter as much once we use the HL7 - * structures - */ - - List preExtensionChildren = new ArrayList(); - List postExtensionChildren = new ArrayList(); - List children = resDef.getChildren(); - for (BaseRuntimeChildDefinition next : children) { - if (next.getElementName().equals("text")) { - preExtensionChildren.add(next); - } else if (next.getElementName().equals("contained")) { - preExtensionChildren.add(next); - } else { - postExtensionChildren.add(next); - } - } - - CompositeChildElement parent = new CompositeChildElement(theResDef); - - encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, preExtensionChildren, theIncludedResource, parent); - - encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); - encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource, parent); - - encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, postExtensionChildren, theIncludedResource, parent); - - } - private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource) throws XMLStreamException, DataFormatException { IIdType resourceId = null; @@ -785,6 +746,7 @@ public class XmlParser extends BaseParser implements IParser { encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId); } + private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, IIdType theResourceId) throws XMLStreamException { if (!theContainedResource) { super.containResourcesForEncoding(theResource); @@ -807,7 +769,7 @@ public class XmlParser extends BaseParser implements IParser { writeCommentsPost(theEventWriter, theResourceId); } - encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource, new CompositeChildElement(resDef)); + encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); } else { @@ -848,8 +810,7 @@ public class XmlParser extends BaseParser implements IParser { } for (BaseCodingDt securityLabel : securityLabels) { theEventWriter.writeStartElement("security"); - BaseRuntimeElementCompositeDefinition def = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(securityLabel.getClass()); - encodeCompositeElementChildrenToStreamWriter(resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource, null); + encodeCompositeElementToStreamWriter(resource, securityLabel, theEventWriter, theContainedResource, null); theEventWriter.writeEndElement(); } if (tags != null) { @@ -872,7 +833,7 @@ public class XmlParser extends BaseParser implements IParser { writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType()); writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64()); } else { - encodeResourceToStreamWriterInDstu2Format(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource); + encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); } } else { @@ -889,7 +850,7 @@ public class XmlParser extends BaseParser implements IParser { } theEventWriter.writeCharacters(bin.getContentAsBase64()); } else { - encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource, new CompositeChildElement(resDef)); + encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); } } @@ -899,6 +860,7 @@ public class XmlParser extends BaseParser implements IParser { theEventWriter.writeEndElement(); } + @Override public void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException { try { @@ -1148,6 +1110,26 @@ public class XmlParser extends BaseParser implements IParser { } } + private void writeCommentsPost(XMLStreamWriter theEventWriter, IBase theElement) throws XMLStreamException { + if (theElement != null && theElement.hasFormatComment()) { + for (String next : theElement.getFormatCommentsPost()) { + if (isNotBlank(next)) { + theEventWriter.writeComment(next); + } + } + } + } + + private void writeCommentsPre(XMLStreamWriter theEventWriter, IBase theElement) throws XMLStreamException { + if (theElement != null && theElement.hasFormatComment()) { + for (String next : theElement.getFormatCommentsPre()) { + if (isNotBlank(next)) { + theEventWriter.writeComment(next); + } + } + } + } + private void writeOptionalAttribute(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException { if (StringUtils.isNotBlank(theValue)) { theEventWriter.writeAttribute(theName, theValue); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index cc574286dd0..0e219ace034 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -189,16 +189,10 @@ public class FhirTerser { } } - @SuppressWarnings("unchecked") @Override public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition theDefinition, ExtensionDt theNextExt) { - if (theType.isAssignableFrom(theNextExt.getClass())) { - retVal.add((T) theNextExt); - } - if (theNextExt.getValue() != null && theType.isAssignableFrom(theNextExt.getValue().getClass())) { - retVal.add((T) theNextExt.getValue()); - } + // nothing } }); return retVal; @@ -221,9 +215,7 @@ public class FhirTerser { @Override public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition theDefinition, ExtensionDt theNextExt) { - if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) { - retVal.add(new ResourceReferenceInfo(myContext, theResource, thePathToElement, (BaseResourceReferenceDt) theNextExt.getValue())); - } + // nothing } }); return retVal; @@ -575,20 +567,12 @@ public class FhirTerser { // These are primitive types break; case RESOURCE_REF: - IBaseReference resRefDt = (IBaseReference) theElement; - if (resRefDt.getReferenceElement().getValue() == null && resRefDt.getResource() != null) { - IBaseResource theResource = resRefDt.getResource(); - if (theResource.getIdElement() == null || theResource.getIdElement().isEmpty() || theResource.getIdElement().isLocal()) { - def = myContext.getResourceDefinition(theResource); - visit(theStack, theResource, pathToElement, null, def, theCallback); - } - } - break; case RESOURCE: case RESOURCE_BLOCK: case COMPOSITE_DATATYPE: { BaseRuntimeElementCompositeDefinition childDef = (BaseRuntimeElementCompositeDefinition) def; for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { + List values = nextChild.getAccessor().getValues(theElement); if (values != null) { for (Object nextValueObject : values) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java index 7bdad76ea5c..df4e137fb40 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java @@ -44,12 +44,12 @@ public interface IModelVisitor { void acceptElement(IBase theElement, List thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition theDefinition); /** - * - * @param theContainingElement - * @param theChildDefinition May be null if this is a root element - * @param theDefinition - * @param theNextExt + * @deprecated As of HAPI FHIR 1.5, this method is not recommended to be used. It will be removed from + * this interface in HAPI FHIR 2.0. Previously, undeclared extensions were handled differently but as of 1.5 + * they will also be called back via {@link #acceptElement(IBase, List, BaseRuntimeChildDefinition, BaseRuntimeElementDefinition)} + * like any other child. */ + @Deprecated void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition theDefinition, ExtensionDt theNextExt); } diff --git a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java index 99989b2ccfe..f481b68448f 100644 --- a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java +++ b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IIdType.java @@ -121,6 +121,7 @@ public interface IIdType extends IPrimitiveType { */ boolean isVersionIdPartValidLong(); + @Override IIdType setValue(String theString); IIdType toUnqualified(); diff --git a/hapi-fhir-cobertura/pom.xml b/hapi-fhir-cobertura/pom.xml index 22845bfe566..40d4fc936bd 100644 --- a/hapi-fhir-cobertura/pom.xml +++ b/hapi-fhir-cobertura/pom.xml @@ -300,6 +300,7 @@ true + false diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index c879478fde8..fd3f322091d 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -38,7 +38,6 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; -import org.hl7.fhir.dstu3.model.OperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.Test; @@ -64,6 +63,7 @@ import ca.uhn.fhir.model.dstu2.resource.Location; import ca.uhn.fhir.model.dstu2.resource.Medication; import ca.uhn.fhir.model.dstu2.resource.MedicationOrder; import ca.uhn.fhir.model.dstu2.resource.Observation; +import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Patient; @@ -100,7 +100,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.UrlUtil; public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { @@ -295,11 +294,11 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { } ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute(); - Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(10).execute(); + Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(10).execute(); assertEquals(100, found.getTotalResults().getValue().intValue()); assertEquals(10, found.getEntries().size()); - found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(999).execute(); + found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(999).execute(); assertEquals(100, found.getTotalResults().getValue().intValue()); assertEquals(50, found.getEntries().size()); @@ -1765,7 +1764,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { .search() .forResource(Organization.class) .where(Organization.NAME.isMissing(false)) - .limitTo(100) + .count(100) .prettyPrint() .execute(); //@formatter:on @@ -1783,7 +1782,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { .search() .forResource(Organization.class) .where(Organization.NAME.isMissing(true)) - .limitTo(100) + .count(100) .prettyPrint() .execute(); //@formatter:on @@ -1917,7 +1916,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { .where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", methodName)) .sort().ascending(Patient.FAMILY) .sort().ascending(Patient.GIVEN) - .limitTo(100) + .count(100) .execute(); //@formatter:on diff --git a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/model/dstu/FhirDstu1.java b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/model/dstu/FhirDstu1.java index 863955df925..3ed5be6f776 100644 --- a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/model/dstu/FhirDstu1.java +++ b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/model/dstu/FhirDstu1.java @@ -50,6 +50,7 @@ import ca.uhn.fhir.context.RuntimeChildChoiceDefinition; import ca.uhn.fhir.context.RuntimeChildCompositeDatatypeDefinition; import ca.uhn.fhir.context.RuntimeChildContainedResources; import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; +import ca.uhn.fhir.context.RuntimeChildExtension; import ca.uhn.fhir.context.RuntimeChildPrimitiveDatatypeDefinition; import ca.uhn.fhir.context.RuntimeChildResourceBlockDefinition; import ca.uhn.fhir.context.RuntimeChildResourceDefinition; @@ -166,18 +167,20 @@ public class FhirDstu1 implements IFhirVersion { } private void fillName(StructureElement elem, BaseRuntimeElementDefinition nextDef, String theServerBase) { + assert nextDef != null; + if (nextDef instanceof RuntimeResourceReferenceDefinition) { - RuntimeResourceReferenceDefinition rr = (RuntimeResourceReferenceDefinition) nextDef; - for (Class next : rr.getResourceTypes()) { - StructureElementDefinitionType type = elem.getDefinition().addType(); - type.getCode().setValue("ResourceReference"); - - if (next != IResource.class) { - @SuppressWarnings("unchecked") - RuntimeResourceDefinition resDef = rr.getDefinitionForResourceType((Class) next); - type.getProfile().setValueAsString(resDef.getResourceProfile(theServerBase)); - } - } +// RuntimeResourceReferenceDefinition rr = (RuntimeResourceReferenceDefinition) nextDef; +// for (Class next : rr.getResourceTypes()) { +// StructureElementDefinitionType type = elem.getDefinition().addType(); +// type.getCode().setValue("ResourceReference"); +// +// if (next != IResource.class) { +// @SuppressWarnings("unchecked") +// RuntimeResourceDefinition resDef = rr.getDefinitionForResourceType((Class) next); +// type.getProfile().setValueAsString(resDef.getResourceProfile(theServerBase)); +// } +// } return; } @@ -232,6 +235,9 @@ public class FhirDstu1 implements IFhirVersion { if (nextChild instanceof RuntimeChildUndeclaredExtensionDefinition) { continue; } + if (nextChild instanceof RuntimeChildExtension) { + continue; + } BaseRuntimeDeclaredChildDefinition child = (BaseRuntimeDeclaredChildDefinition) nextChild; StructureElement elem = theStruct.addElement(); diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/view/ViewGeneratorTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/view/ViewGeneratorTest.java index 7ed6cf75178..bc2d011d232 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/view/ViewGeneratorTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/model/view/ViewGeneratorTest.java @@ -15,6 +15,7 @@ import ca.uhn.fhir.parser.IParser; public class ViewGeneratorTest { private static FhirContext ourCtx = FhirContext.forDstu1(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ViewGeneratorTest.class); @Test public void testView() { @@ -25,7 +26,10 @@ public class ViewGeneratorTest { src.getExt().setValue(100); src.getModExt().setValue(200); - String enc = ourCtx.newXmlParser().encodeResourceToString(src); + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(src); + + ourLog.info(enc); + IParser parser = ourCtx.newXmlParser(); Patient nonExt = parser.parseResource(Patient.class, enc); @@ -54,8 +58,53 @@ public class ViewGeneratorTest { assertEquals("id2", va.getIdentifier().get(1).getValue().getValueAsString()); assertEquals(100, va.getExt().getValue().intValue()); assertEquals(200, va.getModExt().getValue().intValue()); - assertEquals(0, va.getAllUndeclaredExtensions().size()); + assertEquals(0, va.getAllUndeclaredExtensions().size()); } + + @Test + public void testViewJson() { + + ExtPatient src = new ExtPatient(); + src.addIdentifier("urn:sys", "id1"); + src.addIdentifier("urn:sys", "id2"); + src.getExt().setValue(100); + src.getModExt().setValue(200); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(src); + + ourLog.info(enc); + + IParser parser = ourCtx.newJsonParser(); + Patient nonExt = parser.parseResource(Patient.class, enc); + + assertEquals(Patient.class, nonExt.getClass()); + assertEquals("urn:sys", nonExt.getIdentifier().get(0).getSystem().getValueAsString()); + assertEquals("id1", nonExt.getIdentifier().get(0).getValue().getValue()); + assertEquals("urn:sys", nonExt.getIdentifier().get(1).getSystem().getValueAsString()); + assertEquals("id2", nonExt.getIdentifier().get(1).getValue().getValueAsString()); + + List ext = nonExt.getUndeclaredExtensionsByUrl("urn:ext"); + assertEquals(1,ext.size()); + assertEquals("urn:ext", ext.get(0).getUrlAsString()); + assertEquals(IntegerDt.class, ext.get(0).getValueAsPrimitive().getClass()); + assertEquals("100", ext.get(0).getValueAsPrimitive().getValueAsString()); + + List modExt = nonExt.getUndeclaredExtensionsByUrl("urn:modExt"); + assertEquals(1,modExt.size()); + assertEquals("urn:modExt", modExt.get(0).getUrlAsString()); + assertEquals(IntegerDt.class, modExt.get(0).getValueAsPrimitive().getClass()); + assertEquals("200", modExt.get(0).getValueAsPrimitive().getValueAsString()); + + ExtPatient va = ourCtx.newViewGenerator().newView(nonExt, ExtPatient.class); + assertEquals("urn:sys", va.getIdentifier().get(0).getSystem().getValueAsString()); + assertEquals("id1", va.getIdentifier().get(0).getValue().getValue()); + assertEquals("urn:sys", va.getIdentifier().get(1).getSystem().getValueAsString()); + assertEquals("id2", va.getIdentifier().get(1).getValue().getValueAsString()); + assertEquals(100, va.getExt().getValue().intValue()); + assertEquals(200, va.getModExt().getValue().intValue()); + + assertEquals(0, va.getAllUndeclaredExtensions().size()); + } } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java index c9a525c2f76..a3ab3898a2b 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java @@ -37,7 +37,7 @@ import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory; */ public class ContainedResourceEncodingTest { - private static Logger logger = LoggerFactory.getLogger(ContainedResourceEncodingTest.class); + private static Logger ourLog = LoggerFactory.getLogger(ContainedResourceEncodingTest.class); private FhirContext ctx; @@ -53,7 +53,7 @@ public class ContainedResourceEncodingTest { @Before public void initTest() { - logger.info("[initTest]"); + ourLog.info("[initTest]"); initPatient(); initAuthor(); @@ -109,34 +109,34 @@ public class ContainedResourceEncodingTest { @Test public void testPatient() { - logger.debug("[xmlEncoding] encode resource to xml."); + ourLog.debug("[xmlEncoding] encode resource to xml."); /** * This works fine, although patient instance is modifing from encoder */ final String expectedPatientXml = this.ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(this.patient); - logger.debug("[xmlEncoding] first encoding: {}", expectedPatientXml); + ourLog.debug("[xmlEncoding] first encoding: {}", expectedPatientXml); final String actualPatientXml = this.ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(this.patient); // second encoding - xml is corrupt - i.e.: patient content 4 times! should be the same as after first encoding! - logger.debug("[xmlEncoding] second encoding: {}", actualPatientXml); + ourLog.debug("[xmlEncoding] second encoding: {}", actualPatientXml); Assert.assertEquals(expectedPatientXml.length(), actualPatientXml.length()); Assert.assertArrayEquals(expectedPatientXml.getBytes(), actualPatientXml.getBytes()); } - + @Test public void testComposition() { IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); - + assertEquals(0, this.comp.getContained().getContainedResources().size()); - + /** * This doesn't works, secund encoding creates corrupt xml */ final String expectedCompXml = parser.encodeResourceToString(this.comp); - logger.debug("[xmlEncoding] first encoding: {}", expectedCompXml); + ourLog.debug("[xmlEncoding] first encoding: {}", expectedCompXml); assertEquals(0, this.comp.getContained().getContainedResources().size()); @@ -146,7 +146,7 @@ public class ContainedResourceEncodingTest { // second encoding - xml could not be parsed back to compositon - i.e.: patient content 4 times! should be the same // as after first encoding! - logger.debug("[xmlEncoding] second encoding: {}", actualCompXml); + ourLog.debug("[xmlEncoding] second encoding: {}", actualCompXml); final String thirdCompXml = parser.encodeResourceToString(this.comp); @@ -154,96 +154,99 @@ public class ContainedResourceEncodingTest { // third encoding - xml could not be parsed back to compositon i.e.: patient content 4 times! should be the same as // afterfirst encoding! - logger.debug("[xmlEncoding] third encoding: {}", thirdCompXml); + ourLog.debug("[xmlEncoding] third encoding: {}", thirdCompXml); Assert.assertEquals(expectedCompXml.length(), actualCompXml.length()); Assert.assertArrayEquals(expectedCompXml.getBytes(), actualCompXml.getBytes()); } - - + @Test - public void testBundleWithContained() { - + public void testBundleWithContained() { + DiagnosticReport dr = new DiagnosticReport(); - dr.setId(new IdDt("DiagnosticReport","123")); - + dr.setId(new IdDt("DiagnosticReport", "123")); + Observation observation = new Observation(); - - CodeableConceptDt obsName = new CodeableConceptDt(); - obsName.setText("name"); - observation.setName(obsName); - - ResourceReferenceDt result = dr.addResult(); - result.setResource(observation); - - ArrayList performers = new ArrayList(); - ResourceReferenceDt performer = new ResourceReferenceDt(); - - Practitioner p = new Practitioner(); - p.setId(new IdDt(UUID.randomUUID().toString())); + + CodeableConceptDt obsName = new CodeableConceptDt(); + obsName.setText("name"); + observation.setName(obsName); + + dr.addResult().setResource(observation); + + ArrayList performers = new ArrayList(); + ResourceReferenceDt performer = new ResourceReferenceDt(); + + Practitioner p = new Practitioner(); + p.setId("#" + IdDt.newRandomUuid()); p.addIdentifier().setSystem("DoctorID").setValue("4711"); p.addRole(PractitionerRoleEnum.DOCTOR); p.setName(new HumanNameDt().addFamily("Mueller").addGiven("Klaus").addPrefix("Prof. Dr.")); - - performer.setResource(p); - performers.add(performer); - observation.setPerformer(performers); - - - List list = new ArrayList(); - list.add(dr); + + performer.setResource(p); + performers.add(performer); + observation.setPerformer(performers); + + IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); + String xml = parser.encodeResourceToString(dr); + ourLog.info(xml); + Assert.assertTrue(xml.contains("Mueller")); + List list = new ArrayList(); + list.add(dr); + IVersionSpecificBundleFactory factory = ctx.newBundleFactory(); factory.initializeBundleFromResourceList("", list, "http://foo", "http://foo", 2, null); Bundle bundle = factory.getDstu1Bundle(); - - IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); - String xml = parser.encodeBundleToString(bundle); - Assert.assertTrue(xml.contains("Mueller")); - + + parser = this.ctx.newXmlParser().setPrettyPrint(true); + xml = parser.encodeBundleToString(bundle); + ourLog.info(xml); + Assert.assertTrue(xml.contains("Mueller")); + } - + @Test - public void testBundleWithContainedWithNoIdDt() { - + public void testBundleWithContainedWithNoIdDt() { + DiagnosticReport dr = new DiagnosticReport(); - dr.setId(new IdDt("DiagnosticReport","123")); - + dr.setId(new IdDt("DiagnosticReport", "123")); + Observation observation = new Observation(); - - CodeableConceptDt obsName = new CodeableConceptDt(); - obsName.setText("name"); - observation.setName(obsName); - - ResourceReferenceDt result = dr.addResult(); - result.setResource(observation); - - ArrayList performers = new ArrayList(); - ResourceReferenceDt performer = new ResourceReferenceDt(); - - Practitioner p = new Practitioner(); + + CodeableConceptDt obsName = new CodeableConceptDt(); + obsName.setText("name"); + observation.setName(obsName); + + ResourceReferenceDt result = dr.addResult(); + result.setResource(observation); + + ArrayList performers = new ArrayList(); + ResourceReferenceDt performer = new ResourceReferenceDt(); + + Practitioner p = new Practitioner(); // no idDt on practitioner p p.addIdentifier().setSystem("DoctorID").setValue("4711"); p.addRole(PractitionerRoleEnum.DOCTOR); p.setName(new HumanNameDt().addFamily("Mueller").addGiven("Klaus").addPrefix("Prof. Dr.")); - - performer.setResource(p); - performers.add(performer); - observation.setPerformer(performers); - - - List list = new ArrayList(); + + performer.setResource(p); + performers.add(performer); + observation.setPerformer(performers); + + List list = new ArrayList(); list.add(dr); IVersionSpecificBundleFactory factory = ctx.newBundleFactory(); factory.initializeBundleFromResourceList("", list, "http://foo", "http://foo", 2, null); Bundle bundle = factory.getDstu1Bundle(); - IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); - String xml = parser.encodeBundleToString(bundle); - Assert.assertTrue(xml.contains("Mueller")); - + IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); + String xml = parser.encodeBundleToString(bundle); + ourLog.info(xml); + Assert.assertTrue(xml.contains("Mueller")); + } } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java index 73c4d42d161..7373a2e14ce 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java @@ -28,6 +28,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.INarrative; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import ca.uhn.fhir.context.ConfigurationException; @@ -41,7 +42,6 @@ import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.Extension; import ca.uhn.fhir.model.api.annotation.ResourceDef; -import ca.uhn.fhir.model.base.composite.BaseNarrativeDt; import ca.uhn.fhir.model.dstu.composite.AddressDt; import ca.uhn.fhir.model.dstu.composite.HumanNameDt; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; @@ -552,12 +552,17 @@ public class JsonParserTest { code.setDisplay("someDisplay"); code.addUndeclaredExtension(false, "urn:alt", new StringDt("alt name")); - String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + IParser parser = ourCtx.newJsonParser(); + String encoded = parser.encodeResourceToString(valueSet); ourLog.info(encoded); assertThat(encoded, not(containsString("123456"))); - assertEquals("{\"resourceType\":\"ValueSet\",\"define\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}", - encoded); + + String expected = "{\"resourceType\":\"ValueSet\",\"define\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}"; + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", encoded); + + assertEquals(expected, encoded); } @@ -615,9 +620,14 @@ public class JsonParserTest { String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); ourLog.info(encoded); - encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); - ourLog.info(encoded); - assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"); + IParser setPrettyPrint = ourCtx.newJsonParser().setPrettyPrint(false); + encoded = setPrettyPrint.encodeResourceToString(c); + String expected = "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"; + + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", encoded); + + assertEquals(expected, encoded); } @@ -1252,6 +1262,7 @@ public class JsonParserTest { * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" */ @Test + @Ignore public void testParseWithIncorrectReference() throws IOException { String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json")); jsonString = jsonString.replace("\"reference\"", "\"resource\""); diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java index a43e209fd3a..3915a5d9686 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java @@ -711,8 +711,9 @@ public class XmlParserTest { patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123")); String val = parser.encodeResourceToString(patient); - ourLog.info(val); assertThat(val, StringContains.containsString("")); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient)); Patient actual = parser.parseResource(Patient.class, val); assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); @@ -875,7 +876,12 @@ public class XmlParserTest { String val = ourCtx.newXmlParser().encodeResourceToString(q); ourLog.info(val); - assertEquals("", val); + String expected = ""; + + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", val); + + assertEquals(expected, val); } @@ -1033,9 +1039,6 @@ public class XmlParserTest { " \n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + " \n" + " \n" + " \n" + @@ -1052,6 +1055,9 @@ public class XmlParserTest { " \n" + " \n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/model/dstu2/composite/ResourceReferenceDt.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/model/dstu2/composite/ResourceReferenceDt.java index b115e44d124..f7bea64a369 100644 --- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/model/dstu2/composite/ResourceReferenceDt.java +++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/model/dstu2/composite/ResourceReferenceDt.java @@ -65,7 +65,7 @@ import ca.uhn.fhir.model.primitive.StringDt; * *

*/ -@DatatypeDef(name="ResourceReferenceDt") +@DatatypeDef(name="reference") public class ResourceReferenceDt extends BaseResourceReferenceDt implements ICompositeDatatype { diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java index 7431739b5cc..5bea761317c 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java @@ -52,6 +52,7 @@ import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport; import ca.uhn.fhir.model.dstu2.resource.Medication; import ca.uhn.fhir.model.dstu2.resource.MedicationOrder; import ca.uhn.fhir.model.dstu2.resource.Observation; +import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum; @@ -75,6 +76,28 @@ public class JsonParserDstu2Test { private static final FhirContext ourCtx = FhirContext.forDstu2(); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserDstu2Test.class); + @Test + public void testContainedResourceInExtensionUndeclared() { + Patient p = new Patient(); + p.addName().addFamily("PATIENT"); + + Organization o = new Organization(); + o.setName("ORG"); + p.addUndeclaredExtension(new ExtensionDt(false, "urn:foo", new ResourceReferenceDt(o))); + + String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(str); + + p = ourCtx.newJsonParser().parseResource(Patient.class, str); + assertEquals("PATIENT", p.getName().get(0).getFamily().get(0).getValue()); + + List exts = p.getUndeclaredExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + ResourceReferenceDt rr = (ResourceReferenceDt) exts.get(0).getValue(); + o = (Organization) rr.getResource(); + assertEquals("ORG", o.getName()); + } + /** * See #308 @@ -93,24 +116,6 @@ public class JsonParserDstu2Test { obs = p.parseResource(ReportObservation.class, encoded); assertEquals(true, obs.getReadOnly().getValue().booleanValue()); } - - - @Test - public void testParseBundleWithCustomObservationType() { - ReportObservation obs = new ReportObservation(); - obs.setReadOnly(true); - - IParser p = ourCtx.newJsonParser(); -// p.set - p.setParserErrorHandler(mock(IParserErrorHandler.class, new ThrowsException(new IllegalStateException()))); - - String encoded = p.encodeResourceToString(obs); - ourLog.info(encoded); - - obs = p.parseResource(ReportObservation.class, encoded); - assertEquals(true, obs.getReadOnly().getValue().booleanValue()); - } - @Test public void testEncodeAndParseExtensions() throws Exception { @@ -253,6 +258,7 @@ public class JsonParserDstu2Test { assertEquals(new Tag("scheme2", "term2", "label2"), tagList.get(1)); } + @Test public void testEncodeAndParseSecurityLabels() { Patient p = new Patient(); @@ -314,6 +320,7 @@ public class JsonParserDstu2Test { assertEquals("VERSION2", label.getVersion()); } + @Test public void testEncodeBundleNewBundleNoText() { @@ -423,6 +430,87 @@ public class JsonParserDstu2Test { assertThat(encoded, not(containsString("Label"))); } + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + ExtensionDt ext = obs.addUndeclaredExtension(false, "http://exturl"); + ext.setUrl("http://exturl").setValue(new StringDt("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\":\"1\"", + "\"meta\"", + "\"extension\"", + "\"url\":\"http://exturl\"", + "\"valueString\":\"ext_url_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\":\"http://exturl\"", + ",", + "\"url\":\"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getUndeclaredExtensions().size()); + assertEquals("http://exturl", obs.getUndeclaredExtensions().get(0).getUrl()); + assertEquals("ext_url_value", ((StringDt)obs.getUndeclaredExtensions().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + ExtensionDt ext = obs.addUndeclaredExtension(false, "http://exturl"); + ext.setUrl("http://exturl"); + + ExtensionDt subExt = ext.addUndeclaredExtension(false, "http://subext"); + subExt.setUrl("http://subext").setValue(new StringDt("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\":\"1\"", + "\"meta\"", + "\"extension\"", + "\"url\":\"http://exturl\"", + "\"extension\"", + "\"url\":\"http://subext\"", + "\"valueString\":\"sub_ext_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\":\"http://exturl\"", + ",", + "\"url\":\"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getUndeclaredExtensions().size()); + assertEquals("http://exturl", obs.getUndeclaredExtensions().get(0).getUrl()); + assertEquals(1, obs.getUndeclaredExtensions().get(0).getExtension().size()); + assertEquals("http://subext", obs.getUndeclaredExtensions().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringDt)obs.getUndeclaredExtensions().get(0).getExtension().get(0).getValue()).getValue()); + } + @Test public void testEncodeForceResourceId() { Patient p = new Patient(); @@ -511,9 +599,13 @@ public class JsonParserDstu2Test { ResourceMetadataKeyEnum.TAG_LIST.put(pt, tagList); String enc = ourCtx.newJsonParser().encodeResourceToString(pt); - ourLog.info(enc); - assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}", enc); + String expected = "{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}"; + + ourLog.info("Expected: " + expected); + ourLog.info("Actual : " + enc); + + assertEquals(expected, enc); } @@ -671,7 +763,12 @@ public class JsonParserDstu2Test { assertEquals("@fhirabend", parsed.getText().getDiv().getValueAsString()); String encoded = ourCtx.newXmlParser().encodeResourceToString(parsed); - assertEquals("@fhirabend", encoded); + String expected = "@fhirabend"; + + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", encoded); + + assertEquals(expected, encoded); } @Test @@ -1032,6 +1129,22 @@ public class JsonParserDstu2Test { assertEquals("{\"resourceType\":\"Binary\",\"id\":\"11\",\"meta\":{\"versionId\":\"22\"},\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", val); } + @Test + public void testParseBundleWithCustomObservationType() { + ReportObservation obs = new ReportObservation(); + obs.setReadOnly(true); + + IParser p = ourCtx.newJsonParser(); +// p.set + p.setParserErrorHandler(mock(IParserErrorHandler.class, new ThrowsException(new IllegalStateException()))); + + String encoded = p.encodeResourceToString(obs); + ourLog.info(encoded); + + obs = p.parseResource(ReportObservation.class, encoded); + assertEquals(true, obs.getReadOnly().getValue().booleanValue()); + } + /** * see #144 and #146 */ diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java index 1e15840e741..1ef1552cae1 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java @@ -42,7 +42,6 @@ import com.google.common.collect.Sets; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; -import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.ExtensionDt; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; @@ -152,6 +151,8 @@ public class XmlParserDstu2Test { String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed); assertThat(encoded, containsString("")); } + + @Test public void testChoiceTypeWithProfiledType2() { @@ -169,7 +170,7 @@ public class XmlParserDstu2Test { assertEquals(StringDt.class, par.getParameter().get(0).getValue().getClass()); assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass()); } - + @Test public void testContainedResourceInExtensionUndeclared() { Patient p = new Patient(); @@ -179,7 +180,7 @@ public class XmlParserDstu2Test { o.setName("ORG"); p.addUndeclaredExtension(new ExtensionDt(false, "urn:foo", new ResourceReferenceDt(o))); - String str = ourCtx.newXmlParser().encodeResourceToString(p); + String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); ourLog.info(str); p = ourCtx.newXmlParser().parseResource(Patient.class, str); @@ -191,7 +192,7 @@ public class XmlParserDstu2Test { o = (Organization) rr.getResource(); assertEquals("ORG", o.getName()); } - + /** * See #308 */ @@ -852,7 +853,7 @@ public class XmlParserDstu2Test { //@formatter:off } - + /** * See #113 */ @@ -921,7 +922,7 @@ public class XmlParserDstu2Test { //@formatter:off } - + @Test public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); @@ -999,6 +1000,82 @@ public class XmlParserDstu2Test { assertThat(encoded, not(containsString("Label"))); } + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + ExtensionDt ext = obs.addUndeclaredExtension(false, "http://exturl"); + ext.setUrl("http://exturl").setValue(new StringDt("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getUndeclaredExtensions().size()); + assertEquals("http://exturl", obs.getUndeclaredExtensions().get(0).getUrl()); + assertEquals("ext_url_value", ((StringDt)obs.getUndeclaredExtensions().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + ExtensionDt ext = obs.addUndeclaredExtension(false, "http://exturl"); + ext.setUrl("http://exturl"); + + ExtensionDt subExt = ext.addUndeclaredExtension(false, "http://subext"); + subExt.setUrl("http://subext").setValue(new StringDt("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getUndeclaredExtensions().size()); + assertEquals("http://exturl", obs.getUndeclaredExtensions().get(0).getUrl()); + assertEquals(1, obs.getUndeclaredExtensions().get(0).getExtension().size()); + assertEquals("http://subext", obs.getUndeclaredExtensions().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringDt)obs.getUndeclaredExtensions().get(0).getExtension().get(0).getValue()).getValue()); + } + @Test public void testEncodeExtensionWithResourceContent() { IParser parser = ourCtx.newXmlParser(); @@ -1661,72 +1738,6 @@ public class XmlParserDstu2Test { ""+ ""+ ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ ""+ ""+ ""+ @@ -1743,17 +1754,17 @@ public class XmlParserDstu2Test { ""+ ""+ ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ + ""+ ""+ ""+ ""+ @@ -1770,11 +1781,17 @@ public class XmlParserDstu2Test { assertEquals("#2179414", ref.getReference().getValue()); assertEquals(2, ref.getUndeclaredExtensions().size()); + ExtensionDt ext = ref.getUndeclaredExtensions().get(0); assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset", ext.getUrl()); assertEquals(ResourceReferenceDt.class, ext.getValue().getClass()); assertEquals("#2179414-permitted", ((ResourceReferenceDt) ext.getValue()).getReference().getValue()); + ext = ref.getUndeclaredExtensions().get(1); + assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-conceptmap", ext.getUrl()); + assertEquals(ResourceReferenceDt.class, ext.getValue().getClass()); + assertEquals("#2179414-cm", ((ResourceReferenceDt) ext.getValue()).getReference().getValue()); + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de)); assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset")); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java index f1840ff68f7..f93cbc2943d 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java @@ -1,25 +1,31 @@ package ca.uhn.fhir.util; import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; 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.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseReference; 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.api.ExtensionDt; import ca.uhn.fhir.model.dstu2.composite.IdentifierDt; import ca.uhn.fhir.model.dstu2.composite.MoneyDt; import ca.uhn.fhir.model.dstu2.composite.QuantityDt; +import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Patient; @@ -31,6 +37,23 @@ public class FhirTerserDstu2Test { private static FhirContext ourCtx = FhirContext.forDstu2(); + @Test + public void testGetResourceReferenceInExtension() { + Patient p = new Patient(); + p.addName().addFamily("PATIENT"); + + Organization o = new Organization(); + o.setName("ORG"); + ResourceReferenceDt ref = new ResourceReferenceDt(o); + ExtensionDt ext = new ExtensionDt(false, "urn:foo", ref); + p.addUndeclaredExtension(ext); + + List refs = ourCtx.newTerser().getAllPopulatedChildElementsOfType(p, IBaseReference.class); + assertEquals(1, refs.size()); + assertSame(ref, refs.get(0)); + } + + @Test public void testGetAllPopulatedChildElementsOfTypeDoesntDescendIntoEmbedded() { Patient p = new Patient(); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/PatientProfileDstu2.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/PatientProfileDstu2.java new file mode 100644 index 00000000000..034824892a3 --- /dev/null +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/PatientProfileDstu2.java @@ -0,0 +1,72 @@ +package ca.uhn.fhir.validation; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; +import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.util.ElementUtil; + +@ResourceDef(name="Patient", profile = "http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient") +public class PatientProfileDstu2 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name="owner", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#owningOrganization", definedLocally=false, isModifier=false) + @Description(shortDefinition="The organization that owns this animal") + private ResourceReferenceDt owningOrganization; + + public ResourceReferenceDt getOwningOrganization() { + if (owningOrganization == null) { + owningOrganization = new ResourceReferenceDt(); + } + return owningOrganization; + } + + public PatientProfileDstu2 setOwningOrganization(ResourceReferenceDt owningOrganization) { + this.owningOrganization = owningOrganization; + return this; + } + + @Child(name="colorPrimary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorPrimary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals primary color") + private CodeableConceptDt colorPrimary; + + @Child(name="colorSecondary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals secondary color") + private CodeableConceptDt colorSecondary; + + public CodeableConceptDt getColorPrimary() { + if (this.colorPrimary == null) { + return new CodeableConceptDt(); + } + return colorPrimary; + } + + public void setColorPrimary(CodeableConceptDt colorPrimary) { + this.colorPrimary = colorPrimary; + } + + public CodeableConceptDt getColorSecondary() { + if (this.colorSecondary == null) { + return new CodeableConceptDt(); + } + return colorSecondary; + } + + public void setColorSecondary(CodeableConceptDt colorSecondary) { + this.colorSecondary = colorSecondary; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(owningOrganization) && ElementUtil.isEmpty(colorPrimary) + && ElementUtil.isEmpty(colorSecondary) ; + } + +} \ No newline at end of file diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java index e2de1023ad8..d317fba0e96 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java @@ -1,6 +1,8 @@ package ca.uhn.fhir.validation; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -17,6 +19,9 @@ import org.junit.Test; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; +import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.composite.TimingDt; import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance; import ca.uhn.fhir.model.dstu2.resource.MedicationOrder; @@ -25,6 +30,9 @@ import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum; import ca.uhn.fhir.model.dstu2.valueset.UnitsOfTimeEnum; import ca.uhn.fhir.model.primitive.DateDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; public class ResourceValidatorDstu2Test { @@ -32,16 +40,140 @@ public class ResourceValidatorDstu2Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorDstu2Test.class); private FhirValidator createFhirValidator() { - + AllergyIntolerance allergy = new AllergyIntolerance(); allergy.getSubstance().addCoding().setCode("some substance"); - + FhirValidator val = ourCtx.newValidator(); val.setValidateAgainstStandardSchema(true); val.setValidateAgainstStandardSchematron(true); return val; } + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsXml() { + PatientProfileDstu2 myPatient = new PatientProfileDstu2(); + myPatient.setColorPrimary(new CodeableConceptDt("http://example.com#animalColor", "furry-grey")); + myPatient.setColorSecondary(new CodeableConceptDt("http://example.com#animalColor", "furry-white")); + myPatient.setOwningOrganization(new ResourceReferenceDt("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addUndeclaredExtension(new ExtensionDt().setUrl("http://foo.com/example").setValue(new StringDt("String Extension"))); + + IParser p = FhirContext.forDstu2().newXmlParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "String Extension", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + assertThat(messageString, containsString("url=\"http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary\"")); + assertThat(messageString, containsString("url=\"http://foo.com/example\"")); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsJson() { + PatientProfileDstu2 myPatient = new PatientProfileDstu2(); + myPatient.setColorPrimary(new CodeableConceptDt("http://example.com#animalColor", "furry-grey")); + myPatient.setColorSecondary(new CodeableConceptDt("http://example.com#animalColor", "furry-white")); + myPatient.setOwningOrganization(new ResourceReferenceDt("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addUndeclaredExtension(new ExtensionDt().setUrl("http://foo.com/example").setValue(new StringDt("String Extension"))); + + IParser p = FhirContext.forDstu2().newJsonParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "String Extension", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + +// @Test +// public void testValidateWithAny() { +// Provenance prov = new Provenance(); +// prov. +// +// IParser p = FhirContext.forDstu2().newJsonParser().setPrettyPrint(true); +// String messageString = p.encodeResourceToString(myPatient); +// ourLog.info(messageString); +// +// FhirValidator val = ourCtx.newValidator(); +//// val.setValidateAgainstStandardSchema(true); +//// val.setValidateAgainstStandardSchematron(true); +// val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); +// val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); +// +// ValidationResult result = val.validateWithResult(messageString); +// +// OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); +// String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); +// ourLog.info(encoded); +// +// assertTrue(result.isSuccessful()); +// } + /** * See issue #50 */ @@ -63,7 +195,7 @@ public class ResourceValidatorDstu2Test { String resultString = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); ourLog.info(resultString); - assertEquals(2, ((OperationOutcome)result.toOperationOutcome()).getIssue().size()); + assertEquals(2, ((OperationOutcome) result.toOperationOutcome()).getIssue().size()); assertThat(resultString, StringContains.containsString("2000-15-31")); } @@ -80,7 +212,7 @@ public class ResourceValidatorDstu2Test { MedicationOrder p = (MedicationOrder) b.getEntries().get(0).getResource(); TimingDt timing = new TimingDt(); timing.getRepeat().setDuration(123); - timing.getRepeat().setDurationUnits((UnitsOfTimeEnum)null); + timing.getRepeat().setDurationUnits((UnitsOfTimeEnum) null); p.getDosageInstructionFirstRep().setTiming(timing); try { @@ -106,9 +238,9 @@ public class ResourceValidatorDstu2Test { MedicationOrder p = (MedicationOrder) b.getEntries().get(0).getResource(); TimingDt timing = new TimingDt(); timing.getRepeat().setDuration(123); - timing.getRepeat().setDurationUnits((UnitsOfTimeEnum)null); + timing.getRepeat().setDurationUnits((UnitsOfTimeEnum) null); p.getDosageInstructionFirstRep().setTiming(timing); - + validationResult = val.validateWithResult(b); assertFalse(validationResult.isSuccessful()); OperationOutcome operationOutcome = (OperationOutcome) validationResult.toOperationOutcome(); @@ -123,13 +255,13 @@ public class ResourceValidatorDstu2Test { Bundle b = ourCtx.newJsonParser().parseBundle(res); ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b)); - + FhirValidator val = createFhirValidator(); ValidationResult result = val.validateWithResult(b); OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); - + assertTrue(result.toString(), result.isSuccessful()); assertNotNull(operationOutcome); assertEquals(1, operationOutcome.getIssue().size()); @@ -142,7 +274,7 @@ public class ResourceValidatorDstu2Test { Patient p = ourCtx.newJsonParser().parseResource(Patient.class, res); ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p)); - + FhirValidator val = ourCtx.newValidator(); val.setValidateAgainstStandardSchema(true); val.setValidateAgainstStandardSchematron(false); diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PatientProfileDstu3.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PatientProfileDstu3.java new file mode 100644 index 00000000000..3e08dfd6cf2 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PatientProfileDstu3.java @@ -0,0 +1,73 @@ +package org.hl7.fhir.dstu3.hapi.validation; + +import org.hl7.fhir.dstu3.model.CodeableConcept; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.Reference; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.util.ElementUtil; + +@ResourceDef(name="Patient", profile = "http://hl7.org/fhir/StructureDefinition/Patient") +public class PatientProfileDstu3 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name="owner", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#owningOrganization", definedLocally=false, isModifier=false) + @Description(shortDefinition="The organization that owns this animal") + private Reference owningOrganization; + + public Reference getOwningOrganization() { + if (owningOrganization == null) { + owningOrganization = new Reference(); + } + return owningOrganization; + } + + public PatientProfileDstu3 setOwningOrganization(Reference owningOrganization) { + this.owningOrganization = owningOrganization; + return this; + } + + @Child(name="colorPrimary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorPrimary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals primary color") + private CodeableConcept colorPrimary; + + @Child(name="colorSecondary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals secondary color") + private CodeableConcept colorSecondary; + + public CodeableConcept getColorPrimary() { + if (this.colorPrimary == null) { + return new CodeableConcept(); + } + return colorPrimary; + } + + public void setColorPrimary(CodeableConcept colorPrimary) { + this.colorPrimary = colorPrimary; + } + + public CodeableConcept getColorSecondary() { + if (this.colorSecondary == null) { + return new CodeableConcept(); + } + return colorSecondary; + } + + public void setColorSecondary(CodeableConcept colorSecondary) { + this.colorSecondary = colorSecondary; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(owningOrganization) && ElementUtil.isEmpty(colorPrimary) + && ElementUtil.isEmpty(colorSecondary) ; + } + +} \ No newline at end of file diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java index d0385a225c7..7952e0a3ece 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/JsonParserDstu3Test.java @@ -15,13 +15,15 @@ import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.UUID; import org.apache.commons.io.IOUtils; import org.hamcrest.Matchers; +import org.hamcrest.core.StringContains; +import org.hl7.fhir.dstu3.model.Address.AddressUse; +import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory; import org.hl7.fhir.dstu3.model.Binary; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; @@ -34,6 +36,8 @@ import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.DateType; import org.hl7.fhir.dstu3.model.DecimalType; import org.hl7.fhir.dstu3.model.DiagnosticReport; +import org.hl7.fhir.dstu3.model.EnumFactory; +import org.hl7.fhir.dstu3.model.Enumeration; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.Extension; import org.hl7.fhir.dstu3.model.HumanName; @@ -46,6 +50,7 @@ import org.hl7.fhir.dstu3.model.Observation; import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.PrimitiveType; import org.hl7.fhir.dstu3.model.Quantity; import org.hl7.fhir.dstu3.model.QuestionnaireResponse; import org.hl7.fhir.dstu3.model.Reference; @@ -76,43 +81,6 @@ public class JsonParserDstu3Test { } - /** - * See #326 - */ - @Test - public void testEncodeContainedResource() { - Patient patient = new Patient(); - patient.getBirthDateElement().setValueAsString("2016-04-05"); - patient.addExtension().setUrl("test").setValue(new Reference(new Condition())); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); - ourLog.info(encoded); - - //@formatter:off - assertThat(encoded, stringContainsInOrder( - "{", - "\"resourceType\":\"Patient\",", - "\"extension\":[", - "{", - "\"url\":\"test\",", - "\"valueReference\":{", - "\"reference\":\"#1\"", - "}", - "}", - "],", - "\"contained\":[", - "{", - "\"resourceType\":\"Condition\",", - "\"id\":\"1\"", - "}", - "],", - "\"birthDate\":\"2016-04-05\"", - "}" - )); - //@formatter:on - } - - @Test public void testEncodeAndParseExtensions() throws Exception { @@ -335,7 +303,8 @@ public class JsonParserDstu3Test { assertEquals("DISPLAY2", label.getDisplay()); assertEquals("VERSION2", label.getVersion()); } - + + @Test public void testEncodeBundleNewBundleNoText() { @@ -353,7 +322,44 @@ public class JsonParserDstu3Test { assertThat(val, not(containsString("text"))); } + + /** + * See #326 + */ + @Test + public void testEncodeContainedResource() { + Patient patient = new Patient(); + patient.getBirthDateElement().setValueAsString("2016-04-05"); + patient.addExtension().setUrl("test").setValue(new Reference(new Condition())); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "{", + "\"resourceType\":\"Patient\",", + "\"contained\":[", + "{", + "\"resourceType\":\"Condition\",", + "\"id\":\"1\"", + "}", + "],", + "\"extension\":[", + "{", + "\"url\":\"test\",", + "\"valueReference\":{", + "\"reference\":\"#1\"", + "}", + "}", + "],", + "\"birthDate\":\"2016-04-05\"", + "}" + )); + //@formatter:on + } + @Test public void testEncodeDoesntIncludeUuidId() { Patient p = new Patient(); @@ -363,7 +369,7 @@ public class JsonParserDstu3Test { String actual = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); assertThat(actual, not(containsString("78ef6f64c2f2"))); } - + @Test public void testEncodeEmptyBinary() { String output = ourCtx.newJsonParser().encodeResourceToString(new Binary()); @@ -404,6 +410,87 @@ public class JsonParserDstu3Test { assertThat(encoded, not(containsString("Label"))); } + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\":\"1\"", + "\"meta\"", + "\"extension\"", + "\"url\":\"http://exturl\"", + "\"valueString\":\"ext_url_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\":\"http://exturl\"", + ",", + "\"url\":\"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType)obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\":\"1\"", + "\"meta\"", + "\"extension\"", + "\"url\":\"http://exturl\"", + "\"extension\"", + "\"url\":\"http://subext\"", + "\"valueString\":\"sub_ext_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\":\"http://exturl\"", + ",", + "\"url\":\"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType)obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + @Test public void testEncodeNarrativeSuppressed() throws Exception { Patient patient = new Patient(); @@ -423,6 +510,7 @@ public class JsonParserDstu3Test { assertThat(encoded, containsString("maritalStatus")); } + @Test public void testEncodeParametersWithId() { Parameters reqParms = new Parameters(); @@ -509,6 +597,27 @@ public class JsonParserDstu3Test { assertThat(json, not(containsString("\"id\""))); } + @Test + public void testEncodeUndeclaredExtensionWithEnumerationContent() { + IParser parser = ourCtx.newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + EnumFactory fact = new AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueCode\":\"home\"}]")); + + MyPatientWithOneDeclaredEnumerationExtension actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + @Test public void testEncodeWithDontEncodeElements() throws Exception { Patient patient = new Patient(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java new file mode 100644 index 00000000000..e1b52719913 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java @@ -0,0 +1,27 @@ +package ca.uhn.fhir.parser; + +import org.hl7.fhir.dstu3.model.Address.AddressUse; +import org.hl7.fhir.dstu3.model.Enumeration; +import org.hl7.fhir.dstu3.model.Patient; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; + +@ResourceDef(name = "Patient") +public class MyPatientWithOneDeclaredEnumerationExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Enumeration myFoo; + + public Enumeration getFoo() { + return myFoo; + } + + public void setFoo(Enumeration theFoo) { + myFoo = theFoo; + } + +} \ No newline at end of file diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java index ff0d1ea5369..c6d6d52eaa4 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.UUID; @@ -34,6 +33,7 @@ import org.hamcrest.collection.IsEmptyCollection; import org.hamcrest.core.StringContains; import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu3.model.Address.AddressUse; +import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory; import org.hl7.fhir.dstu3.model.AllergyIntolerance; import org.hl7.fhir.dstu3.model.Annotation; import org.hl7.fhir.dstu3.model.Binary; @@ -57,6 +57,8 @@ import org.hl7.fhir.dstu3.model.Duration; import org.hl7.fhir.dstu3.model.ElementDefinition; import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.dstu3.model.Encounter; +import org.hl7.fhir.dstu3.model.EnumFactory; +import org.hl7.fhir.dstu3.model.Enumeration; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.Enumerations.DocumentReferenceStatus; import org.hl7.fhir.dstu3.model.Extension; @@ -74,6 +76,7 @@ import org.hl7.fhir.dstu3.model.Observation.ObservationRelationshipType; import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; import org.hl7.fhir.dstu3.model.Organization; import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.PrimitiveType; import org.hl7.fhir.dstu3.model.Quantity; import org.hl7.fhir.dstu3.model.Reference; import org.hl7.fhir.dstu3.model.SimpleQuantity; @@ -730,17 +733,17 @@ public class XmlParserDstu3Test { //@formatter:off assertThat(encoded, stringContainsInOrder( "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", "" )); //@formatter:on @@ -927,8 +930,84 @@ public class XmlParserDstu3Test { assertThat(encoded, not(containsString("Label"))); } + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType)obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType)obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + @Test public void testEncodeExtensionWithResourceContent() { IParser parser = ourCtx.newXmlParser(); @@ -969,7 +1048,7 @@ public class XmlParserDstu3Test { assertThat(encoded, containsString("family")); assertThat(encoded, containsString("maritalStatus")); } - + @Test public void testEncodeNonContained() { // Create an organization @@ -1065,7 +1144,7 @@ public class XmlParserDstu3Test { assertThat(str, containsString("")); assertThat(str, containsString("")); } - + @Test public void testEncodeSummary() { Patient patient = new Patient(); @@ -1083,7 +1162,6 @@ public class XmlParserDstu3Test { assertThat(encoded, containsString("family")); assertThat(encoded, not(containsString("maritalStatus"))); } - @Test public void testEncodeSummary2() { @@ -1106,6 +1184,28 @@ public class XmlParserDstu3Test { assertThat(encoded, not(containsString("maritalStatus"))); } + + @Test + public void testEncodeUndeclaredExtensionWithEnumerationContent() { + IParser parser = ourCtx.newXmlParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + EnumFactory fact = new AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + MyPatientWithOneDeclaredEnumerationExtension actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + @Test public void testEncodeWithDontEncodeElements() throws Exception { Patient patient = new Patient(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java index 0b57c91de99..3aad140a989 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java @@ -56,15 +56,16 @@ public class CreateDstu3Test { assertEquals(200, status.getStatusLine().getStatusCode()); //@formatter:off - assertThat(responseContent, stringContainsInOrder("", + assertThat(responseContent, stringContainsInOrder( + "", "", - "", - "", - "", "", - "", + "", "", - "")); + "", + "", + "", + "")); //@formatter:on } @@ -82,15 +83,16 @@ public class CreateDstu3Test { assertEquals(200, status.getStatusLine().getStatusCode()); //@formatter:off - assertThat(responseContent, stringContainsInOrder("", + assertThat(responseContent, stringContainsInOrder( + "", "", - "", - "", - "", "", - "", + "", "", - "")); + "", + "", + "", + "")); //@formatter:on assertThat(responseContent, not(containsString("http://hl7.org/fhir/"))); diff --git a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java new file mode 100644 index 00000000000..8e4a19d8e12 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java @@ -0,0 +1,133 @@ +package org.hl7.fhir.dstu3.hapi.validation; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import org.apache.naming.StringManager; +import org.hl7.fhir.dstu3.model.CodeableConcept; +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Reference; +import org.hl7.fhir.dstu3.model.StringType; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.validation.FhirValidator; +import ca.uhn.fhir.validation.SchemaBaseValidator; +import ca.uhn.fhir.validation.ValidationResult; +import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; + +public class ResourceValidatorDstu3Test { + + private static FhirContext ourCtx = FhirContext.forDstu3(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorDstu3Test.class); + + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsXml() { + PatientProfileDstu3 myPatient = new PatientProfileDstu3(); + myPatient.setId("1"); + myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey"))); + myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setSystem("furry-white"))); + myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension")); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "String Extension", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + assertThat(messageString, containsString("url=\"http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary\"")); + assertThat(messageString, containsString("url=\"http://foo.com/example\"")); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsJson() { + PatientProfileDstu3 myPatient = new PatientProfileDstu3(); + myPatient.setId("1"); + myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey"))); + myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setSystem("furry-white"))); + myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension")); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "String Extension", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + +} diff --git a/hapi-fhir-structures-hl7org-dstu2/src/main/resources/org/hl7/fhir/instance/model/fhirversion.properties b/hapi-fhir-structures-hl7org-dstu2/src/main/resources/org/hl7/fhir/instance/model/fhirversion.properties index c7028ae4dff..cb0d5b45aa4 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/main/resources/org/hl7/fhir/instance/model/fhirversion.properties +++ b/hapi-fhir-structures-hl7org-dstu2/src/main/resources/org/hl7/fhir/instance/model/fhirversion.properties @@ -126,5 +126,6 @@ datatype.unsignedInt=org.hl7.fhir.instance.model.UnsignedIntType datatype.uri=org.hl7.fhir.instance.model.UriType #datatype.xhtml=org.hl7.fhir.instance.model.XhtmlType +datatype.Extension=org.hl7.fhir.instance.model.Extension datatype.reference=org.hl7.fhir.instance.model.Reference datatype.enumeration=org.hl7.fhir.instance.model.Enumeration \ No newline at end of file diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgTest.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java similarity index 94% rename from hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgTest.java rename to hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java index 5390b38f08a..4e3cb3872c1 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgTest.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserHl7OrgDstu2Test.java @@ -26,6 +26,7 @@ import org.hamcrest.core.StringContains; import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.instance.model.Address; import org.hl7.fhir.instance.model.Address.AddressUse; +import org.hl7.fhir.instance.model.Address.AddressUseEnumFactory; import org.hl7.fhir.instance.model.Binary; import org.hl7.fhir.instance.model.Bundle; import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent; @@ -36,6 +37,7 @@ import org.hl7.fhir.instance.model.DateTimeType; import org.hl7.fhir.instance.model.DateType; import org.hl7.fhir.instance.model.DecimalType; import org.hl7.fhir.instance.model.DiagnosticReport; +import org.hl7.fhir.instance.model.EnumFactory; import org.hl7.fhir.instance.model.Enumeration; import org.hl7.fhir.instance.model.Extension; import org.hl7.fhir.instance.model.HumanName; @@ -46,6 +48,8 @@ import org.hl7.fhir.instance.model.Narrative.NarrativeStatus; import org.hl7.fhir.instance.model.Observation; import org.hl7.fhir.instance.model.Organization; import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.Patient.ContactComponent; +import org.hl7.fhir.instance.model.PrimitiveType; import org.hl7.fhir.instance.model.Reference; import org.hl7.fhir.instance.model.Specimen; import org.hl7.fhir.instance.model.StringType; @@ -57,6 +61,7 @@ import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.utilities.xhtml.XhtmlNode; import org.junit.After; +import org.junit.Ignore; import org.junit.Test; import org.xml.sax.SAXException; @@ -64,21 +69,41 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.ResourceDef; -import ca.uhn.fhir.model.base.composite.BaseNarrativeDt; import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.rest.server.Constants; import net.sf.json.JSON; import net.sf.json.JSONSerializer; -public class JsonParserHl7OrgTest { +public class JsonParserHl7OrgDstu2Test { private static final FhirContext ourCtx = FhirContext.forDstu2Hl7Org(); - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserHl7OrgTest.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserHl7OrgDstu2Test.class); @After public void after() { ourCtx.setNarrativeGenerator(null); } + @Test + public void testEncodeUndeclaredExtensionWithEnumerationContent() { + IParser parser = ourCtx.newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + EnumFactory fact = new AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueCode\":\"home\"}]")); + + MyPatientWithOneDeclaredEnumerationExtension actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + @Test public void testEncodeNarrativeSuppressed() throws Exception { @@ -613,7 +638,7 @@ public class JsonParserHl7OrgTest { list.setId("listId"); list.addEntry().setItem(new Reference(pt)).setDeleted(true); - String enc = ourCtx.newJsonParser().encodeResourceToString(list); + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(list); ourLog.info(enc); assertThat(enc, containsString("\"id\":\"1\"")); @@ -1096,6 +1121,7 @@ public class JsonParserHl7OrgTest { * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" */ @Test + @Ignore public void testParseWithIncorrectReference() throws IOException { String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json")); jsonString = jsonString.replace("\"reference\"", "\"resource\""); @@ -1152,12 +1178,57 @@ public class JsonParserHl7OrgTest { } + @Test + public void testParsePrimitiveExtension() { + //@formatter:off + String input = "{\n" + + " \"resourceType\":\"Patient\",\n" + + " \"contact\":[\n" + + " {\n" + + " \"name\":{\n" + + " \"family\":[\n" + + " \"du\",\n" + + " \"Marché\"\n" + + " ],\n" + + " \"_family\":[\n" + + " {\n" + + " \"extension\":[\n" + + " {\n" + + " \"url\":\"http://hl7.org/fhir/Profile/iso-21090#qualifier\",\n" + + " \"valueCode\":\"VV\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " null\n" + + " ]\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + //@formatter:off + + Patient p = ourCtx.newJsonParser().parseResource(Patient.class, input); + ContactComponent contact = p.getContact().get(0); + StringType family = contact.getName().getFamily().get(0); + + assertEquals("du", family.getValueAsString()); + assertEquals(1, family.getExtension().size()); + } + + @Test public void testSimpleResourceEncodeWithCustomType() throws IOException, SAXException { String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"), Charset.forName("UTF-8")); MyObservationWithExtensions obs = ourCtx.newJsonParser().parseResource(MyObservationWithExtensions.class, jsonString); + { + ContactComponent contact = obs.getContact().get(0); + StringType family = contact.getName().getFamily().get(0); + assertEquals("du", family.getValueAsString()); + assertEquals(1, family.getExtension().size()); + } + assertEquals(0, obs.getExtension().size()); assertEquals("aaaa", obs.getExtAtt().getContentType()); assertEquals("str1", obs.getMoreExt().getStr1().getValue()); @@ -1271,25 +1342,6 @@ public class JsonParserHl7OrgTest { } - @ResourceDef(name = "Patient") - public static class MyPatientWithOneDeclaredEnumerationExtension extends Patient { - - private static final long serialVersionUID = 1L; - - @Child(order = 0, name = "foo") - @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) - private Enumeration myFoo; - - public Enumeration getFoo() { - return myFoo; - } - - public void setFoo(Enumeration theFoo) { - myFoo = theFoo; - } - - } - @ResourceDef(name = "Patient") public static class MyPatientWithOneDeclaredExtension extends Patient { diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java new file mode 100644 index 00000000000..2c287fbc5b2 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/MyPatientWithOneDeclaredEnumerationExtension.java @@ -0,0 +1,27 @@ +package ca.uhn.fhir.parser; + +import org.hl7.fhir.instance.model.Enumeration; +import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.Address.AddressUse; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; + +@ResourceDef(name = "Patient") +public class MyPatientWithOneDeclaredEnumerationExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Enumeration myFoo; + + public Enumeration getFoo() { + return myFoo; + } + + public void setFoo(Enumeration theFoo) { + myFoo = theFoo; + } + +} \ No newline at end of file diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/ResourceWithExtensionsA.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/ResourceWithExtensionsA.java index a2ac0b89096..e10003606ce 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/ResourceWithExtensionsA.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/ResourceWithExtensionsA.java @@ -5,6 +5,7 @@ import java.util.List; import org.hl7.fhir.instance.model.BackboneElement; import org.hl7.fhir.instance.model.CodeableConcept; import org.hl7.fhir.instance.model.DateType; +import org.hl7.fhir.instance.model.DomainResource; import org.hl7.fhir.instance.model.Identifier; import org.hl7.fhir.instance.model.Resource; import org.hl7.fhir.instance.model.ResourceType; @@ -17,7 +18,7 @@ import ca.uhn.fhir.model.api.annotation.Extension; import ca.uhn.fhir.model.api.annotation.ResourceDef; @ResourceDef(name = "ResourceWithExtensionsA", id="0001") -public class ResourceWithExtensionsA extends Resource { +public class ResourceWithExtensionsA extends DomainResource { /* * NB: several unit tests depend on the structure here @@ -192,7 +193,7 @@ public class ResourceWithExtensionsA extends Resource { @Override - public Resource copy() { + public DomainResource copy() { // TODO Auto-generated method stub return null; } diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java index e3a93c5bc70..b7c23943453 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java @@ -69,9 +69,8 @@ import org.xml.sax.SAXException; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.narrative.INarrativeGenerator; -import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredAddressExtension; -import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredEnumerationExtension; -import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredExtension; +import ca.uhn.fhir.parser.JsonParserHl7OrgDstu2Test.MyPatientWithOneDeclaredAddressExtension; +import ca.uhn.fhir.parser.JsonParserHl7OrgDstu2Test.MyPatientWithOneDeclaredExtension; import ca.uhn.fhir.rest.server.AddProfileTagEnum; import ca.uhn.fhir.rest.server.Constants; import net.sf.json.JSON; @@ -87,13 +86,13 @@ public class XmlParserHl7OrgDstu2Test { ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.ONLY_FOR_CUSTOM); } - private String fixDivNodeText(String htmlNoNs) { + private String fixDivNodeText(String htmlNoNs) { return htmlNoNs.replace("
", "
"); } - - private String fixDivNodeTextJson(String htmlNoNs) { - return htmlNoNs.replace("
", "
"); - } + + private String fixDivNodeTextJson(String htmlNoNs) { + return htmlNoNs.replace("
", "
"); + } @Test @@ -111,7 +110,7 @@ public class XmlParserHl7OrgDstu2Test { } - @Test + @Test public void testContainedResourceInExtensionUndeclared() { Patient p = new Patient(); p.addName().addFamily("PATIENT"); @@ -133,6 +132,7 @@ public class XmlParserHl7OrgDstu2Test { assertEquals("ORG", o.getName()); } + @Test public void testDuplicateContainedResources() { @@ -152,6 +152,159 @@ public class XmlParserHl7OrgDstu2Test { } + @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("")); + assertThat(encoded, containsString("")); + + // Create a bundle with just the patient resource + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + // Encode the bundle + encoded = xmlParser.encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + // Re-parse the bundle + patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReferenceElement().getValue()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getIdElement().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("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + patient.getManagingOrganization().getResource().setId(("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + + } + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + patient.getExtension().add(ext); + + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.getExtension().add(parent); + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.getExtension().add(child1); + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); + parent.getExtension().add(child2); + + Extension modExt = new Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new DateType("1995-01-02")); + patient.getModifierExtension().add(modExt); + + HumanName name = patient.addName(); + name.addFamily("Blah"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.getExtension().add(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.getExtension().add(given2ext); + given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + + /* + * Now parse this back + */ + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); + + } + // TODO: uncomment with new model updates // @Test // public void testEncodeAndParseExtensionOnResourceReference() { @@ -409,159 +562,6 @@ public class XmlParserHl7OrgDstu2Test { - @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("")); - assertThat(encoded, containsString("")); - - // Create a bundle with just the patient resource - Bundle b = new Bundle(); - b.addEntry().setResource(patient); - - // Encode the bundle - encoded = xmlParser.encodeResourceToString(b); - ourLog.info(encoded); - assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); - assertThat(encoded, containsString("")); - assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); - assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); - - // Re-parse the bundle - patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); - assertEquals("#1", patient.getManagingOrganization().getReferenceElement().getValue()); - - assertNotNull(patient.getManagingOrganization().getResource()); - org = (Organization) patient.getManagingOrganization().getResource(); - assertEquals("#1", org.getIdElement().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("", "", "", ""))); - assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); - assertThat(encoded, containsString("")); - - // And re-encode once more, with the references cleared - patient.getContained().clear(); - patient.getManagingOrganization().setReference(null); - encoded = xmlParser.encodeResourceToString(patient); - ourLog.info(encoded); - assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); - assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); - assertThat(encoded, containsString("")); - - // And re-encode once more, with the references cleared and a manually set local ID - patient.getContained().clear(); - patient.getManagingOrganization().setReference(null); - patient.getManagingOrganization().getResource().setId(("#333")); - encoded = xmlParser.encodeResourceToString(patient); - ourLog.info(encoded); - assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); - assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); - - } - - @Test - public void testEncodeAndParseExtensions() throws Exception { - - Patient patient = new Patient(); - patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); - - Extension ext = new Extension(); - ext.setUrl("http://example.com/extensions#someext"); - ext.setValue(new DateTimeType("2011-01-02T11:13:15")); - patient.getExtension().add(ext); - - Extension parent = new Extension().setUrl("http://example.com#parent"); - patient.getExtension().add(parent); - Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); - parent.getExtension().add(child1); - Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); - parent.getExtension().add(child2); - - Extension modExt = new Extension(); - modExt.setUrl("http://example.com/extensions#modext"); - modExt.setValue(new DateType("1995-01-02")); - patient.getModifierExtension().add(modExt); - - HumanName name = patient.addName(); - name.addFamily("Blah"); - StringType given = name.addGivenElement(); - given.setValue("Joe"); - Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); - given.getExtension().add(ext2); - - StringType given2 = name.addGivenElement(); - given2.setValue("Shmoe"); - Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); - given2.getExtension().add(given2ext); - given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); - - String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); - ourLog.info(output); - - String enc = ourCtx.newXmlParser().encodeResourceToString(patient); - assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - - /* - * Now parse this back - */ - - Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); - ext = parsed.getExtension().get(0); - assertEquals("http://example.com/extensions#someext", ext.getUrl()); - assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); - - parent = patient.getExtension().get(1); - assertEquals("http://example.com#parent", parent.getUrl()); - assertNull(parent.getValue()); - child1 = parent.getExtension().get(0); - assertEquals("http://example.com#child", child1.getUrl()); - assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); - child2 = parent.getExtension().get(1); - assertEquals("http://example.com#child", child2.getUrl()); - assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); - - modExt = parsed.getModifierExtension().get(0); - assertEquals("http://example.com/extensions#modext", modExt.getUrl()); - assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); - - name = parsed.getName().get(0); - - ext2 = name.getGiven().get(0).getExtension().get(0); - assertEquals("http://examples.com#givenext", ext2.getUrl()); - assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); - - given2ext = name.getGiven().get(1).getExtension().get(0); - assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); - assertNull(given2ext.getValue()); - Extension given2ext2 = given2ext.getExtension().get(0); - assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); - assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); - - } - /** * See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name * @@ -581,7 +581,6 @@ public class XmlParserHl7OrgDstu2Test { assertThat(output, containsString("")); } - @Test public void testEncodeBinaryResource() { @@ -605,6 +604,7 @@ public class XmlParserHl7OrgDstu2Test { assertEquals("", output); } + @Test public void testEncodeBoundCode() { @@ -619,6 +619,7 @@ public class XmlParserHl7OrgDstu2Test { assertThat(val, containsString("home")); assertThat(val, containsString("male")); } + @Test public void testEncodeBundle() throws InterruptedException { Bundle b = new Bundle(); @@ -655,7 +656,7 @@ public class XmlParserHl7OrgDstu2Test { assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings)); } - + @Test public void testEncodeBundleCategory() { @@ -682,7 +683,6 @@ public class XmlParserHl7OrgDstu2Test { assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode()); assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay()); } - @Test public void testEncodeContainedAndIncludedResources() { @@ -699,7 +699,7 @@ public class XmlParserHl7OrgDstu2Test { ourLog.info(str); } - + @Test public void testEncodeContainedResources() throws Exception { @@ -724,7 +724,6 @@ public class XmlParserHl7OrgDstu2Test { } - @Test public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); @@ -771,6 +770,7 @@ public class XmlParserHl7OrgDstu2Test { } + @Test public void testEncodeDeclaredExtensionWithResourceContent() { IParser parser = ourCtx.newXmlParser(); @@ -833,6 +833,82 @@ public class XmlParserHl7OrgDstu2Test { assertEquals("uuml ü", p.getName().get(0).getFamily().get(0).getValue()); } + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType)obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType)obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + @Test public void testEncodeExtensionWithResourceContent() { IParser parser = ourCtx.newXmlParser(); @@ -1235,9 +1311,6 @@ public class XmlParserHl7OrgDstu2Test { " \n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + " \n" + " \n" + " \n" + @@ -1254,6 +1327,9 @@ public class XmlParserHl7OrgDstu2Test { " \n" + " \n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -1270,7 +1346,7 @@ public class XmlParserHl7OrgDstu2Test { assertEquals("2013-01-12", resource.getBar1().get(0).getBar12().get(0).getBar121().get(1).getValueAsString()); assertEquals("2013-01-03", resource.getBar1().get(0).getBar12().get(0).getBar122().get(0).getValueAsString()); - String encoded = p.encodeResourceToString(resource); + String encoded = p.setPrettyPrint(true).encodeResourceToString(resource); ourLog.info(encoded); Diff d = new Diff(new StringReader(msg), new StringReader(encoded)); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.json b/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.json index 1b21190ab60..2e740d86b27 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.json +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.json @@ -1,5 +1,9 @@ { "resourceType":"Patient", + "text":{ + "status":"generated", + "div":"
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NamePeter James Chalmers (\"Jim\")
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
\n
" + }, "extension":[ { "url":"urn:patientext:att", @@ -28,10 +32,6 @@ "valueDate":"2011-01-02" } ], - "text":{ - "status":"generated", - "div":"
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NamePeter James Chalmers (\"Jim\")
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
\n
" - }, "identifier":[ { "use":"usual", diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.xml b/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.xml index 0a9d055e455..2cfd768c113 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.xml +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/resources/example-patient-general-hl7orgdstu2.xml @@ -1,24 +1,4 @@ - - - - - - - - - - - - - - - - - - - -
@@ -45,6 +25,26 @@
+ + + + + + + + + + + + + + + + + + + + diff --git a/hapi-tinder-plugin/dstu2/fhirversion.properties b/hapi-tinder-plugin/dstu2/fhirversion.properties new file mode 100644 index 00000000000..f9c235c15b4 --- /dev/null +++ b/hapi-tinder-plugin/dstu2/fhirversion.properties @@ -0,0 +1,164 @@ +# This file contains version definitions + +resource.Account=ca.uhn.fhir.model.dstu2.resource.Account +resource.AllergyIntolerance=ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance +resource.Appointment=ca.uhn.fhir.model.dstu2.resource.Appointment +resource.AppointmentResponse=ca.uhn.fhir.model.dstu2.resource.AppointmentResponse +resource.AuditEvent=ca.uhn.fhir.model.dstu2.resource.AuditEvent +resource.Basic=ca.uhn.fhir.model.dstu2.resource.Basic +resource.Binary=ca.uhn.fhir.model.dstu2.resource.Binary +resource.BodySite=ca.uhn.fhir.model.dstu2.resource.BodySite +resource.Bundle=ca.uhn.fhir.model.dstu2.resource.Bundle +resource.CarePlan=ca.uhn.fhir.model.dstu2.resource.CarePlan +resource.Claim=ca.uhn.fhir.model.dstu2.resource.Claim +resource.ClaimResponse=ca.uhn.fhir.model.dstu2.resource.ClaimResponse +resource.ClinicalImpression=ca.uhn.fhir.model.dstu2.resource.ClinicalImpression +resource.Communication=ca.uhn.fhir.model.dstu2.resource.Communication +resource.CommunicationRequest=ca.uhn.fhir.model.dstu2.resource.CommunicationRequest +resource.Composition=ca.uhn.fhir.model.dstu2.resource.Composition +resource.ConceptMap=ca.uhn.fhir.model.dstu2.resource.ConceptMap +resource.Condition=ca.uhn.fhir.model.dstu2.resource.Condition +resource.Conformance=ca.uhn.fhir.model.dstu2.resource.Conformance +resource.Contract=ca.uhn.fhir.model.dstu2.resource.Contract +resource.Coverage=ca.uhn.fhir.model.dstu2.resource.Coverage +resource.DataElement=ca.uhn.fhir.model.dstu2.resource.DataElement +resource.DetectedIssue=ca.uhn.fhir.model.dstu2.resource.DetectedIssue +resource.Device=ca.uhn.fhir.model.dstu2.resource.Device +resource.DeviceComponent=ca.uhn.fhir.model.dstu2.resource.DeviceComponent +resource.DeviceMetric=ca.uhn.fhir.model.dstu2.resource.DeviceMetric +resource.DeviceUseRequest=ca.uhn.fhir.model.dstu2.resource.DeviceUseRequest +resource.DeviceUseStatement=ca.uhn.fhir.model.dstu2.resource.DeviceUseStatement +resource.DiagnosticOrder=ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder +resource.DiagnosticReport=ca.uhn.fhir.model.dstu2.resource.DiagnosticReport +resource.DocumentManifest=ca.uhn.fhir.model.dstu2.resource.DocumentManifest +resource.DocumentReference=ca.uhn.fhir.model.dstu2.resource.DocumentReference +resource.Documentation=ca.uhn.fhir.model.dstu2.resource.Documentation +resource.EligibilityRequest=ca.uhn.fhir.model.dstu2.resource.EligibilityRequest +resource.EligibilityResponse=ca.uhn.fhir.model.dstu2.resource.EligibilityResponse +resource.Encounter=ca.uhn.fhir.model.dstu2.resource.Encounter +resource.EnrollmentRequest=ca.uhn.fhir.model.dstu2.resource.EnrollmentRequest +resource.EnrollmentResponse=ca.uhn.fhir.model.dstu2.resource.EnrollmentResponse +resource.EpisodeOfCare=ca.uhn.fhir.model.dstu2.resource.EpisodeOfCare +resource.ExplanationOfBenefit=ca.uhn.fhir.model.dstu2.resource.ExplanationOfBenefit +resource.FamilyMemberHistory=ca.uhn.fhir.model.dstu2.resource.FamilyMemberHistory +resource.Flag=ca.uhn.fhir.model.dstu2.resource.Flag +resource.Goal=ca.uhn.fhir.model.dstu2.resource.Goal +resource.Group=ca.uhn.fhir.model.dstu2.resource.Group +resource.HealthcareService=ca.uhn.fhir.model.dstu2.resource.HealthcareService +resource.ImagingObjectSelection=ca.uhn.fhir.model.dstu2.resource.ImagingObjectSelection +resource.ImagingStudy=ca.uhn.fhir.model.dstu2.resource.ImagingStudy +resource.Immunization=ca.uhn.fhir.model.dstu2.resource.Immunization +resource.ImmunizationRecommendation=ca.uhn.fhir.model.dstu2.resource.ImmunizationRecommendation +resource.ImplementationGuide=ca.uhn.fhir.model.dstu2.resource.ImplementationGuide +resource.List=ca.uhn.fhir.model.dstu2.resource.ListResource +resource.Location=ca.uhn.fhir.model.dstu2.resource.Location +resource.Media=ca.uhn.fhir.model.dstu2.resource.Media +resource.Medication=ca.uhn.fhir.model.dstu2.resource.Medication +resource.MedicationAdministration=ca.uhn.fhir.model.dstu2.resource.MedicationAdministration +resource.MedicationDispense=ca.uhn.fhir.model.dstu2.resource.MedicationDispense +resource.MedicationOrder=ca.uhn.fhir.model.dstu2.resource.MedicationOrder +resource.MedicationStatement=ca.uhn.fhir.model.dstu2.resource.MedicationStatement +resource.MessageHeader=ca.uhn.fhir.model.dstu2.resource.MessageHeader +resource.NamingSystem=ca.uhn.fhir.model.dstu2.resource.NamingSystem +resource.NutritionOrder=ca.uhn.fhir.model.dstu2.resource.NutritionOrder +resource.Observation=ca.uhn.fhir.model.dstu2.resource.Observation +resource.OperationDefinition=ca.uhn.fhir.model.dstu2.resource.OperationDefinition +resource.OperationOutcome=ca.uhn.fhir.model.dstu2.resource.OperationOutcome +resource.Order=ca.uhn.fhir.model.dstu2.resource.Order +resource.OrderResponse=ca.uhn.fhir.model.dstu2.resource.OrderResponse +resource.Organization=ca.uhn.fhir.model.dstu2.resource.Organization +resource.Parameters=ca.uhn.fhir.model.dstu2.resource.Parameters +resource.Patient=ca.uhn.fhir.model.dstu2.resource.Patient +resource.PaymentNotice=ca.uhn.fhir.model.dstu2.resource.PaymentNotice +resource.PaymentReconciliation=ca.uhn.fhir.model.dstu2.resource.PaymentReconciliation +resource.Person=ca.uhn.fhir.model.dstu2.resource.Person +resource.Practitioner=ca.uhn.fhir.model.dstu2.resource.Practitioner +resource.Procedure=ca.uhn.fhir.model.dstu2.resource.Procedure +resource.ProcedureRequest=ca.uhn.fhir.model.dstu2.resource.ProcedureRequest +resource.ProcessRequest=ca.uhn.fhir.model.dstu2.resource.ProcessRequest +resource.ProcessResponse=ca.uhn.fhir.model.dstu2.resource.ProcessResponse +resource.Provenance=ca.uhn.fhir.model.dstu2.resource.Provenance +resource.Questionnaire=ca.uhn.fhir.model.dstu2.resource.Questionnaire +resource.QuestionnaireResponse=ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse +resource.ReferralRequest=ca.uhn.fhir.model.dstu2.resource.ReferralRequest +resource.RelatedPerson=ca.uhn.fhir.model.dstu2.resource.RelatedPerson +resource.Remittance=ca.uhn.fhir.model.dstu2.resource.Remittance +resource.RiskAssessment=ca.uhn.fhir.model.dstu2.resource.RiskAssessment +resource.Schedule=ca.uhn.fhir.model.dstu2.resource.Schedule +resource.SearchParameter=ca.uhn.fhir.model.dstu2.resource.SearchParameter +resource.Slot=ca.uhn.fhir.model.dstu2.resource.Slot +resource.Specimen=ca.uhn.fhir.model.dstu2.resource.Specimen +resource.StructureDefinition=ca.uhn.fhir.model.dstu2.resource.StructureDefinition +resource.Subscription=ca.uhn.fhir.model.dstu2.resource.Subscription +resource.Substance=ca.uhn.fhir.model.dstu2.resource.Substance +resource.SupplyDelivery=ca.uhn.fhir.model.dstu2.resource.SupplyDelivery +resource.SupplyRequest=ca.uhn.fhir.model.dstu2.resource.SupplyRequest +resource.SupportingDocumentation=ca.uhn.fhir.model.dstu2.resource.SupportingDocumentation +resource.Test=ca.uhn.fhir.model.dstu2.resource.Test +resource.TestScript=ca.uhn.fhir.model.dstu2.resource.TestScript +resource.User=ca.uhn.fhir.model.dstu2.resource.User +resource.ValueSet=ca.uhn.fhir.model.dstu2.resource.ValueSet +resource.VisionPrescription=ca.uhn.fhir.model.dstu2.resource.VisionPrescription + +datatype.Address=ca.uhn.fhir.model.dstu2.composite.AddressDt +datatype.AddressDt=ca.uhn.fhir.model.dstu2.composite.AddressDt +datatype.AgeDt=ca.uhn.fhir.model.dstu2.composite.AgeDt +datatype.Annotation=ca.uhn.fhir.model.dstu2.composite.AnnotationDt +datatype.AnnotationDt=ca.uhn.fhir.model.dstu2.composite.AnnotationDt +datatype.Attachment=ca.uhn.fhir.model.dstu2.composite.AttachmentDt +datatype.AttachmentDt=ca.uhn.fhir.model.dstu2.composite.AttachmentDt +datatype.CodeableConcept=ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt +datatype.CodeableConceptDt=ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt +datatype.Coding=ca.uhn.fhir.model.dstu2.composite.CodingDt +datatype.CodingDt=ca.uhn.fhir.model.dstu2.composite.CodingDt +datatype.ContactPoint=ca.uhn.fhir.model.dstu2.composite.ContactPointDt +datatype.ContactPointDt=ca.uhn.fhir.model.dstu2.composite.ContactPointDt +datatype.CountDt=ca.uhn.fhir.model.dstu2.composite.CountDt +datatype.DistanceDt=ca.uhn.fhir.model.dstu2.composite.DistanceDt +datatype.DurationDt=ca.uhn.fhir.model.dstu2.composite.DurationDt +datatype.ElementDefinition=ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt +datatype.ElementDefinitionDt=ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt +datatype.Extension=ca.uhn.fhir.model.api.ExtensionDt +datatype.HumanName=ca.uhn.fhir.model.dstu2.composite.HumanNameDt +datatype.HumanNameDt=ca.uhn.fhir.model.dstu2.composite.HumanNameDt +datatype.Identifier=ca.uhn.fhir.model.dstu2.composite.IdentifierDt +datatype.IdentifierDt=ca.uhn.fhir.model.dstu2.composite.IdentifierDt +datatype.Meta=ca.uhn.fhir.model.dstu2.composite.MetaDt +datatype.MetaDt=ca.uhn.fhir.model.dstu2.composite.MetaDt +datatype.Money=ca.uhn.fhir.model.dstu2.composite.MoneyDt +datatype.Narrative=ca.uhn.fhir.model.dstu2.composite.NarrativeDt +datatype.Period=ca.uhn.fhir.model.dstu2.composite.PeriodDt +datatype.PeriodDt=ca.uhn.fhir.model.dstu2.composite.PeriodDt +datatype.Quantity=ca.uhn.fhir.model.dstu2.composite.QuantityDt +datatype.QuantityDt=ca.uhn.fhir.model.dstu2.composite.QuantityDt +datatype.Range=ca.uhn.fhir.model.dstu2.composite.RangeDt +datatype.RangeDt=ca.uhn.fhir.model.dstu2.composite.RangeDt +datatype.Ratio=ca.uhn.fhir.model.dstu2.composite.RatioDt +datatype.RatioDt=ca.uhn.fhir.model.dstu2.composite.RatioDt +datatype.ResourceReferenceDt=ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt +datatype.SampledData=ca.uhn.fhir.model.dstu2.composite.SampledDataDt +datatype.SampledDataDt=ca.uhn.fhir.model.dstu2.composite.SampledDataDt +datatype.Signature=ca.uhn.fhir.model.dstu2.composite.SignatureDt +datatype.SignatureDt=ca.uhn.fhir.model.dstu2.composite.SignatureDt +datatype.SimpleQuantity=ca.uhn.fhir.model.dstu2.composite.SimpleQuantityDt +datatype.Timing=ca.uhn.fhir.model.dstu2.composite.TimingDt +datatype.TimingDt=ca.uhn.fhir.model.dstu2.composite.TimingDt +datatype.base64Binary=ca.uhn.fhir.model.primitive.Base64BinaryDt +datatype.boolean=ca.uhn.fhir.model.primitive.BooleanDt +datatype.code=ca.uhn.fhir.model.primitive.CodeDt +datatype.contained=ca.uhn.fhir.model.dstu2.composite.ContainedDt +datatype.date=ca.uhn.fhir.model.primitive.DateDt +datatype.dateTime=ca.uhn.fhir.model.primitive.DateTimeDt +datatype.decimal=ca.uhn.fhir.model.primitive.DecimalDt +datatype.id=ca.uhn.fhir.model.primitive.IdDt +datatype.idref=ca.uhn.fhir.model.primitive.IdrefDt +datatype.instant=ca.uhn.fhir.model.primitive.InstantDt +datatype.integer=ca.uhn.fhir.model.primitive.IntegerDt +datatype.markdown=ca.uhn.fhir.model.primitive.MarkdownDt +datatype.oid=ca.uhn.fhir.model.primitive.OidDt +datatype.positiveInt=ca.uhn.fhir.model.primitive.PositiveIntDt +datatype.string=ca.uhn.fhir.model.primitive.StringDt +datatype.time=ca.uhn.fhir.model.primitive.TimeDt +datatype.unsignedInt=ca.uhn.fhir.model.primitive.UnsignedIntDt +datatype.uri=ca.uhn.fhir.model.primitive.UriDt +datatype.xhtml=ca.uhn.fhir.model.primitive.XhtmlDt diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/parser/BaseStructureParser.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/parser/BaseStructureParser.java index bbacb56b7e7..62cb3440eb5 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/parser/BaseStructureParser.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/parser/BaseStructureParser.java @@ -560,6 +560,7 @@ public abstract class BaseStructureParser { // Binary is manually generated but should still go in the list myNameToResourceClass.put("Binary", thePackageBase + ".resource.Binary"); + myNameToDatatypeClass.put("Extension", ExtensionDt.class.getName()); try { File versionFile = new File(theResourceOutputDirectory, "fhirversion.properties"); diff --git a/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu/fhirversion.properties b/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu/fhirversion.properties index f40f346b576..a38fb447505 100644 --- a/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu/fhirversion.properties +++ b/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu/fhirversion.properties @@ -65,21 +65,40 @@ resource.User=ca.uhn.fhir.model.dstu.resource.User resource.ValueSet=ca.uhn.fhir.model.dstu.resource.ValueSet datatype.Address=ca.uhn.fhir.model.dstu.composite.AddressDt +datatype.AddressDt=ca.uhn.fhir.model.dstu.composite.AddressDt +datatype.AgeDt=ca.uhn.fhir.model.dstu.composite.AgeDt datatype.Attachment=ca.uhn.fhir.model.dstu.composite.AttachmentDt +datatype.AttachmentDt=ca.uhn.fhir.model.dstu.composite.AttachmentDt datatype.CodeableConcept=ca.uhn.fhir.model.dstu.composite.CodeableConceptDt +datatype.CodeableConceptDt=ca.uhn.fhir.model.dstu.composite.CodeableConceptDt datatype.Coding=ca.uhn.fhir.model.dstu.composite.CodingDt +datatype.CodingDt=ca.uhn.fhir.model.dstu.composite.CodingDt datatype.Contact=ca.uhn.fhir.model.dstu.composite.ContactDt +datatype.ContactDt=ca.uhn.fhir.model.dstu.composite.ContactDt +datatype.Duration=ca.uhn.fhir.model.dstu.composite.DurationDt +datatype.Extension=ca.uhn.fhir.model.api.ExtensionDt datatype.HumanName=ca.uhn.fhir.model.dstu.composite.HumanNameDt +datatype.HumanNameDt=ca.uhn.fhir.model.dstu.composite.HumanNameDt datatype.Identifier=ca.uhn.fhir.model.dstu.composite.IdentifierDt +datatype.IdentifierDt=ca.uhn.fhir.model.dstu.composite.IdentifierDt +datatype.Narrative=ca.uhn.fhir.model.dstu.composite.NarrativeDt datatype.Period=ca.uhn.fhir.model.dstu.composite.PeriodDt +datatype.PeriodDt=ca.uhn.fhir.model.dstu.composite.PeriodDt datatype.Quantity=ca.uhn.fhir.model.dstu.composite.QuantityDt +datatype.QuantityDt=ca.uhn.fhir.model.dstu.composite.QuantityDt datatype.Range=ca.uhn.fhir.model.dstu.composite.RangeDt +datatype.RangeDt=ca.uhn.fhir.model.dstu.composite.RangeDt datatype.Ratio=ca.uhn.fhir.model.dstu.composite.RatioDt +datatype.RatioDt=ca.uhn.fhir.model.dstu.composite.RatioDt +datatype.ResourceReferenceDt=ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt datatype.SampledData=ca.uhn.fhir.model.dstu.composite.SampledDataDt +datatype.SampledDataDt=ca.uhn.fhir.model.dstu.composite.SampledDataDt datatype.Schedule=ca.uhn.fhir.model.dstu.composite.ScheduleDt +datatype.ScheduleDt=ca.uhn.fhir.model.dstu.composite.ScheduleDt datatype.base64Binary=ca.uhn.fhir.model.primitive.Base64BinaryDt datatype.boolean=ca.uhn.fhir.model.primitive.BooleanDt datatype.code=ca.uhn.fhir.model.primitive.CodeDt +datatype.contained=ca.uhn.fhir.model.dstu.composite.ContainedDt datatype.date=ca.uhn.fhir.model.primitive.DateDt datatype.dateTime=ca.uhn.fhir.model.primitive.DateTimeDt datatype.decimal=ca.uhn.fhir.model.primitive.DecimalDt @@ -87,8 +106,11 @@ datatype.id=ca.uhn.fhir.model.primitive.IdDt datatype.idref=ca.uhn.fhir.model.primitive.IdrefDt datatype.instant=ca.uhn.fhir.model.primitive.InstantDt datatype.integer=ca.uhn.fhir.model.primitive.IntegerDt +datatype.markdown=ca.uhn.fhir.model.primitive.MarkdownDt datatype.oid=ca.uhn.fhir.model.primitive.OidDt +datatype.positiveInt=ca.uhn.fhir.model.primitive.PositiveIntDt datatype.string=ca.uhn.fhir.model.primitive.StringDt datatype.time=ca.uhn.fhir.model.primitive.TimeDt +datatype.unsignedInt=ca.uhn.fhir.model.primitive.UnsignedIntDt datatype.uri=ca.uhn.fhir.model.primitive.UriDt datatype.xhtml=ca.uhn.fhir.model.primitive.XhtmlDt diff --git a/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu2/fhirversion.properties b/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu2/fhirversion.properties new file mode 100644 index 00000000000..f9c235c15b4 --- /dev/null +++ b/hapi-tinder-plugin/src/main/resources/ca/uhn/fhir/model/dstu2/fhirversion.properties @@ -0,0 +1,164 @@ +# This file contains version definitions + +resource.Account=ca.uhn.fhir.model.dstu2.resource.Account +resource.AllergyIntolerance=ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance +resource.Appointment=ca.uhn.fhir.model.dstu2.resource.Appointment +resource.AppointmentResponse=ca.uhn.fhir.model.dstu2.resource.AppointmentResponse +resource.AuditEvent=ca.uhn.fhir.model.dstu2.resource.AuditEvent +resource.Basic=ca.uhn.fhir.model.dstu2.resource.Basic +resource.Binary=ca.uhn.fhir.model.dstu2.resource.Binary +resource.BodySite=ca.uhn.fhir.model.dstu2.resource.BodySite +resource.Bundle=ca.uhn.fhir.model.dstu2.resource.Bundle +resource.CarePlan=ca.uhn.fhir.model.dstu2.resource.CarePlan +resource.Claim=ca.uhn.fhir.model.dstu2.resource.Claim +resource.ClaimResponse=ca.uhn.fhir.model.dstu2.resource.ClaimResponse +resource.ClinicalImpression=ca.uhn.fhir.model.dstu2.resource.ClinicalImpression +resource.Communication=ca.uhn.fhir.model.dstu2.resource.Communication +resource.CommunicationRequest=ca.uhn.fhir.model.dstu2.resource.CommunicationRequest +resource.Composition=ca.uhn.fhir.model.dstu2.resource.Composition +resource.ConceptMap=ca.uhn.fhir.model.dstu2.resource.ConceptMap +resource.Condition=ca.uhn.fhir.model.dstu2.resource.Condition +resource.Conformance=ca.uhn.fhir.model.dstu2.resource.Conformance +resource.Contract=ca.uhn.fhir.model.dstu2.resource.Contract +resource.Coverage=ca.uhn.fhir.model.dstu2.resource.Coverage +resource.DataElement=ca.uhn.fhir.model.dstu2.resource.DataElement +resource.DetectedIssue=ca.uhn.fhir.model.dstu2.resource.DetectedIssue +resource.Device=ca.uhn.fhir.model.dstu2.resource.Device +resource.DeviceComponent=ca.uhn.fhir.model.dstu2.resource.DeviceComponent +resource.DeviceMetric=ca.uhn.fhir.model.dstu2.resource.DeviceMetric +resource.DeviceUseRequest=ca.uhn.fhir.model.dstu2.resource.DeviceUseRequest +resource.DeviceUseStatement=ca.uhn.fhir.model.dstu2.resource.DeviceUseStatement +resource.DiagnosticOrder=ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder +resource.DiagnosticReport=ca.uhn.fhir.model.dstu2.resource.DiagnosticReport +resource.DocumentManifest=ca.uhn.fhir.model.dstu2.resource.DocumentManifest +resource.DocumentReference=ca.uhn.fhir.model.dstu2.resource.DocumentReference +resource.Documentation=ca.uhn.fhir.model.dstu2.resource.Documentation +resource.EligibilityRequest=ca.uhn.fhir.model.dstu2.resource.EligibilityRequest +resource.EligibilityResponse=ca.uhn.fhir.model.dstu2.resource.EligibilityResponse +resource.Encounter=ca.uhn.fhir.model.dstu2.resource.Encounter +resource.EnrollmentRequest=ca.uhn.fhir.model.dstu2.resource.EnrollmentRequest +resource.EnrollmentResponse=ca.uhn.fhir.model.dstu2.resource.EnrollmentResponse +resource.EpisodeOfCare=ca.uhn.fhir.model.dstu2.resource.EpisodeOfCare +resource.ExplanationOfBenefit=ca.uhn.fhir.model.dstu2.resource.ExplanationOfBenefit +resource.FamilyMemberHistory=ca.uhn.fhir.model.dstu2.resource.FamilyMemberHistory +resource.Flag=ca.uhn.fhir.model.dstu2.resource.Flag +resource.Goal=ca.uhn.fhir.model.dstu2.resource.Goal +resource.Group=ca.uhn.fhir.model.dstu2.resource.Group +resource.HealthcareService=ca.uhn.fhir.model.dstu2.resource.HealthcareService +resource.ImagingObjectSelection=ca.uhn.fhir.model.dstu2.resource.ImagingObjectSelection +resource.ImagingStudy=ca.uhn.fhir.model.dstu2.resource.ImagingStudy +resource.Immunization=ca.uhn.fhir.model.dstu2.resource.Immunization +resource.ImmunizationRecommendation=ca.uhn.fhir.model.dstu2.resource.ImmunizationRecommendation +resource.ImplementationGuide=ca.uhn.fhir.model.dstu2.resource.ImplementationGuide +resource.List=ca.uhn.fhir.model.dstu2.resource.ListResource +resource.Location=ca.uhn.fhir.model.dstu2.resource.Location +resource.Media=ca.uhn.fhir.model.dstu2.resource.Media +resource.Medication=ca.uhn.fhir.model.dstu2.resource.Medication +resource.MedicationAdministration=ca.uhn.fhir.model.dstu2.resource.MedicationAdministration +resource.MedicationDispense=ca.uhn.fhir.model.dstu2.resource.MedicationDispense +resource.MedicationOrder=ca.uhn.fhir.model.dstu2.resource.MedicationOrder +resource.MedicationStatement=ca.uhn.fhir.model.dstu2.resource.MedicationStatement +resource.MessageHeader=ca.uhn.fhir.model.dstu2.resource.MessageHeader +resource.NamingSystem=ca.uhn.fhir.model.dstu2.resource.NamingSystem +resource.NutritionOrder=ca.uhn.fhir.model.dstu2.resource.NutritionOrder +resource.Observation=ca.uhn.fhir.model.dstu2.resource.Observation +resource.OperationDefinition=ca.uhn.fhir.model.dstu2.resource.OperationDefinition +resource.OperationOutcome=ca.uhn.fhir.model.dstu2.resource.OperationOutcome +resource.Order=ca.uhn.fhir.model.dstu2.resource.Order +resource.OrderResponse=ca.uhn.fhir.model.dstu2.resource.OrderResponse +resource.Organization=ca.uhn.fhir.model.dstu2.resource.Organization +resource.Parameters=ca.uhn.fhir.model.dstu2.resource.Parameters +resource.Patient=ca.uhn.fhir.model.dstu2.resource.Patient +resource.PaymentNotice=ca.uhn.fhir.model.dstu2.resource.PaymentNotice +resource.PaymentReconciliation=ca.uhn.fhir.model.dstu2.resource.PaymentReconciliation +resource.Person=ca.uhn.fhir.model.dstu2.resource.Person +resource.Practitioner=ca.uhn.fhir.model.dstu2.resource.Practitioner +resource.Procedure=ca.uhn.fhir.model.dstu2.resource.Procedure +resource.ProcedureRequest=ca.uhn.fhir.model.dstu2.resource.ProcedureRequest +resource.ProcessRequest=ca.uhn.fhir.model.dstu2.resource.ProcessRequest +resource.ProcessResponse=ca.uhn.fhir.model.dstu2.resource.ProcessResponse +resource.Provenance=ca.uhn.fhir.model.dstu2.resource.Provenance +resource.Questionnaire=ca.uhn.fhir.model.dstu2.resource.Questionnaire +resource.QuestionnaireResponse=ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse +resource.ReferralRequest=ca.uhn.fhir.model.dstu2.resource.ReferralRequest +resource.RelatedPerson=ca.uhn.fhir.model.dstu2.resource.RelatedPerson +resource.Remittance=ca.uhn.fhir.model.dstu2.resource.Remittance +resource.RiskAssessment=ca.uhn.fhir.model.dstu2.resource.RiskAssessment +resource.Schedule=ca.uhn.fhir.model.dstu2.resource.Schedule +resource.SearchParameter=ca.uhn.fhir.model.dstu2.resource.SearchParameter +resource.Slot=ca.uhn.fhir.model.dstu2.resource.Slot +resource.Specimen=ca.uhn.fhir.model.dstu2.resource.Specimen +resource.StructureDefinition=ca.uhn.fhir.model.dstu2.resource.StructureDefinition +resource.Subscription=ca.uhn.fhir.model.dstu2.resource.Subscription +resource.Substance=ca.uhn.fhir.model.dstu2.resource.Substance +resource.SupplyDelivery=ca.uhn.fhir.model.dstu2.resource.SupplyDelivery +resource.SupplyRequest=ca.uhn.fhir.model.dstu2.resource.SupplyRequest +resource.SupportingDocumentation=ca.uhn.fhir.model.dstu2.resource.SupportingDocumentation +resource.Test=ca.uhn.fhir.model.dstu2.resource.Test +resource.TestScript=ca.uhn.fhir.model.dstu2.resource.TestScript +resource.User=ca.uhn.fhir.model.dstu2.resource.User +resource.ValueSet=ca.uhn.fhir.model.dstu2.resource.ValueSet +resource.VisionPrescription=ca.uhn.fhir.model.dstu2.resource.VisionPrescription + +datatype.Address=ca.uhn.fhir.model.dstu2.composite.AddressDt +datatype.AddressDt=ca.uhn.fhir.model.dstu2.composite.AddressDt +datatype.AgeDt=ca.uhn.fhir.model.dstu2.composite.AgeDt +datatype.Annotation=ca.uhn.fhir.model.dstu2.composite.AnnotationDt +datatype.AnnotationDt=ca.uhn.fhir.model.dstu2.composite.AnnotationDt +datatype.Attachment=ca.uhn.fhir.model.dstu2.composite.AttachmentDt +datatype.AttachmentDt=ca.uhn.fhir.model.dstu2.composite.AttachmentDt +datatype.CodeableConcept=ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt +datatype.CodeableConceptDt=ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt +datatype.Coding=ca.uhn.fhir.model.dstu2.composite.CodingDt +datatype.CodingDt=ca.uhn.fhir.model.dstu2.composite.CodingDt +datatype.ContactPoint=ca.uhn.fhir.model.dstu2.composite.ContactPointDt +datatype.ContactPointDt=ca.uhn.fhir.model.dstu2.composite.ContactPointDt +datatype.CountDt=ca.uhn.fhir.model.dstu2.composite.CountDt +datatype.DistanceDt=ca.uhn.fhir.model.dstu2.composite.DistanceDt +datatype.DurationDt=ca.uhn.fhir.model.dstu2.composite.DurationDt +datatype.ElementDefinition=ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt +datatype.ElementDefinitionDt=ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt +datatype.Extension=ca.uhn.fhir.model.api.ExtensionDt +datatype.HumanName=ca.uhn.fhir.model.dstu2.composite.HumanNameDt +datatype.HumanNameDt=ca.uhn.fhir.model.dstu2.composite.HumanNameDt +datatype.Identifier=ca.uhn.fhir.model.dstu2.composite.IdentifierDt +datatype.IdentifierDt=ca.uhn.fhir.model.dstu2.composite.IdentifierDt +datatype.Meta=ca.uhn.fhir.model.dstu2.composite.MetaDt +datatype.MetaDt=ca.uhn.fhir.model.dstu2.composite.MetaDt +datatype.Money=ca.uhn.fhir.model.dstu2.composite.MoneyDt +datatype.Narrative=ca.uhn.fhir.model.dstu2.composite.NarrativeDt +datatype.Period=ca.uhn.fhir.model.dstu2.composite.PeriodDt +datatype.PeriodDt=ca.uhn.fhir.model.dstu2.composite.PeriodDt +datatype.Quantity=ca.uhn.fhir.model.dstu2.composite.QuantityDt +datatype.QuantityDt=ca.uhn.fhir.model.dstu2.composite.QuantityDt +datatype.Range=ca.uhn.fhir.model.dstu2.composite.RangeDt +datatype.RangeDt=ca.uhn.fhir.model.dstu2.composite.RangeDt +datatype.Ratio=ca.uhn.fhir.model.dstu2.composite.RatioDt +datatype.RatioDt=ca.uhn.fhir.model.dstu2.composite.RatioDt +datatype.ResourceReferenceDt=ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt +datatype.SampledData=ca.uhn.fhir.model.dstu2.composite.SampledDataDt +datatype.SampledDataDt=ca.uhn.fhir.model.dstu2.composite.SampledDataDt +datatype.Signature=ca.uhn.fhir.model.dstu2.composite.SignatureDt +datatype.SignatureDt=ca.uhn.fhir.model.dstu2.composite.SignatureDt +datatype.SimpleQuantity=ca.uhn.fhir.model.dstu2.composite.SimpleQuantityDt +datatype.Timing=ca.uhn.fhir.model.dstu2.composite.TimingDt +datatype.TimingDt=ca.uhn.fhir.model.dstu2.composite.TimingDt +datatype.base64Binary=ca.uhn.fhir.model.primitive.Base64BinaryDt +datatype.boolean=ca.uhn.fhir.model.primitive.BooleanDt +datatype.code=ca.uhn.fhir.model.primitive.CodeDt +datatype.contained=ca.uhn.fhir.model.dstu2.composite.ContainedDt +datatype.date=ca.uhn.fhir.model.primitive.DateDt +datatype.dateTime=ca.uhn.fhir.model.primitive.DateTimeDt +datatype.decimal=ca.uhn.fhir.model.primitive.DecimalDt +datatype.id=ca.uhn.fhir.model.primitive.IdDt +datatype.idref=ca.uhn.fhir.model.primitive.IdrefDt +datatype.instant=ca.uhn.fhir.model.primitive.InstantDt +datatype.integer=ca.uhn.fhir.model.primitive.IntegerDt +datatype.markdown=ca.uhn.fhir.model.primitive.MarkdownDt +datatype.oid=ca.uhn.fhir.model.primitive.OidDt +datatype.positiveInt=ca.uhn.fhir.model.primitive.PositiveIntDt +datatype.string=ca.uhn.fhir.model.primitive.StringDt +datatype.time=ca.uhn.fhir.model.primitive.TimeDt +datatype.unsignedInt=ca.uhn.fhir.model.primitive.UnsignedIntDt +datatype.uri=ca.uhn.fhir.model.primitive.UriDt +datatype.xhtml=ca.uhn.fhir.model.primitive.XhtmlDt diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 13a35d81460..514e525297b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -403,6 +403,15 @@ which enables finding resources that to not have a given tag/profile/security tag. Thanks to Lars Kristian Roland for the suggestion! + + Extensions containing resource references did not get encoded correctly + some of the time. Thanks to Poseidon for reporting! + + + Parsers (both XML and JSON) encoded the first few elements of DSTU3 structures in the wrong order: + Extensions were placed before any other content, which is incorrect (several + elements come first: meta, text, etc.) +