Fix #233 - elementQuantity gets incorrectly encoded as elementDuration

This commit is contained in:
jamesagnew 2015-09-29 19:41:31 -04:00
parent 04764ed07e
commit f9e4a3e1b5
12 changed files with 102 additions and 43 deletions

View File

@ -11,8 +11,13 @@
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>

View File

@ -16,13 +16,23 @@
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (1).launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>

View File

@ -27,7 +27,7 @@ public interface IRuntimeDatatypeDefinition {
boolean isSpecialization();
public BaseRuntimeElementDefinition<?> getProfileOf();
public Class<? extends IBaseDatatype> getProfileOf();
boolean isProfileOf(Class<? extends IBaseDatatype> theType);

View File

@ -30,6 +30,8 @@ import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.annotation.Child;
@ -41,6 +43,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
private Map<String, BaseRuntimeElementDefinition<?>> myNameToChildDefinition;
private Map<Class<? extends IBase>, String> myDatatypeToElementName;
private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myDatatypeToElementDefinition;
private String myReferenceSuffix;
public RuntimeChildChoiceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBase>> theChoiceTypes) {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
@ -82,9 +85,15 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
myDatatypeToElementName = new HashMap<Class<? extends IBase>, String>();
myDatatypeToElementDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
myReferenceSuffix = "Resource";
} else {
myReferenceSuffix = "Reference";
}
for (Class<? extends IBase> next : myChoiceTypes) {
String elementName;
String elementName = null;
BaseRuntimeElementDefinition<?> nextDef;
boolean nonPreferred = false;
if (IBaseResource.class.isAssignableFrom(next)) {
@ -109,32 +118,43 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
* element fooString when encoded, because markdown is a profile of string. This is according to the
* FHIR spec
*/
nextDefForChoice = nextDefDatatype.getProfileOf();
nextDefForChoice = null;
nonPreferred = true;
Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
}
}
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
}
if (myNameToChildDefinition.containsKey(elementName) == false || !nonPreferred) {
myNameToChildDefinition.put(elementName, nextDef);
}
if (IBaseResource.class.isAssignableFrom(next)) {
Class<? extends IBase> refType = theContext.getVersion().getResourceReferenceType();
myDatatypeToElementDefinition.put(refType, nextDef);
String alternateElementName;
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
alternateElementName = getElementName() + "Resource";
} else {
alternateElementName = getElementName() + "Reference";
if (nextDefForChoice != null) {
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
}
myDatatypeToElementName.put(refType, alternateElementName);
}
// I don't see how elementName could be null here, but eclipse complains..
if (elementName != null) {
if (myNameToChildDefinition.containsKey(elementName) == false || !nonPreferred) {
myNameToChildDefinition.put(elementName, nextDef);
}
}
/*
* If this is a resource reference, the element name is "fooNameReference"
*/
if (IBaseResource.class.isAssignableFrom(next) || IBaseReference.class.isAssignableFrom(next)) {
next = theContext.getVersion().getResourceReferenceType();
elementName = getElementName() + myReferenceSuffix;
}
myDatatypeToElementDefinition.put(next, nextDef);
myDatatypeToElementName.put(next, elementName);
if (myDatatypeToElementName.containsKey(next)) {
String existing = myDatatypeToElementName.get(next);
if (!existing.equals(elementName)) {
throw new ConfigurationException("Already have element name " + existing + " for datatype " + next.getClass().getSimpleName() + " in " + getElementName() + ", cannot add " + elementName);
}
} else {
myDatatypeToElementName.put(next, elementName);
}
}
myNameToChildDefinition = Collections.unmodifiableMap(myNameToChildDefinition);
@ -145,7 +165,8 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
@Override
public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
return myDatatypeToElementName.get(theDatatype);
String retVal = myDatatypeToElementName.get(theDatatype);
return retVal;
}
@Override

View File

@ -65,8 +65,8 @@ public class RuntimeCompositeDatatypeDefinition extends BaseRuntimeElementCompos
}
@Override
public BaseRuntimeElementDefinition<?> getProfileOf() {
return myProfileOf;
public Class<? extends IBaseDatatype> getProfileOf() {
return myProfileOfType;
}
@Override

View File

@ -58,8 +58,8 @@ public class RuntimePrimitiveDatatypeDefinition extends BaseRuntimeElementDefini
}
@Override
public BaseRuntimeElementDefinition<?> getProfileOf() {
return myProfileOf;
public Class<? extends IBaseDatatype> getProfileOf() {
return myProfileOfType;
}
@Override

View File

@ -17,13 +17,23 @@
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder (1).launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (2).launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>

View File

@ -119,11 +119,11 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
}
}
private class SimpleBoundState implements IState {
private class BoundStaticSubscipriptionState implements IState {
private WebSocketSession mySession;
public SimpleBoundState(WebSocketSession theSession) {
public BoundStaticSubscipriptionState(WebSocketSession theSession) {
mySession = theSession;
}
@ -157,12 +157,12 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
@Autowired
private FhirContext myCtx;
private class ResourceBoundState implements IState {
private class BoundDynamicSubscriptionState implements IState {
private WebSocketSession mySession;
private EncodingEnum myEncoding;
public ResourceBoundState(WebSocketSession theSession, EncodingEnum theEncoding) {
public BoundDynamicSubscriptionState(WebSocketSession theSession, EncodingEnum theEncoding) {
mySession = theSession;
myEncoding = theEncoding;
}
@ -241,12 +241,12 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
subscription.setCriteria(theRemaining);
try {
String params = theRemaining.substring(theRemaining.indexOf('?'));
List<NameValuePair> paramValues = URLEncodedUtils.parse("http://example.com" + params, Constants.CHARSET_UTF8);
String params = theRemaining.substring(theRemaining.indexOf('?')+1);
List<NameValuePair> paramValues = URLEncodedUtils.parse(params, Constants.CHARSET_UTF8, '&');
EncodingEnum encoding = EncodingEnum.JSON;
for (NameValuePair nameValuePair : paramValues) {
if (Constants.PARAM_FORMAT.equals(nameValuePair)) {
EncodingEnum nextEncoding = EncodingEnum.forContentType(nameValuePair.getValue());
if (Constants.PARAM_FORMAT.equals(nameValuePair.getName())) {
EncodingEnum nextEncoding = Constants.FORMAT_VAL_TO_ENCODING.get(nameValuePair.getValue());
if (nextEncoding != null) {
encoding = nextEncoding;
}
@ -257,7 +257,7 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new ResourceBoundState(theSession, encoding);
myState = new BoundDynamicSubscriptionState(theSession, encoding);
return id;
} catch (UnprocessableEntityException e) {
@ -298,7 +298,7 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
Subscription subscription = mySubscriptionDao.read(id);
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new SimpleBoundState(theSession);
myState = new BoundStaticSubscipriptionState(theSession);
} catch (ResourceNotFoundException e) {
try {
theSession.close(new CloseStatus(CloseStatus.PROTOCOL_ERROR.getCode(), "Invalid bind request - Unknown subscription: " + id.getValue()));

View File

@ -1919,6 +1919,10 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
@Test()
public void testSortByComposite() {
Observation o = new Observation();
o.getCode().setText("testSortByComposite");
myObservationDao.create(o);
SearchParameterMap pm = new SearchParameterMap();
pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT));
try {

View File

@ -1293,6 +1293,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
@Test(expected = InvalidRequestException.class)
public void testSearchWithInvalidSort() throws Exception {
Observation o = new Observation();
o.getCode().setText("testSearchWithInvalidSort");
myObservationDao.create(o);
//@formatter:off
Bundle found = ourClient
.search()

View File

@ -176,7 +176,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
WebSocketClient client = new WebSocketClient();
try {
client.start();
URI echoUri = new URI("ws://localhost:" + ourPort + "/baseDstu2/websocket");
URI echoUri = new URI("ws://localhost:" + ourPort + "/websocket/dstu2");
client.connect(socket, echoUri, new ClientUpgradeRequest());
ourLog.info("Connecting to : {}", echoUri);
@ -241,7 +241,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
WebSocketClient client = new WebSocketClient();
try {
client.start();
URI echoUri = new URI("ws://localhost:" + ourPort + "/baseDstu2/websocket");
URI echoUri = new URI("ws://localhost:" + ourPort + "/websocket/dstu2");
client.connect(socket, echoUri, new ClientUpgradeRequest());
ourLog.info("Connecting to : {}", echoUri);

View File

@ -95,6 +95,12 @@
JPA server Patient/[id]/$everything operation now supports
_lastUpdated filtering and _sort'ing of results.
</action>
<action type="fix" issue="233">
Fix parser issue where profiled choice element datatypes (e.g. value[x] where one allowable
type is Duration, which is a profile of Quantity) get incorrectly encoded using the
profiled datatype name instead of the base datatype name as required by the FHIR
spec. Thanks to Nehashri Puttu Lokesh for reporting!
</action>
</release>
<release version="1.2" date="2015-09-18">
<action type="add">