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

This commit is contained in:
James Agnew 2015-12-16 12:04:54 -05:00
commit 9e110506f7
18 changed files with 281 additions and 135 deletions

View File

@ -192,7 +192,7 @@ class ModelScanner {
Map<String, Class<? extends IBaseResource>> resourceTypes = myNameToResourceType;
myVersionTypes = scanVersionPropertyFile(theDatatypes, resourceTypes, myVersion);
// toScan.add(DateDt.class);
// toScan.add(CodeDt.class);
// toScan.add(DecimalDt.class);

View File

@ -109,22 +109,26 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
} else {
nextDef = theClassToElementDefinitions.get(next);
BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef;
if (nextDef instanceof IRuntimeDatatypeDefinition) {
IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
if (nextDefDatatype.getProfileOf() != null) {
/*
* Elements which are called foo[x] and have a choice which is a profiled datatype must use the
* unprofiled datatype as the element name. E.g. if foo[x] allows markdown as a datatype, it calls the
* element fooString when encoded, because markdown is a profile of string. This is according to the
* FHIR spec
*/
nextDefForChoice = null;
nonPreferred = true;
Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
}
}
/*
* In HAPI 1.3 the following applied:
* Elements which are called foo[x] and have a choice which is a profiled datatype must use the
* unprofiled datatype as the element name. E.g. if foo[x] allows markdown as a datatype, it calls the
* element fooString when encoded, because markdown is a profile of string. This is according to the
* FHIR spec
*
* As of HAPI 1.4 this has been disabled after conversation with Grahame. It appears
* that it is not correct behaviour.
*/
// if (nextDef instanceof IRuntimeDatatypeDefinition) {
// IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
// if (nextDefDatatype.getProfileOf() != null) {
// nextDefForChoice = null;
// nonPreferred = true;
// Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
// BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
// elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
// }
// }
if (nextDefForChoice != null) {
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
}

View File

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.text.WordUtils;
import org.hl7.fhir.instance.model.api.IBase;
@ -34,6 +35,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.CodeDt;
public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildDefinition {
@ -153,13 +155,8 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
myDatatypeToAttributeName = new HashMap<Class<? extends IBase>, String>();
myDatatypeToDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
// for (theContext.get)
for (BaseRuntimeElementDefinition<?> next : theClassToElementDefinitions.values()) {
if (next instanceof IRuntimeDatatypeDefinition) {
// if (next.getName().equals("CodeableConcept")) {
// System.out.println();
// }
myDatatypeToDefinition.put(next.getImplementingClass(), next);
@ -178,7 +175,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
* type.
*/
if (!qualifiedName.startsWith("ca.uhn.fhir.model")) {
if (!qualifiedName.startsWith("org.hl7.fhir.instance.model")) {
if (!qualifiedName.startsWith("org.hl7.fhir")) {
continue;
}
}
@ -198,12 +195,6 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
myAttributeNameToDefinition = datatypeAttributeNameToDefinition;
// for (Entry<String, BaseRuntimeElementDefinition<?>> next : myAttributeNameToDefinition.entrySet()) {
// @SuppressWarnings("unchecked")
// Class<? extends IDatatype> type = (Class<? extends IDatatype>) next.getValue().getImplementingClass();
// myDatatypeToDefinition.put(type, next.getValue());
// }
/*
* Resource reference - The correct name is 'valueReference' in DSTU2 and 'valueResource' in DSTU1
*/

View File

@ -1,8 +1,9 @@
package ca.uhn.fhir.model.api;
import org.apache.commons.lang3.builder.ToStringBuilder;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import ch.qos.logback.core.db.dialect.MySQLDialect;
import org.apache.commons.lang3.builder.ToStringBuilder;
/*
* #%L
@ -34,9 +35,9 @@ import ch.qos.logback.core.db.dialect.MySQLDialect;
*/
public class Include {
private final boolean myImmutable;
private boolean myRecurse;
private String myValue;
private final boolean myImmutable;
/**
* Constructor for <b>non-recursive</b> include
@ -91,22 +92,6 @@ public class Include {
return new Include(myValue, true);
}
public String getValue() {
return myValue;
}
/**
* See the note on equality on the {@link Include class documentation}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (myRecurse ? 1231 : 1237);
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
return result;
}
/**
* See the note on equality on the {@link Include class documentation}
*/
@ -135,6 +120,73 @@ public class Include {
return true;
}
/**
* Returns the portion of the value before the first colon
*/
public String getParamType() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
return myValue.substring(0, firstColon);
}
/**
* Returns the portion of the value after the first colon but before the second colon
*/
public String getParamName() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
int secondColon = myValue.indexOf(':', firstColon + 1);
if (secondColon != -1) {
return myValue.substring(firstColon + 1, secondColon);
} else {
return myValue.substring(firstColon + 1);
}
}
/**
* Returns the portion of the string after the second colon, or null if there are not two colons in the value.
*/
public String getParamTargetType() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
int secondColon = myValue.indexOf(':', firstColon + 1);
if (secondColon != -1) {
return myValue.substring(secondColon + 1);
} else {
return null;
}
}
public String getValue() {
return myValue;
}
/**
* See the note on equality on the {@link Include class documentation}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (myRecurse ? 1231 : 1237);
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
return result;
}
/**
* Is this object {@link #toLocked() locked}?
*/
public boolean isLocked() {
return myImmutable;
}
public boolean isRecurse() {
return myRecurse;
}
@ -151,20 +203,13 @@ public class Include {
}
/**
* Is this object {@link #toLocked() locked}?
*/
public boolean isLocked() {
return myImmutable;
}
/**
* Return a new
* Return a new
*/
public Include toLocked() {
Include retVal = new Include(myValue, myRecurse, true);
return retVal;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
@ -172,36 +217,56 @@ public class Include {
builder.append("recurse", myRecurse);
return builder.toString();
}
/**
* Creates and returns a new copy of this Include with the given type. The
* following table shows what will be returned:
* Creates and returns a new copy of this Include with the given type. The following table shows what will be
* returned:
* <table>
* <tr><th>Initial Contents</th><th>theResourceType</th><th>Output</th></tr>
* <tr><td>Patient:careProvider</th><th>Organization</th><th>Patient:careProvider:Organization</th></tr>
* <tr><td>Patient:careProvider:Practitioner</th><th>Organization</th><th>Patient:careProvider:Organization</th></tr>
* <tr><td>Patient</th><th>(any)</th><th>{@link IllegalStateException}</th></tr>
* <tr>
* <th>Initial Contents</th>
* <th>theResourceType</th>
* <th>Output</th>
* </tr>
* <tr>
* <td>Patient:careProvider</th>
* <th>Organization</th>
* <th>Patient:careProvider:Organization</th>
* </tr>
* <tr>
* <td>Patient:careProvider:Practitioner</th>
* <th>Organization</th>
* <th>Patient:careProvider:Organization</th>
* </tr>
* <tr>
* <td>Patient</th>
* <th>(any)</th>
* <th>{@link IllegalStateException}</th>
* </tr>
* </table>
*
* @param theResourceType The resource type (e.g. "Organization")
* @return A new copy of the include. Note that if this include is {@link #toLocked() locked}, the returned include will be too
* @param theResourceType
* The resource type (e.g. "Organization")
* @return A new copy of the include. Note that if this include is {@link #toLocked() locked}, the returned include
* will be too
*/
public Include withType(String theResourceType) {
StringBuilder b = new StringBuilder();
b.append(myValue);
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == b.length() - 1) {
String paramType = getParamType();
String paramName = getParamName();
if (isBlank(paramType) || isBlank(paramName)) {
throw new IllegalStateException("This include does not contain a value in the format [ResourceType]:[paramName]");
}
int secondColon = myValue.indexOf(':', firstColon + 1);
if (secondColon != -1) {
b.delete(secondColon, b.length());
}
b.append(paramType);
b.append(":");
b.append(theResourceType);
b.append(paramName);
if (isNotBlank(theResourceType)) {
b.append(':');
b.append(theResourceType);
}
Include retVal = new Include(b.toString(), myRecurse, myImmutable);
return retVal;
}
}

View File

@ -28,6 +28,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.defaultString;
/*
* #%L
* HAPI FHIR JPA Server
@ -1378,19 +1380,18 @@ public class SearchBuilder {
if (myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
paths = Collections.singletonList(nextInclude.getValue());
} else {
int colonIdx = nextInclude.getValue().indexOf(':');
if (colonIdx < 2) {
String resType = nextInclude.getParamType();
if (isBlank(resType)) {
continue;
}
String resType = nextInclude.getValue().substring(0, colonIdx);
RuntimeResourceDefinition def = myContext.getResourceDefinition(resType);
if (def == null) {
ourLog.warn("Unknown resource type in include/revinclude=" + nextInclude.getValue());
continue;
}
String paramName = nextInclude.getValue().substring(colonIdx + 1);
RuntimeSearchParam param = def.getSearchParam(paramName);
String paramName = nextInclude.getParamName();
RuntimeSearchParam param = isNotBlank(paramName) ? def.getSearchParam(paramName) : null;
if (param == null) {
ourLog.warn("Unknown param name in include/revinclude=" + nextInclude.getValue());
continue;
@ -1399,11 +1400,20 @@ public class SearchBuilder {
paths = param.getPathsSplit();
}
String targetResourceType = defaultString(nextInclude.getParamTargetType(), null);
for (String nextPath : paths) {
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
String sql;
if (targetResourceType != null) {
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType = :target_resource_type";
} else {
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
}
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
q.setParameter("src_path", nextPath);
q.setParameter("target_pids", nextRoundMatches);
if (targetResourceType != null) {
q.setParameter("target_resource_type", targetResourceType);
}
List<ResourceLink> results = q.getResultList();
for (ResourceLink resourceLink : results) {
if (theReverseMode) {

View File

@ -36,6 +36,7 @@ import javax.persistence.Table;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.search.annotations.Field;
@Entity
@ -64,6 +65,11 @@ public class ResourceLink implements Serializable {
@Column(name = "SRC_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
private Long mySourceResourcePid;
@Column(name = "SOURCE_RESOURCE_TYPE", nullable=false, length=ResourceTable.RESTYPE_LEN)
@ColumnDefault("''") // TODO: remove this (it's only here for simplifying upgrades of 1.3 -> 1.4)
@Field()
private String mySourceResourceType;
@ManyToOne(optional = false, fetch=FetchType.LAZY)
@JoinColumn(name = "TARGET_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false)
private ResourceTable myTargetResource;
@ -71,18 +77,21 @@ public class ResourceLink implements Serializable {
@Column(name = "TARGET_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
@Field()
private Long myTargetResourcePid;
@Column(name = "TARGET_RESOURCE_TYPE", nullable=false, length=ResourceTable.RESTYPE_LEN)
@ColumnDefault("''") // TODO: remove this (it's only here for simplifying upgrades of 1.3 -> 1.4)
@Field()
private String myTargetResourceType;
public ResourceLink() {
super();
}
public ResourceLink(String theSourcePath, ResourceTable theSourceResource, ResourceTable theTargetResource) {
super();
mySourcePath = theSourcePath;
mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
setSourcePath(theSourcePath);
setSourceResource(theSourceResource);
setTargetResource(theTargetResource);
}
@Override
@ -140,12 +149,14 @@ public class ResourceLink implements Serializable {
public void setSourceResource(ResourceTable theSourceResource) {
mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
mySourceResourceType = theSourceResource.getResourceType();
}
public void setTargetResource(ResourceTable theTargetResource) {
Validate.notNull(theTargetResource);
myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
myTargetResourceType = theTargetResource.getResourceType();
}
@Override

View File

@ -1462,6 +1462,13 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
patientId2 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
}
{
// Typed include
SearchParameterMap params = new SearchParameterMap();
params.addInclude(Patient.INCLUDE_CAREPROVIDER.withType("Practitioner"));
List<IIdType> ids = toUnqualifiedVersionlessIds(myPatientDao.search(params));
assertThat(ids, containsInAnyOrder(patientId, patientId2, practId2));
}
{
// No includes
SearchParameterMap params = new SearchParameterMap();
@ -1545,13 +1552,6 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
List<IIdType> ids = toUnqualifiedVersionlessIds(myPatientDao.search(params));
assertThat(ids, containsInAnyOrder(orgId, patientId, patientId2, practId2));
}
{
// // Typed include
// SearchParameterMap params = new SearchParameterMap();
// params.addInclude(Patient.INCLUDE_CAREPROVIDER.withType("Practitioner"));
// List<IIdType> ids = toUnqualifiedVersionlessIds(myPatientDao.search(params));
// assertThat(ids, containsInAnyOrder(patientId, patientId2, practId2));
}
}
@SuppressWarnings("unused")

View File

@ -20,9 +20,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import org.apache.commons.io.IOUtils;
import org.hamcrest.core.IsNot;
import org.hamcrest.core.StringContains;
@ -30,7 +27,6 @@ import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import ca.uhn.fhir.context.ConfigurationException;
@ -68,6 +64,7 @@ import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
@ -76,6 +73,8 @@ 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.narrative.INarrativeGenerator;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
public class JsonParserTest {
private static FhirContext ourCtx;
@ -1318,11 +1317,14 @@ public class JsonParserTest {
public void testSimpleResourceEncode() throws IOException {
String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8"));
Patient obs = ourCtx.newXmlParser().parseResource(Patient.class, xmlString);
IParser parser = ourCtx.newXmlParser();
parser.setParserErrorHandler(new StrictErrorHandler());
Patient obs = parser.parseResource(Patient.class, xmlString);
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
assertEquals("VV", ((CodeDt)undeclaredExtension.getValue()).getValue());
ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));
@ -1376,8 +1378,7 @@ public class JsonParserTest {
ourLog.info("Expected: {}", exp);
ourLog.info("Actual : {}", act);
assertEquals(exp, act);
assertEquals("\nExpected: " + exp + "\nActual : " + act, exp, act);
}
@Test

View File

@ -177,6 +177,8 @@ public class IncludeTest {
assertEquals("Patient:careProvider:Practitioner", new Include("Patient:careProvider", true).withType("Practitioner").getValue());
assertEquals(true, new Include("Patient:careProvider", true).withType("Practitioner").isRecurse());
assertEquals(false, new Include("Patient:careProvider:Organization", true).withType("Practitioner").isLocked());
assertEquals("Practitioner", new Include("Patient:careProvider", true).withType("Practitioner").getParamTargetType());
assertEquals(null, new Include("Patient:careProvider", true).getParamTargetType());
assertEquals("Patient:careProvider:Practitioner", new Include("Patient:careProvider:Organization", true).withType("Practitioner").getValue());
assertEquals(true, new Include("Patient:careProvider:Organization", true).toLocked().withType("Practitioner").isLocked());

View File

@ -125,7 +125,7 @@ public class XmlParserDstu21Test {
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, bin.getContent());
}
@Test
public void testEncodeEmptyBinary() {
String output = ourCtx.newXmlParser().encodeResourceToString(new Binary());
@ -142,18 +142,16 @@ public class XmlParserDstu21Test {
ourCtx.newJsonParser().parseResource(encoded);
}
@Test
public void testEncodeDoesntIncludeUuidId() {
Patient p = new Patient();
p.setId(new IdDt("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2"));
p.addIdentifier().setSystem("ACME");
String actual = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
assertThat(actual, not(containsString("78ef6f64c2f2")));
}
@Test
public void testContainedResourceInExtensionUndeclared() {
Patient p = new Patient();
@ -341,11 +339,9 @@ public class XmlParserDstu21Test {
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(enc, containsString(
"<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString(
"<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
@ -524,8 +520,11 @@ public class XmlParserDstu21Test {
/**
* Test for #233
*
* This was rolled back after a conversation with grahame
*/
@Test
@Ignore
public void testEncodeAndParseProfiledDatatype() {
MedicationOrder mo = new MedicationOrder();
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new DurationDt().setCode("code"));
@ -541,7 +540,8 @@ public class XmlParserDstu21Test {
/**
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
*/
@Test @Ignore
@Test
@Ignore
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
IParser xmlParser = ourCtx.newXmlParser();
@ -751,10 +751,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded);
// @formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -786,10 +784,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded);
//@formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -824,10 +820,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded);
//@formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -1630,7 +1624,8 @@ public class XmlParserDstu21Test {
/**
* See #191
*/
@Test @Ignore
@Test
@Ignore
public void testParseBundleWithLinksOfUnknownRelation() throws Exception {
String input = IOUtils.toString(XmlParserDstu21Test.class.getResourceAsStream("/bundle_orion.xml"));
ca.uhn.fhir.model.dstu21.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu21.resource.Bundle.class, input);
@ -1664,7 +1659,8 @@ public class XmlParserDstu21Test {
/**
* see #144 and #146
*/
@Test @Ignore
@Test
@Ignore
public void testParseContained() {
FhirContext c = FhirContext.forDstu2();

View File

@ -9,6 +9,7 @@ import java.util.Date;
import org.hamcrest.core.StringContains;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
@ -195,6 +196,7 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
}
@Test
@Ignore
public void testGenerateMedicationPrescription() {
MedicationOrder mp = new MedicationOrder();
mp.setId("12345");

View File

@ -32,6 +32,7 @@ import org.hamcrest.core.StringContains;
import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@ -68,6 +69,7 @@ import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
import ca.uhn.fhir.model.dstu2.resource.MedicationStatement;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.AddressUseEnum;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
@ -84,6 +86,7 @@ import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.MarkdownDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
import ca.uhn.fhir.rest.client.IGenericClient;
@ -93,6 +96,46 @@ public class XmlParserDstu2Test {
private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
@Test
public void testChoiceTypeWithProfiledType() {
//@formatter:off
String input = "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://example.com\">\n" +
" <valueMarkdown value=\"THIS IS MARKDOWN\"/>\n" +
" </extension>\n" +
"</Patient>";
//@formatter:on
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, input);
assertEquals(1, parsed.getUndeclaredExtensions().size());
ExtensionDt ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com", ext.getUrl());
assertEquals("THIS IS MARKDOWN", ((MarkdownDt)ext.getValue()).getValue());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
assertThat(encoded, containsString("<valueMarkdown value=\"THIS IS MARKDOWN\"/>"));
}
@Test
public void testChoiceTypeWithProfiledType2() {
Parameters par = new Parameters();
par.addParameter().setValue((StringDt)new StringDt().setValue("ST"));
par.addParameter().setValue((MarkdownDt)new MarkdownDt().setValue("MD"));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(par);
ourLog.info(str);
assertThat(str, stringContainsInOrder("<valueString value=\"ST\"/>", "<valueMarkdown value=\"MD\"/>"));
par = ourCtx.newXmlParser().parseResource(Parameters.class, str);
assertEquals(2, par.getParameter().size());
assertEquals(StringDt.class, par.getParameter().get(0).getValue().getClass());
assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass());
}
@Test
public void testBundleWithBinary() {
//@formatter:off
@ -522,7 +565,7 @@ public class XmlParserDstu2Test {
}
/**
* Test for #233
* Test for #233 - This was reversed after a conversation with Grahame
*/
@Test
public void testEncodeAndParseProfiledDatatype() {
@ -530,7 +573,7 @@ public class XmlParserDstu2Test {
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new DurationDt().setCode("code"));
String out = ourCtx.newXmlParser().encodeResourceToString(mo);
ourLog.info(out);
assertThat(out, containsString("</boundsQuantity>"));
assertThat(out, containsString("</boundsDuration>"));
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, out);
DurationDt duration = (DurationDt) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
@ -539,8 +582,11 @@ public class XmlParserDstu2Test {
/**
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
*
* Disabled because we reverted this change after a conversation with Grahame
*/
@Test
@Ignore
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
IParser xmlParser = ourCtx.newXmlParser();
@ -550,7 +596,7 @@ public class XmlParserDstu2Test {
assertEquals("1", q.getValueElement().getValueAsString());
String output = xmlParser.encodeResourceToString(ms);
assertThat(output, containsString("<quantityQuantity><value value=\"1\"/></quantityQuantity>"));
assertThat(output, containsString("<quantitySimpleQuantity><value value=\"1\"/></quantitySimpleQuantity>"));
}
@Test

View File

@ -1143,7 +1143,7 @@ public class GenericClientDstu2Test {
assertEquals("http://example.com/fhir/Patient/1/$validate-code", capt.getAllValues().get(idx).getURI().toASCIIString());
ourLog.info(extractBody(capt, idx));
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"code\"/><valueString value=\"8495-4\"/></parameter><parameter><name value=\"system\"/><valueUri value=\"http://loinc.org\"/></parameter></Parameters>",extractBody(capt, idx));
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"code\"/><valueCode value=\"8495-4\"/></parameter><parameter><name value=\"system\"/><valueUri value=\"http://loinc.org\"/></parameter></Parameters>",extractBody(capt, idx));
}

View File

@ -182,7 +182,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<redirectTestOutputToFile>false</redirectTestOutputToFile>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<runOrder>random</runOrder>
<argLine>-Dfile.encoding=UTF-8</argLine>
<reuseForks>false</reuseForks>

View File

@ -26,7 +26,6 @@ import org.hamcrest.core.IsNot;
import org.hamcrest.core.StringContains;
import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.Address;
import org.hl7.fhir.instance.model.Attachment;
import org.hl7.fhir.instance.model.Address.AddressUse;
import org.hl7.fhir.instance.model.Address.AddressUseEnumFactory;
import org.hl7.fhir.instance.model.Binary;
@ -49,7 +48,6 @@ import org.hl7.fhir.instance.model.Identifier.IdentifierUse;
import org.hl7.fhir.instance.model.InstantType;
import org.hl7.fhir.instance.model.MedicationStatement;
import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.Observation;
import org.hl7.fhir.instance.model.Organization;
import org.hl7.fhir.instance.model.Patient;
@ -62,6 +60,7 @@ import org.hl7.fhir.instance.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.xml.sax.SAXException;
@ -91,8 +90,11 @@ public class XmlParserHl7OrgDstu2Test {
/**
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
*
* Disabled after conversation with Grahame
*/
@Test
@Ignore
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
IParser xmlParser = ourCtx.newXmlParser();

View File

@ -68,7 +68,9 @@ public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
for (ClassInfo classInfo : tlc) {
DatatypeDef def = Class.forName(classInfo.getName()).getAnnotation(DatatypeDef.class);
if (def != null) {
getNameToDatatypeClass().put(def.name(), classInfo.getName());
if (classInfo.getName().contains("Bound") == false) {
getNameToDatatypeClass().put(def.name(), classInfo.getName());
}
}
}
} catch (IOException e) {
@ -82,7 +84,9 @@ public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
for (ClassInfo classInfo : tlc) {
DatatypeDef def = Class.forName(classInfo.getName()).getAnnotation(DatatypeDef.class);
if (def != null) {
getNameToDatatypeClass().put(def.name(), classInfo.getName());
if (classInfo.getName().contains("Bound") == false) {
getNameToDatatypeClass().put(def.name(), classInfo.getName());
}
}
}
} catch (IOException e) {

View File

@ -65,6 +65,17 @@
remains committed to supporting JDK 6+ in the compiled library, but these
days it can only be built using JDK 8. Thanks to joelsch for the PR!
</action>
<action type="fix">
When serializing a value[x] field, if the value type was a profiled type (e.g. markdown is a
profile of string) HAPI 1.3 would use the base type in the element name, e.g.
valueString instead of valueMarkdown. After discussion with Grahame, this appears to
be incorrect behaviour so it has been fixed.
</action>
<action type="add" issue="240">
Support target parameter type in _include / _revinclude values, e.g.
_include=Patient:careProvider:Organization. Thanks to Joe Portner
for reporting!
<action>
<action type="add">
Use ResponseHighlighterInterceptor in the hapi-fhir-jpaserver-example
project to provide nice syntax highlighting. Thanks to Rob Hausam for