Begin multi version work
This commit is contained in:
parent
383d4929c8
commit
c294e1c064
|
@ -50,16 +50,20 @@ import ca.uhn.fhir.util.FhirTerser;
|
|||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
|
||||
/**
|
||||
* The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then used as a factory for various other types of objects (parsers, clients, etc.).
|
||||
* The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then
|
||||
* used as a factory for various other types of objects (parsers, clients, etc.).
|
||||
*
|
||||
* <p>
|
||||
* Important usage notes:
|
||||
* <ul>
|
||||
* <li>Thread safety: <b>This class is thread safe</b> and may be shared between multiple processing threads.</li>
|
||||
* <li>
|
||||
* Performance: <b>This class is expensive</b> to create, as it scans every resource class it needs to parse or encode to build up an internal model of those classes. For that reason, you should try
|
||||
* to create one FhirContext instance which remains for the life of your application and reuse that instance. Note that it will not cause problems to create multiple instances (ie. resources
|
||||
* originating from one FhirContext may be passed to parsers originating from another) but you will incur a performance penalty if a new FhirContext is created for every message you parse/encode.</li>
|
||||
* Performance: <b>This class is expensive</b> to create, as it scans every resource class it needs to parse or encode
|
||||
* to build up an internal model of those classes. For that reason, you should try to create one FhirContext instance
|
||||
* which remains for the life of your application and reuse that instance. Note that it will not cause problems to
|
||||
* create multiple instances (ie. resources originating from one FhirContext may be passed to parsers originating from
|
||||
* another) but you will incur a performance penalty if a new FhirContext is created for every message you parse/encode.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
|
@ -74,7 +78,7 @@ public class FhirContext {
|
|||
private volatile INarrativeGenerator myNarrativeGenerator;
|
||||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||
private IFhirVersion myVersion;
|
||||
private final IFhirVersion myVersion;
|
||||
|
||||
/**
|
||||
* Default constructor. In most cases this is the right constructor to use.
|
||||
|
@ -92,18 +96,31 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
public FhirContext(Collection<Class<? extends IResource>> theResourceTypes) {
|
||||
scanResourceTypes(theResourceTypes);
|
||||
this(null, theResourceTypes);
|
||||
}
|
||||
|
||||
if (FhirVersionEnum.DSTU1.isPresentOnClasspath()) {
|
||||
public FhirContext(FhirVersionEnum theVersion) {
|
||||
this(theVersion, null);
|
||||
}
|
||||
|
||||
private FhirContext(FhirVersionEnum theVersion, Collection<Class<? extends IResource>> theResourceTypes) {
|
||||
if (theVersion != null) {
|
||||
if (!theVersion.isPresentOnClasspath()) {
|
||||
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructuresForSpecifiedVersion"));
|
||||
}
|
||||
myVersion = theVersion.getVersionImplementation();
|
||||
} else if (FhirVersionEnum.DSTU1.isPresentOnClasspath()) {
|
||||
myVersion = FhirVersionEnum.DSTU1.getVersionImplementation();
|
||||
} else {
|
||||
throw new IllegalStateException("Could not find any HAPI-FHIR structure JARs on the classpath. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath or project pom.xml");
|
||||
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructures"));
|
||||
}
|
||||
|
||||
scanResourceTypes(theResourceTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||
* for extending the core library.
|
||||
*/
|
||||
public BaseRuntimeElementDefinition<?> getElementDefinition(Class<? extends IElement> theElementType) {
|
||||
return myClassToElementDefinition.get(theElementType);
|
||||
|
@ -115,7 +132,8 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with caution
|
||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||
* caution
|
||||
*/
|
||||
public HapiLocalizer getLocalizer() {
|
||||
if (myLocalizer == null) {
|
||||
|
@ -129,7 +147,8 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||
* for extending the core library.
|
||||
*/
|
||||
public RuntimeResourceDefinition getResourceDefinition(Class<? extends IResource> theResourceType) {
|
||||
RuntimeResourceDefinition retVal = (RuntimeResourceDefinition) myClassToElementDefinition.get(theResourceType);
|
||||
|
@ -140,21 +159,24 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||
* for extending the core library.
|
||||
*/
|
||||
public RuntimeResourceDefinition getResourceDefinition(IResource theResource) {
|
||||
return getResourceDefinition(theResource.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||
* for extending the core library.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public RuntimeResourceDefinition getResourceDefinition(String theResourceName) {
|
||||
String resourceName = theResourceName;
|
||||
|
||||
/*
|
||||
* TODO: this is a bit of a hack, really we should have a translation table based on a property file or something so that we can detect names like diagnosticreport
|
||||
* TODO: this is a bit of a hack, really we should have a translation table based on a property file or
|
||||
* something so that we can detect names like diagnosticreport
|
||||
*/
|
||||
if (Character.isLowerCase(resourceName.charAt(0))) {
|
||||
resourceName = WordUtils.capitalize(resourceName);
|
||||
|
@ -188,14 +210,16 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||
* for extending the core library.
|
||||
*/
|
||||
public RuntimeResourceDefinition getResourceDefinitionById(String theId) {
|
||||
return myIdToResourceDefinition.get(theId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the core library.
|
||||
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the
|
||||
* core library.
|
||||
*/
|
||||
public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
||||
return myIdToResourceDefinition.values();
|
||||
|
@ -220,10 +244,12 @@ public class FhirContext {
|
|||
* Create and return a new JSON parser.
|
||||
*
|
||||
* <p>
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or every message being parsed/encoded.
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread
|
||||
* or every message being parsed/encoded.
|
||||
* </p>
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed without incurring any performance penalty
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed
|
||||
* without incurring any performance penalty
|
||||
* </p>
|
||||
*/
|
||||
public IParser newJsonParser() {
|
||||
|
@ -231,12 +257,16 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new client instance. This method requires an interface which is defined specifically for your use cases to contain methods for each of the RESTful operations you wish to
|
||||
* implement (e.g. "read ImagingStudy", "search Patient by identifier", etc.). This interface must extend {@link IRestfulClient} (or commonly its sub-interface {@link IBasicClient}). See the <a
|
||||
* href="http://hl7api.sourceforge.net/hapi-fhir/doc_rest_client.html">RESTful Client</a> documentation for more information on how to define this interface.
|
||||
* Instantiates a new client instance. This method requires an interface which is defined specifically for your use
|
||||
* cases to contain methods for each of the RESTful operations you wish to implement (e.g. "read ImagingStudy",
|
||||
* "search Patient by identifier", etc.). This interface must extend {@link IRestfulClient} (or commonly its
|
||||
* sub-interface {@link IBasicClient}). See the <a
|
||||
* href="http://hl7api.sourceforge.net/hapi-fhir/doc_rest_client.html">RESTful Client</a> documentation for more
|
||||
* information on how to define this interface.
|
||||
*
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every operation invocation without incurring any performance penalty
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every operation invocation
|
||||
* without incurring any performance penalty
|
||||
* </p>
|
||||
*
|
||||
* @param theClientType
|
||||
|
@ -252,11 +282,13 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new generic client. A generic client is able to perform any of the FHIR RESTful operations against a compliant server, but does not have methods defining the specific
|
||||
* functionality required (as is the case with {@link #newRestfulClient(Class, String) non-generic clients}).
|
||||
* Instantiates a new generic client. A generic client is able to perform any of the FHIR RESTful operations against
|
||||
* a compliant server, but does not have methods defining the specific functionality required (as is the case with
|
||||
* {@link #newRestfulClient(Class, String) non-generic clients}).
|
||||
*
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every operation invocation without incurring any performance penalty
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every operation invocation
|
||||
* without incurring any performance penalty
|
||||
* </p>
|
||||
*
|
||||
* @param theServerBase
|
||||
|
@ -283,10 +315,12 @@ public class FhirContext {
|
|||
* Create and return a new XML parser.
|
||||
*
|
||||
* <p>
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or every message being parsed/encoded.
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread
|
||||
* or every message being parsed/encoded.
|
||||
* </p>
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed without incurring any performance penalty
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed
|
||||
* without incurring any performance penalty
|
||||
* </p>
|
||||
*/
|
||||
public IParser newXmlParser() {
|
||||
|
@ -328,7 +362,8 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with caution
|
||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||
* caution
|
||||
*/
|
||||
public void setLocalizer(HapiLocalizer theMessages) {
|
||||
myLocalizer = theMessages;
|
||||
|
@ -356,4 +391,18 @@ public class FhirContext {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU1}
|
||||
*/
|
||||
public static FhirContext forDstu1() {
|
||||
return new FhirContext(FhirVersionEnum.DSTU1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DEV}
|
||||
*/
|
||||
public static FhirContext forDev() {
|
||||
return new FhirContext(FhirVersionEnum.DEV);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,15 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
|
||||
public enum FhirVersionEnum {
|
||||
|
||||
DSTU1("ca.uhn.fhir.model.dstu.FhirDstu1");
|
||||
/*
|
||||
* ***********************
|
||||
* Don't sort this type!!!
|
||||
* ***********************
|
||||
*/
|
||||
|
||||
DSTU1("ca.uhn.fhir.model.dstu.FhirDstu1"),
|
||||
|
||||
DEV("ca.uhn.fhir.model.dev.FhirDev");
|
||||
|
||||
private final String myVersionClass;
|
||||
private volatile Boolean myPresentOnClasspath;
|
||||
|
@ -35,6 +43,10 @@ public enum FhirVersionEnum {
|
|||
myVersionClass = theVersionClass;
|
||||
}
|
||||
|
||||
public boolean isNewerThan(FhirVersionEnum theVersion) {
|
||||
return ordinal() > theVersion.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given version is present on the classpath
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.context;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -93,20 +93,26 @@ class ModelScanner {
|
|||
private FhirContext myContext;
|
||||
|
||||
ModelScanner(FhirContext theContext, Class<? extends IResource> theResourceTypes) throws ConfigurationException {
|
||||
myContext=theContext;
|
||||
myContext = theContext;
|
||||
Set<Class<? extends IElement>> singleton = new HashSet<Class<? extends IElement>>();
|
||||
singleton.add(theResourceTypes);
|
||||
init(null, singleton);
|
||||
}
|
||||
|
||||
ModelScanner(FhirContext theContext, Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
|
||||
myContext=theContext;
|
||||
myContext = theContext;
|
||||
init(null, new HashSet<Class<? extends IElement>>(theResourceTypes));
|
||||
}
|
||||
|
||||
ModelScanner(FhirContext theContext, Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> theExistingDefinitions, Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
|
||||
myContext=theContext;
|
||||
init(theExistingDefinitions, new HashSet<Class<? extends IElement>>(theResourceTypes));
|
||||
myContext = theContext;
|
||||
Set<Class<? extends IElement>> toScan;
|
||||
if (theResourceTypes != null) {
|
||||
toScan = new HashSet<Class<? extends IElement>>(theResourceTypes);
|
||||
} else {
|
||||
toScan = new HashSet<Class<? extends IElement>>();
|
||||
}
|
||||
init(theExistingDefinitions, toScan);
|
||||
}
|
||||
|
||||
public Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> getClassToElementDefinitions() {
|
||||
|
@ -175,13 +181,7 @@ class ModelScanner {
|
|||
int startSize = myClassToElementDefinitions.size();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
InputStream str = ModelScanner.class.getResourceAsStream("/ca/uhn/fhir/model/dstu/fhirversion.properties");
|
||||
if (str == null) {
|
||||
str = ModelScanner.class.getResourceAsStream("ca/uhn/fhir/model/dstu/fhirversion.properties");
|
||||
}
|
||||
if (str == null) {
|
||||
throw new ConfigurationException("Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dstu/model.properties");
|
||||
}
|
||||
InputStream str = myContext.getVersion().getFhirVersionPropertiesFile();
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
prop.load(str);
|
||||
|
@ -386,13 +386,13 @@ class ModelScanner {
|
|||
for (Field next : theClass.getDeclaredFields()) {
|
||||
|
||||
if (Modifier.isFinal(next.getModifiers())) {
|
||||
ourLog.trace("Ignoring constant {} on target type {}", next.getName(), theClass);
|
||||
ourLog.trace("Ignoring constant {} on target type {}", next.getName(), theClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
Child childAnnotation = next.getAnnotation(Child.class);
|
||||
if (childAnnotation == null) {
|
||||
ourLog.trace("Ignoring non @Child field {} on target type {}",next.getName() , theClass);
|
||||
ourLog.trace("Ignoring non @Child field {} on target type {}", next.getName(), theClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -422,8 +422,8 @@ class ModelScanner {
|
|||
}
|
||||
}
|
||||
if (order == Child.REPLACE_PARENT) {
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT + ") but no parent element with extension URL " + extensionAttr.url()
|
||||
+ " could be found on type " + next.getDeclaringClass().getSimpleName());
|
||||
throw new ConfigurationException("Field " + next.getName() + "' on target type " + theClass.getSimpleName() + " has order() of REPLACE_PARENT (" + Child.REPLACE_PARENT + ") but no parent element with extension URL " + extensionAttr.url() + " could be found on type "
|
||||
+ next.getDeclaringClass().getSimpleName());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -454,7 +454,7 @@ class ModelScanner {
|
|||
int min = childAnnotation.min();
|
||||
int max = childAnnotation.max();
|
||||
/*
|
||||
* Anything that's marked as unknown is given a new ID that is <0 so that it doesn't conflict wityh any
|
||||
* Anything that's marked as unknown is given a new ID that is <0 so that it doesn't conflict with any
|
||||
* given IDs and can be figured out later
|
||||
*/
|
||||
while (order == Child.ORDER_UNKNOWN && orderMap.containsKey(order)) {
|
||||
|
|
|
@ -37,23 +37,27 @@ public class HapiLocalizer {
|
|||
myBundle = ResourceBundle.getBundle(HapiLocalizer.class.getPackage().getName() + ".hapi-messages");
|
||||
}
|
||||
|
||||
public String getMessage(String theKey, Object... theParameters) {
|
||||
public String getMessage(Class<?> theType, String theKey, Object... theParameters) {
|
||||
return getMessage(theType.getName() + '.' + theKey, theParameters);
|
||||
}
|
||||
|
||||
public String getMessage(String theQualifiedKey, Object... theParameters) {
|
||||
if (theParameters != null && theParameters.length > 0) {
|
||||
MessageFormat format = myKeyToMessageFormat.get(theKey);
|
||||
MessageFormat format = myKeyToMessageFormat.get(theQualifiedKey);
|
||||
if (format != null) {
|
||||
return format.format(theParameters).toString();
|
||||
}
|
||||
|
||||
String formatString = myBundle.getString(theKey);
|
||||
String formatString = myBundle.getString(theQualifiedKey);
|
||||
if (formatString== null) {
|
||||
formatString = "!MESSAGE!";
|
||||
}
|
||||
|
||||
format = new MessageFormat(formatString);
|
||||
myKeyToMessageFormat.put(theKey, format);
|
||||
myKeyToMessageFormat.put(theQualifiedKey, format);
|
||||
return format.format(theParameters).toString();
|
||||
} else {
|
||||
String retVal = myBundle.getString(theKey);
|
||||
String retVal = myBundle.getString(theQualifiedKey);
|
||||
if (retVal == null) {
|
||||
retVal = "!MESSAGE!";
|
||||
}
|
||||
|
|
|
@ -20,20 +20,18 @@ package ca.uhn.fhir.model.api;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
|
||||
public abstract class BaseResource extends BaseElement implements IResource {
|
||||
|
@ -70,7 +68,7 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||
@Child(name = "language", order = 0, min = 0, max = Child.MAX_UNLIMITED)
|
||||
private CodeDt myLanguage;
|
||||
|
||||
private Map<ResourceMetadataKeyEnum<?>, Object> myResourceMetadata;
|
||||
private ResourceMetadataMap myResourceMetadata;
|
||||
|
||||
@Child(name = "text", order = 1, min = 0, max = 1)
|
||||
private NarrativeDt myText;
|
||||
|
@ -99,9 +97,9 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<ResourceMetadataKeyEnum<?>, Object> getResourceMetadata() {
|
||||
public ResourceMetadataMap getResourceMetadata() {
|
||||
if (myResourceMetadata == null) {
|
||||
myResourceMetadata = new HashMap<ResourceMetadataKeyEnum<?>, Object>();
|
||||
myResourceMetadata = new ResourceMetadataMap();
|
||||
}
|
||||
return myResourceMetadata;
|
||||
}
|
||||
|
@ -136,7 +134,7 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setResourceMetadata(Map<ResourceMetadataKeyEnum<?>, Object> theMap) {
|
||||
public void setResourceMetadata(ResourceMetadataMap theMap) {
|
||||
Validate.notNull(theMap, "The Map must not be null");
|
||||
myResourceMetadata = theMap;
|
||||
}
|
||||
|
|
|
@ -34,17 +34,21 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
public class Bundle extends BaseBundle /* implements IElement */{
|
||||
|
||||
private ResourceMetadataMap myResourceMetadata;
|
||||
private BoundCodeDt<BundleTypeEnum> myType;
|
||||
private StringDt myBundleId;
|
||||
|
||||
private TagList myCategories;
|
||||
private List<BundleEntry> myEntries;
|
||||
private volatile transient Map<IdDt, IResource> myIdToEntries;
|
||||
|
@ -60,7 +64,8 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
private InstantDt myUpdated;
|
||||
|
||||
/**
|
||||
* @deprecated Tags wil become immutable in a future release of HAPI, so {@link #addCategory(String, String, String)} should be used instead
|
||||
* @deprecated Tags wil become immutable in a future release of HAPI, so
|
||||
* {@link #addCategory(String, String, String)} should be used instead
|
||||
*/
|
||||
public Tag addCategory() {
|
||||
Tag retVal = new Tag();
|
||||
|
@ -72,7 +77,6 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
getCategories().add(new Tag(theScheme, theTerm, theLabel));
|
||||
}
|
||||
|
||||
|
||||
public void addCategory(Tag theTag) {
|
||||
getCategories().add(theTag);
|
||||
}
|
||||
|
@ -208,6 +212,27 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
return entry;
|
||||
}
|
||||
|
||||
public StringDt getBundleId() {
|
||||
if (myBundleId == null) {
|
||||
myBundleId = new StringDt();
|
||||
}
|
||||
return myBundleId;
|
||||
}
|
||||
|
||||
public TagList getCategories() {
|
||||
if (myCategories == null) {
|
||||
myCategories = new TagList();
|
||||
}
|
||||
return myCategories;
|
||||
}
|
||||
|
||||
public List<BundleEntry> getEntries() {
|
||||
if (myEntries == null) {
|
||||
myEntries = new ArrayList<BundleEntry>();
|
||||
}
|
||||
return myEntries;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
//
|
||||
// FhirContext ctx = new FhirContext();
|
||||
|
@ -234,27 +259,6 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
// }
|
||||
//
|
||||
|
||||
public StringDt getBundleId() {
|
||||
if (myBundleId == null) {
|
||||
myBundleId = new StringDt();
|
||||
}
|
||||
return myBundleId;
|
||||
}
|
||||
|
||||
public TagList getCategories() {
|
||||
if (myCategories == null) {
|
||||
myCategories = new TagList();
|
||||
}
|
||||
return myCategories;
|
||||
}
|
||||
|
||||
public List<BundleEntry> getEntries() {
|
||||
if (myEntries == null) {
|
||||
myEntries = new ArrayList<BundleEntry>();
|
||||
}
|
||||
return myEntries;
|
||||
}
|
||||
|
||||
public StringDt getLinkBase() {
|
||||
if (myLinkBase == null) {
|
||||
myLinkBase = new StringDt();
|
||||
|
@ -307,9 +311,11 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
/**
|
||||
* Retrieves a resource from a bundle given its logical ID.
|
||||
* <p>
|
||||
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
|
||||
* <code>http://bar/Patient/123</code>. Also, this method is intended to be used for bundles which have already been populated. It will cache its results for fast performance, but that means that
|
||||
* modifications to the bundle after this method is called may not be accurately reflected.
|
||||
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of
|
||||
* <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
|
||||
* <code>http://bar/Patient/123</code>. Also, this method is intended to be used for bundles which have already been
|
||||
* populated. It will cache its results for fast performance, but that means that modifications to the bundle after
|
||||
* this method is called may not be accurately reflected.
|
||||
* </p>
|
||||
*
|
||||
* @param theId
|
||||
|
@ -330,6 +336,13 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
return map.get(theId.toUnqualified());
|
||||
}
|
||||
|
||||
public ResourceMetadataMap getResourceMetadata() {
|
||||
if (myResourceMetadata == null) {
|
||||
myResourceMetadata = new ResourceMetadataMap();
|
||||
}
|
||||
return myResourceMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all resources of the given type from this bundle
|
||||
*/
|
||||
|
@ -359,6 +372,13 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
return myTotalResults;
|
||||
}
|
||||
|
||||
public BoundCodeDt<BundleTypeEnum> getType() {
|
||||
if (myType == null) {
|
||||
myType = new BoundCodeDt<BundleTypeEnum>(BundleTypeEnum.VALUESET_BINDER);
|
||||
}
|
||||
return myType;
|
||||
}
|
||||
|
||||
public InstantDt getUpdated() {
|
||||
if (myUpdated == null) {
|
||||
myUpdated = new InstantDt();
|
||||
|
@ -382,6 +402,10 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
myPublished = thePublished;
|
||||
}
|
||||
|
||||
public void setType(BoundCodeDt<BundleTypeEnum> theType) {
|
||||
myType = theType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of entries in this bundle
|
||||
*/
|
||||
|
|
|
@ -24,9 +24,13 @@ import org.apache.commons.lang3.Validate;
|
|||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
|
||||
public class BundleEntry extends BaseBundle {
|
||||
|
@ -38,20 +42,61 @@ public class BundleEntry extends BaseBundle {
|
|||
//@formatter:on
|
||||
private TagList myCategories;
|
||||
private InstantDt myDeletedAt;
|
||||
private CodeDt myDeletedResourceType;
|
||||
private StringDt myDeletedResourceId;
|
||||
private StringDt myDeletedResourceVersion;
|
||||
|
||||
public CodeDt getDeletedResourceType() {
|
||||
if (myDeletedResourceType == null) {
|
||||
myDeletedResourceType = new CodeDt();
|
||||
}
|
||||
return myDeletedResourceType;
|
||||
}
|
||||
|
||||
public void setDeletedResourceType(CodeDt theDeletedResourceType) {
|
||||
myDeletedResourceType = theDeletedResourceType;
|
||||
}
|
||||
|
||||
public StringDt getDeletedResourceId() {
|
||||
if (myDeletedResourceId == null) {
|
||||
myDeletedResourceId = new StringDt();
|
||||
}
|
||||
return myDeletedResourceId;
|
||||
}
|
||||
|
||||
public void setDeletedResourceId(StringDt theDeletedResourceId) {
|
||||
myDeletedResourceId = theDeletedResourceId;
|
||||
}
|
||||
|
||||
public StringDt getDeletedResourceVersion() {
|
||||
if (myDeletedResourceVersion == null) {
|
||||
myDeletedResourceVersion = new StringDt();
|
||||
}
|
||||
return myDeletedResourceVersion;
|
||||
}
|
||||
|
||||
public void setDeletedResourceVersion(StringDt theDeletedResourceVersion) {
|
||||
myDeletedResourceVersion = theDeletedResourceVersion;
|
||||
}
|
||||
|
||||
private StringDt myDeletedByEmail;
|
||||
private StringDt myDeletedByName;
|
||||
private StringDt myDeletedComment;
|
||||
private StringDt myLinkAlternate;
|
||||
private StringDt myLinkSearch;
|
||||
private StringDt myLinkSelf;
|
||||
private StringDt myLinkBase;
|
||||
private InstantDt myPublished;
|
||||
private IResource myResource;
|
||||
private XhtmlDt mySummary;
|
||||
private StringDt myTitle;
|
||||
private InstantDt myUpdated;
|
||||
private BoundCodeDt<BundleEntryStatusEnum> myStatus;
|
||||
private DecimalDt myScore;
|
||||
|
||||
/**
|
||||
* @deprecated Tags wil become immutable in a future release of HAPI, so {@link #addCategory(String, String, String)} should be used instead
|
||||
* @deprecated Tags wil become immutable in a future release of HAPI, so
|
||||
* {@link #addCategory(String, String, String)} should be used instead
|
||||
*/
|
||||
public Tag addCategory() {
|
||||
Tag retVal = new Tag();
|
||||
|
@ -112,6 +157,13 @@ public class BundleEntry extends BaseBundle {
|
|||
return myLinkAlternate;
|
||||
}
|
||||
|
||||
public StringDt getLinkBase() {
|
||||
if (myLinkBase == null) {
|
||||
myLinkBase = new StringDt();
|
||||
}
|
||||
return myLinkBase;
|
||||
}
|
||||
|
||||
public StringDt getLinkSearch() {
|
||||
if (myLinkSearch == null) {
|
||||
myLinkSearch = new StringDt();
|
||||
|
@ -137,6 +189,13 @@ public class BundleEntry extends BaseBundle {
|
|||
return myResource;
|
||||
}
|
||||
|
||||
public BoundCodeDt<BundleEntryStatusEnum> getStatus() {
|
||||
if (myStatus == null) {
|
||||
myStatus = new BoundCodeDt<BundleEntryStatusEnum>(BundleEntryStatusEnum.VALUESET_BINDER);
|
||||
}
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
public XhtmlDt getSummary() {
|
||||
if (mySummary == null) {
|
||||
mySummary = new XhtmlDt();
|
||||
|
@ -162,7 +221,7 @@ public class BundleEntry extends BaseBundle {
|
|||
public boolean isEmpty() {
|
||||
//@formatter:off
|
||||
return super.isEmpty() &&
|
||||
ElementUtil.isEmpty(myCategories, myDeletedAt, myLinkAlternate, myLinkSelf, myPublished, myResource, mySummary, myTitle, myUpdated, myDeletedByEmail, myDeletedByName, myDeletedComment);
|
||||
ElementUtil.isEmpty(myDeletedResourceId, myDeletedResourceType, myDeletedResourceVersion, myScore,myStatus, myCategories, myDeletedAt, myLinkAlternate, myLinkSelf, myPublished, myResource, mySummary, myTitle, myUpdated, myDeletedByEmail, myDeletedByName, myDeletedComment);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
|
@ -192,6 +251,10 @@ public class BundleEntry extends BaseBundle {
|
|||
myLinkAlternate = theLinkAlternate;
|
||||
}
|
||||
|
||||
public void setLinkBase(StringDt theLinkBase) {
|
||||
myLinkBase = theLinkBase;
|
||||
}
|
||||
|
||||
public void setLinkSearch(StringDt theLinkSearch) {
|
||||
myLinkSearch = theLinkSearch;
|
||||
}
|
||||
|
@ -212,6 +275,10 @@ public class BundleEntry extends BaseBundle {
|
|||
myResource = theResource;
|
||||
}
|
||||
|
||||
public void setStatus(BoundCodeDt<BundleEntryStatusEnum> theStatus) {
|
||||
myStatus = theStatus;
|
||||
}
|
||||
|
||||
public void setUpdated(InstantDt theUpdated) {
|
||||
Validate.notNull(theUpdated, "Updated may not be null");
|
||||
myUpdated = theUpdated;
|
||||
|
@ -229,4 +296,15 @@ public class BundleEntry extends BaseBundle {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
public DecimalDt getScore() {
|
||||
if (myScore == null) {
|
||||
myScore = new DecimalDt();
|
||||
}
|
||||
return myScore;
|
||||
}
|
||||
|
||||
public void setScore(DecimalDt theScore) {
|
||||
myScore = theScore;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,16 +20,23 @@ package ca.uhn.fhir.model.api;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
||||
public interface IFhirVersion {
|
||||
|
||||
FhirVersionEnum getVersion();
|
||||
|
||||
IResource generateProfile(RuntimeResourceDefinition theRuntimeResourceDefinition);
|
||||
|
||||
Object createServerConformanceProvider(RestfulServer theServer);
|
||||
|
||||
IResourceProvider createServerProfilesProvider(RestfulServer theRestfulServer);
|
||||
|
||||
InputStream getFhirVersionPropertiesFile();
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.model.api;
|
|||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
|
@ -88,7 +89,7 @@ public interface IResource extends ICompositeElement {
|
|||
* @see ResourceMetadataKeyEnum for a list of allowable keys and the object
|
||||
* types that values of a given key must use.
|
||||
*/
|
||||
Map<ResourceMetadataKeyEnum<?>, Object> getResourceMetadata();
|
||||
ResourceMetadataMap getResourceMetadata();
|
||||
|
||||
/**
|
||||
* Returns the narrative block for this resource
|
||||
|
@ -122,7 +123,7 @@ public interface IResource extends ICompositeElement {
|
|||
* @throws NullPointerException
|
||||
* The map must not be null
|
||||
*/
|
||||
void setResourceMetadata(Map<ResourceMetadataKeyEnum<?>, Object> theMap);
|
||||
void setResourceMetadata(ResourceMetadataMap theMap);
|
||||
|
||||
/**
|
||||
* Returns a String representing the name of this Resource. This return
|
||||
|
|
|
@ -206,6 +206,24 @@ public abstract class ResourceMetadataKeyEnum<T> {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The value for this key is the version ID of the resource object.
|
||||
* <p>
|
||||
* Values for this key are of type <b>{@link String}</b>
|
||||
* </p>
|
||||
*/
|
||||
public static final ResourceMetadataKeyEnum<String> VERSION = new ResourceMetadataKeyEnum<String>("VERSION") {
|
||||
@Override
|
||||
public String get(IResource theResource) {
|
||||
return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(IResource theResource, String theObject) {
|
||||
theResource.getResourceMetadata().put(VERSION, theObject);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If present and populated with a string, provides the "search link" (the link element in the bundle entry with <code>rel="search"</code>). Server implementations may populate this with a
|
||||
* complete URL, in which case the URL will be placed as-is in the bundle. They may alternately specify a resource relative URL (e.g. "Patient?name=tester") in which case the server will convert
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.model.base.resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
|
||||
public class ResourceMetadataMap extends HashMap<ResourceMetadataKeyEnum<?>, Object> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -44,6 +44,7 @@ import ca.uhn.fhir.model.api.IResource;
|
|||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
@ -86,6 +87,7 @@ public class ResourceReferenceDt
|
|||
* @param theResource
|
||||
* The resource instance
|
||||
*/
|
||||
@SimpleSetter()
|
||||
public ResourceReferenceDt(IResource theResource) {
|
||||
super(theResource);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.commons.lang3.ObjectUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.hamcrest.core.IsNot;
|
||||
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
@ -134,6 +135,23 @@ public class IdDt implements IPrimitiveDatatype<String> {
|
|||
* The version ID ("e.g. "456")
|
||||
*/
|
||||
public IdDt(String theResourceType, String theId, String theVersionId) {
|
||||
this(null,theResourceType,theId,theVersionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theBaseUrl
|
||||
* The server base URL (e.g. "http://example.com/fhir")
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theId
|
||||
* The ID (e.g. "123")
|
||||
* @param theVersionId
|
||||
* The version ID ("e.g. "456")
|
||||
*/
|
||||
public IdDt(String theBaseUrl, String theResourceType, String theId, String theVersionId) {
|
||||
myBaseUrl = theBaseUrl;
|
||||
myResourceType = theResourceType;
|
||||
myUnqualifiedId = theId;
|
||||
myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionId, null);
|
||||
|
@ -242,10 +260,21 @@ public class IdDt implements IPrimitiveDatatype<String> {
|
|||
public String getValue() {
|
||||
if (myValue == null && myHaveComponentParts) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isNotBlank(myBaseUrl)) {
|
||||
b.append(myBaseUrl);
|
||||
if (myBaseUrl.charAt(myBaseUrl.length()-1)!='/') {
|
||||
b.append('/');
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotBlank(myResourceType)) {
|
||||
b.append(myResourceType);
|
||||
}
|
||||
|
||||
if (b.length() > 0) {
|
||||
b.append('/');
|
||||
}
|
||||
|
||||
b.append(myUnqualifiedId);
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
package ca.uhn.fhir.model.valueset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
|
||||
public enum BundleEntryStatusEnum {
|
||||
|
||||
CREATE("create", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
UPDATE("update", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
MATCH("match", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
INCLUDE("include", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Identifier for this Value Set:
|
||||
* http://hl7.org/fhir/vs/address-use
|
||||
*/
|
||||
public static final String VALUESET_IDENTIFIER = "http://hl7.org/fhir/bundle-entry-status";
|
||||
|
||||
/**
|
||||
* Name for this Value Set:
|
||||
* AddressUse
|
||||
*/
|
||||
public static final String VALUESET_NAME = "BundleEntryStatus";
|
||||
|
||||
private static Map<String, BundleEntryStatusEnum> CODE_TO_ENUM = new HashMap<String, BundleEntryStatusEnum>();
|
||||
private static Map<String, Map<String, BundleEntryStatusEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, BundleEntryStatusEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (BundleEntryStatusEnum next : BundleEntryStatusEnum.values()) {
|
||||
CODE_TO_ENUM.put(next.getCode(), next);
|
||||
|
||||
if (!SYSTEM_TO_CODE_TO_ENUM.containsKey(next.getSystem())) {
|
||||
SYSTEM_TO_CODE_TO_ENUM.put(next.getSystem(), new HashMap<String, BundleEntryStatusEnum>());
|
||||
}
|
||||
SYSTEM_TO_CODE_TO_ENUM.get(next.getSystem()).put(next.getCode(), next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code associated with this enumerated value
|
||||
*/
|
||||
public String getCode() {
|
||||
return myCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code system associated with this enumerated value
|
||||
*/
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enumerated value associated with this code
|
||||
*/
|
||||
public BundleEntryStatusEnum forCode(String theCode) {
|
||||
BundleEntryStatusEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<BundleEntryStatusEnum> VALUESET_BINDER = new IValueSetEnumBinder<BundleEntryStatusEnum>() {
|
||||
@Override
|
||||
public String toCodeString(BundleEntryStatusEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(BundleEntryStatusEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryStatusEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryStatusEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, BundleEntryStatusEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(theCodeString);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
BundleEntryStatusEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
package ca.uhn.fhir.model.valueset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
|
||||
public enum BundleTypeEnum {
|
||||
|
||||
TRANSACTION("transaction", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
DOCUMENT("document", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
MESSAGE("message", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
TRANSACTION_RESPONSE("transaction-response", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
HISTORY("history", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
SEARCHSET("searchset", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
COLLECTION("collection", "http://hl7.org/fhir/bundle-type"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Identifier for this Value Set:
|
||||
* http://hl7.org/fhir/vs/address-use
|
||||
*/
|
||||
public static final String VALUESET_IDENTIFIER = "http://hl7.org/fhir/bundle-type";
|
||||
|
||||
/**
|
||||
* Name for this Value Set:
|
||||
* AddressUse
|
||||
*/
|
||||
public static final String VALUESET_NAME = "BundleType";
|
||||
|
||||
private static Map<String, BundleTypeEnum> CODE_TO_ENUM = new HashMap<String, BundleTypeEnum>();
|
||||
private static Map<String, Map<String, BundleTypeEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, BundleTypeEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (BundleTypeEnum next : BundleTypeEnum.values()) {
|
||||
CODE_TO_ENUM.put(next.getCode(), next);
|
||||
|
||||
if (!SYSTEM_TO_CODE_TO_ENUM.containsKey(next.getSystem())) {
|
||||
SYSTEM_TO_CODE_TO_ENUM.put(next.getSystem(), new HashMap<String, BundleTypeEnum>());
|
||||
}
|
||||
SYSTEM_TO_CODE_TO_ENUM.get(next.getSystem()).put(next.getCode(), next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code associated with this enumerated value
|
||||
*/
|
||||
public String getCode() {
|
||||
return myCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code system associated with this enumerated value
|
||||
*/
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enumerated value associated with this code
|
||||
*/
|
||||
public BundleTypeEnum forCode(String theCode) {
|
||||
BundleTypeEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<BundleTypeEnum> VALUESET_BINDER = new IValueSetEnumBinder<BundleTypeEnum>() {
|
||||
@Override
|
||||
public String toCodeString(BundleTypeEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(BundleTypeEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleTypeEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleTypeEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, BundleTypeEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(theCodeString);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
BundleTypeEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@ import java.util.Set;
|
|||
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonNumber;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonReader;
|
||||
import javax.json.JsonString;
|
||||
|
@ -56,6 +57,7 @@ import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||
|
@ -86,22 +88,32 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
|||
|
||||
public class JsonParser extends BaseParser implements IParser {
|
||||
|
||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN;
|
||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1;
|
||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU2;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParser.HeldExtension.class);
|
||||
|
||||
static {
|
||||
HashSet<String> hashSet = new HashSet<String>();
|
||||
hashSet.add("title");
|
||||
hashSet.add("id");
|
||||
hashSet.add("updated");
|
||||
hashSet.add("published");
|
||||
BUNDLE_TEXTNODE_CHILDREN = Collections.unmodifiableSet(hashSet);
|
||||
HashSet<String> hashSetDstu1 = new HashSet<String>();
|
||||
hashSetDstu1.add("title");
|
||||
hashSetDstu1.add("id");
|
||||
hashSetDstu1.add("updated");
|
||||
hashSetDstu1.add("published");
|
||||
BUNDLE_TEXTNODE_CHILDREN_DSTU1 = Collections.unmodifiableSet(hashSetDstu1);
|
||||
|
||||
HashSet<String> hashSetDstu2 = new HashSet<String>();
|
||||
hashSetDstu2.add("type");
|
||||
hashSetDstu2.add("base");
|
||||
hashSetDstu2.add("total");
|
||||
BUNDLE_TEXTNODE_CHILDREN_DSTU2 = Collections.unmodifiableSet(hashSetDstu2);
|
||||
}
|
||||
|
||||
private FhirContext myContext;
|
||||
|
||||
private boolean myPrettyPrint;
|
||||
|
||||
/**
|
||||
* Do not use this constructor, the recommended way to obtain a new instance of the JSON parser is to invoke
|
||||
* {@link FhirContext#newJsonParser()}.
|
||||
*/
|
||||
public JsonParser(FhirContext theContext) {
|
||||
super(theContext);
|
||||
myContext = theContext;
|
||||
|
@ -145,6 +157,15 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
@Override
|
||||
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
|
||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
encodeBundleToWriterInDstu2Format(theBundle, eventWriter);
|
||||
}else {
|
||||
encodeBundleToWriterInDstu1Format(theBundle, eventWriter);
|
||||
}
|
||||
eventWriter.flush();
|
||||
}
|
||||
|
||||
private void encodeBundleToWriterInDstu1Format(Bundle theBundle, JsonGenerator eventWriter) throws IOException {
|
||||
eventWriter.writeStartObject();
|
||||
|
||||
eventWriter.write("resourceType", "Bundle");
|
||||
|
@ -155,12 +176,12 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
writeOptionalTagWithTextNode(eventWriter, "published", theBundle.getPublished());
|
||||
|
||||
boolean linkStarted = false;
|
||||
linkStarted = writeAtomLink(eventWriter, "self", theBundle.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "first", theBundle.getLinkFirst(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "next", theBundle.getLinkNext(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "last", theBundle.getLinkLast(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "self", theBundle.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "first", theBundle.getLinkFirst(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "previous", theBundle.getLinkPrevious(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "next", theBundle.getLinkNext(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "last", theBundle.getLinkLast(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "fhir-base", theBundle.getLinkBase(), linkStarted);
|
||||
if (linkStarted) {
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
|
@ -183,9 +204,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
|
||||
|
||||
linkStarted = false;
|
||||
linkStarted = writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "alternate", nextEntry.getLinkAlternate(), linkStarted);
|
||||
linkStarted = writeAtomLink(eventWriter, "search", nextEntry.getLinkSearch(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "self", nextEntry.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "alternate", nextEntry.getLinkAlternate(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "search", nextEntry.getLinkSearch(), linkStarted);
|
||||
if (linkStarted) {
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
|
@ -203,7 +224,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
encodeResourceToJsonStreamWriter(resDef, resource, eventWriter, "content", false);
|
||||
}
|
||||
|
||||
if (nextEntry.getSummary().isEmpty()==false) {
|
||||
if (nextEntry.getSummary().isEmpty() == false) {
|
||||
eventWriter.write("summary", nextEntry.getSummary().getValueAsString());
|
||||
}
|
||||
|
||||
|
@ -212,25 +233,71 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
eventWriter.writeEnd(); // entry array
|
||||
|
||||
eventWriter.writeEnd();
|
||||
eventWriter.flush();
|
||||
}
|
||||
|
||||
private void writeCategories(JsonGenerator eventWriter, TagList categories) {
|
||||
if (categories != null && categories.size() > 0) {
|
||||
eventWriter.writeStartArray("category");
|
||||
for (Tag next : categories) {
|
||||
eventWriter.writeStartObject();
|
||||
eventWriter.write("term", defaultString(next.getTerm()));
|
||||
eventWriter.write("label", defaultString(next.getLabel()));
|
||||
eventWriter.write("scheme", defaultString(next.getScheme()));
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
private void encodeBundleToWriterInDstu2Format(Bundle theBundle, JsonGenerator eventWriter) throws IOException {
|
||||
eventWriter.writeStartObject();
|
||||
|
||||
eventWriter.write("resourceType", "Bundle");
|
||||
|
||||
writeTagWithTextNode(eventWriter, "id", theBundle.getId().getIdPart());
|
||||
writeOptionalTagWithTextNode(eventWriter, "type", theBundle.getType());
|
||||
writeOptionalTagWithTextNode(eventWriter, "base", theBundle.getLinkBase());
|
||||
writeOptionalTagWithNumberNode(eventWriter, "base", theBundle.getTotalResults());
|
||||
|
||||
boolean linkStarted = false;
|
||||
linkStarted = writeAtomLinkInDstu2Format(eventWriter, "self", theBundle.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu2Format(eventWriter, "first", theBundle.getLinkFirst(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu2Format(eventWriter, "previous", theBundle.getLinkPrevious(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu2Format(eventWriter, "next", theBundle.getLinkNext(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu2Format(eventWriter, "last", theBundle.getLinkLast(), linkStarted);
|
||||
if (linkStarted) {
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
|
||||
eventWriter.writeStartArray("entry");
|
||||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
eventWriter.writeStartObject();
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "base", nextEntry.getLinkBase());
|
||||
writeOptionalTagWithTextNode(eventWriter, "status", nextEntry.getStatus());
|
||||
writeOptionalTagWithTextNode(eventWriter, "search", nextEntry.getLinkSearch());
|
||||
writeOptionalTagWithDecimalNode(eventWriter, "score", nextEntry.getScore());
|
||||
|
||||
linkStarted = false;
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "self", nextEntry.getLinkSelf(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "alternate", nextEntry.getLinkAlternate(), linkStarted);
|
||||
linkStarted = writeAtomLinkInDstu1Format(eventWriter, "search", nextEntry.getLinkSearch(), linkStarted);
|
||||
if (linkStarted) {
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
|
||||
|
||||
writeCategories(eventWriter, nextEntry.getCategories());
|
||||
|
||||
writeAuthor(nextEntry, eventWriter);
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
if (resource != null && !resource.isEmpty() && !deleted) {
|
||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource);
|
||||
encodeResourceToJsonStreamWriter(resDef, resource, eventWriter, "content", false);
|
||||
}
|
||||
|
||||
if (nextEntry.getSummary().isEmpty() == false) {
|
||||
eventWriter.write("summary", nextEntry.getSummary().getValueAsString());
|
||||
}
|
||||
|
||||
eventWriter.writeEnd(); // entry object
|
||||
}
|
||||
eventWriter.writeEnd(); // entry array
|
||||
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
||||
String theChildName, boolean theIsSubElementWithinResource) throws IOException {
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException {
|
||||
|
||||
switch (theChildDef.getChildType()) {
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
|
@ -305,7 +372,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theWriter.writeStartArray(theChildName);
|
||||
ContainedDt value = (ContainedDt) theValue;
|
||||
for (IResource next : value.getContainedResources()) {
|
||||
if (getContainedResources().getResourceId(next)!=null) {
|
||||
if (getContainedResources().getResourceId(next) != null) {
|
||||
continue;
|
||||
}
|
||||
encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, fixContainedResourceId(next.getId().getValue()));
|
||||
|
@ -341,8 +408,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
|
||||
for (BaseRuntimeChildDefinition nextChild : theChildren) {
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
|
@ -395,12 +461,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
||||
// Don't encode extensions
|
||||
// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
||||
// if (extDef.isModifier()) {
|
||||
// addToHeldExtensions(valueIdx, modifierExtensions, extDef, nextValue);
|
||||
// } else {
|
||||
// addToHeldExtensions(valueIdx, extensions, extDef, nextValue);
|
||||
// }
|
||||
// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition)
|
||||
// nextChild;
|
||||
// if (extDef.isModifier()) {
|
||||
// addToHeldExtensions(valueIdx, modifierExtensions, extDef, nextValue);
|
||||
// } else {
|
||||
// addToHeldExtensions(valueIdx, extensions, extDef, nextValue);
|
||||
// }
|
||||
} else {
|
||||
|
||||
if (currentChildName == null || !currentChildName.equals(childName)) {
|
||||
|
@ -465,15 +532,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
|
||||
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, resDef, theResDef, theResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(),theIsSubElementWithinResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(), theIsSubElementWithinResource);
|
||||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||
boolean theIsSubElementWithinResource) throws IOException {
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theIsSubElementWithinResource) throws IOException {
|
||||
String resourceId = null;
|
||||
if (theIsSubElementWithinResource && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
resourceId = theResource.getId().getValue();
|
||||
|
@ -482,8 +547,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theIsSubElementWithinResource, resourceId);
|
||||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theIsSubElementWithinResource,
|
||||
String theResourceId) throws IOException {
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theIsSubElementWithinResource, String theResourceId) throws IOException {
|
||||
if (!theIsSubElementWithinResource) {
|
||||
super.containResourcesForEncoding(theResource);
|
||||
}
|
||||
|
@ -553,10 +617,10 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object called _name): resource extensions, and extension extensions
|
||||
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object
|
||||
* called _name): resource extensions, and extension extensions
|
||||
*/
|
||||
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
|
||||
IResource theResource) throws IOException {
|
||||
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef, IResource theResource) throws IOException {
|
||||
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
||||
List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
||||
|
||||
|
@ -665,7 +729,11 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
ParserState<Bundle> state = ParserState.getPreAtomInstance(myContext, theResourceType, true);
|
||||
state.enteringNewElement(null, "feed");
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
state.enteringNewElement(null, "Bundle");
|
||||
} else {
|
||||
state.enteringNewElement(null, "feed");
|
||||
}
|
||||
|
||||
parseBundleChildren(object, state);
|
||||
|
||||
|
@ -680,18 +748,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
for (String nextName : theObject.keySet()) {
|
||||
if ("resourceType".equals(nextName)) {
|
||||
continue;
|
||||
} else if ("link".equals(nextName)) {
|
||||
JsonArray entries = theObject.getJsonArray(nextName);
|
||||
for (JsonValue jsonValue : entries) {
|
||||
theState.enteringNewElement(null, "link");
|
||||
JsonObject linkObj = (JsonObject) jsonValue;
|
||||
String rel = linkObj.getString("rel", null);
|
||||
String href = linkObj.getString("href", null);
|
||||
theState.attributeValue("rel", rel);
|
||||
theState.attributeValue("href", href);
|
||||
theState.endingElement();
|
||||
}
|
||||
continue;
|
||||
} else if ("entry".equals(nextName)) {
|
||||
JsonArray entries = theObject.getJsonArray(nextName);
|
||||
for (JsonValue jsonValue : entries) {
|
||||
|
@ -700,11 +756,60 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theState.endingElement();
|
||||
}
|
||||
continue;
|
||||
} else if (BUNDLE_TEXTNODE_CHILDREN.contains(nextName)) {
|
||||
theState.enteringNewElement(null, nextName);
|
||||
theState.string(theObject.getString(nextName, null));
|
||||
theState.endingElement();
|
||||
continue;
|
||||
} else if (myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
if ("link".equals(nextName)) {
|
||||
JsonArray entries = theObject.getJsonArray(nextName);
|
||||
for (JsonValue jsonValue : entries) {
|
||||
theState.enteringNewElement(null, "link");
|
||||
JsonObject linkObj = (JsonObject) jsonValue;
|
||||
String rel = linkObj.getString("rel", null);
|
||||
String href = linkObj.getString("href", null);
|
||||
theState.attributeValue("rel", rel);
|
||||
theState.attributeValue("href", href);
|
||||
theState.endingElement();
|
||||
}
|
||||
continue;
|
||||
} else if (BUNDLE_TEXTNODE_CHILDREN_DSTU1.contains(nextName)) {
|
||||
theState.enteringNewElement(null, nextName);
|
||||
theState.string(theObject.getString(nextName, null));
|
||||
theState.endingElement();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ("link".equals(nextName)) {
|
||||
JsonArray entries = theObject.getJsonArray(nextName);
|
||||
for (JsonValue jsonValue : entries) {
|
||||
theState.enteringNewElement(null, "link");
|
||||
JsonObject linkObj = (JsonObject) jsonValue;
|
||||
String rel = linkObj.getString("relation", null);
|
||||
String href = linkObj.getString("url", null);
|
||||
theState.enteringNewElement(null, "relation");
|
||||
theState.attributeValue("value", rel);
|
||||
theState.endingElement();
|
||||
theState.enteringNewElement(null, "url");
|
||||
theState.attributeValue("value", href);
|
||||
theState.endingElement();
|
||||
theState.endingElement();
|
||||
}
|
||||
continue;
|
||||
} else if (BUNDLE_TEXTNODE_CHILDREN_DSTU2.contains(nextName)) {
|
||||
theState.enteringNewElement(null, nextName);
|
||||
// String obj = theObject.getString(nextName, null);
|
||||
|
||||
JsonValue obj = theObject.get(nextName);
|
||||
if (obj == null) {
|
||||
theState.attributeValue("value", null);
|
||||
} else if (obj instanceof JsonString) {
|
||||
theState.attributeValue("value", theObject.getString(nextName, null));
|
||||
} else if (obj instanceof JsonNumber) {
|
||||
theState.attributeValue("value", obj.toString());
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected JSON object for entry '" + nextName + "'");
|
||||
}
|
||||
|
||||
theState.endingElement();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
JsonValue nextVal = theObject.get(nextName);
|
||||
|
@ -720,7 +825,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
continue;
|
||||
} else if ("id".equals(nextName)) {
|
||||
elementId = theObject.getString(nextName);
|
||||
continue;
|
||||
// if (myContext.getVersion().getVersion()==FhirVersionEnum.DSTU1) {
|
||||
// continue;
|
||||
// }
|
||||
} else if ("_id".equals(nextName)) {
|
||||
// _id is incorrect, but some early examples in the FHIR spec used it
|
||||
elementId = theObject.getString(nextName);
|
||||
|
@ -893,7 +1000,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
return this;
|
||||
}
|
||||
|
||||
private boolean writeAtomLink(JsonGenerator theEventWriter, String theRel, StringDt theLink, boolean theStarted) {
|
||||
private boolean writeAtomLinkInDstu1Format(JsonGenerator theEventWriter, String theRel, StringDt theLink, boolean theStarted) {
|
||||
boolean retVal = theStarted;
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
if (theStarted == false) {
|
||||
|
@ -909,6 +1016,21 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private boolean writeAtomLinkInDstu2Format(JsonGenerator theEventWriter, String theRel, StringDt theLink, boolean theStarted) {
|
||||
boolean retVal = theStarted;
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
if (theStarted == false) {
|
||||
theEventWriter.writeStartArray("link");
|
||||
retVal = true;
|
||||
}
|
||||
|
||||
theEventWriter.writeStartObject();
|
||||
theEventWriter.write("relation", theRel);
|
||||
theEventWriter.write("url", theLink.getValue());
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
private void writeAuthor(BaseBundle theBundle, JsonGenerator eventWriter) {
|
||||
if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
|
||||
eventWriter.writeStartArray("author");
|
||||
|
@ -920,8 +1042,21 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
||||
List<HeldExtension> modifierExtensions) throws IOException {
|
||||
private void writeCategories(JsonGenerator eventWriter, TagList categories) {
|
||||
if (categories != null && categories.size() > 0) {
|
||||
eventWriter.writeStartArray("category");
|
||||
for (Tag next : categories) {
|
||||
eventWriter.writeStartObject();
|
||||
eventWriter.write("term", defaultString(next.getTerm()));
|
||||
eventWriter.write("label", defaultString(next.getLabel()));
|
||||
eventWriter.write("scheme", defaultString(next.getScheme()));
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) throws IOException {
|
||||
if (extensions.isEmpty() == false) {
|
||||
theEventWriter.writeStartArray("extension");
|
||||
for (HeldExtension next : extensions) {
|
||||
|
@ -938,6 +1073,17 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithNumberNode(JsonGenerator theEventWriter, String theElementName, IntegerDt theValue) {
|
||||
if (theValue != null && theValue.isEmpty()==false) {
|
||||
theEventWriter.write(theElementName, theValue.getValue().intValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithDecimalNode(JsonGenerator theEventWriter, String theElementName, DecimalDt theValue) {
|
||||
if (theValue != null && theValue.isEmpty()==false) {
|
||||
theEventWriter.write(theElementName, theValue.getValue());
|
||||
}
|
||||
}
|
||||
private void writeOptionalTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IPrimitiveDatatype<?> theInstantDt) {
|
||||
String str = theInstantDt.getValueAsString();
|
||||
if (StringUtils.isNotBlank(str)) {
|
||||
|
@ -953,6 +1099,14 @@ 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());
|
||||
|
@ -995,7 +1149,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
// theEventWriter, myValue, def, "value" +
|
||||
// WordUtils.capitalize(def.getName()));
|
||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName,false);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
@ -1026,7 +1180,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
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);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
|
|
@ -37,6 +37,7 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeElemContainedResources;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
|
@ -59,11 +60,13 @@ import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
|||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.IModelVisitor;
|
||||
|
@ -158,7 +161,8 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoked after any new XML event is individually processed, containing a copy of the XML event. This is basically intended for embedded XHTML content
|
||||
* Invoked after any new XML event is individually processed, containing a copy of the XML event. This is basically
|
||||
* intended for embedded XHTML content
|
||||
*/
|
||||
public void xmlEvent(XMLEvent theNextEvent) {
|
||||
myState.xmlEvent(theNextEvent);
|
||||
|
@ -166,7 +170,11 @@ class ParserState<T> {
|
|||
|
||||
public static ParserState<Bundle> getPreAtomInstance(FhirContext theContext, Class<? extends IResource> theResourceType, boolean theJsonMode) throws DataFormatException {
|
||||
ParserState<Bundle> retVal = new ParserState<Bundle>(theContext, theJsonMode);
|
||||
retVal.push(retVal.new PreAtomState(theResourceType));
|
||||
if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
retVal.push(retVal.new PreAtomState(theResourceType));
|
||||
} else {
|
||||
retVal.push(retVal.new PreBundleState(theResourceType));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -241,7 +249,8 @@ class ParserState<T> {
|
|||
myScheme = theValue;
|
||||
} else if ("value".equals(theName)) {
|
||||
/*
|
||||
* This handles XML parsing, which is odd for this quasi-resource type, since the tag has three values instead of one like everything else.
|
||||
* This handles XML parsing, which is odd for this quasi-resource type, since the tag has three values
|
||||
* instead of one like everything else.
|
||||
*/
|
||||
switch (myCatState) {
|
||||
case STATE_LABEL:
|
||||
|
@ -289,6 +298,33 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
public class AtomDeletedEntryByState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
||||
public AtomDeletedEntryByState(BundleEntry theEntry) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("name".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getDeletedByName()));
|
||||
} else if ("email".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getDeletedByEmail()));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element in entry: " + theLocalPart);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AtomDeletedEntryState extends AtomEntryState {
|
||||
|
||||
public AtomDeletedEntryState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||
|
@ -304,6 +340,12 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
putPlacerResourceInDeletedEntry(getEntry());
|
||||
super.endingElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("by".equals(theLocalPart) && verifyNamespace(XmlParser.TOMBSTONES_NS, theNamespaceURI)) {
|
||||
|
@ -315,39 +357,6 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
putPlacerResourceInDeletedEntry(getEntry());
|
||||
super.endingElement();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AtomDeletedEntryByState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
||||
public AtomDeletedEntryByState(BundleEntry theEntry) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("name".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getDeletedByName()));
|
||||
} else if ("email".equals(theLocalPart)) {
|
||||
push(new AtomPrimitiveState(myEntry.getDeletedByEmail()));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element in entry: " + theLocalPart);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class AtomDeletedJsonWhenState extends BaseState {
|
||||
|
@ -654,6 +663,72 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
private class BasePreAtomOrBundleState extends BaseState {
|
||||
|
||||
private Bundle myInstance;
|
||||
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public BasePreAtomOrBundleState(Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
public Bundle getInstance() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
protected Class<? extends IResource> getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setInstance(Bundle theInstance) {
|
||||
myInstance = theInstance;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void wereBack() {
|
||||
myObject = (T) myInstance;
|
||||
|
||||
/*
|
||||
* Stitch together resource references
|
||||
*/
|
||||
|
||||
Map<String, IResource> idToResource = new HashMap<String, IResource>();
|
||||
List<IResource> resources = myInstance.toListOfResources();
|
||||
for (IResource next : resources) {
|
||||
if (next.getId() != null && next.getId().isEmpty() == false) {
|
||||
idToResource.put(next.getId().toUnqualifiedVersionless().getValue(), next);
|
||||
}
|
||||
}
|
||||
|
||||
for (IResource next : resources) {
|
||||
List<ResourceReferenceDt> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, ResourceReferenceDt.class);
|
||||
for (ResourceReferenceDt nextRef : refs) {
|
||||
if (nextRef.isEmpty() == false && nextRef.getReference() != null) {
|
||||
IResource target = idToResource.get(nextRef.getReference().getValue());
|
||||
if (target != null) {
|
||||
nextRef.setResource(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private abstract class BaseState {
|
||||
|
||||
private PreResourceState myPreResourceState;
|
||||
|
@ -809,6 +884,303 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
private class BundleEntryDeletedState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
||||
public BundleEntryDeletedState(PreResourceState thePreResourceState, BundleEntry theEntry) {
|
||||
super(thePreResourceState);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
String resType = myEntry.getDeletedResourceType().getValue();
|
||||
String id = myEntry.getDeletedResourceId().getValue();
|
||||
String version = myEntry.getDeletedResourceVersion().getValue();
|
||||
myEntry.setLinkSelf(new StringDt(new IdDt(resType, id, version).getValue()));
|
||||
putPlacerResourceInDeletedEntry(myEntry);
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("type".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getDeletedResourceType()));
|
||||
} else if ("id".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getDeletedResourceId()));
|
||||
} else if ("version".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getDeletedResourceVersion()));
|
||||
} else if ("instant".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getDeletedAt()));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element '" + theLocalPart + "' in element 'deleted'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class BundleEntryState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public BundleEntryState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myEntry = new BundleEntry();
|
||||
myResourceType = theResourceType;
|
||||
theInstance.getEntries().add(myEntry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
populateResourceMetadata();
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("base".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getLinkBase()));
|
||||
} else if ("status".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getStatus()));
|
||||
} else if ("search".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getLinkSearch()));
|
||||
} else if ("score".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getScore()));
|
||||
} else if ("resource".equals(theLocalPart)) {
|
||||
push(new PreResourceState(myEntry, myResourceType));
|
||||
} else if ("deleted".equals(theLocalPart)) {
|
||||
push(new BundleEntryDeletedState(getPreResourceState(), myEntry));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element in entry: " + theLocalPart);
|
||||
}
|
||||
|
||||
// TODO: handle category
|
||||
}
|
||||
|
||||
protected BundleEntry getEntry() {
|
||||
return myEntry;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void populateResourceMetadata() {
|
||||
if (myEntry.getResource() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IdDt id = myEntry.getId();
|
||||
if (id != null && id.isEmpty() == false) {
|
||||
myEntry.getResource().setId(id);
|
||||
}
|
||||
|
||||
Map<ResourceMetadataKeyEnum<?>, Object> metadata = myEntry.getResource().getResourceMetadata();
|
||||
if (myEntry.getPublished().isEmpty() == false) {
|
||||
ResourceMetadataKeyEnum.PUBLISHED.put(myEntry.getResource(), myEntry.getPublished());
|
||||
}
|
||||
if (myEntry.getUpdated().isEmpty() == false) {
|
||||
ResourceMetadataKeyEnum.UPDATED.put(myEntry.getResource(), myEntry.getUpdated());
|
||||
}
|
||||
|
||||
ResourceMetadataKeyEnum.TITLE.put(myEntry.getResource(), myEntry.getTitle().getValue());
|
||||
|
||||
if (myEntry.getCategories().isEmpty() == false) {
|
||||
TagList tagList = new TagList();
|
||||
for (Tag next : myEntry.getCategories()) {
|
||||
tagList.add(next);
|
||||
}
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(myEntry.getResource(), tagList);
|
||||
}
|
||||
if (!myEntry.getLinkSelf().isEmpty()) {
|
||||
String linkSelfValue = myEntry.getLinkSelf().getValue();
|
||||
IdDt linkSelf = new IdDt(linkSelfValue);
|
||||
myEntry.getResource().setId(linkSelf);
|
||||
if (isNotBlank(linkSelf.getVersionIdPart())) {
|
||||
metadata.put(ResourceMetadataKeyEnum.VERSION_ID, linkSelf);
|
||||
}
|
||||
}
|
||||
if (!myEntry.getLinkAlternate().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.LINK_ALTERNATE.put(myEntry.getResource(), myEntry.getLinkAlternate().getValue());
|
||||
}
|
||||
if (!myEntry.getLinkSearch().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(myEntry.getResource(), myEntry.getLinkSearch().getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class BundleLinkState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
private String myHref;
|
||||
private Bundle myInstance;
|
||||
private String myRel;
|
||||
private boolean myInRelation = false;
|
||||
private boolean myInUrl = false;
|
||||
|
||||
public BundleLinkState(Bundle theInstance) {
|
||||
super(null);
|
||||
myInstance = theInstance;
|
||||
}
|
||||
|
||||
public BundleLinkState(BundleEntry theEntry) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
if (myInRelation) {
|
||||
myRel = theValue;
|
||||
} else if (myInUrl) {
|
||||
myHref = theValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
if (!myInRelation && !myInUrl) {
|
||||
if (myInstance != null) {
|
||||
if ("self".equals(myRel)) {
|
||||
myInstance.getLinkSelf().setValueAsString(myHref);
|
||||
} else if ("first".equals(myRel)) {
|
||||
myInstance.getLinkFirst().setValueAsString(myHref);
|
||||
} else if ("previous".equals(myRel)) {
|
||||
myInstance.getLinkPrevious().setValueAsString(myHref);
|
||||
} else if ("next".equals(myRel)) {
|
||||
myInstance.getLinkNext().setValueAsString(myHref);
|
||||
} else if ("last".equals(myRel)) {
|
||||
myInstance.getLinkLast().setValueAsString(myHref);
|
||||
} else if ("fhir-base".equals(myRel)) {
|
||||
myInstance.getLinkBase().setValueAsString(myHref);
|
||||
}
|
||||
} else {
|
||||
if ("self".equals(myRel)) {
|
||||
myEntry.getLinkSelf().setValueAsString(myHref);
|
||||
} else if ("search".equals(myRel)) {
|
||||
myEntry.getLinkSearch().setValueAsString(myHref);
|
||||
} else if ("alternate".equals(myRel)) {
|
||||
myEntry.getLinkAlternate().setValueAsString(myHref);
|
||||
}
|
||||
}
|
||||
pop();
|
||||
} else {
|
||||
myInRelation = false;
|
||||
myInUrl = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if (myInRelation || myInUrl) {
|
||||
throw new DataFormatException("Unexpected element '" + theLocalPart + "' in element 'link'");
|
||||
}
|
||||
if ("relation".equals(theLocalPart)) {
|
||||
myInRelation = true;
|
||||
} else if ("url".equals(theLocalPart)) {
|
||||
myInUrl = true;
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element '" + theLocalPart + "' in element 'link'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class BundleState extends BaseState {
|
||||
|
||||
private Bundle myInstance;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public BundleState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myInstance = theInstance;
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wereBack() {
|
||||
for (BundleEntry nextEntry : myInstance.getEntries()) {
|
||||
IResource nextResource = nextEntry.getResource();
|
||||
|
||||
String baseUrl = myInstance.getLinkBase().getValue();
|
||||
String version = ResourceMetadataKeyEnum.VERSION.get(nextResource);
|
||||
String resourceName = myContext.getResourceDefinition(nextResource).getName();
|
||||
nextResource.setId(new IdDt(baseUrl, resourceName, nextResource.getId().getIdPart(), version));
|
||||
}
|
||||
|
||||
String bundleVersion = (String) myInstance.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION);
|
||||
String baseUrl = myInstance.getLinkBase().getValue();
|
||||
String id = myInstance.getId().getIdPart();
|
||||
myInstance.setId(new IdDt(baseUrl, "Bundle", id, bundleVersion));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("id".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(null, myInstance.getId()));
|
||||
} else if ("meta".equals(theLocalPart)) {
|
||||
push(new MetaElementState(null, myInstance.getResourceMetadata()));
|
||||
} else if ("type".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myInstance.getType()));
|
||||
} else if ("base".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myInstance.getLinkBase()));
|
||||
} else if ("total".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myInstance.getTotalResults()));
|
||||
} else if ("link".equals(theLocalPart)) {
|
||||
push(new BundleLinkState(myInstance));
|
||||
} else if ("entry".equals(theLocalPart)) {
|
||||
push(new BundleEntryState(myInstance, myResourceType));
|
||||
} else {
|
||||
throw new DataFormatException("Unxpected element '" + theLocalPart + " in element 'Bundle'");
|
||||
}
|
||||
|
||||
// if ("entry".equals(theLocalPart) && verifyNamespace(XmlParser.ATOM_NS, theNamespaceURI)) {
|
||||
// push(new AtomEntryState(myInstance, myResourceType));
|
||||
// } else if (theLocalPart.equals("published")) {
|
||||
// push(new AtomPrimitiveState(myInstance.getPublished()));
|
||||
// } else if (theLocalPart.equals("title")) {
|
||||
// push(new AtomPrimitiveState(myInstance.getTitle()));
|
||||
// } else if ("id".equals(theLocalPart)) {
|
||||
// push(new AtomPrimitiveState(myInstance.getBundleId()));
|
||||
// } else if ("link".equals(theLocalPart)) {
|
||||
// push(new AtomLinkState(myInstance));
|
||||
// } else if ("totalResults".equals(theLocalPart) && (verifyNamespace(XmlParser.OPENSEARCH_NS,
|
||||
// theNamespaceURI) || verifyNamespace(Constants.OPENSEARCH_NS_OLDER, theNamespaceURI))) {
|
||||
// push(new AtomPrimitiveState(myInstance.getTotalResults()));
|
||||
// } else if ("updated".equals(theLocalPart)) {
|
||||
// push(new AtomPrimitiveState(myInstance.getUpdated()));
|
||||
// } else if ("author".equals(theLocalPart)) {
|
||||
// push(new AtomAuthorState(myInstance));
|
||||
// } else if ("category".equals(theLocalPart)) {
|
||||
// push(new AtomCategoryState(myInstance.getCategories()));
|
||||
// } else if ("deleted-entry".equals(theLocalPart) && verifyNamespace(XmlParser.TOMBSTONES_NS,
|
||||
// theNamespaceURI)) {
|
||||
// push(new AtomDeletedEntryState(myInstance, myResourceType));
|
||||
// } else {
|
||||
// if (theNamespaceURI != null) {
|
||||
// throw new DataFormatException("Unexpected element: {" + theNamespaceURI + "}" + theLocalPart);
|
||||
// } else {
|
||||
// throw new DataFormatException("Unexpected element: " + theLocalPart);
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: handle category and DSig
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ContainedResourcesState extends PreResourceState {
|
||||
|
||||
public ContainedResourcesState(PreResourceState thePreResourcesState) {
|
||||
|
@ -920,12 +1292,12 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
private class ElementCompositeState extends BaseState {
|
||||
private class ElementCompositeState<T2 extends IElement> extends BaseState {
|
||||
|
||||
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
|
||||
private ICompositeElement myInstance;
|
||||
private T2 myInstance;
|
||||
|
||||
public ElementCompositeState(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, ICompositeElement theInstance) {
|
||||
public ElementCompositeState(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, T2 theInstance) {
|
||||
super(thePreResourceState);
|
||||
myDefinition = theDef;
|
||||
myInstance = theInstance;
|
||||
|
@ -976,7 +1348,7 @@ class ParserState<T> {
|
|||
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
|
||||
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance(child.getInstanceConstructorArguments());
|
||||
child.getMutator().addValue(myInstance, newChildInstance);
|
||||
ElementCompositeState newState = new ElementCompositeState(getPreResourceState(), compositeTarget, newChildInstance);
|
||||
ElementCompositeState<ICompositeElement> newState = new ElementCompositeState<ICompositeElement>(getPreResourceState(), compositeTarget, newChildInstance);
|
||||
push(newState);
|
||||
return;
|
||||
}
|
||||
|
@ -1002,7 +1374,7 @@ class ParserState<T> {
|
|||
RuntimeResourceBlockDefinition blockTarget = (RuntimeResourceBlockDefinition) target;
|
||||
IResourceBlock newBlockInstance = blockTarget.newInstance();
|
||||
child.getMutator().addValue(myInstance, newBlockInstance);
|
||||
ElementCompositeState newState = new ElementCompositeState(getPreResourceState(), blockTarget, newBlockInstance);
|
||||
ElementCompositeState<ICompositeElement> newState = new ElementCompositeState<ICompositeElement>(getPreResourceState(), blockTarget, newBlockInstance);
|
||||
push(newState);
|
||||
return;
|
||||
}
|
||||
|
@ -1051,7 +1423,7 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
protected T2 getCurrentElement() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
|
@ -1122,14 +1494,64 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
private class PreAtomState extends BaseState {
|
||||
private class MetaElementState extends BaseState {
|
||||
private ResourceMetadataMap myMap;
|
||||
|
||||
private Bundle myInstance;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
public MetaElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
|
||||
super(thePreResourceState);
|
||||
myMap = theMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if (theLocalPart.equals("versionId")) {
|
||||
push(new MetaVersionElementState(getPreResourceState(), myMap));
|
||||
} else if (theLocalPart.equals("lastUpdated")) {
|
||||
InstantDt updated = new InstantDt();
|
||||
push(new PrimitiveState(getPreResourceState(), updated));
|
||||
myMap.put(ResourceMetadataKeyEnum.UPDATED, updated);
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element '" + theLocalPart + "' found in 'meta' element");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MetaVersionElementState extends BaseState {
|
||||
|
||||
private ResourceMetadataMap myMap;
|
||||
|
||||
public MetaVersionElementState(ParserState<T>.PreResourceState thePreResourceState, ResourceMetadataMap theMap) {
|
||||
super(thePreResourceState);
|
||||
myMap = theMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
myMap.put(ResourceMetadataKeyEnum.VERSION, theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
throw new DataFormatException("Unexpected child element '" + theLocalPart + "' in element 'meta'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class PreAtomState extends BasePreAtomOrBundleState {
|
||||
|
||||
public PreAtomState(Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myResourceType = theResourceType;
|
||||
super(theResourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1143,49 +1565,59 @@ class ParserState<T> {
|
|||
throw new DataFormatException("Expecting outer element called 'feed', found: " + theLocalPart);
|
||||
}
|
||||
|
||||
myInstance = new Bundle();
|
||||
push(new AtomState(myInstance, myResourceType));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void wereBack() {
|
||||
myObject = (T) myInstance;
|
||||
|
||||
/*
|
||||
* Stitch together resource references
|
||||
*/
|
||||
|
||||
Map<String, IResource> idToResource = new HashMap<String, IResource>();
|
||||
List<IResource> resources = myInstance.toListOfResources();
|
||||
for (IResource next : resources) {
|
||||
if (next.getId() != null && next.getId().isEmpty() == false) {
|
||||
idToResource.put(next.getId().toUnqualifiedVersionless().getValue(), next);
|
||||
}
|
||||
}
|
||||
|
||||
for (IResource next : resources) {
|
||||
List<ResourceReferenceDt> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, ResourceReferenceDt.class);
|
||||
for (ResourceReferenceDt nextRef : refs) {
|
||||
if (nextRef.isEmpty() == false && nextRef.getReference() != null) {
|
||||
IResource target = idToResource.get(nextRef.getReference().getValue());
|
||||
if (target != null) {
|
||||
nextRef.setResource(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setInstance(new Bundle());
|
||||
push(new AtomState(getInstance(), getResourceType()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class PreBundleState extends BasePreAtomOrBundleState {
|
||||
|
||||
public PreBundleState(Class<? extends IResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if (!"Bundle".equals(theLocalPart)) {
|
||||
throw new DataFormatException("Expecting outer element called 'Bundle', found: " + theLocalPart);
|
||||
}
|
||||
|
||||
setInstance(new Bundle());
|
||||
push(new BundleState(getInstance(), getResourceType()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ResourceState extends ElementCompositeState<IResource>
|
||||
{
|
||||
|
||||
public ResourceState(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IResource theInstance) {
|
||||
super(thePreResourceState, theDef, theInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespace, String theChildName) throws DataFormatException {
|
||||
if ("id".equals(theChildName)) {
|
||||
push(new PrimitiveState(getPreResourceState(), getCurrentElement().getId()));
|
||||
} else if ("meta".equals(theChildName)) {
|
||||
push(new MetaElementState(getPreResourceState(), getCurrentElement().getResourceMetadata()));
|
||||
}else {
|
||||
super.enteringNewElement(theNamespace, theChildName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class PreResourceState extends BaseState {
|
||||
|
||||
private Map<String, IResource> myContainedResources = new HashMap<String, IResource>();
|
||||
|
@ -1242,10 +1674,11 @@ class ParserState<T> {
|
|||
myEntry.setResource(myInstance);
|
||||
}
|
||||
|
||||
if ("Binary".equals(def.getName())) {
|
||||
String resourceName = def.getName();
|
||||
if ("Binary".equals(resourceName)) {
|
||||
push(new BinaryResourceState(getRootPreResourceState(), (Binary) myInstance));
|
||||
} else {
|
||||
push(new ElementCompositeState(getRootPreResourceState(), def, myInstance));
|
||||
push(new ResourceState(getRootPreResourceState(), def, myInstance));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1284,12 +1717,6 @@ class ParserState<T> {
|
|||
|
||||
myContext.newTerser().visit(myInstance, new IModelVisitor() {
|
||||
|
||||
@Override
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition,
|
||||
ExtensionDt theNextExt) {
|
||||
acceptElement(theNextExt.getValue(), null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
|
||||
if (theElement instanceof ResourceReferenceDt) {
|
||||
|
@ -1307,6 +1734,11 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
|
||||
acceptElement(theNextExt.getValue(), null, null);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -1496,12 +1928,12 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
myDepth++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
|
||||
myDepth++;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,7 @@ package ca.uhn.fhir.parser;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
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 static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -53,6 +51,7 @@ import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||
|
@ -64,6 +63,7 @@ import ca.uhn.fhir.model.api.IElement;
|
|||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
|
@ -94,6 +94,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
private FhirContext myContext;
|
||||
private boolean myPrettyPrint;
|
||||
|
||||
/**
|
||||
* Do not use this constructor, the recommended way to obtain a new instance of the
|
||||
* XML parser is to invoke {@link FhirContext#newXmlParser()}.
|
||||
*/
|
||||
public XmlParser(FhirContext theContext) {
|
||||
super(theContext);
|
||||
myContext = theContext;
|
||||
|
@ -111,118 +115,213 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws DataFormatException {
|
||||
try {
|
||||
XMLStreamWriter eventWriter = createXmlWriter(theWriter);
|
||||
|
||||
eventWriter.writeStartElement("feed");
|
||||
eventWriter.writeDefaultNamespace(ATOM_NS);
|
||||
|
||||
writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
|
||||
writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());
|
||||
|
||||
writeAtomLink(eventWriter, "self", theBundle.getLinkSelf());
|
||||
writeAtomLink(eventWriter, "first", theBundle.getLinkFirst());
|
||||
writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious());
|
||||
writeAtomLink(eventWriter, "next", theBundle.getLinkNext());
|
||||
writeAtomLink(eventWriter, "last", theBundle.getLinkLast());
|
||||
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase());
|
||||
|
||||
if (theBundle.getTotalResults().getValue() != null) {
|
||||
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
|
||||
eventWriter.writeNamespace("os", OPENSEARCH_NS);
|
||||
eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString());
|
||||
eventWriter.writeEndElement();
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
encodeBundleToWriterUsingBundleResource(theBundle, eventWriter);
|
||||
} else {
|
||||
encodeBundleToWriterUsingAtom(theBundle, eventWriter);
|
||||
}
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", theBundle.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", theBundle.getPublished());
|
||||
|
||||
if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
|
||||
eventWriter.writeStartElement("author");
|
||||
writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
|
||||
writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
writeCategories(eventWriter, theBundle.getCategories());
|
||||
|
||||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
boolean deleted = false;
|
||||
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
|
||||
deleted = true;
|
||||
eventWriter.writeStartElement("at", "deleted-entry", TOMBSTONES_NS);
|
||||
eventWriter.writeNamespace("at", TOMBSTONES_NS);
|
||||
eventWriter.writeAttribute("ref", nextEntry.getId().getValueAsString());
|
||||
eventWriter.writeAttribute("when", nextEntry.getDeletedAt().getValueAsString());
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false || nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "by");
|
||||
if (nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "name");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedByName().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "email");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedByEmail().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
if (nextEntry.getDeletedComment().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "comment");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedComment().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
} else {
|
||||
eventWriter.writeStartElement("entry");
|
||||
}
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
|
||||
if (!deleted) {
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
|
||||
}
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
|
||||
|
||||
writeCategories(eventWriter, nextEntry.getCategories());
|
||||
|
||||
if (!nextEntry.getLinkSelf().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
}
|
||||
|
||||
if (!nextEntry.getLinkAlternate().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "alternate", nextEntry.getLinkAlternate());
|
||||
}
|
||||
|
||||
if (!nextEntry.getLinkSearch().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "search", nextEntry.getLinkSearch());
|
||||
}
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
if (resource != null && !resource.isEmpty() && !deleted) {
|
||||
eventWriter.writeStartElement("content");
|
||||
eventWriter.writeAttribute("type", "text/xml");
|
||||
encodeResourceToXmlStreamWriter(resource, eventWriter, false);
|
||||
eventWriter.writeEndElement(); // content
|
||||
} else {
|
||||
ourLog.debug("Bundle entry contains null resource");
|
||||
}
|
||||
|
||||
if (!nextEntry.getSummary().isEmpty()) {
|
||||
eventWriter.writeStartElement("summary");
|
||||
eventWriter.writeAttribute("type", "xhtml");
|
||||
encodeXhtml(nextEntry.getSummary(), eventWriter);
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement(); // entry
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
eventWriter.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeBundleToWriterUsingAtom(Bundle theBundle, XMLStreamWriter eventWriter) throws XMLStreamException {
|
||||
eventWriter.writeStartElement("feed");
|
||||
eventWriter.writeDefaultNamespace(ATOM_NS);
|
||||
|
||||
writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
|
||||
writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());
|
||||
|
||||
writeAtomLink(eventWriter, "self", theBundle.getLinkSelf());
|
||||
writeAtomLink(eventWriter, "first", theBundle.getLinkFirst());
|
||||
writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious());
|
||||
writeAtomLink(eventWriter, "next", theBundle.getLinkNext());
|
||||
writeAtomLink(eventWriter, "last", theBundle.getLinkLast());
|
||||
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase());
|
||||
|
||||
if (theBundle.getTotalResults().getValue() != null) {
|
||||
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
|
||||
eventWriter.writeNamespace("os", OPENSEARCH_NS);
|
||||
eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", theBundle.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", theBundle.getPublished());
|
||||
|
||||
if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
|
||||
eventWriter.writeStartElement("author");
|
||||
writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
|
||||
writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
writeCategories(eventWriter, theBundle.getCategories());
|
||||
|
||||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
boolean deleted = false;
|
||||
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
|
||||
deleted = true;
|
||||
eventWriter.writeStartElement("at", "deleted-entry", TOMBSTONES_NS);
|
||||
eventWriter.writeNamespace("at", TOMBSTONES_NS);
|
||||
eventWriter.writeAttribute("ref", nextEntry.getId().getValueAsString());
|
||||
eventWriter.writeAttribute("when", nextEntry.getDeletedAt().getValueAsString());
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false || nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "by");
|
||||
if (nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "name");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedByName().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "email");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedByEmail().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
if (nextEntry.getDeletedComment().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "comment");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedComment().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
} else {
|
||||
eventWriter.writeStartElement("entry");
|
||||
}
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
|
||||
if (!deleted) {
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
|
||||
}
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
|
||||
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
|
||||
|
||||
writeCategories(eventWriter, nextEntry.getCategories());
|
||||
|
||||
if (!nextEntry.getLinkSelf().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
}
|
||||
|
||||
if (!nextEntry.getLinkAlternate().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "alternate", nextEntry.getLinkAlternate());
|
||||
}
|
||||
|
||||
if (!nextEntry.getLinkSearch().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "search", nextEntry.getLinkSearch());
|
||||
}
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
if (resource != null && !resource.isEmpty() && !deleted) {
|
||||
eventWriter.writeStartElement("content");
|
||||
eventWriter.writeAttribute("type", "text/xml");
|
||||
encodeResourceToXmlStreamWriter(resource, eventWriter, false);
|
||||
eventWriter.writeEndElement(); // content
|
||||
} else {
|
||||
ourLog.debug("Bundle entry contains null resource");
|
||||
}
|
||||
|
||||
if (!nextEntry.getSummary().isEmpty()) {
|
||||
eventWriter.writeStartElement("summary");
|
||||
eventWriter.writeAttribute("type", "xhtml");
|
||||
encodeXhtml(nextEntry.getSummary(), eventWriter);
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement(); // entry
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
eventWriter.close();
|
||||
}
|
||||
|
||||
private void encodeBundleToWriterUsingBundleResource(Bundle theBundle, XMLStreamWriter theEventWriter) throws XMLStreamException {
|
||||
theEventWriter.writeStartElement("Bundle");
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theBundle.getId().getIdPart());
|
||||
|
||||
theEventWriter.writeStartElement("meta");
|
||||
writeOptionalTagWithValue(theEventWriter, "versionId", theBundle.getId().getVersionIdPart());
|
||||
InstantDt updated = (InstantDt) theBundle.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
if (updated != null) {
|
||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
|
||||
String bundleBaseUrl = theBundle.getLinkBase().getValue();
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "type", theBundle.getType().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "base", bundleBaseUrl);
|
||||
writeOptionalTagWithValue(theEventWriter, "total", theBundle.getTotalResults().getValueAsString());
|
||||
|
||||
writeBundleResourceLink(theEventWriter, "first", theBundle.getLinkFirst());
|
||||
writeBundleResourceLink(theEventWriter, "previous", theBundle.getLinkPrevious());
|
||||
writeBundleResourceLink(theEventWriter, "next", theBundle.getLinkNext());
|
||||
writeBundleResourceLink(theEventWriter, "last", theBundle.getLinkLast());
|
||||
writeBundleResourceLink(theEventWriter, "self", theBundle.getLinkSelf());
|
||||
|
||||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
theEventWriter.writeStartElement("entry");
|
||||
|
||||
IResource nextResource = nextEntry.getResource();
|
||||
if (nextResource.getId() != null && nextResource.getId().hasBaseUrl()) {
|
||||
if (!nextResource.getId().getBaseUrl().equals(bundleBaseUrl)) {
|
||||
writeOptionalTagWithValue(theEventWriter, "base", bundleBaseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "status", nextEntry.getStatus().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "search", nextEntry.getLinkSearch().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "score", nextEntry.getScore().getValueAsString());
|
||||
|
||||
boolean deleted = false;
|
||||
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
|
||||
deleted = true;
|
||||
theEventWriter.writeStartElement("deleted");
|
||||
writeOptionalTagWithValue(theEventWriter, "type", nextEntry.getId().getResourceType());
|
||||
writeOptionalTagWithValue(theEventWriter, "id", nextEntry.getId().getIdPart());
|
||||
writeOptionalTagWithValue(theEventWriter, "versionId", nextEntry.getId().getVersionIdPart());
|
||||
writeOptionalTagWithValue(theEventWriter, "instant", nextEntry.getDeletedAt().getValueAsString());
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
if (resource != null && !resource.isEmpty() && !deleted) {
|
||||
theEventWriter.writeStartElement("resource");
|
||||
encodeResourceToXmlStreamWriter(resource, theEventWriter, false);
|
||||
theEventWriter.writeEndElement(); // content
|
||||
} else {
|
||||
ourLog.debug("Bundle entry contains null resource");
|
||||
}
|
||||
|
||||
theEventWriter.writeEndElement(); // entry
|
||||
}
|
||||
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.close();
|
||||
}
|
||||
|
||||
private void writeBundleResourceLink(XMLStreamWriter theEventWriter, String theRel, StringDt theUrl) throws XMLStreamException {
|
||||
if (theUrl.isEmpty()==false) {
|
||||
theEventWriter.writeStartElement("link");
|
||||
theEventWriter.writeStartElement("relation");
|
||||
theEventWriter.writeAttribute("value", theRel);
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeStartElement("url");
|
||||
theEventWriter.writeAttribute("value", theUrl.getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithValue(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theValue)) {
|
||||
theEventWriter.writeStartElement(theName);
|
||||
theEventWriter.writeAttribute("value", theValue);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
|
||||
if (categories != null) {
|
||||
for (Tag next : categories) {
|
||||
|
@ -421,10 +520,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theEventWriter, IElement nextValue, String childName,
|
||||
BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theEventWriter, IElement 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) {
|
||||
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
|
||||
// We still want to go in..
|
||||
} else {
|
||||
return;
|
||||
|
@ -467,7 +566,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
ContainedDt value = (ContainedDt) nextValue;
|
||||
theEventWriter.writeStartElement("contained");
|
||||
for (IResource next : value.getContainedResources()) {
|
||||
if (getContainedResources().getResourceId(next)!=null) {
|
||||
if (getContainedResources().getResourceId(next) != null) {
|
||||
continue;
|
||||
}
|
||||
encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(next.getId().getValue()));
|
||||
|
@ -497,9 +596,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, XMLStreamWriter theEventWriter,
|
||||
List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException,
|
||||
DataFormatException {
|
||||
for (BaseRuntimeChildDefinition nextChild : children) {
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
|
@ -558,15 +656,13 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, XMLStreamWriter theEventWriter,
|
||||
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement 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 encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theWriter, IElement theElement, boolean theIncludedResource)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
private void encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theWriter, IElement theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredExtensions(), "extension", theIncludedResource);
|
||||
|
@ -589,7 +685,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
String resourceId = null;
|
||||
if (theIncludedResource && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
|
@ -612,10 +707,24 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeStartElement(resDef.getName());
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
if (theResourceId != null) {
|
||||
theEventWriter.writeAttribute("id", theResourceId);
|
||||
if (!myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
if (theResourceId != null) {
|
||||
theEventWriter.writeAttribute("id", theResourceId);
|
||||
}
|
||||
} else {
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "id", theResource.getId().getIdPart());
|
||||
|
||||
theEventWriter.writeStartElement("meta");
|
||||
writeOptionalTagWithValue(theEventWriter, "versionId", theResource.getId().getVersionIdPart());
|
||||
InstantDt updated = (InstantDt) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
if (updated != null) {
|
||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
if (theResource instanceof Binary) {
|
||||
Binary bin = (Binary) theResource;
|
||||
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
||||
|
@ -627,8 +736,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
private void encodeUndeclaredExtensions(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theWriter, List<ExtensionDt> extensions, String tagName,
|
||||
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeUndeclaredExtensions(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theWriter, List<ExtensionDt> extensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (ExtensionDt next : extensions) {
|
||||
theWriter.writeStartElement(tagName);
|
||||
theWriter.writeAttribute("url", next.getUrl().getValue());
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
|
||||
ca.uhn.fhir.context.FhirContext.noStructures=Could not find any HAPI-FHIR structure JARs on the classpath. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath (or project pom.xml if you are using Maven)
|
||||
ca.uhn.fhir.context.FhirContext.noStructuresForSpecifiedVersion=Could not find the HAPI-FHIR structure JAR on the classpath for version {0}. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath (or project pom.xml if you are using Maven)
|
||||
|
||||
ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread=No version specified in URL for 'vread' operation: {0}
|
||||
ca.uhn.fhir.rest.client.GenericClient.incompleteUriForRead=The given URI is not an absolute URL and is not usable for this operation: {0}
|
||||
ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable to determine the resource type from the given URI: {0}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<value>blaze , Blaze (Orion Health) , https://fhir.orionhealth.com/blaze/fhir</value>
|
||||
<value>oridashi , Oridashi , http://demo.oridashi.com.au:8190</value>
|
||||
<!-- <value>fhirbase , FHIRPlace (Health Samurai) , http://try-fhirplace.hospital-systems.com/ </value> -->
|
||||
<value>nortal , Nortal , http://fhir.nortal.com/fhir-server</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="src/test/resources"/>
|
||||
<classpathentry kind="src" path="target/generated-resources/tinder"/>
|
||||
<classpathentry kind="src" path="target/generated-sources/tinder"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
|
|
|
@ -20,8 +20,12 @@ package ca.uhn.fhir.model.dev;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -61,4 +65,21 @@ public class FhirDev implements IFhirVersion {
|
|||
return new ServerProfileProvider(theRestfulServer.getFhirContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FhirVersionEnum getVersion() {
|
||||
return FhirVersionEnum.DEV;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFhirVersionPropertiesFile() {
|
||||
InputStream str = FhirDev.class.getResourceAsStream("/ca/uhn/fhir/model/dev/fhirversion.properties");
|
||||
if (str == null) {
|
||||
str = FhirDev.class.getResourceAsStream("ca/uhn/fhir/model/dev/fhirversion.properties");
|
||||
}
|
||||
if (str == null) {
|
||||
throw new ConfigurationException("Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dev/model.properties");
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.dev.composite;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - DEV (FHIR Latest)
|
||||
|
@ -20,6 +22,7 @@ package ca.uhn.fhir.model.dev.composite;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
@DatatypeDef(name="AgeDt")
|
||||
public class AgeDt extends QuantityDt {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.dev.composite;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - DEV (FHIR Latest)
|
||||
|
@ -20,6 +22,7 @@ package ca.uhn.fhir.model.dev.composite;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
@DatatypeDef(name="CountDt")
|
||||
public class CountDt extends QuantityDt {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.dev.composite;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - DEV (FHIR Latest)
|
||||
|
@ -20,6 +22,7 @@ package ca.uhn.fhir.model.dev.composite;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
@DatatypeDef(name="DistanceDt")
|
||||
public class DistanceDt extends QuantityDt {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.dev.composite;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - DEV (FHIR Latest)
|
||||
|
@ -20,6 +22,7 @@ package ca.uhn.fhir.model.dev.composite;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
@DatatypeDef(name="DurationDt")
|
||||
public class DurationDt extends QuantityDt {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.model.dev.composite;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - DEV (FHIR Latest)
|
||||
|
@ -20,6 +22,7 @@ package ca.uhn.fhir.model.dev.composite;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
@DatatypeDef(name="MoneyDt")
|
||||
public class MoneyDt extends QuantityDt {
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import net.sf.json.JSON;
|
||||
import net.sf.json.JSONSerializer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dev.resource.MedicationPrescription;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
||||
public class JsonParserTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class);
|
||||
private static final FhirContext ourCtx = FhirContext.forDev();
|
||||
|
||||
@Test
|
||||
public void testParseBundleWithBinary() {
|
||||
// TODO: implement this test, make sure we handle ID and meta correctly in Binary
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAndEncodeBundle() throws Exception {
|
||||
String content = IOUtils.toString(JsonParserTest.class.getResourceAsStream("/bundle-example.json"));
|
||||
|
||||
Bundle parsed = ourCtx.newJsonParser().parseBundle(content);
|
||||
assertEquals("http://example.com/base/Bundle/example/_history/1", parsed.getId().getValue());
|
||||
assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
|
||||
assertEquals("1", parsed.getId().getVersionIdPart());
|
||||
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
assertEquals("transaction", parsed.getType().getValue());
|
||||
assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
assertEquals("http://example.com/base", parsed.getLinkBase().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2", parsed.getLinkNext().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347", parsed.getLinkSelf().getValue());
|
||||
|
||||
assertEquals(1, parsed.getEntries().size());
|
||||
assertEquals("update", parsed.getEntries().get(0).getStatus().getValue());
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
assertEquals("Patient/example", p.getPatient().getReference().getValue());
|
||||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
||||
JSON expected = JSONSerializer.toJSON(content.trim());
|
||||
JSON actual = JSONSerializer.toJSON(reencoded.trim());
|
||||
|
||||
String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("§", "§");
|
||||
String act = actual.toString().replace("\\r\\n", "\\n");
|
||||
|
||||
ourLog.info("Expected: {}", exp);
|
||||
ourLog.info("Actual : {}", act);
|
||||
|
||||
assertEquals(exp, act);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.custommonkey.xmlunit.Diff;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dev.resource.MedicationPrescription;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
||||
public class XmlParserTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
|
||||
private static final FhirContext ourCtx = FhirContext.forDev();
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
XMLUnit.setIgnoreAttributeOrder(true);
|
||||
XMLUnit.setIgnoreComments(true);
|
||||
XMLUnit.setIgnoreWhitespace(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseBundleWithBinary() {
|
||||
// TODO: implement this test, make sure we handle ID and meta correctly in Binary
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAndEncodeBundle() throws Exception {
|
||||
String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/bundle-example(example).xml"));
|
||||
|
||||
Bundle parsed = ourCtx.newXmlParser().parseBundle(content);
|
||||
assertEquals("http://example.com/base/Bundle/example/_history/1", parsed.getId().getValue());
|
||||
assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
|
||||
assertEquals("1", parsed.getId().getVersionIdPart());
|
||||
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
assertEquals("transaction", parsed.getType().getValue());
|
||||
assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
assertEquals("http://example.com/base", parsed.getLinkBase().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2", parsed.getLinkNext().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347", parsed.getLinkSelf().getValue());
|
||||
|
||||
assertEquals(1, parsed.getEntries().size());
|
||||
assertEquals("update", parsed.getEntries().get(0).getStatus().getValue());
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
assertEquals("Patient/example", p.getPatient().getReference().getValue());
|
||||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
String reencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
||||
Diff d = new Diff(new StringReader(content), new StringReader(reencoded));
|
||||
assertTrue(d.toString(), d.identical());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="example"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-18T01:43:30Z"/>
|
||||
</meta>
|
||||
<type value="transaction"/>
|
||||
<base value="http://example.com/base"/>
|
||||
<total value="3"/>
|
||||
<link>
|
||||
<relation value="next"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2"/>
|
||||
</link>
|
||||
<link>
|
||||
<relation value="self"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347"/>
|
||||
</link>
|
||||
<entry>
|
||||
<status value="update"/>
|
||||
<resource>
|
||||
<MedicationPrescription>
|
||||
<id value="3123"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-16T05:31:17Z"/>
|
||||
</meta>
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Penicillin VK 5ml suspension to be administered by oral route</p>
|
||||
<p>ONE 5ml spoonful to be taken THREE times a day</p>
|
||||
<p>100ml bottle</p>
|
||||
<p>to patient ref: a23</p>
|
||||
<p>by doctor X</p>
|
||||
</div>
|
||||
</text>
|
||||
<status value="active"/>
|
||||
<patient>
|
||||
<reference value="Patient/example"/>
|
||||
</patient>
|
||||
<prescriber>
|
||||
<reference value="Practitioner/example"/>
|
||||
</prescriber>
|
||||
|
||||
<medication>
|
||||
<reference value="Medication/example"/>
|
||||
</medication>
|
||||
|
||||
<dosageInstruction>
|
||||
<scheduledTiming>
|
||||
<repeat>
|
||||
<frequency value="3"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</scheduledTiming>
|
||||
<route>
|
||||
<coding>
|
||||
<system value="http://snomed.info/sct"/>
|
||||
<code value="394899003"/>
|
||||
<display value="oral administration of treatment"/>
|
||||
</coding>
|
||||
</route>
|
||||
<doseQuantity>
|
||||
<value value="5"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</doseQuantity>
|
||||
</dosageInstruction>
|
||||
|
||||
<dispense>
|
||||
<quantity>
|
||||
<value value="100"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</quantity>
|
||||
</dispense>
|
||||
|
||||
</MedicationPrescription>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"resourceType": "Bundle",
|
||||
"id": "example",
|
||||
"meta": {
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2014-08-18T01:43:30Z"
|
||||
},
|
||||
"type": "transaction",
|
||||
"base": "http://example.com/base",
|
||||
"total": 3,
|
||||
"link": [
|
||||
{
|
||||
"relation": "next",
|
||||
"url": "https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2"
|
||||
},
|
||||
{
|
||||
"relation": "self",
|
||||
"url": "https://example.com/base/MedicationPrescription?patient=347"
|
||||
}
|
||||
],
|
||||
"entry": [
|
||||
{
|
||||
"status": "update",
|
||||
"resource": {
|
||||
"resourceType": "MedicationPrescription",
|
||||
"id": "3123",
|
||||
"meta": {
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2014-08-16T05:31:17Z"
|
||||
},
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div>\n <p>Penicillin VK 5ml suspension to be administered by oral route</p>\n <p>ONE 5ml spoonful to be taken THREE times a day</p>\n <p>100ml bottle</p>\n <p>to patient ref: a23</p>\n <p>by doctor X</p>\n </div>"
|
||||
},
|
||||
"status": "active",
|
||||
"patient": {
|
||||
"reference": "Patient/example"
|
||||
},
|
||||
"prescriber": {
|
||||
"reference": "Practitioner/example"
|
||||
},
|
||||
"medication": {
|
||||
"reference": "Medication/example"
|
||||
},
|
||||
"dosageInstruction": [
|
||||
{
|
||||
"scheduledTiming": {
|
||||
"repeat": {
|
||||
"frequency": 3,
|
||||
"duration": 1,
|
||||
"units": "d"
|
||||
}
|
||||
},
|
||||
"route": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://snomed.info/sct",
|
||||
"code": "394899003",
|
||||
"display": "oral administration of treatment"
|
||||
}
|
||||
]
|
||||
},
|
||||
"doseQuantity": {
|
||||
"value": 5,
|
||||
"units": "ml",
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "ml"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dispense": {
|
||||
"quantity": {
|
||||
"value": 100,
|
||||
"units": "ml",
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "ml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.model.dstu;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.join;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -31,12 +31,30 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildCompositeDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildContainedResources;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildPrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildResourceBlockDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeCompositeDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
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.IFhirVersion;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -318,4 +336,24 @@ public class FhirDstu1 implements IFhirVersion {
|
|||
return new ServerProfileProvider(theRestfulServer.getFhirContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FhirVersionEnum getVersion() {
|
||||
return FhirVersionEnum.DSTU1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFhirVersionPropertiesFile() {
|
||||
InputStream str = FhirDstu1.class.getResourceAsStream("/ca/uhn/fhir/model/dstu/fhirversion.properties");
|
||||
if (str == null) {
|
||||
str = FhirDstu1.class.getResourceAsStream("ca/uhn/fhir/model/dstu/fhirversion.properties");
|
||||
}
|
||||
if (str == null) {
|
||||
throw new ConfigurationException("Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dstu/model.properties");
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -23,4 +24,14 @@ public class FhirContextTest {
|
|||
assertEquals("Binary", def.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnknownVersion() {
|
||||
try {
|
||||
new FhirContext(FhirVersionEnum.DEV);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage(), containsString("Could not find the HAPI-FHIR structure JAR on the classpath for version {0}"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class FhirVersionEnumTest {
|
||||
|
||||
@Test
|
||||
public void testIsNewerThan() {
|
||||
assertTrue(FhirVersionEnum.DEV.isNewerThan(FhirVersionEnum.DSTU1));
|
||||
assertFalse(FhirVersionEnum.DSTU1.isNewerThan(FhirVersionEnum.DEV));
|
||||
assertFalse(FhirVersionEnum.DEV.isNewerThan(FhirVersionEnum.DEV));
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@ import net.sf.json.JSON;
|
|||
import net.sf.json.JSONSerializer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.IsNot;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hamcrest.text.StringContainsInOrder;
|
||||
|
|
|
@ -132,7 +132,7 @@ function addSearchControls(theConformance, theSearchParamType, theSearchParamNam
|
|||
} else if (theSearchParamType == 'date') {
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, true);
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, false);
|
||||
} else if (theSearchParamType == 'reference' && theSearchParamChain.length == 0) {
|
||||
} else if (theSearchParamType == 'reference' && (!theSearchParamChain || theSearchParamChain.length == 0)) {
|
||||
/*
|
||||
* This is a reference parameter with no chain options, so just display a simple
|
||||
* text box for the ID of the referenced resource
|
||||
|
|
|
@ -30,6 +30,18 @@
|
|||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
<action type="add">
|
||||
<![CDATA[
|
||||
<b>API Change</b>: The IResource#getResourceMetadata() method has been changed
|
||||
from returning
|
||||
<code>Map<ResourceMetadataKeyEnum<?>, Object><code>
|
||||
to returning a new type called
|
||||
<code>ResourceMetadataMap</code>. This new type implements
|
||||
<code>Map<ResourceMetadataKeyEnum<?>, Object><code>
|
||||
itself, so this change should not break existing code, but may
|
||||
require a clean build in order to run correctly.
|
||||
]]>
|
||||
</action>
|
||||
<action type="add" issue="38" dev="wdebeau1">
|
||||
Profile generation on the server was not working due to IdDt being
|
||||
incorrectly used. Thanks to Bill de Beaubien for the pull request!
|
||||
|
|
Loading…
Reference in New Issue