Automatically populate Bundle.entry.base when encoding a bunde

This commit is contained in:
James Agnew 2015-06-17 14:32:11 -04:00
parent 6f7ef96b97
commit 39dd48bc41
16 changed files with 386 additions and 107 deletions

View File

@ -58,6 +58,8 @@ public abstract class BaseRuntimeChildDefinition {
public abstract int getMin(); public abstract int getMin();
public interface IMutator { public interface IMutator {
void setValue(Object theTarget, IBase theValue);
void addValue(Object theTarget, IBase theValue); void addValue(Object theTarget, IBase theValue);
} }

View File

@ -194,6 +194,11 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
throw new ConfigurationException("Failed to set value", e); throw new ConfigurationException("Failed to set value", e);
} }
} }
@Override
public void setValue(Object theTarget, IBase theValue) {
addValue(theTarget, theValue);
}
} }
private final class FieldPlainAccessor implements IAccessor { private final class FieldPlainAccessor implements IAccessor {
@ -217,6 +222,15 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
protected final class FieldListMutator implements IMutator { protected final class FieldListMutator implements IMutator {
@Override @Override
public void addValue(Object theTarget, IBase theValue) { public void addValue(Object theTarget, IBase theValue) {
addValue(theTarget, theValue, false);
}
@Override
public void setValue(Object theTarget, IBase theValue) {
addValue(theTarget, theValue, true);
}
private void addValue(Object theTarget, IBase theValue, boolean theClear) {
try { try {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<IBase> existingList = (List<IBase>) myField.get(theTarget); List<IBase> existingList = (List<IBase>) myField.get(theTarget);
@ -224,6 +238,9 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
existingList = new ArrayList<IBase>(2); existingList = new ArrayList<IBase>(2);
myField.set(theTarget, existingList); myField.set(theTarget, existingList);
} }
if (theClear) {
existingList.clear();
}
existingList.add(theValue); existingList.add(theValue);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new ConfigurationException("Failed to set value", e); throw new ConfigurationException("Failed to set value", e);
@ -283,6 +300,10 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
@Override @Override
public void addValue(Object theTarget, IBase theValue) { public void addValue(Object theTarget, IBase theValue) {
addValue(theTarget, false, theValue);
}
private void addValue(Object theTarget, boolean theClear, IBase theValue) {
List<IBase> existingList = myAccessor.getValues(theTarget); List<IBase> existingList = myAccessor.getValues(theTarget);
if (existingList == null) { if (existingList == null) {
existingList = new ArrayList<IBase>(); existingList = new ArrayList<IBase>();
@ -296,8 +317,16 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
throw new ConfigurationException("Failed to get value", e); throw new ConfigurationException("Failed to get value", e);
} }
} }
if (theClear) {
existingList.clear();
}
existingList.add(theValue); existingList.add(theValue);
} }
@Override
public void setValue(Object theTarget, IBase theValue) {
addValue(theTarget, true, theValue);
}
} }
private final class PlainAccessor implements IAccessor { private final class PlainAccessor implements IAccessor {
@ -348,6 +377,11 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
throw new ConfigurationException("Failed to get value", e); throw new ConfigurationException("Failed to get value", e);
} }
} }
@Override
public void setValue(Object theTarget, IBase theValue) {
addValue(theTarget, theValue);
}
} }
} }

View File

@ -104,6 +104,17 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
target.getUndeclaredExtensions().add((ExtensionDt) theValue); target.getUndeclaredExtensions().add((ExtensionDt) theValue);
} }
} }
@Override
public void setValue(Object theTarget, IBase theValue) {
ExtensionDt target = (ExtensionDt) theTarget;
if (theValue instanceof IDatatype) {
target.setValue((IDatatype) theTarget);
} else {
target.getUndeclaredExtensions().clear();
target.getUndeclaredExtensions().add((ExtensionDt) theValue);
}
}
}; };
} }

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.model.primitive;
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.UUID;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -634,4 +635,12 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return theIdPart.toString(); return theIdPart.toString();
} }
/**
* Construct a new ID with with form "urn:uuid:[UUID]" where [UUID] is a new, randomly
* created UUID generated by {@link UUID#randomUUID()}
*/
public static IdDt newRandomUuid() {
return new IdDt("urn:uuid:" + UUID.randomUUID().toString());
}
} }

View File

@ -39,6 +39,7 @@ import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
@ -61,6 +62,8 @@ import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ObjectUtil;
public abstract class BaseParser implements IParser { public abstract class BaseParser implements IParser {
@ -74,7 +77,8 @@ public abstract class BaseParser implements IParser {
/** /**
* Constructor * Constructor
* @param theParserErrorHandler *
* @param theParserErrorHandler
*/ */
public BaseParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) { public BaseParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) {
myContext = theContext; myContext = theContext;
@ -205,6 +209,10 @@ public abstract class BaseParser implements IParser {
return resourceBaseUrl; return resourceBaseUrl;
} }
protected abstract void doEncodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException, DataFormatException;
protected abstract void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
protected abstract <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException; protected abstract <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
@Override @Override
@ -222,6 +230,13 @@ public abstract class BaseParser implements IParser {
return stringWriter.toString(); return stringWriter.toString();
} }
@Override
public final void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException, DataFormatException {
Validate.notNull(theBundle, "theBundle must not be null");
Validate.notNull(theWriter, "theWriter must not be null");
doEncodeBundleToWriter(theBundle, theWriter);
}
@Override @Override
public String encodeResourceToString(IBaseResource theResource) throws DataFormatException { public String encodeResourceToString(IBaseResource theResource) throws DataFormatException {
Writer stringWriter = new StringWriter(); Writer stringWriter = new StringWriter();
@ -233,6 +248,18 @@ public abstract class BaseParser implements IParser {
return stringWriter.toString(); return stringWriter.toString();
} }
@Override
public final void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException {
Validate.notNull(theResource, "theResource can not be null");
Validate.notNull(theWriter, "theWriter can not be null");
if (theResource instanceof IBaseBundle) {
fixBaseLinksForBundle((IBaseBundle) theResource);
}
doEncodeResourceToWriter(theResource, theWriter);
}
@Override @Override
public String encodeTagListToString(TagList theTagList) { public String encodeTagListToString(TagList theTagList) {
Writer stringWriter = new StringWriter(); Writer stringWriter = new StringWriter();
@ -244,6 +271,49 @@ public abstract class BaseParser implements IParser {
return stringWriter.toString(); return stringWriter.toString();
} }
/**
* If individual resources in the bundle have an ID that has the base set, we make sure that Bundle.entry.base gets set as needed.
*/
private void fixBaseLinksForBundle(IBaseBundle theBundle) {
/*
* ATTENTION IF YOU ARE EDITING THIS:
* There are two versions of this method, one for DSTU1/atom bundle and
* one for DSTU2/resource bundle. If you edit one, edit both and also
* update unit tests for both.
*/
FhirTerser t = myContext.newTerser();
IPrimitiveType<?> element = t.getSingleValueOrNull(theBundle, "base", IPrimitiveType.class);
String bundleBase = element != null ? element.getValueAsString() : null;
for (IBase nextEntry : t.getValues(theBundle, "Bundle.entry", IBase.class)) {
IBaseResource resource = t.getSingleValueOrNull(nextEntry, "resource", IBaseResource.class);
if (resource == null) {
continue;
}
IPrimitiveType<?> baseElement = t.getSingleValueOrNull(nextEntry, "base", IPrimitiveType.class);
String entryBase = baseElement != null ? baseElement.getValueAsString() : null;
if (isNotBlank(entryBase)) {
continue;
}
IIdType resourceId = resource.getIdElement();
String resourceIdBase = resourceId.getBaseUrl();
if (isNotBlank(resourceIdBase)) {
if (!ObjectUtil.equals(bundleBase, resourceIdBase)) {
if (baseElement == null) {
baseElement = (IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(nextEntry.getClass());
entryDef.getChildByNameOrThrowDataFormatException("base").getMutator().setValue(nextEntry, baseElement);
}
baseElement.setValueAsString(resourceIdBase);
}
}
}
}
protected String fixContainedResourceId(String theValue) { protected String fixContainedResourceId(String theValue) {
if (StringUtils.isNotBlank(theValue) && theValue.charAt(0) == '#') { if (StringUtils.isNotBlank(theValue) && theValue.charAt(0) == '#') {
return theValue.substring(1); return theValue.substring(1);
@ -330,7 +400,7 @@ public abstract class BaseParser implements IParser {
String baseUrl = baseType.getValueAsString(); String baseUrl = baseType.getValueAsString();
String idPart = res.getIdElement().getIdPart(); String idPart = res.getIdElement().getIdPart();
String resourceName = resDef.getName(); String resourceName = resDef.getName();
if (!baseUrl.startsWith("cid:") && !baseUrl.startsWith("urn:")) { if (!baseUrl.startsWith("cid:") && !baseUrl.startsWith("urn:")) {
res.setId(new IdDt(baseUrl, resourceName, idPart, versionIdPart)); res.setId(new IdDt(baseUrl, resourceName, idPart, versionIdPart));
@ -376,15 +446,15 @@ public abstract class BaseParser implements IParser {
} }
@Override @Override
public BaseParser setParserErrorHandler(IParserErrorHandler theErrorHandler) { public BaseParser setOmitResourceId(boolean theOmitResourceId) {
Validate.notNull(theErrorHandler, "theErrorHandler must not be null"); myOmitResourceId = theOmitResourceId;
myErrorHandler = theErrorHandler;
return this; return this;
} }
@Override @Override
public BaseParser setOmitResourceId(boolean theOmitResourceId) { public BaseParser setParserErrorHandler(IParserErrorHandler theErrorHandler) {
myOmitResourceId = theOmitResourceId; Validate.notNull(theErrorHandler, "theErrorHandler must not be null");
myErrorHandler = theErrorHandler;
return this; return this;
} }

View File

@ -180,7 +180,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
@Override @Override
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException { public void doEncodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
JsonGenerator eventWriter = createJsonGenerator(theWriter); JsonGenerator eventWriter = createJsonGenerator(theWriter);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
encodeBundleToWriterInDstu2Format(theBundle, eventWriter); encodeBundleToWriterInDstu2Format(theBundle, eventWriter);
@ -777,9 +777,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
@Override @Override
public void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException { protected void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException {
Validate.notNull(theResource, "Resource can not be null");
JsonGenerator eventWriter = createJsonGenerator(theWriter); JsonGenerator eventWriter = createJsonGenerator(theWriter);
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);

View File

@ -84,14 +84,14 @@ import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.XhtmlDt; import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper; import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
import ca.uhn.fhir.util.PrettyPrintWriterWrapper; import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
import ca.uhn.fhir.util.XmlUtil; import ca.uhn.fhir.util.XmlUtil;
/** /**
* This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use * This class is the FHIR XML parser/encoder. Users should not interact with this class directly, but should use {@link FhirContext#newXmlParser()} to get an instance.
* {@link FhirContext#newXmlParser()} to get an instance.
*/ */
public class XmlParser extends BaseParser implements IParser { public class XmlParser extends BaseParser implements IParser {
@ -110,9 +110,9 @@ public class XmlParser extends BaseParser implements IParser {
private boolean myPrettyPrint; private boolean myPrettyPrint;
/** /**
* Do not use this constructor, the recommended way to obtain a new instance of the XML parser is to invoke * Do not use this constructor, the recommended way to obtain a new instance of the XML parser is to invoke {@link FhirContext#newXmlParser()}.
* {@link FhirContext#newXmlParser()}. *
* @param theParserErrorHandler * @param theParserErrorHandler
*/ */
public XmlParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) { public XmlParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) {
super(theContext, theParserErrorHandler); super(theContext, theParserErrorHandler);
@ -224,13 +224,17 @@ public class XmlParser extends BaseParser implements IParser {
@Override @Override
public String encodeBundleToString(Bundle theBundle) throws DataFormatException { public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
encodeBundleToWriter(theBundle, stringWriter); try {
encodeBundleToWriter(theBundle, stringWriter);
} catch (IOException e) {
throw new InternalErrorException("IOException writing to StringWriter - Should not happen", e);
}
return stringWriter.toString(); return stringWriter.toString();
} }
@Override @Override
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws DataFormatException { public void doEncodeBundleToWriter(Bundle theBundle, Writer theWriter) throws DataFormatException {
try { try {
XMLStreamWriter eventWriter = createXmlWriter(theWriter); XMLStreamWriter eventWriter = createXmlWriter(theWriter);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
@ -442,7 +446,8 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.close(); theEventWriter.close();
} }
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef,
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
if (nextValue == null || nextValue.isEmpty()) { if (nextValue == null || nextValue.isEmpty()) {
if (isChildContained(childDef, theIncludedResource)) { if (isChildContained(childDef, theIncludedResource)) {
// We still want to go in.. // We still want to go in..
@ -497,10 +502,9 @@ public class XmlParser extends BaseParser implements IParser {
case CONTAINED_RESOURCE_LIST: case CONTAINED_RESOURCE_LIST:
case CONTAINED_RESOURCES: { case CONTAINED_RESOURCES: {
/* /*
* Disable per #103 for (IResource next : value.getContainedResources()) { if * Disable per #103 for (IResource next : value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; }
* (getContainedResources().getResourceId(next) != null) { continue; } * theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(next.getId().getValue()));
* theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter, * theEventWriter.writeEndElement(); }
* true, fixContainedResourceId(next.getId().getValue())); theEventWriter.writeEndElement(); }
*/ */
for (IBaseResource next : getContainedResources().getContainedResources()) { for (IBaseResource next : getContainedResources().getContainedResources()) {
IIdType resourceId = getContainedResources().getResourceId(next); IIdType resourceId = getContainedResources().getResourceId(next);
@ -544,7 +548,8 @@ public class XmlParser extends BaseParser implements IParser {
} }
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (BaseRuntimeChildDefinition nextChild : children) { for (BaseRuntimeChildDefinition nextChild : children) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) { if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue; continue;
@ -570,30 +575,30 @@ public class XmlParser extends BaseParser implements IParser {
} }
} else { } else {
// Narrative generation not currently supported for HL7org structures // Narrative generation not currently supported for HL7org structures
// INarrative narr1 = ((IDomainResource) theResource).getText(); // INarrative narr1 = ((IDomainResource) theResource).getText();
// BaseNarrativeDt<?> narr2 = null; // BaseNarrativeDt<?> narr2 = null;
// if (gen != null && narr1.isEmpty()) { // if (gen != null && narr1.isEmpty()) {
// // TODO: need to implement this // // TODO: need to implement this
// String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile(); // String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
// gen.generateNarrative(resourceProfile, theResource, null); // gen.generateNarrative(resourceProfile, theResource, null);
// } // }
// if (narr2 != null) { // if (narr2 != null) {
// RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild; // RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
// String childName = nextChild.getChildNameByDatatype(child.getDatatype()); // String childName = nextChild.getChildNameByDatatype(child.getDatatype());
// BaseRuntimeElementDefinition<?> type = child.getChildByName(childName); // BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
// encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource); // encodeChildElementToStreamWriter(theResource, theEventWriter, narr2, childName, type, null, theIncludedResource);
// continue; // continue;
// } // }
} }
} }
if (nextChild instanceof RuntimeChildContainedResources) { if (nextChild instanceof RuntimeChildContainedResources) {
if (!theIncludedResource) { if (!theIncludedResource) {
encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theIncludedResource); encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null,
theIncludedResource);
} }
} else { } else {
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement); List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
if (values == null || values.isEmpty()) { if (values == null || values.isEmpty()) {
continue; continue;
@ -636,7 +641,8 @@ public class XmlParser extends BaseParser implements IParser {
} }
} }
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition,
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource); encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource); encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
@ -659,9 +665,8 @@ public class XmlParser extends BaseParser implements IParser {
} }
/** /**
* This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to * This is just to work around the fact that casting java.util.List<ca.uhn.fhir.model.api.ExtensionDt> to java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?, ?>> seems to be
* java.util.List<? extends org.hl7.fhir.instance.model.api.IBaseExtension<?, ?>> seems to be rejected by the compiler * rejected by the compiler some of the time.
* some of the time.
*/ */
private <Q extends IBaseExtension<?, ?>> List<IBaseExtension<?, ?>> toBaseExtensionList(final List<Q> theList) { private <Q extends IBaseExtension<?, ?>> List<IBaseExtension<?, ?>> toBaseExtensionList(final List<Q> theList) {
List<IBaseExtension<?, ?>> retVal = new ArrayList<IBaseExtension<?, ?>>(theList.size()); List<IBaseExtension<?, ?>> retVal = new ArrayList<IBaseExtension<?, ?>>(theList.size());
@ -673,7 +678,7 @@ public class XmlParser extends BaseParser implements IParser {
String reference = determineReferenceText(theRef); String reference = determineReferenceText(theRef);
encodeExtensionsIfPresent(theResource, theEventWriter, theRef, theIncludedResource); encodeExtensionsIfPresent(theResource, theEventWriter, theRef, theIncludedResource);
if (StringUtils.isNotBlank(reference)) { if (StringUtils.isNotBlank(reference)) {
theEventWriter.writeStartElement(RESREF_REFERENCE); theEventWriter.writeStartElement(RESREF_REFERENCE);
theEventWriter.writeAttribute("value", reference); theEventWriter.writeAttribute("value", reference);
@ -686,10 +691,11 @@ public class XmlParser extends BaseParser implements IParser {
} }
} }
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
/* /*
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy * DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy way to make that happen, but hopefully this won't matter as much once we use the
* way to make that happen, but hopefully this won't matter as much once we use the HL7 structures * HL7 structures
*/ */
List<BaseRuntimeChildDefinition> preExtensionChildren = new ArrayList<BaseRuntimeChildDefinition>(); List<BaseRuntimeChildDefinition> preExtensionChildren = new ArrayList<BaseRuntimeChildDefinition>();
@ -714,18 +720,7 @@ public class XmlParser extends BaseParser implements IParser {
} }
@Override @Override
public String encodeResourceToString(IBaseResource theResource) throws DataFormatException { public void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws DataFormatException {
if (theResource == null) {
throw new NullPointerException("Resource can not be null");
}
Writer stringWriter = new StringWriter();
encodeResourceToWriter(theResource, stringWriter);
return stringWriter.toString();
}
@Override
public void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws DataFormatException {
XMLStreamWriter eventWriter; XMLStreamWriter eventWriter;
try { try {
eventWriter = createXmlWriter(theWriter); eventWriter = createXmlWriter(theWriter);
@ -756,7 +751,7 @@ public class XmlParser extends BaseParser implements IParser {
if (isOmitResourceId() && !theIncludedResource) { if (isOmitResourceId() && !theIncludedResource) {
resourceId = null; resourceId = null;
} }
encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId); encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId);
} }
@ -774,7 +769,7 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeDefaultNamespace(FHIR_NS); theEventWriter.writeDefaultNamespace(FHIR_NS);
if (theResource instanceof IAnyResource) { if (theResource instanceof IAnyResource) {
// HL7.org Structures // HL7.org Structures
writeOptionalTagWithValue(theEventWriter, "id", theResourceId); writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource); encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
@ -890,7 +885,8 @@ public class XmlParser extends BaseParser implements IParser {
} }
} }
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource)
throws XMLStreamException, DataFormatException {
for (IBaseExtension<?, ?> next : theExtensions) { for (IBaseExtension<?, ?> next : theExtensions) {
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) { if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
continue; continue;

View File

@ -45,4 +45,4 @@ public enum ValidationModeEnum implements IBase {
public boolean isEmpty() { public boolean isEmpty() {
return false; return false;
} }
} }

View File

@ -756,7 +756,7 @@ public class RestfulServer extends HttpServlet {
public final void init() throws ServletException { public final void init() throws ServletException {
initialize(); initialize();
try { try {
ourLog.info("Initializing HAPI FHIR restful server"); ourLog.info("Initializing HAPI FHIR restful server running in " + getFhirContext().getVersion().getVersion().name() + " mode");
ProvidedResourceScanner providedResourceScanner = new ProvidedResourceScanner(getFhirContext()); ProvidedResourceScanner providedResourceScanner = new ProvidedResourceScanner(getFhirContext());
providedResourceScanner.scanForProvidedResources(this); providedResourceScanner.scanForProvidedResources(this);

View File

@ -118,7 +118,7 @@ public class FhirTerser {
return retVal; return retVal;
} }
public <T extends IBase> List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) { public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>(); final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, null, def, new IModelVisitor() { visit(theResource, null, null, def, new IModelVisitor() {
@ -168,33 +168,44 @@ public class FhirTerser {
} }
private List<Object> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList) { @SuppressWarnings("unchecked")
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass) {
String name = theSubList.get(0); String name = theSubList.get(0);
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name); BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name);
List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj); List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj);
List<Object> retVal = new ArrayList<Object>(); List<T> retVal = new ArrayList<T>();
if (theSubList.size() == 1) { if (theSubList.size() == 1) {
if (nextDef instanceof RuntimeChildChoiceDefinition) { if (nextDef instanceof RuntimeChildChoiceDefinition) {
for (IBase next : values) { for (IBase next : values) {
if (next != null) { if (next != null) {
if (name.endsWith("[x]")) { if (name.endsWith("[x]")) {
retVal.add(next); if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
retVal.add((T) next);
}
} else { } else {
String childName = nextDef.getChildNameByDatatype(next.getClass()); String childName = nextDef.getChildNameByDatatype(next.getClass());
if (theSubList.get(0).equals(childName)) { if (theSubList.get(0).equals(childName)) {
retVal.add(next); if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
retVal.add((T) next);
}
} }
} }
} }
} }
} else { } else {
retVal.addAll(values); for (IBase next : values) {
if (next != null) {
if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
retVal.add((T) next);
}
}
}
} }
} else { } else {
for (IBase nextElement : values) { for (IBase nextElement : values) {
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(nextElement.getClass()); BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(nextElement.getClass());
List<?> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size())); List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass);
retVal.addAll(foundValues); retVal.addAll(foundValues);
} }
} }
@ -202,6 +213,13 @@ public class FhirTerser {
} }
public List<Object> getValues(IBaseResource theResource, String thePath) { public List<Object> getValues(IBaseResource theResource, String thePath) {
Class<Object> wantedClass = Object.class;
return getValues(theResource, thePath, wantedClass);
}
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass) {
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
BaseRuntimeElementCompositeDefinition<?> currentDef = def; BaseRuntimeElementCompositeDefinition<?> currentDef = def;
@ -212,8 +230,7 @@ public class FhirTerser {
if (subList.size() < 1) { if (subList.size() < 1) {
throw new ConfigurationException("Invalid path: " + thePath); throw new ConfigurationException("Invalid path: " + thePath);
} }
return getValues(currentDef, currentObj, subList); return getValues(currentDef, currentObj, subList, theWantedClass);
} }
private List<String> addNameToList(List<String> theCurrentList, BaseRuntimeChildDefinition theChildDefinition) { private List<String> addNameToList(List<String> theCurrentList, BaseRuntimeChildDefinition theChildDefinition) {
@ -469,6 +486,12 @@ public class FhirTerser {
} }
public Object getSingleValueOrNull(IBase theTarget, String thePath) { public Object getSingleValueOrNull(IBase theTarget, String thePath) {
Class<Object> wantedType = Object.class;
return getSingleValueOrNull(theTarget, thePath, wantedType);
}
public <T> T getSingleValueOrNull(IBase theTarget, String thePath, Class<T> theWantedType) {
Validate.notNull(theTarget, "theTarget must not be null"); Validate.notNull(theTarget, "theTarget must not be null");
Validate.notBlank(thePath, "thePath must not be empty"); Validate.notBlank(thePath, "thePath must not be empty");
@ -481,7 +504,7 @@ public class FhirTerser {
Object currentObj = theTarget; Object currentObj = theTarget;
List<String> parts = Arrays.asList(thePath.split("\\.")); List<String> parts = Arrays.asList(thePath.split("\\."));
List<Object> retVal = getValues(currentDef, currentObj, parts); List<T> retVal = getValues(currentDef, currentObj, parts, theWantedType);
if (retVal.isEmpty()) { if (retVal.isEmpty()) {
return null; return null;
} else { } else {
@ -489,4 +512,5 @@ public class FhirTerser {
} }
} }
} }

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.dao; package ca.uhn.fhir.jpa.dao;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2015 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.model.primitive.UriDt;

View File

@ -127,7 +127,8 @@ public class XmlParserDstu2Test {
assertThat(str, not(containsString("meta"))); assertThat(str, not(containsString("meta")));
assertThat(str, containsString("<length><value value=\"123\"/><units value=\"day\"/></length>")); assertThat(str, containsString("<length><value value=\"123\"/><units value=\"day\"/></length>"));
} }
@Test @Test
public void testEncodeAndParseBundleWithoutResourceIds() { public void testEncodeAndParseBundleWithoutResourceIds() {
Organization org = new Organization(); Organization org = new Organization();
@ -211,6 +212,7 @@ public class XmlParserDstu2Test {
} }
@Test @Test
public void testEncodeAndParseExtensionOnResourceReference() { public void testEncodeAndParseExtensionOnResourceReference() {
DataElement de = new DataElement(); DataElement de = new DataElement();
@ -236,6 +238,7 @@ public class XmlParserDstu2Test {
} }
@Test @Test
public void testEncodeAndParseExtensions() throws Exception { public void testEncodeAndParseExtensions() throws Exception {
@ -381,6 +384,7 @@ public class XmlParserDstu2Test {
assertEquals(new Tag("scheme1", "term1", "label1"), tagList.get(0)); assertEquals(new Tag("scheme1", "term1", "label1"), tagList.get(0));
assertEquals(new Tag("scheme2", "term2", "label2"), tagList.get(1)); assertEquals(new Tag("scheme2", "term2", "label2"), tagList.get(1));
} }
@Test @Test
public void testEncodeAndParseMetaProfiles() { public void testEncodeAndParseMetaProfiles() {
@ -427,7 +431,7 @@ public class XmlParserDstu2Test {
assertEquals(new Tag("scheme1", "term1", "label1"), tagList.get(0)); assertEquals(new Tag("scheme1", "term1", "label1"), tagList.get(0));
assertEquals(new Tag("scheme2", "term2", "label2"), tagList.get(1)); assertEquals(new Tag("scheme2", "term2", "label2"), tagList.get(1));
} }
@Test @Test
public void testEncodeAndParseSecurityLabels() { public void testEncodeAndParseSecurityLabels() {
Patient p = new Patient(); Patient p = new Patient();
@ -485,7 +489,7 @@ public class XmlParserDstu2Test {
assertEquals(false, label.getPrimary()); assertEquals(false, label.getPrimary());
assertEquals("VERSION2", label.getVersion()); assertEquals("VERSION2", label.getVersion());
} }
/** /**
* See #103 * See #103
*/ */
@ -510,7 +514,7 @@ public class XmlParserDstu2Test {
parsed = parser.parseResource(Composition.class, string); parsed = parser.parseResource(Composition.class, string);
assertEquals(2, parsed.getContained().getContainedResources().size()); assertEquals(2, parsed.getContained().getContainedResources().size());
} }
/** /**
* See #103 * See #103
*/ */
@ -536,7 +540,6 @@ public class XmlParserDstu2Test {
assertEquals(2, parsed.getContained().getContainedResources().size()); assertEquals(2, parsed.getContained().getContainedResources().size());
} }
@Test @Test
public void testEncodeBinaryWithNoContentType() { public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary(); Binary b = new Binary();
@ -548,6 +551,97 @@ public class XmlParserDstu2Test {
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output); assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
} }
@Test
public void testEncodeBundleContainingResourceWithUuidBase() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Bundle", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value="));
}
@Test
public void testEncodeBundleContainingResourceWithUuidBaseBundleBaseIsSet() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
b.setBase("urn:uuid:");
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, not(stringContainsInOrder("<Bundle", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value=")));
assertThat(encoded, stringContainsInOrder("<Bundle", "<base value=\"urn:uuid:\"/>", "<entry>", "<Patient", "<id value="));
}
@Test
public void testEncodeBundleContainingResourceWithUuidBaseBundleBaseIsSetDifferently() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
b.setBase("urn:oid:");
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Bundle", "<base value=\"urn:oid:\"/>", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value="));
}
@Test
public void testEncodeBundleOldStyleContainingResourceWithUuidBase() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
Bundle b = new Bundle();
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Bundle", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value="));
}
@Test
public void testEncodeBundleOldStyleContainingResourceWithUuidBaseBundleBaseIsSet() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
Bundle b = new Bundle();
b.getLinkBase().setValue("urn:uuid:");
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(encoded);
assertThat(encoded, not(stringContainsInOrder("<Bundle", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value=")));
assertThat(encoded, stringContainsInOrder("<Bundle", "<base value=\"urn:uuid:\"/>", "<entry>", "<Patient", "<id value="));
}
@Test
public void testEncodeBundleOldStyleContainingResourceWithUuidBaseBundleBaseIsSetDifferently() {
Patient p = new Patient();
p.setId(IdDt.newRandomUuid());
p.addName().addFamily("PATIENT");
Bundle b = new Bundle();
b.getLinkBase().setValue("urn:oid:");
b.addEntry().setResource(p);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder("<Bundle", "<base value=\"urn:oid:\"/>", "<entry>", "<base value=\"urn:uuid:\"/>", "<Patient", "<id value="));
}
/** /**
* See #113 * See #113
*/ */

View File

@ -33,6 +33,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.UUID;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -43,6 +44,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
/** /**
@ -656,4 +658,12 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
return theIdPart.toString(); return theIdPart.toString();
} }
/**
* Construct a new ID with with form "urn:uuid:[UUID]" where [UUID] is a new, randomly
* created UUID generated by {@link UUID#randomUUID()}
*/
public static IdDt newRandomUuid() {
return new IdDt("urn:uuid:" + UUID.randomUUID().toString());
}
} }

View File

@ -87,7 +87,10 @@
<action type="fix"> <action type="fix">
When parsing Bundles, if Bundle.entry.base is set to "cid:" (for DSTU1) When parsing Bundles, if Bundle.entry.base is set to "cid:" (for DSTU1)
or "urn:uuid:" / "urn:oid:" (for DSTU2) this is now correctly passed as or "urn:uuid:" / "urn:oid:" (for DSTU2) this is now correctly passed as
the base in resource.getId() the base in resource.getId(). Conversely, when
encoding bundles, if a resource ID has a base defined,
and Bundle.entry.base is empty, it will now be
automatically set by the parser.
</action> </action>
<action type="add"> <action type="add">
Add fluent client method for validate operation, and support the Add fluent client method for validate operation, and support the

View File

@ -113,15 +113,20 @@ a[name]:before {
margin: auto; margin: auto;
} }
DIV.main-body DIV.row DIV.span8 DIV.body-content {
top: -8px;
position: relative;
}
.section h2 { .section h2 {
border-bottom-width: 2px; border-bottom: 2px solid #CF4711;
border-bottom-style: solid; background-color: #FF7741;
border-bottom-color: #CF4711;
background-color: #FF5721;
color: #FFA; color: #FFA;
font-size: 1.5em; font-size: 1.5em;
line-height: 1.4em; line-height: 1.4em;
border-radius: 6px;
padding-left: 5px;
padding-right: 5px;
} }
.section h3 { .section h3 {
@ -195,4 +200,4 @@ a,a.externalLink,a:active,a:hover,a:link,a:visited {
DIV.sidebar-nav UL LI UL LI { DIV.sidebar-nav UL LI UL LI {
font-size: 0.9em; font-size: 0.9em;
} }
*/ */

View File

@ -21,6 +21,9 @@
<a href="https://github.com/jamesagnew/hapi-fhir/releases">GitHub Release Section</a>. <a href="https://github.com/jamesagnew/hapi-fhir/releases">GitHub Release Section</a>.
</p> </p>
</section>
<section name="Maven Users">
<p> <p>
To use HAPI in your application, at a minimum you need to include the HAPI-FHIR core To use HAPI in your application, at a minimum you need to include the HAPI-FHIR core
JAR <code>hapi-fhir-base-[version].jar</code>, as well as at least one "structures" JAR. JAR <code>hapi-fhir-base-[version].jar</code>, as well as at least one "structures" JAR.
@ -49,7 +52,7 @@
<version>${hapi_stable_version}</version> <version>${hapi_stable_version}</version>
</dependency>]]></source> </dependency>]]></source>
<subsection name="Supporting DSTU2 Resources"> <subsection name="Supporting DSTU2 Resources - HAPI Structures">
<p> <p>
HAPI also has a <code>hapi-fhir-structures-dstu2-[version].jar</code>, which HAPI also has a <code>hapi-fhir-structures-dstu2-[version].jar</code>, which
@ -72,24 +75,6 @@
</dependency>]]></source> </dependency>]]></source>
</subsection> </subsection>
<subsection name="Gradle Users">
<p>
If you are using Gradle, you may use the following dependencies. Note that if
you are doing Android development, you may want to use our
<a href="./doc_android.html">Android build</a> instead.
</p>
<p>
DSTU1:
</p>
<source><![CDATA[compile 'ca.uhn.hapi.fhir:hapi-fhir-base:${hapi_stable_version}'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu:${hapi_stable_version}']]></source>
<p>
DSTU2:
</p>
<source><![CDATA[compile 'ca.uhn.hapi.fhir:hapi-fhir-base:${hapi_stable_version}'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:${hapi_stable_version}']]></source>
</subsection>
<subsection name="Using Reference Implementation Structures"> <subsection name="Using Reference Implementation Structures">
@ -105,7 +90,25 @@ compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:${hapi_stable_version}']]><
</dependency>]]></source> </dependency>]]></source>
</subsection> </subsection>
</section>
<section name="Gradle Users">
<p>
If you are using Gradle, you may use the following dependencies. Note that if
you are doing Android development, you may want to use our
<a href="./doc_android.html">Android build</a> instead.
</p>
<p>
DSTU1:
</p>
<source><![CDATA[compile 'ca.uhn.hapi.fhir:hapi-fhir-base:${hapi_stable_version}'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu:${hapi_stable_version}']]></source>
<p>
DSTU2:
</p>
<source><![CDATA[compile 'ca.uhn.hapi.fhir:hapi-fhir-base:${hapi_stable_version}'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:${hapi_stable_version}']]></source>
</section> </section>
<section name="Using Snapshot Builds"> <section name="Using Snapshot Builds">