Get extensions working for HL7.org structures

This commit is contained in:
James Agnew 2015-02-20 17:34:13 -05:00
parent cf3a78ecd2
commit 0f01260301
53 changed files with 1254 additions and 531 deletions

View File

@ -8,6 +8,7 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
@ -36,6 +37,7 @@ public class PlainProvider {
//START SNIPPET: plainProviderServer
public class ExampleServlet extends RestfulServer {
/** Constructor */
public ExampleServlet() {
/*
* Plain providers are passed to the server in the same way
@ -54,5 +56,23 @@ public class ExampleServlet extends RestfulServer {
}
//END SNIPPET: plainProviderServer
//START SNIPPET: addressStrategy
public class MyServlet extends RestfulServer {
/** Constructor */
public MyServlet() {
String serverBaseUrl = "http://foo.com/fhir";
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverBaseUrl));
// ...add some resource providers, etc...
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
setResourceProviders(resourceProviders);
}
}
//END SNIPPET: addressStrategy
}

View File

@ -12,6 +12,7 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.IResourceProvider;
@SuppressWarnings("null")
//START SNIPPET: provider
public class PagingPatientProvider implements IResourceProvider {
@ -21,11 +22,22 @@ public class PagingPatientProvider implements IResourceProvider {
@Search
public IBundleProvider search(@RequiredParam(name = Patient.SP_FAMILY) StringParam theFamily) {
final InstantDt searchTime = InstantDt.withCurrentTime();
final List<String> matchingResourceIds = findIdsByFamily(theFamily);
/*
* First, we'll search the database for a set of database row IDs that
* match the given search criteria. That way we can keep just the
* row IDs around, and load the actual resources on demand later
* as the client pages through them.
*/
final List<Long> matchingResourceIds = null; // <-- implement this
/*
* Return a bundle provider which can page through the IDs and
* return the resources that go with them.
*/
return new IBundleProvider() {
@Override
@Override
public int size() {
return matchingResourceIds.size();
}
@ -33,7 +45,7 @@ public class PagingPatientProvider implements IResourceProvider {
@Override
public List<IResource> getResources(int theFromIndex, int theToIndex) {
int end = Math.max(theToIndex, matchingResourceIds.size() - 1);
List<String> idsToReturn = matchingResourceIds.subList(theFromIndex, end);
List<Long> idsToReturn = matchingResourceIds.subList(theFromIndex, end);
return loadResourcesByIds(idsToReturn);
}
@ -44,18 +56,10 @@ public class PagingPatientProvider implements IResourceProvider {
};
}
/**
* Get a list of resource IDs which match a given family name
*/
private List<String> findIdsByFamily(StringParam theFamily) {
// .. implement this search against the database ..
return null;
}
/**
* Load a list of patient resources given their IDs
*/
private List<IResource> loadResourcesByIds(List<String> theFamily) {
private List<IResource> loadResourcesByIds(List<Long> theIdsToReturn) {
// .. implement this search against the database ..
return null;
}

View File

@ -195,69 +195,6 @@
</plugins>
</reporting>
</profile>
<profile>
<id>ANDROID</id>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>0.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-android</artifactId>
<version>${slf4j_version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<artifactSet>
<includes>
<!--
<include>javax.json:javax.json-api</include>
-->
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
<include>org.glassfish:javax.json</include>
<include>org.codehaus.woodstox:woodstox-core-asl</include>
<include>javax.xml.stream:stax-api</include>
<include>org.codehaus.woodstox:stax2-api</include>
<include>org.slf4j:slf4j*</include>
<include>org.apache.commons:*</include>
<include>org.apache.httpcomponents:*</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>javax.xml.stream</pattern>
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
</relocation>
<relocation>
<pattern>javax.json</pattern>
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.context;
*/
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@ -28,7 +29,6 @@ import java.util.Set;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.ICodeEnum;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
@ -41,7 +41,7 @@ public abstract class BaseRuntimeChildDatatypeDefinition extends BaseRuntimeDecl
public BaseRuntimeChildDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype) {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
assert theDatatype != IDatatype.class; // should use RuntimeChildAny
assert Modifier.isInterface(theDatatype.getModifiers()) == false : "Type of " + theDatatype + " shouldn't be here"; // should use RuntimeChildAny
myDatatype = theDatatype;
}

View File

@ -45,9 +45,6 @@ public abstract class BaseRuntimeElementCompositeDefinition<T extends IBase> ext
if (theNext == null) {
throw new NullPointerException();
}
// if (theNext.getValidChildNames().contains("performetPractitioner")) {
// throw new NullPointerException();
// }
if (theNext.getExtensionUrl() != null) {
throw new IllegalArgumentException("Shouldn't haven an extension URL, use addExtension instead");
}

View File

@ -29,6 +29,7 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
@ -102,8 +103,10 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
try {
if (theArgument == null) {
return getImplementingClass().newInstance();
} else {
} else if (theArgument instanceof IValueSetEnumBinder) {
return getImplementingClass().getConstructor(IValueSetEnumBinder.class).newInstance(theArgument);
}else {
return getImplementingClass().getConstructor(IBaseEnumFactory.class).newInstance(theArgument);
}
} catch (InstantiationException e) {
throw new ConfigurationException("Failed to instantiate type:" + getImplementingClass().getName(), e);

View File

@ -55,6 +55,7 @@ import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IDatatypeElement;
import org.hl7.fhir.instance.model.api.IDomainResource;
@ -555,7 +556,7 @@ class ModelScanner {
RuntimeChildResourceBlockDefinition def = new RuntimeChildResourceBlockDefinition(next, childAnnotation, descriptionAnnotation, elementName, blockDef);
orderMap.put(order, def);
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "org.hl7.fhir.instance.model.Type".equals(nextElementType.getName())) {
} else if (IDatatype.class.equals(nextElementType) || IElement.class.equals(nextElementType) || "org.hl7.fhir.instance.model.Type".equals(nextElementType.getName()) || IBaseDatatype.class.equals(nextElementType)) {
RuntimeChildAny def = new RuntimeChildAny(next, elementName, childAnnotation, descriptionAnnotation);
orderMap.put(order, def);
@ -565,10 +566,13 @@ class ModelScanner {
addScanAlso(nextDatatype);
BaseRuntimeChildDatatypeDefinition def;
if (IPrimitiveDatatype.class.isAssignableFrom(nextElementType)) {
if (IPrimitiveType.class.isAssignableFrom(nextElementType)) {
if (nextElementType.equals(BoundCodeDt.class)) {
IValueSetEnumBinder<Enum<?>> binder = getBoundCodeBinder(next);
def = new RuntimeChildPrimitiveBoundCodeDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binder);
} else if (childAnnotation.enumFactory().getSimpleName().equals("NoEnumFactory") == false) {
Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory();
def = new RuntimeChildEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, enumFactory);
} else {
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
}

View File

@ -0,0 +1,58 @@
package ca.uhn.fhir.context;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.lang.reflect.Field;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildEnumerationDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
private Class<? extends IBaseEnumFactory<?>> myBinderType;
private volatile IBaseEnumFactory<?> myBinder;
public RuntimeChildEnumerationDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype, Class<? extends IBaseEnumFactory<?>> theBinderType) {
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
myBinderType = theBinderType;
}
@Override
public IBaseEnumFactory<?> getInstanceConstructorArguments() {
IBaseEnumFactory<?> retVal = myBinder;
if (retVal == null) {
try {
retVal = myBinderType.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
}
myBinder = retVal;
}
return retVal;
}
}

View File

@ -32,5 +32,7 @@ public class RuntimeChildPrimitiveDatatypeDefinition extends BaseRuntimeChildDat
public RuntimeChildPrimitiveDatatypeDefinition(Field theField, String theElementName, Description theDescriptionAnnotation, Child theChildAnnotation, Class<? extends IBase> theDatatype) {
super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation, theDatatype);
}
}

View File

@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
public abstract class BaseElement implements IElement, ISupportsUndeclaredExtensions {
@ -32,7 +33,7 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
private List<ExtensionDt> myUndeclaredModifierExtensions;
@Override
public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IDatatype theValue) {
public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
Validate.notEmpty(theUrl, "URL must be populated");
Validate.notNull(theValue, "Value must not be null");
ExtensionDt retVal = new ExtensionDt(theIsModifier, theUrl, theValue);

View File

@ -24,13 +24,15 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.primitive.StringDt;
@DatatypeDef(name="Extension")
public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDatatype {
public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDatatype, IBaseExtension<ExtensionDt> {
private boolean myModifier;
@ -38,7 +40,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
private StringDt myUrl;
@Child(name="value", type=IDatatype.class, order=1, min=0, max=1)
private IElement myValue;
private IBaseDatatype myValue;
public ExtensionDt() {
}
@ -54,7 +56,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
myUrl = new StringDt(theUrl);
}
public ExtensionDt(boolean theIsModifier, String theUrl, IDatatype theValue) {
public ExtensionDt(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
Validate.notEmpty(theUrl, "URL must be populated");
Validate.notNull(theValue, "Value must not be null");
@ -63,15 +65,25 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
myValue=theValue;
}
public StringDt getUrl() {
if (myUrl==null) {
myUrl=new StringDt();
}
return myUrl;
/**
* Returns the URL for this extension.
* <p>
* Note that before HAPI 0.9 this method returned a {@link StringDt} but as of
* HAPI 0.9 this method returns a plain string. This was changed because it does not make sense to use a StringDt here
* since the URL itself can not contain extensions and it was therefore misleading.
* </p>
*/
public String getUrl() {
return myUrl != null ? myUrl.getValue() : null;
}
/**
* Retained for backward compatibility
*
* @see ExtensionDt#getUrl()
*/
public String getUrlAsString() {
return getUrl().getValue();
return getUrl();
}
/**
@ -81,7 +93,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
* {@link #getUndeclaredModifierExtensions()} to retrieve the child extensions.
* </p>
*/
public IElement getValue() {
public IBaseDatatype getValue() {
return myValue;
}
@ -117,7 +129,7 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
}
public ExtensionDt setUrl(String theUrl) {
myUrl = new StringDt(theUrl);
myUrl = theUrl != null ? new StringDt(theUrl) : myUrl;
return this;
}
@ -126,8 +138,9 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
return this;
}
public void setValue(IElement theValue) {
public ExtensionDt setValue(IBaseDatatype theValue) {
myValue = theValue;
return this;
}
@Override
@ -135,4 +148,9 @@ public class ExtensionDt extends BaseIdentifiableElement implements ICompositeDa
return new ArrayList<T>();
}
@Override
public List<ExtensionDt> getExtension() {
return getAllUndeclaredExtensions();
}
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.model.api;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
/*
* #%L
* HAPI FHIR - Core Library
@ -20,6 +22,6 @@ package ca.uhn.fhir.model.api;
* #L%
*/
public interface IDatatype extends IElement {
public interface IDatatype extends IElement, IBaseDatatype {
}

View File

@ -22,6 +22,8 @@ package ca.uhn.fhir.model.api;
import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
public interface ISupportsUndeclaredExtensions extends IElement {
/**
@ -52,7 +54,7 @@ public interface ISupportsUndeclaredExtensions extends IElement {
* <li>{@link ExtensionDt#setUrl(String) URL}</li>
* <li>And one of:
* <ul>
* <li>{@link ExtensionDt#setValue(IElement) A datatype value}</li>
* <li>{@link ExtensionDt#setValue(IBaseDatatype) A datatype value}</li>
* <li>{@link #addUndeclaredExtension(ExtensionDt) Further sub-extensions}</li>
* </ul>
* </ul>
@ -64,7 +66,7 @@ public interface ISupportsUndeclaredExtensions extends IElement {
/**
* Adds an extension to this object
*/
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IDatatype theValue);
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue);
/**
* Adds an extension to this object. This method is intended for use when

View File

@ -28,6 +28,8 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.IBase;
/**
* A collection of tags present on a single resource. TagList is backed by a {@link LinkedHashSet}, so the order of added tags will be consistent, but duplicates will not be preserved.
*
@ -35,7 +37,7 @@ import java.util.Set;
* <b>Thread safety:</b> This class is not thread safe
* </p>
*/
public class TagList implements Set<Tag>, Serializable {
public class TagList implements Set<Tag>, Serializable, IBase {
public static final String ATTR_CATEGORY = "category";
public static final String ELEMENT_NAME = "TagList";

View File

@ -24,6 +24,9 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Enumeration;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import ca.uhn.fhir.model.api.IElement;
@ -97,4 +100,28 @@ public @interface Child {
// */
// String replaces() default "";
/**
* For children which accept an {@link Enumeration} as the type, this
* field indicates the type to use for the enum factory
*/
Class<? extends IBaseEnumFactory<?>> enumFactory() default NoEnumFactory.class;
public static class NoEnumFactory implements IBaseEnumFactory<Enum<?>> {
private NoEnumFactory() {
// non instantiable
}
@Override
public Enum<?> fromCode(String theCodeString) throws IllegalArgumentException {
return null;
}
@Override
public String toCode(Enum<?> theCode) {
return null;
}
}
}

View File

@ -22,14 +22,12 @@ package ca.uhn.fhir.model.base.composite;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import javax.json.JsonValue;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
@ -40,7 +38,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.client.BaseClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement {
public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement implements IBaseDatatype {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
private IResource myResource;

View File

@ -20,7 +20,9 @@ package ca.uhn.fhir.parser;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.Reader;
@ -54,7 +56,11 @@ import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.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 ca.uhn.fhir.context.BaseRuntimeChildDefinition;
@ -85,7 +91,6 @@ import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseBinary;
import ca.uhn.fhir.model.primitive.BooleanDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
@ -127,7 +132,7 @@ public class JsonParser extends BaseParser implements IParser {
myContext = theContext;
}
private void addToHeldExtensions(int valueIdx, List<ExtensionDt> ext, ArrayList<ArrayList<HeldExtension>> list) {
private void addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier) {
if (ext.size() > 0) {
list.ensureCapacity(valueIdx);
while (list.size() <= valueIdx) {
@ -136,8 +141,8 @@ public class JsonParser extends BaseParser implements IParser {
if (list.get(valueIdx) == null) {
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
}
for (ExtensionDt next : ext) {
list.get(valueIdx).add(new HeldExtension(next));
for (IBaseExtension<?> next : ext) {
list.get(valueIdx).add(new HeldExtension(next, theIsModifier));
}
}
}
@ -283,7 +288,7 @@ public class JsonParser extends BaseParser implements IParser {
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource);
encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "resource", false);
}
if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
theEventWriter.writeStartObject("search");
writeOptionalTagWithTextNode(theEventWriter, "mode", nextEntry.getSearchMode().getValueAsString());
@ -325,7 +330,6 @@ public class JsonParser extends BaseParser implements IParser {
//
// writeAuthor(nextEntry, theEventWriter);
if (nextEntry.getSummary().isEmpty() == false) {
theEventWriter.write("summary", nextEntry.getSummary().getValueAsString());
}
@ -411,8 +415,7 @@ public class JsonParser extends BaseParser implements IParser {
}
case CONTAINED_RESOURCES: {
/*
* Disabled per #103
* ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) {
* Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) {
* continue; } encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(next.getId().getValue())); }
*/
List<IBaseResource> containedResources = getContainedResources().getContainedResources();
@ -460,11 +463,15 @@ public class JsonParser extends BaseParser implements IParser {
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
for (BaseRuntimeChildDefinition nextChild : theChildren) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue;
}
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
if (gen != null) {
BaseNarrativeDt<?> narr = ((IResource)theResource).getText();
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
if (narr != null) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
@ -540,12 +547,25 @@ public class JsonParser extends BaseParser implements IParser {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource);
}
if (nextValue instanceof ISupportsUndeclaredExtensions && primitive) {
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
addToHeldExtensions(valueIdx, ext, extensions);
if (primitive) {
if (nextValue instanceof ISupportsUndeclaredExtensions) {
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
addToHeldExtensions(valueIdx, ext, extensions,false);
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
addToHeldExtensions(valueIdx, ext, modifierExtensions);
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
addToHeldExtensions(valueIdx, ext, modifierExtensions,true);
}else {
if (nextValue instanceof IBaseHasExtensions) {
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
List<? extends IBaseExtension<?>> ext = element.getExtension();
addToHeldExtensions(valueIdx, ext, extensions, false);
}
if (nextValue instanceof IBaseHasModifierExtensions) {
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
List<? extends IBaseExtension<?>> ext = element.getModifierExtension();
addToHeldExtensions(valueIdx, ext, extensions, true);
}
}
}
}
@ -663,7 +683,7 @@ public class JsonParser extends BaseParser implements IParser {
} else {
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource);
}
theEventWriter.writeEnd();
}
@ -751,22 +771,44 @@ public class JsonParser extends BaseParser implements IParser {
}
}
private void extractUndeclaredExtensions(IBase theResource, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
if (theResource instanceof ISupportsUndeclaredExtensions) {
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) theResource).getUndeclaredExtensions();
private void extractUndeclaredExtensions(IBase theElement, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions element = (ISupportsUndeclaredExtensions) theElement;
List<ExtensionDt> ext = element.getUndeclaredExtensions();
for (ExtensionDt next : ext) {
if (next == null || next.isEmpty()) {
continue;
}
extensions.add(new HeldExtension(next));
extensions.add(new HeldExtension(next, false));
}
ext = ((ISupportsUndeclaredExtensions) theResource).getUndeclaredModifierExtensions();
ext = element.getUndeclaredModifierExtensions();
for (ExtensionDt next : ext) {
if (next == null || next.isEmpty()) {
continue;
}
modifierExtensions.add(new HeldExtension(next));
modifierExtensions.add(new HeldExtension(next, true));
}
} else {
if (theElement instanceof IBaseHasExtensions) {
IBaseHasExtensions element = (IBaseHasExtensions) theElement;
List<? extends IBaseExtension<?>> ext = element.getExtension();
for (IBaseExtension<?> next : ext) {
if (next == null || next.isEmpty()) {
continue;
}
extensions.add(new HeldExtension(next, false));
}
}
if (theElement instanceof IBaseHasModifierExtensions) {
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) theElement;
List<? extends IBaseExtension<?>> ext = element.getModifierExtension();
for (IBaseExtension<?> next : ext) {
if (next == null || next.isEmpty()) {
continue;
}
modifierExtensions.add(new HeldExtension(next, true));
}
}
}
}
@ -788,16 +830,15 @@ public class JsonParser extends BaseParser implements IParser {
return;
}
boolean newerThanDstu1 = myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1);
JsonObject alternate = (JsonObject) theAlternateVal;
for (Entry<String, JsonValue> nextEntry : alternate.entrySet()) {
String nextKey = nextEntry.getKey();
JsonValue nextVal = nextEntry.getValue();
if (!newerThanDstu1 && "extension".equals(nextKey)) {
if ("extension".equals(nextKey)) {
boolean isModifier = false;
JsonArray array = (JsonArray) nextEntry.getValue();
parseExtension(theState, array, isModifier);
} else if (!newerThanDstu1 && "modifierExtension".equals(nextKey)) {
} else if ("modifierExtension".equals(nextKey)) {
boolean isModifier = true;
JsonArray array = (JsonArray) nextEntry.getValue();
parseExtension(theState, array, isModifier);
@ -811,12 +852,6 @@ public class JsonParser extends BaseParser implements IParser {
default:
break;
}
} else if (newerThanDstu1) {
if (nextKey.indexOf(':') > -1 && newerThanDstu1) {
JsonArray array = (JsonArray) nextEntry.getValue();
parseExtensionInDstu2Style(false, theState, null, nextKey, array);
continue;
}
}
}
}
@ -935,7 +970,6 @@ public class JsonParser extends BaseParser implements IParser {
private void parseChildren(JsonObject theObject, ParserState<?> theState) {
String elementId = null;
boolean newerThanDstu1 = myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1);
for (String nextName : theObject.keySet()) {
if ("resourceType".equals(nextName)) {
continue;
@ -948,29 +982,16 @@ public class JsonParser extends BaseParser implements IParser {
// _id is incorrect, but some early examples in the FHIR spec used it
elementId = theObject.getString(nextName);
continue;
} else if (!newerThanDstu1 && "extension".equals(nextName)) {
} else if ("extension".equals(nextName)) {
JsonArray array = theObject.getJsonArray(nextName);
parseExtension(theState, array, false);
continue;
} else if (!newerThanDstu1 && "modifierExtension".equals(nextName)) {
} else if ("modifierExtension".equals(nextName)) {
JsonArray array = theObject.getJsonArray(nextName);
parseExtension(theState, array, true);
continue;
} else if (newerThanDstu1 && "modifier".equals(nextName)) {
JsonObject obj = theObject.getJsonObject(nextName);
for (String nextUrl : obj.keySet()) {
JsonArray array = obj.getJsonArray(nextUrl);
parseExtensionInDstu2Style(true, theState, null, nextUrl, array);
}
continue;
} else if (nextName.charAt(0) == '_') {
continue;
} else {
if (newerThanDstu1 && nextName.indexOf(':') > -1) {
JsonArray array = theObject.getJsonArray(nextName);
parseExtensionInDstu2Style(false, theState, null, nextName, array);
continue;
}
}
JsonValue nextVal = theObject.get(nextName);
@ -1210,42 +1231,18 @@ public class JsonParser extends BaseParser implements IParser {
private void writeExtensionsAsDirectChild(IBaseResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
List<HeldExtension> modifierExtensions, String theParentExtensionUrl) throws IOException {
if (extensions.isEmpty() == false) {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
Collections.sort(extensions);
String currentlyWritingExtensionUrl = null;
for (HeldExtension next : extensions) {
currentlyWritingExtensionUrl = next.writeExtensionInDstu2Format(resDef, theResource, theEventWriter, currentlyWritingExtensionUrl, theParentExtensionUrl);
}
if (currentlyWritingExtensionUrl != null) {
theEventWriter.writeEnd();
}
} else {
theEventWriter.writeStartArray("extension");
for (HeldExtension next : extensions) {
next.write(resDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
theEventWriter.writeStartArray("extension");
for (HeldExtension next : extensions) {
next.write(resDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
}
if (modifierExtensions.isEmpty() == false) {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
Collections.sort(modifierExtensions);
theEventWriter.writeStartObject("modifier");
String currentlyWritingExtensionUrl = null;
for (HeldExtension next : modifierExtensions) {
currentlyWritingExtensionUrl = next.writeExtensionInDstu2Format(resDef, theResource, theEventWriter, currentlyWritingExtensionUrl, theParentExtensionUrl);
}
if (currentlyWritingExtensionUrl != null) {
theEventWriter.writeEnd();
}
theEventWriter.writeEnd();
} else {
theEventWriter.writeStartArray("modifierExtension");
for (HeldExtension next : modifierExtensions) {
next.write(resDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
theEventWriter.writeStartArray("modifierExtension");
for (HeldExtension next : modifierExtensions) {
next.write(resDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
}
}
@ -1283,14 +1280,6 @@ public class JsonParser extends BaseParser implements IParser {
}
}
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, String theValue) {
if (theValue != null && !theValue.isEmpty()) {
theEventWriter.write(theElementName, theValue);
} else {
theEventWriter.writeNull(theElementName);
}
}
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
if (StringUtils.isNotBlank(theStringDt.getValue())) {
theEventWriter.write(theElementName, theStringDt.getValue());
@ -1303,12 +1292,14 @@ public class JsonParser extends BaseParser implements IParser {
private class HeldExtension implements Comparable<HeldExtension> {
private RuntimeChildDeclaredExtensionDefinition myDef;
private ExtensionDt myUndeclaredExtension;
private IBaseExtension<?> myUndeclaredExtension;
private IBase myValue;
private boolean myModifier;
public HeldExtension(ExtensionDt theUndeclaredExtension) {
public HeldExtension(IBaseExtension<?> theUndeclaredExtension, boolean theModifier) {
assert theUndeclaredExtension != null;
myUndeclaredExtension = theUndeclaredExtension;
myModifier = theModifier;
}
public HeldExtension(RuntimeChildDeclaredExtensionDefinition theDef, IBase theValue) {
@ -1337,66 +1328,38 @@ public class JsonParser extends BaseParser implements IParser {
}
}
public String writeExtensionInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theCurrentlyWritingExtensionUrl,
String theParentExtensionUrl) throws IOException {
if (myUndeclaredExtension != null) {
return writeUndeclaredExtInDstu2Format(theResDef, theResource, theEventWriter, myUndeclaredExtension, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
} else {
String extensionUrl = myDef.getExtensionUrl();
checkIfNewExtensionUrlArrayIsNeeded(theEventWriter, extensionUrl, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
theEventWriter.writeStartObject();
BaseRuntimeElementDefinition<?> def = myDef.getChildElementDefinitionByDatatype(myValue.getClass());
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource, extensionUrl);
} else {
String childName = myDef.getChildNameByDatatype(myValue.getClass());
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false);
}
theEventWriter.writeEnd();
return extensionUrl;
}
}
private void checkIfNewExtensionUrlArrayIsNeeded(JsonGenerator theEventWriter, String theExtensionUrl, String theCurrentlyWritingExtensionUrl, String theParentExtensionUrl) {
if (StringUtils.equals(theCurrentlyWritingExtensionUrl, theExtensionUrl) == false) {
if (isNotBlank(theCurrentlyWritingExtensionUrl)) {
theEventWriter.writeEnd();
}
String urlToWrite = UrlUtil.constructRelativeUrl(theParentExtensionUrl, theExtensionUrl);
theEventWriter.writeStartArray(urlToWrite);
}
}
private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, ExtensionDt ext) throws IOException {
IElement value = ext.getValue();
String extensionUrl = ext.getUrl().getValue();
private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, IBaseExtension<?> ext) throws IOException {
IBaseDatatype value = ext.getValue();
String extensionUrl = ext.getUrl();
theEventWriter.writeStartObject();
theEventWriter.write("url", extensionUrl);
boolean noValue = value == null || value.isEmpty();
if (noValue && ext.getAllUndeclaredExtensions().isEmpty()) {
if (noValue && ext.getExtension().isEmpty()) {
ourLog.debug("Extension with URL[{}] has no value", extensionUrl);
} else if (noValue) {
theEventWriter.writeStartArray("extension");
if (myModifier) {
theEventWriter.writeStartArray("modifierExtension");
}else {
theEventWriter.writeStartArray("extension");
}
for (ExtensionDt next : ext.getUndeclaredExtensions()) {
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, next);
for (Object next : ext.getExtension()) {
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, (IBaseExtension<?>) next);
}
theEventWriter.writeEnd();
} else {
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
String childName = extDef.getChildNameByDatatype(value.getClass());
if (childName == null) {
childName = "value" + myContext.getElementDefinition(value.getClass()).getName();
}
BaseRuntimeElementDefinition<?> childDef = myContext.getElementDefinition(value.getClass());
if (childDef == null) {
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
}
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true);
}
@ -1405,53 +1368,10 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeEnd();
}
private String writeUndeclaredExtInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, ExtensionDt ext,
String theCurrentlyWritingExtensionUrl, String theParentExtensionUrl) throws IOException {
IElement value = ext.getValue();
String extensionUrl = ext.getUrl().getValue();
checkIfNewExtensionUrlArrayIsNeeded(theEventWriter, extensionUrl, theCurrentlyWritingExtensionUrl, theParentExtensionUrl);
theEventWriter.writeStartObject();
boolean noValue = value == null || value.isEmpty();
if (noValue && ext.getAllUndeclaredExtensions().isEmpty()) {
ourLog.debug("Extension with URL[{}] has no value", extensionUrl);
} else if (noValue) {
BaseRuntimeElementDefinition<?> elemDef = null;
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
extractAndWriteExtensionsAsDirectChild(ext, theEventWriter, elemDef, resDef, theResource, extensionUrl);
} else {
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
String childName = extDef.getChildNameByDatatype(value.getClass());
BaseRuntimeElementDefinition<?> childDef;
if (childName == null) {
childDef = myContext.getElementDefinition(value.getClass());
if (childDef == null) {
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
} else {
childName = RuntimeChildUndeclaredExtensionDefinition.createExtensionChildName(childDef);
}
} else {
childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
}
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true);
}
theEventWriter.writeEnd();
return extensionUrl;
}
@Override
public int compareTo(HeldExtension theArg0) {
String url1 = myDef != null ? myDef.getExtensionUrl() : myUndeclaredExtension.getUrlAsString();
String url2 = theArg0.myDef != null ? theArg0.myDef.getExtensionUrl() : theArg0.myUndeclaredExtension.getUrlAsString();
String url1 = myDef != null ? myDef.getExtensionUrl() : myUndeclaredExtension.getUrl();
String url2 = theArg0.myDef != null ? theArg0.myDef.getExtensionUrl() : theArg0.myUndeclaredExtension.getUrl();
url1 = defaultString(url1);
url2 = defaultString(url2);
return url1.compareTo(url2);

View File

@ -37,7 +37,11 @@ import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.ICompositeType;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource;
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;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
@ -61,6 +65,7 @@ import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.ICompositeElement;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IExtension;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IIdentifiableElement;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
@ -819,11 +824,29 @@ class ParserState<T> {
ExtensionState newState = new ExtensionState(myPreResourceState, newExtension);
push(newState);
} else {
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
if (theIsModifier == false) {
if (getCurrentElement() instanceof IBaseHasExtensions) {
IBaseExtension<?> ext = ((IBaseHasExtensions)getCurrentElement()).addExtension();
ext.setUrl(theUrlAttr);
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
push(newState);
} else {
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
}
}else {
if (getCurrentElement() instanceof IBaseHasModifierExtensions) {
IBaseExtension<?> ext = ((IBaseHasModifierExtensions)getCurrentElement()).addModifierExtension();
ext.setUrl(theUrlAttr);
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
push(newState);
} else {
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
}
}
}
}
protected Object getCurrentElement() {
protected IBase getCurrentElement() {
return null;
}
@ -879,7 +902,7 @@ class ParserState<T> {
if ("id".equals(theName)) {
if (myInstance instanceof IIdentifiableElement) {
((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
} else if (myInstance instanceof IBaseResource) {
} else {
(myInstance).setId(new IdDt(theValue));
}
} else if ("contentType".equals(theName)) {
@ -1578,16 +1601,16 @@ class ParserState<T> {
private class ExtensionState extends BaseState {
private ExtensionDt myExtension;
private IBaseExtension<?> myExtension;
public ExtensionState(PreResourceState thePreResourceState, ExtensionDt theExtension) {
public ExtensionState(PreResourceState thePreResourceState, IBaseExtension<?> theExtension) {
super(thePreResourceState);
myExtension = theExtension;
}
@Override
public void endingElement() throws DataFormatException {
if (myExtension.getValue() != null && myExtension.getUndeclaredExtensions().size() > 0) {
if (myExtension.getValue() != null && myExtension.getExtension().size() > 0) {
throw new DataFormatException("Extension must not have both a value and other contained extensions");
}
pop();
@ -1612,7 +1635,7 @@ class ParserState<T> {
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance();
myExtension.setValue((IElement) newChildInstance);
myExtension.setValue(newChildInstance);
PrimitiveState newState = new PrimitiveState(getPreResourceState(), newChildInstance);
push(newState);
return;
@ -1635,7 +1658,7 @@ class ParserState<T> {
}
@Override
protected IElement getCurrentElement() {
protected IBaseExtension<?> getCurrentElement() {
return myExtension;
}
@ -1805,6 +1828,15 @@ class ParserState<T> {
super(theResourceType);
}
@SuppressWarnings("unchecked")
@Override
public void wereBack() {
super.wereBack();
if (myTarget == null) {
myObject = (T) getCurrentElement();
}
}
@Override
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
super.enteringNewElement(theNamespaceURI, theLocalPart);
@ -1953,7 +1985,7 @@ class ParserState<T> {
}
@Override
protected TagList getCurrentElement() {
protected IBase getCurrentElement() {
return myTagList;
}
@ -2237,6 +2269,11 @@ class ParserState<T> {
pop();
}
@Override
protected IBase getCurrentElement() {
return myTagList;
}
@Override
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
if (TagList.ATTR_CATEGORY.equals(theLocalPart)) {

View File

@ -27,8 +27,10 @@ import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
@ -49,6 +51,10 @@ import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.INarrative;
@ -171,7 +177,6 @@ public class XmlParser extends BaseParser implements IParser {
throw new DataFormatException("Extension element has no 'url' attribute");
}
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), true);
} else {
String elementName = elem.getName().getLocalPart();
@ -433,8 +438,8 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.close();
}
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName,
BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef,
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
if (nextValue.isEmpty()) {
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
// We still want to go in..
@ -450,7 +455,7 @@ public class XmlParser extends BaseParser implements IParser {
if (value != null) {
theEventWriter.writeStartElement(childName);
theEventWriter.writeAttribute("value", value);
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, nextValue, theIncludedResource);
encodeExtensionsIfPresent(theResource, theEventWriter, nextValue, theIncludedResource);
theEventWriter.writeEndElement();
}
break;
@ -462,7 +467,7 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeAttribute("url", theExtensionUrl);
}
BaseRuntimeElementCompositeDefinition<?> childCompositeDef = (BaseRuntimeElementCompositeDefinition<?>) childDef;
encodeCompositeElementToStreamWriter(theResDef, theResource, nextValue, theEventWriter, childCompositeDef, theIncludedResource);
encodeCompositeElementToStreamWriter(theResource, nextValue, theEventWriter, childCompositeDef, theIncludedResource);
theEventWriter.writeEndElement();
break;
}
@ -512,21 +517,26 @@ public class XmlParser extends BaseParser implements IParser {
}
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (BaseRuntimeChildDefinition nextChild : children) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue;
}
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
if (theResource instanceof IResource) {
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
if (gen != null && narr.isEmpty()) {
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
gen.generateNarrative(resourceProfile, theResource, narr);
}
if (narr.isEmpty() == false) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, childName, type, null, theIncludedResource);
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theIncludedResource);
continue;
}
} else {
@ -534,13 +544,14 @@ public class XmlParser extends BaseParser implements IParser {
BaseNarrativeDt<?> narr2 = null;
if (gen != null && narr1.isEmpty()) {
// TODO: need to implement this
gen.generateNarrative(theResDef.getResourceProfile(), theResource, null);
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
gen.generateNarrative(resourceProfile, theResource, null);
}
if (narr2 != null) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
continue;
}
}
@ -563,11 +574,11 @@ public class XmlParser extends BaseParser implements IParser {
super.throwExceptionForUnknownChildType(nextChild, type);
}
if (nextValue instanceof ExtensionDt) {
extensionUrl = ((ExtensionDt) nextValue).getUrlAsString();
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
// This is called for the Query resource in DSTU1 only
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
} else if (extensionUrl != null && childName.equals("extension") == false) {
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
if (extDef.isModifier()) {
@ -577,31 +588,48 @@ public class XmlParser extends BaseParser implements IParser {
}
theEventWriter.writeAttribute("url", extensionUrl);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
theEventWriter.writeEndElement();
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) {
// suppress narratives from contained resources
} else {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
}
}
}
}
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(), theIncludedResource);
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
}
private void encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource)
throws XMLStreamException, DataFormatException {
private void encodeExtensionsIfPresent(IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredExtensions(), "extension", theIncludedResource);
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension", theIncludedResource);
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredExtensions()), "extension", theIncludedResource);
encodeUndeclaredExtensions(theResource, theWriter, toBaseExtensionList(res.getUndeclaredModifierExtensions()), "modifierExtension", theIncludedResource);
}
if (theElement instanceof IBaseHasExtensions) {
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
encodeUndeclaredExtensions(theResource, theWriter, res.getExtension(), "extension", theIncludedResource);
}
if (theElement instanceof IBaseHasModifierExtensions) {
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
encodeUndeclaredExtensions(theResource, theWriter, res.getModifierExtension(), "modifierExtension", theIncludedResource);
}
}
/**
* This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?>> seems to be
* rejected by the compiler some of the time.
*/
private <Q extends IBaseExtension<?>> List<IBaseExtension<?>> toBaseExtensionList(final List<Q> theList) {
List<IBaseExtension<?>> retVal = new ArrayList<IBaseExtension<?>>(theList.size());
retVal.addAll(theList);
return retVal;
}
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, BaseResourceReferenceDt theRef) throws XMLStreamException {
@ -638,12 +666,12 @@ public class XmlParser extends BaseParser implements IParser {
postExtensionChildren.add(next);
}
}
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, preExtensionChildren, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, preExtensionChildren, theIncludedResource);
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, postExtensionChildren, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, postExtensionChildren, theIncludedResource);
}
@ -706,7 +734,7 @@ public class XmlParser extends BaseParser implements IParser {
if (theResource instanceof IAnyResource) {
// HL7.org Structures
encodeCompositeElementToStreamWriter(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
} else {
@ -753,7 +781,7 @@ public class XmlParser extends BaseParser implements IParser {
}
theEventWriter.writeCharacters(bin.getContentAsBase64());
} else {
encodeCompositeElementToStreamWriter(resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
}
}
@ -794,25 +822,20 @@ public class XmlParser extends BaseParser implements IParser {
}
}
private void encodeUndeclaredExtensions(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, List<ExtensionDt> theExtensions, String tagName,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (ExtensionDt next : theExtensions) {
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource)
throws XMLStreamException, DataFormatException {
for (IBaseExtension<?> next : theExtensions) {
if (next == null) {
continue;
}
theWriter.writeStartElement(tagName);
theWriter.writeAttribute("url", next.getUrl().getValue());
String url = next.getUrl();
theWriter.writeAttribute("url", url);
if (next.getValue() != null) {
IElement value = next.getValue();
// RuntimeChildUndeclaredExtensionDefinition extDef =
// myContext.getRuntimeChildUndeclaredExtensionDefinition();
// String childName = extDef.getChildNameByDatatype(nextValue.getClass());
// if (childName == null) {
// throw new ConfigurationException("Unable to encode extension, unregognized child element type: " +
// nextValue.getClass().getCanonicalName());
// }
// BaseRuntimeElementDefinition<?> childDef =
// extDef.getChildElementDefinitionByDatatype(nextValue.getClass());
//
//
IBaseDatatype value = next.getValue();
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
String childName = extDef.getChildNameByDatatype(value.getClass());
BaseRuntimeElementDefinition<?> childDef;
@ -826,11 +849,11 @@ public class XmlParser extends BaseParser implements IParser {
} else {
childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
}
encodeChildElementToStreamWriter(theResDef, theResource, theWriter, value, childName, childDef, null, theIncludedResource);
encodeChildElementToStreamWriter(theResource, theWriter, value, childName, childDef, null, theIncludedResource);
}
// child extensions
encodeExtensionsIfPresent(theResDef, theResource, theWriter, next, theIncludedResource);
encodeExtensionsIfPresent(theResource, theWriter, next, theIncludedResource);
theWriter.writeEndElement();
}

View File

@ -26,15 +26,12 @@ import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import ca.uhn.fhir.rest.annotation.*;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.IBaseResource;
@ -47,6 +44,18 @@ import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.AddTags;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.DeleteTags;
import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
@ -61,9 +70,9 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionNotSpecifiedException;
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ReflectionUtil;
@ -217,7 +226,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
ex = new ResourceVersionConflictException("Server responded with HTTP 409");
break;
case Constants.STATUS_HTTP_412_PRECONDITION_FAILED:
ex = new ResourceVersionNotSpecifiedException("Server responded with HTTP 412");
ex = new PreconditionFailedException("Server responded with HTTP 412");
break;
case Constants.STATUS_HTTP_422_UNPROCESSABLE_ENTITY:
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theStatusCode);

View File

@ -0,0 +1,25 @@
package org.hl7.fhir.instance.model.api;
public interface IBaseEnumFactory<T extends Enum<?>> {
/**
* Read an enumeration value from the string that represents it on the XML or JSON
*
* @param codeString
* the value found in the XML or JSON
* @return the enumeration value
* @throws IllegalArgumentException
* is the value is not known
*/
public T fromCode(String codeString) throws IllegalArgumentException;
/**
* Get the XML/JSON representation for an enumerated value
*
* @param code
* - the enumeration value
* @return the XML/JSON representation
*/
public String toCode(T code);
}

View File

@ -11,5 +11,9 @@ public interface IBaseExtension<T> extends ICompositeType {
String getUrl();
IBaseDatatype getValue();
T setUrl(String theUrl);
T setValue(IBaseDatatype theValue);
}

View File

@ -0,0 +1,11 @@
package org.hl7.fhir.instance.model.api;
import java.util.List;
public interface IBaseHasExtensions {
public List<? extends IBaseExtension<?>> getExtension();
public IBaseExtension<?> addExtension();
}

View File

@ -0,0 +1,11 @@
package org.hl7.fhir.instance.model.api;
import java.util.List;
public interface IBaseHasModifierExtensions {
public List<? extends IBaseExtension<?>> getModifierExtension();
public IBaseExtension<?> addModifierExtension();
}

View File

@ -22,7 +22,7 @@ public class MultiVersionJsonParserTest {
String str = FhirContext.forDstu2().newJsonParser().encodeResourceToString(p);
ourLog.info(str);
assertThat(str,StringContains.containsString("{\"resourceType\":\"Patient\",\"http://foo#ext\":[{\"valueQuantity\":{\"value\":2.2}}],\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]}"));
assertThat(str,StringContains.containsString("{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://foo#ext\",\"valueQuantity\":{\"value\":2.2}}],\"identifier\":[{\"system\":\"urn:sys\",\"value\":\"001\"}]}"));
}
}

View File

@ -9,22 +9,23 @@ import ca.uhn.fhir.validation.FhirValidator;
public class ValidatorTest {
@Test
public void testValidator() {
FhirContext ctx = new FhirContext();
FhirValidator val = ctx.newValidator();
// Phloc is not onthe classpath
assertTrue(val.isValidateAgainstStandardSchema());
assertFalse(val.isValidateAgainstStandardSchematron());
@Test
public void testValidator() {
FhirContext ctx = new FhirContext();
FhirValidator val = ctx.newValidator();
// Phloc is not onthe classpath
assertTrue(val.isValidateAgainstStandardSchema());
assertFalse(val.isValidateAgainstStandardSchematron());
try {
val.setValidateAgainstStandardSchematron(true);
fail();
} catch (IllegalArgumentException e) {
assertEquals("Phloc-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
}
}
try { val.setValidateAgainstStandardSchematron(true);
fail();
} catch (IllegalArgumentException e) {
assertEquals("Phloc-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
}
}
}

View File

@ -9,6 +9,7 @@ import org.springframework.web.context.WebApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.server.ETagSupportEnum;
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
@ -48,7 +49,7 @@ public class JpaServerDemo extends RestfulServer {
* The system provider implements non-resource-type methods, such as
* transaction, and global history.
*/
JpaSystemProviderDstu1 systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu1.class);
JpaSystemProviderDstu2 systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
setPlainProviders(systemProvider);
/*

View File

@ -23,10 +23,12 @@ package ca.uhn.fhir.model.dev;
import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
@ -102,6 +104,4 @@ public class FhirDev implements IFhirVersion {
return ContainedDt.class;
}
}

View File

@ -57,7 +57,6 @@ import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceReferenceDefinition;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource;
@ -378,6 +377,4 @@ public class FhirDstu1 implements IFhirVersion {
return ContainedDt.class;
}
}

View File

@ -1,9 +1,15 @@
package ca.uhn.fhir.parser;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.OutputStreamWriter;
@ -24,8 +30,6 @@ import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
@ -41,7 +45,6 @@ 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.NarrativeDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.Binary;
import ca.uhn.fhir.model.dstu.resource.Conformance;
@ -59,7 +62,10 @@ import ca.uhn.fhir.model.dstu.resource.ValueSet;
import ca.uhn.fhir.model.dstu.resource.ValueSet.Define;
import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
@ -94,6 +100,120 @@ public class JsonParserTest {
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135");
ExtensionDt ext = new ExtensionDt();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
patient.addUndeclaredExtension(ext);
ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value2"));
parent.addUndeclaredExtension(child2);
ExtensionDt modExt = new ExtensionDt();
modExt.setUrl("http://example.com/extensions#modext");
modExt.setValue(new DateDt("1995-01-02"));
modExt.setModifier(true);
patient.addUndeclaredExtension(modExt);
HumanNameDt name = patient.addName();
name.addFamily("Blah");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given"));
given.addUndeclaredExtension(ext2);
StringDt given2 = name.addGiven();
given2.setValue("Shmoe");
ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent");
given2.addUndeclaredExtension(given2ext);
given2ext.addUndeclaredExtension(new ExtensionDt().setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD")));
String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",",
"\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"
));
assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("\"modifierExtension\":[" +
"{" +
"\"url\":\"http://example.com/extensions#modext\"," +
"\"valueDate\":\"1995-01-02\"" +
"}" +
"],"));
assertThat(enc, containsString("\"_given\":[" +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext\"," +
"\"valueString\":\"given\"" +
"}" +
"]" +
"}," +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_parent\"," +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_child\"," +
"\"valueString\":\"CHILD\"" +
"}" +
"]" +
"}" +
"]" +
"}"));
/*
* Now parse this back
*/
Patient parsed =ourCtx.newJsonParser().parseResource(Patient.class, enc);
ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com/extensions#someext", ext.getUrl());
assertEquals("2011-01-02T11:13:15", ((DateTimeDt)ext.getValue()).getValueAsString());
parent = patient.getUndeclaredExtensions().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", ((StringDt)child1.getValue()).getValueAsString());
child2 = parent.getExtension().get(1);
assertEquals( "http://example.com#child", child2.getUrl());
assertEquals("value2", ((StringDt)child2.getValue()).getValueAsString());
modExt = parsed.getUndeclaredModifierExtensions().get(0);
assertEquals("http://example.com/extensions#modext", modExt.getUrl());
assertEquals("1995-01-02", ((DateDt)modExt.getValue()).getValueAsString());
name = parsed.getName().get(0);
ext2 = name.getGiven().get(0).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext", ext2.getUrl());
assertEquals("given", ((StringDt)ext2.getValue()).getValueAsString());
given2ext = name.getGiven().get(1).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
assertNull(given2ext.getValue());
ExtensionDt given2ext2 = given2ext.getExtension().get(0);
assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
assertEquals("CHILD", ((StringDt)given2ext2.getValue()).getValue());
}
/**
* #65
*/
@ -1136,7 +1256,7 @@ public class JsonParserTest {
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));
@ -1184,7 +1304,7 @@ public class JsonParserTest {
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
IParser jsonParser = fhirCtx.newJsonParser().setPrettyPrint(true);
String encoded = jsonParser.encodeResourceToString(obs);

View File

@ -67,6 +67,7 @@ import ca.uhn.fhir.model.dstu.valueset.AdministrativeGenderCodesEnum;
import ca.uhn.fhir.model.dstu.valueset.DocumentReferenceStatusEnum;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt;
@ -151,6 +152,95 @@ public class XmlParserTest {
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135");
ExtensionDt ext = new ExtensionDt();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
patient.addUndeclaredExtension(ext);
ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value2"));
parent.addUndeclaredExtension(child2);
ExtensionDt modExt = new ExtensionDt();
modExt.setUrl("http://example.com/extensions#modext");
modExt.setValue(new DateDt("1995-01-02"));
modExt.setModifier(true);
patient.addUndeclaredExtension(modExt);
HumanNameDt name = patient.addName();
name.addFamily("Blah");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given"));
given.addUndeclaredExtension(ext2);
StringDt given2 = name.addGiven();
given2.setValue("Shmoe");
ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent");
given2.addUndeclaredExtension(given2ext);
given2ext.addUndeclaredExtension(new ExtensionDt().setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD")));
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(
enc,
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
*/
Patient parsed =ourCtx.newXmlParser().parseResource(Patient.class, enc);
ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com/extensions#someext", ext.getUrl());
assertEquals("2011-01-02T11:13:15", ((DateTimeDt)ext.getValue()).getValueAsString());
parent = patient.getUndeclaredExtensions().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", ((StringDt)child1.getValue()).getValueAsString());
child2 = parent.getExtension().get(1);
assertEquals( "http://example.com#child", child2.getUrl());
assertEquals("value2", ((StringDt)child2.getValue()).getValueAsString());
modExt = parsed.getUndeclaredModifierExtensions().get(0);
assertEquals("http://example.com/extensions#modext", modExt.getUrl());
assertEquals("1995-01-02", ((DateDt)modExt.getValue()).getValueAsString());
name = parsed.getName().get(0);
ext2 = name.getGiven().get(0).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext", ext2.getUrl());
assertEquals("given", ((StringDt)ext2.getValue()).getValueAsString());
given2ext = name.getGiven().get(1).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
assertNull(given2ext.getValue());
ExtensionDt given2ext2 = given2ext.getExtension().get(0);
assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
assertEquals("CHILD", ((StringDt)given2ext2.getValue()).getValue());
}
@Test
public void testEncodeBundle() throws InterruptedException {
Bundle b = new Bundle();
@ -1490,7 +1580,7 @@ public class XmlParserTest {
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));
@ -1545,7 +1635,7 @@ public class XmlParserTest {
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
fhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));

View File

@ -23,10 +23,12 @@ package ca.uhn.fhir.model.dstu2;
import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IResource;

View File

@ -13,6 +13,7 @@ import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.junit.Test;
import ca.uhn.fhir.context.ConfigurationException;
@ -20,13 +21,16 @@ 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.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.resource.Binary;
import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireAnswers;
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.BooleanDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -65,6 +69,120 @@ public class JsonParserTest {
//@formatter:on
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135");
ExtensionDt ext = new ExtensionDt();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
patient.addUndeclaredExtension(ext);
ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value2"));
parent.addUndeclaredExtension(child2);
ExtensionDt modExt = new ExtensionDt();
modExt.setUrl("http://example.com/extensions#modext");
modExt.setValue(new DateDt("1995-01-02"));
modExt.setModifier(true);
patient.addUndeclaredExtension(modExt);
HumanNameDt name = patient.addName();
name.addFamily("Blah");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given"));
given.addUndeclaredExtension(ext2);
StringDt given2 = name.addGiven();
given2.setValue("Shmoe");
ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent");
given2.addUndeclaredExtension(given2ext);
given2ext.addUndeclaredExtension(new ExtensionDt().setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD")));
String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
assertThat(enc, Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",",
"\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"
));
assertThat(enc, Matchers.stringContainsInOrder("\"modifierExtension\":[" +
"{" +
"\"url\":\"http://example.com/extensions#modext\"," +
"\"valueDate\":\"1995-01-02\"" +
"}" +
"],"));
assertThat(enc, containsString("\"_given\":[" +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext\"," +
"\"valueString\":\"given\"" +
"}" +
"]" +
"}," +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_parent\"," +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_child\"," +
"\"valueString\":\"CHILD\"" +
"}" +
"]" +
"}" +
"]" +
"}"));
/*
* Now parse this back
*/
Patient parsed =ourCtx.newJsonParser().parseResource(Patient.class, enc);
ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com/extensions#someext", ext.getUrl());
assertEquals("2011-01-02T11:13:15", ((DateTimeDt)ext.getValue()).getValueAsString());
parent = patient.getUndeclaredExtensions().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", ((StringDt)child1.getValue()).getValueAsString());
child2 = parent.getExtension().get(1);
assertEquals( "http://example.com#child", child2.getUrl());
assertEquals("value2", ((StringDt)child2.getValue()).getValueAsString());
modExt = parsed.getUndeclaredModifierExtensions().get(0);
assertEquals("http://example.com/extensions#modext", modExt.getUrl());
assertEquals("1995-01-02", ((DateDt)modExt.getValue()).getValueAsString());
name = parsed.getName().get(0);
ext2 = name.getGiven().get(0).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext", ext2.getUrl());
assertEquals("given", ((StringDt)ext2.getValue()).getValueAsString());
given2ext = name.getGiven().get(1).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
assertNull(given2ext.getValue());
ExtensionDt given2ext2 = given2ext.getExtension().get(0);
assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
assertEquals("CHILD", ((StringDt)given2ext2.getValue()).getValue());
}
/**
* #65
*/
@ -77,7 +195,7 @@ public class JsonParserTest {
String encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(parsed);
ourLog.info(encoded);
assertThat(encoded, containsString("{\"linkId\":\"value123\",\"_linkId\":{\"http://123\":[{\"valueString\":\"HELLO\"}]}}"));
assertThat(encoded, containsString("{\"linkId\":\"value123\",\"_linkId\":{\"extension\":[{\"url\":\"http://123\",\"valueString\":\"HELLO\"}]}}"));
}
@ -244,102 +362,6 @@ public class JsonParserTest {
}
@Test
public void testParseAndEncodeNewExtensionFormat() {
//@formatter:off
String resource = "{\n" +
" \"resourceType\" : \"Patient\",\n" +
" \"http://acme.org/fhir/ExtensionDefinition/trial-status\" : [{\n" +
" \"code\" : [{ \"valueCode\" : \"unsure\" }],\n" +
" \"date\" : [{ \"valueDate\" : \"2009-03-14\" }], \n" +
" \"registrar\" : [{ \"valueReference\" : {\n" +
" \"reference\" : \"Practitioner/example\"\n" +
" }\n" +
" }]\n" +
" }],\n" +
" \"modifier\" : { \n" +
" \"http://example.org/fhir/ExtensionDefinition/some-kind-of-modifier\" : [{\n" +
" \"valueBoolean\" : true\n" +
" }]\n" +
" }," +
" \"name\" : [{\n" +
" \"family\": [\n" +
" \"du\",\n" +
" \"Marché\"\n" +
" ],\n" +
" \"_family\": [\n" +
" {\n" +
" \"http://hl7.org/fhir/ExtensionDefinition/iso21090-EN-qualifier\": [\n" +
" {\n" +
" \"valueCode\": \"VV\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" null\n" +
" ],\n" +
" \"given\": [\n" +
" \"Bénédicte\"\n" +
" ]\n" +
" }],\n" +
" \"gender\" : \"M\"\n" +
"}";
//@formatter:on
// ourLog.info(resource);
Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, resource);
// Modifier extension
assertEquals(1, parsed.getUndeclaredExtensionsByUrl("http://example.org/fhir/ExtensionDefinition/some-kind-of-modifier").size());
assertTrue( parsed.getUndeclaredExtensionsByUrl("http://example.org/fhir/ExtensionDefinition/some-kind-of-modifier").get(0).isModifier());
assertEquals(BooleanDt.class, parsed.getUndeclaredExtensionsByUrl("http://example.org/fhir/ExtensionDefinition/some-kind-of-modifier").get(0).getValueAsPrimitive().getClass());
assertEquals("true", parsed.getUndeclaredExtensionsByUrl("http://example.org/fhir/ExtensionDefinition/some-kind-of-modifier").get(0).getValueAsPrimitive().getValueAsString());
// Gender
assertEquals("M",parsed.getGender());
assertEquals(1, parsed.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/trial-status").size());
// Trial status
ExtensionDt ext = parsed.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/trial-status").get(0);
assertNull(ext.getValue());
assertEquals(1, ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/code").size());
assertEquals(CodeDt.class, ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/code").get(0).getValue().getClass());
assertEquals("unsure", ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/code").get(0).getValueAsPrimitive().getValueAsString());
assertEquals(1, ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/date").size());
assertEquals(DateDt.class, ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/date").get(0).getValue().getClass());
assertEquals("2009-03-14", ext.getUndeclaredExtensionsByUrl("http://acme.org/fhir/ExtensionDefinition/date").get(0).getValueAsPrimitive().getValueAsString());
// Name
assertEquals(1, parsed.getName().size());
assertEquals(2, parsed.getName().get(0).getFamily().size());
assertEquals("du Marché", parsed.getName().get(0).getFamilyAsSingleString());
assertEquals(1, parsed.getName().get(0).getGiven().size());
assertEquals("Bénédicte", parsed.getName().get(0).getGivenAsSingleString());
// Patient.name[0].family extensions
assertEquals(1, parsed.getNameFirstRep().getFamily().get(0).getUndeclaredExtensionsByUrl("http://hl7.org/fhir/ExtensionDefinition/iso21090-EN-qualifier").size());
assertEquals(CodeDt.class, parsed.getNameFirstRep().getFamily().get(0).getUndeclaredExtensionsByUrl("http://hl7.org/fhir/ExtensionDefinition/iso21090-EN-qualifier").get(0).getValueAsPrimitive().getClass());
assertEquals("VV", parsed.getNameFirstRep().getFamily().get(0).getUndeclaredExtensionsByUrl("http://hl7.org/fhir/ExtensionDefinition/iso21090-EN-qualifier").get(0).getValueAsPrimitive().getValueAsString());
/*
* Now re-encode
*/
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
ourLog.info(encoded);
JSON expected = JSONSerializer.toJSON(resource.trim());
JSON actual = JSONSerializer.toJSON(encoded.trim());
String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("&sect;", "§");
String act = actual.toString().replace("\\r\\n", "\\n");
ourLog.info("Expected: {}", exp);
ourLog.info("Actual : {}", act);
assertEquals(exp, act);
}
@Test
public void testParseAndEncodeBundleWithDeletedEntry() {

View File

@ -1,7 +1,13 @@
package ca.uhn.fhir.parser;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.StringReader;
@ -13,8 +19,10 @@ 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.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu2.composite.DurationDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance;
import ca.uhn.fhir.model.dstu2.resource.Binary;
import ca.uhn.fhir.model.dstu2.resource.Composition;
@ -22,7 +30,11 @@ import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
public class XmlParserTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
@ -89,7 +101,8 @@ public class XmlParserTest {
public void testParseAndEncodeBundleNewStyle() throws Exception {
String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/bundle-example.xml"));
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, content);
IParser newXmlParser = ourCtx.newXmlParser();
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = newXmlParser.parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, content);
assertEquals("http://example.com/base/Bundle/example/_history/1", parsed.getId().getValue());
assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
@ -275,4 +288,93 @@ public class XmlParserTest {
assertEquals(2, parsed.getContained().getContainedResources().size());
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135");
ExtensionDt ext = new ExtensionDt();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
patient.addUndeclaredExtension(ext);
ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt().setUrl( "http://example.com#child").setValue( new StringDt("value2"));
parent.addUndeclaredExtension(child2);
ExtensionDt modExt = new ExtensionDt();
modExt.setUrl("http://example.com/extensions#modext");
modExt.setValue(new DateDt("1995-01-02"));
modExt.setModifier(true);
patient.addUndeclaredExtension(modExt);
HumanNameDt name = patient.addName();
name.addFamily("Blah");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given"));
given.addUndeclaredExtension(ext2);
StringDt given2 = name.addGiven();
given2.setValue("Shmoe");
ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent");
given2.addUndeclaredExtension(given2ext);
given2ext.addUndeclaredExtension(new ExtensionDt().setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD")));
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(
enc,
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
*/
Patient parsed =ourCtx.newXmlParser().parseResource(Patient.class, enc);
ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com/extensions#someext", ext.getUrl());
assertEquals("2011-01-02T11:13:15", ((DateTimeDt)ext.getValue()).getValueAsString());
parent = patient.getUndeclaredExtensions().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", ((StringDt)child1.getValue()).getValueAsString());
child2 = parent.getExtension().get(1);
assertEquals( "http://example.com#child", child2.getUrl());
assertEquals("value2", ((StringDt)child2.getValue()).getValueAsString());
modExt = parsed.getUndeclaredModifierExtensions().get(0);
assertEquals("http://example.com/extensions#modext", modExt.getUrl());
assertEquals("1995-01-02", ((DateDt)modExt.getValue()).getValueAsString());
name = parsed.getName().get(0);
ext2 = name.getGiven().get(0).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext", ext2.getUrl());
assertEquals("given", ((StringDt)ext2.getValue()).getValueAsString());
given2ext = name.getGiven().get(1).getUndeclaredExtensions().get(0);
assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
assertNull(given2ext.getValue());
ExtensionDt given2ext2 = given2ext.getExtension().get(0);
assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
assertEquals("CHILD", ((StringDt)given2ext2.getValue()).getValue());
}
}

View File

@ -475,21 +475,4 @@ public class IncludeTest {
}
public static void main(String[] args) {
Organization org = new Organization();
org.setId("Organization/65546");
org.getNameElement().setValue("Contained Test Organization");
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getManagingOrganization().setResource(patient);
System.out.println(new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
patient.getManagingOrganization().getReference();
}
}

View File

@ -27,7 +27,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
public class ResourceValidatorTest {
private static FhirContext ourCtx = new FhirContext();
private static FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorTest.class);
@SuppressWarnings("deprecation")

View File

@ -26,12 +26,15 @@ import java.util.ArrayList;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.conf.ServerConformanceProvider;
import org.hl7.fhir.instance.conf.ServerProfileProvider;
import org.hl7.fhir.instance.model.Extension;
import org.hl7.fhir.instance.model.Profile;
import org.hl7.fhir.instance.model.Reference;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;

View File

@ -37,11 +37,13 @@ import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
/**
* Base definition for all elements that are defined inside a resource - but not those in a data type.
*/
@DatatypeDef(name="BackboneElement")
public abstract class BackboneElement extends Element implements IBackboneElement {
public abstract class BackboneElement extends Element implements IBackboneElement, IBaseHasExtensions, IBaseHasModifierExtensions {
/**
* May be used to represent additional information that is not part of the basic definition of the element, 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.

View File

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

View File

@ -37,10 +37,11 @@ import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
/**
* Base definition for all elements in a resource.
*/
public abstract class Element extends Base {
public abstract class Element extends Base implements IBaseHasExtensions {
/**
* unique id for the element within a resource (for internal references).

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
/*
Copyright (c) 2011+, HL7, Inc
@ -33,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
/**
* Helper class to help manage generic enumerated types
*/
public interface EnumFactory<T extends Enum<?>> {
public interface EnumFactory<T extends Enum<?>> extends IBaseEnumFactory<T> {
/**
* Read an enumeration value from the string that represents it on the XML or JSON

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
/*
Copyright (c) 2011+, HL7, Inc
@ -50,6 +51,16 @@ public class Enumeration<T extends Enum<?>> extends PrimitiveType<T> {
myEnumFactory = theEnumFactory;
}
/**
* Constructor
*/
public Enumeration(IBaseEnumFactory<T> theEnumFactory) {
if (theEnumFactory == null)
throw new IllegalArgumentException("An enumeration factory must be provided");
myEnumFactory = (EnumFactory<T>) theEnumFactory;
}
/**
* Constructor
*/

View File

@ -36,12 +36,14 @@ import java.util.List;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
/**
* Optional Extensions Element - found in all resources.
*/
@DatatypeDef(name="Extension")
public class Extension extends Element implements IBaseExtension<Extension> {
public class Extension extends Element implements IBaseExtension<Extension>, IBaseHasExtensions {
/**
* Source of the definition for the extension code - a logical name or a URL.
@ -175,6 +177,11 @@ public class Extension extends Element implements IBaseExtension<Extension> {
;
}
@Override
public Extension setValue(IBaseDatatype theValue) {
return setValue((Type)theValue);
}
}

View File

@ -146,7 +146,7 @@ public class Identifier extends Type implements ICompositeType {
/**
* The purpose of this identifier.
*/
@Child(name="use", type={CodeType.class}, order=0, min=0, max=1)
@Child(name="use", type={CodeType.class}, order=0, min=0, max=1, enumFactory=IdentifierUseEnumFactory.class)
@Description(shortDefinition="usual | official | temp | secondary (If known)", formalDefinition="The purpose of this identifier." )
protected Enumeration<IdentifierUse> use;

View File

@ -2,8 +2,9 @@ package org.hl7.fhir.instance.model;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T> {
public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>, IBaseHasExtensions {
private static final long serialVersionUID = 3L;

View File

@ -34,7 +34,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hl7.fhir.instance.model.Enumeration;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
/**
* Field annotation for fields within resource and datatype definitions, indicating
@ -96,6 +98,12 @@ public @interface Child {
*/
Class<? extends IBase>[] type() default {};
/**
* For children which accept an {@link Enumeration} as the type, this
* field indicates the type to use for the enum factory
*/
Class<? extends IBaseEnumFactory<?>> enumFactory() default NoEnumFactory.class;
// Not implemented
// /**
// * This value is used when extending a built-in model class and defining a
@ -105,5 +113,23 @@ public @interface Child {
// * HumanNameDt which adds extensions of your choosing) you could do that using a replacement field.
// */
// String replaces() default "";
public static class NoEnumFactory implements IBaseEnumFactory<Enum<?>> {
private NoEnumFactory() {
// non instantiable
}
@Override
public Enum<?> fromCode(String theCodeString) throws IllegalArgumentException {
return null;
}
@Override
public String toCode(Enum<?> theCode) {
return null;
}
}
}

View File

@ -1,19 +1,24 @@
package ca.uhn.fhir.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.hl7.fhir.instance.model.Address;
import org.hl7.fhir.instance.model.BackboneElement;
import org.hl7.fhir.instance.model.Base;
import org.hl7.fhir.instance.model.BooleanType;
import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Coding;
import org.hl7.fhir.instance.model.DecimalType;
import org.hl7.fhir.instance.model.DomainResource;
import org.hl7.fhir.instance.model.Element;
import org.hl7.fhir.instance.model.Extension;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.ICompositeType;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.IdType;
import org.hl7.fhir.instance.model.Identifier;
import org.hl7.fhir.instance.model.IntegerType;
import org.hl7.fhir.instance.model.Meta;
import org.hl7.fhir.instance.model.Narrative;
@ -22,7 +27,9 @@ import org.hl7.fhir.instance.model.Reference;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.Timing;
import org.hl7.fhir.instance.model.Type;
import org.hl7.fhir.instance.model.Identifier.IdentifierUseEnumFactory;
import org.hl7.fhir.instance.model.annotations.Block;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
@ -30,6 +37,8 @@ import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
import org.hl7.fhir.instance.model.api.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.ICoding;
import org.hl7.fhir.instance.model.api.IDatatypeElement;
@ -56,6 +65,9 @@ public class ModelInheritanceTest {
*
* ElementDefinition
* * Backbone elements (eg .ElementDefinitionSlicingComponent) do not extend BackboneElement or have a @Block annotation for some reason
*
* Extension
* * Should URL not be StringType since it can't take extensions?
* </pre>
*/
@ -76,13 +88,20 @@ public class ModelInheritanceTest {
public void testBase() {
assertTrue(IBase.class.isAssignableFrom(Base.class));
}
public void testIdentifierUse() throws Exception {
Child child = Identifier.class.getField("use").getAnnotation(Child.class);
assertEquals(IdentifierUseEnumFactory.class, child.enumFactory());
}
/**
* Should be "implements IBaseExtension<Extension>"
*/
@Test
public void testExtension() {
assertTrue(IBaseExtension.class.isAssignableFrom(Extension.class));
assertTrue(IBaseHasExtensions.class.isAssignableFrom(Extension.class));
}
@Test
@ -108,6 +127,7 @@ public class ModelInheritanceTest {
@Test
public void testPrimitiveType() {
assertTrue(IPrimitiveType.class.isAssignableFrom(PrimitiveType.class));
assertTrue(IBaseHasExtensions.class.isAssignableFrom(PrimitiveType.class));
}
@Test
@ -136,7 +156,20 @@ public class ModelInheritanceTest {
@Test
public void testBackboneElement() {
assertTrue(IBackboneElement.class.isAssignableFrom(IBackboneElement.class));
assertTrue(IBackboneElement.class.isAssignableFrom(BackboneElement.class));
assertTrue(IBaseHasExtensions.class.isAssignableFrom(BackboneElement.class));
assertTrue(IBaseHasModifierExtensions.class.isAssignableFrom(BackboneElement.class));
}
@Test
public void testElement() {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(Element.class));
}
@Test
public void testDomainResource() {
assertTrue(IBaseHasExtensions.class.isAssignableFrom(DomainResource.class));
assertTrue(IBaseHasModifierExtensions.class.isAssignableFrom(DomainResource.class));
}
@Test

View File

@ -1,7 +1,16 @@
package ca.uhn.fhir.parser;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.OutputStreamWriter;
@ -25,15 +34,16 @@ import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.Conformance;
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.Extension;
import org.hl7.fhir.instance.model.HumanName;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.Identifier.IdentifierUse;
import org.hl7.fhir.instance.model.InstantType;
import org.hl7.fhir.instance.model.List_;
import org.hl7.fhir.instance.model.Identifier.IdentifierUse;
import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
import org.hl7.fhir.instance.model.Observation;
import org.hl7.fhir.instance.model.Organization;
@ -83,6 +93,119 @@ public class JsonParserTest {
}
@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.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",",
"\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"
));
assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("\"modifierExtension\":[" +
"{" +
"\"url\":\"http://example.com/extensions#modext\"," +
"\"valueDate\":\"1995-01-02\"" +
"}" +
"],"));
assertThat(enc, containsString("\"_given\":[" +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext\"," +
"\"valueString\":\"given\"" +
"}" +
"]" +
"}," +
"{" +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_parent\"," +
"\"extension\":[" +
"{" +
"\"url\":\"http://examples.com#givenext_child\"," +
"\"valueString\":\"CHILD\"" +
"}" +
"]" +
"}" +
"]" +
"}"));
/*
* Now parse this back
*/
Patient parsed =ourCtx.newJsonParser().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());
}
@Test
public void testEncodeNonContained() {
Organization org = new Organization();
@ -740,6 +863,7 @@ public class JsonParserTest {
enc,
containsString("<extension><extension><url value=\"http://example.com#child\"/><valueString value=\"value1\"/></extension><extension><url value=\"http://example.com#child\"/><valueString value=\"value1\"/></extension><url value=\"http://example.com#parent\"/></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension><url value=\"http://examples.com#givenext\"/><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension><extension><url value=\"http://examples.com#givenext\"/><valueString value=\"given\"/></extension><url value=\"http://examples.com#givenext_child\"/></extension></given>"));
}

View File

@ -37,6 +37,7 @@ import org.hl7.fhir.instance.model.Composition;
import org.hl7.fhir.instance.model.Conformance;
import org.hl7.fhir.instance.model.Conformance.ConformanceRestResourceComponent;
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.DocumentManifest;
@ -876,7 +877,7 @@ public class XmlParserTest {
}
@Test
public void testMoreExtensions() throws Exception {
public void testEncodeAndParseExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
@ -884,14 +885,22 @@ public class XmlParserTest {
Extension ext = new Extension();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.getExtension().add(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
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("Shmoe");
name.addFamily("Blah");
StringType given = name.addGivenElement();
given.setValue("Joe");
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
@ -902,28 +911,55 @@ public class XmlParserTest {
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"));
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
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("value1"));
parent.getExtension().add(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension><url value=\"http://example.com/extensions#someext\"/><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(
enc,
containsString("<extension><extension><url value=\"http://example.com#child\"/><valueString value=\"value1\"/></extension><extension><url value=\"http://example.com#child\"/><valueString value=\"value1\"/></extension><url value=\"http://example.com#parent\"/></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension><url value=\"http://examples.com#givenext\"/><valueString value=\"given\"/></extension></given>"));
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
*/
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());
}
@Test

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -107,5 +108,11 @@ public class FhirDev implements IFhirVersion {
}
@Override
public IBaseExtension<?> newExtension() {
return null;
}
}

View File

@ -35,6 +35,7 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
@ -379,6 +380,11 @@ public class FhirDstu1 implements IFhirVersion {
return ContainedDt.class;
}
@Override
public IBaseExtension<?> newExtension() {
return null;
}
}

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.model.dstu2;
import java.io.InputStream;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -92,4 +93,9 @@ public class FhirDstu2 implements IFhirVersion {
throw new UnsupportedOperationException();
}
@Override
public IBaseExtension<?> newExtension() {
return null;
}
}

View File

@ -141,6 +141,29 @@
</subsection>
<subsection name="Configure the Server's Identity/Web Address">
<p>
The server will return data in a number of places that includes the
complete "identity" of a resource. Identity in this case refers to the
web address that a user can use to access the resource.
</p>
<p>
For instance, if your server is hosted at <code>http://foo.com/fhir</code>
and your resource provider returns a Patient resource with the ID "123",
the server should translate that ID to "http://foo.com/fhir/Patient/123".
</p>
<p>
The server will attempt to determine what the base URL should be based on
what the request it receives looks like, but if it is not getting
the right address you may wish to hardcode the base URL, as shown
in the following example:
</p>
<macro name="snippet">
<param name="id" value="addressStrategy" />
<param name="file" value="examples/src/main/java/example/ExampleProviders.java" />
</macro>
</subsection>
<subsection name="Deploy">
<p>