Add suport for composite and sorting to JPA (not yet complete)
This commit is contained in:
parent
318dcfcaaf
commit
0bc703107c
|
@ -6,7 +6,6 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="bin" path="src/site/example/java"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
|
|
|
@ -2,6 +2,5 @@
|
|||
<wb-module deploy-name="hapi-fhir-base">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/site/example/java"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
|
@ -75,6 +75,11 @@
|
|||
are encoded even if they have no value. Thanks to David Hay of Orion for
|
||||
reporting this!
|
||||
</action>
|
||||
<action type="fix">
|
||||
Fix: RESTful server deployed to a location where the URL to access it contained a
|
||||
space (e.g. a WAR file with a space in the name) failed to work correctly.
|
||||
Thanks to David Hay of Orion for reporting this!
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.4" date="2014-Jul-13">
|
||||
<action type="add">
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -48,7 +49,6 @@ import ca.uhn.fhir.model.api.ICompositeDatatype;
|
|||
import ca.uhn.fhir.model.api.ICompositeElement;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IExtension;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.IResourceBlock;
|
||||
|
@ -299,8 +299,6 @@ class ModelScanner {
|
|||
scanCompositeElementForChildren(theClass, resourceDef);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String scanCodeTable(Class<? extends ICodeEnum> theCodeType, CodeTableDef theCodeTableDefinition) {
|
||||
return null; // TODO: implement
|
||||
}
|
||||
|
@ -602,6 +600,9 @@ class ModelScanner {
|
|||
|
||||
private void scanResourceForSearchParams(Class<? extends IResource> theClass, RuntimeResourceDefinition theResourceDef) {
|
||||
|
||||
Map<String, RuntimeSearchParam> nameToParam = new HashMap<String, RuntimeSearchParam>();
|
||||
Map<Field, SearchParamDefinition> compositeFields = new LinkedHashMap<Field, SearchParamDefinition>();
|
||||
|
||||
for (Field nextField : theClass.getFields()) {
|
||||
SearchParamDefinition searchParam = nextField.getAnnotation(SearchParamDefinition.class);
|
||||
if (searchParam != null) {
|
||||
|
@ -609,11 +610,34 @@ class ModelScanner {
|
|||
if (paramType == null) {
|
||||
throw new ConfigurationException("Searc param " + searchParam.name() + " has an invalid type: " + searchParam.type());
|
||||
}
|
||||
if(paramType==SearchParamTypeEnum.COMPOSITE) {
|
||||
compositeFields.put(nextField, searchParam);
|
||||
continue;
|
||||
}
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), paramType);
|
||||
theResourceDef.addSearchParam(param);
|
||||
nameToParam.put(param.getName(), param);
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Field, SearchParamDefinition> nextEntry : compositeFields.entrySet()) {
|
||||
Field nextField = nextEntry.getKey();
|
||||
SearchParamDefinition searchParam = nextEntry.getValue();
|
||||
|
||||
List<RuntimeSearchParam> compositeOf = new ArrayList<RuntimeSearchParam>();
|
||||
for (String nextName:searchParam.compositeOf()) {
|
||||
RuntimeSearchParam param = nameToParam.get(nextName);
|
||||
if (param==null) {
|
||||
ourLog.warn("Search parameter {}.{} declares that it is a composite with compositeOf value '{}' but that is not a valid parametr name itself. Valid values are: {}",
|
||||
new Object[] {theResourceDef.getName(), searchParam.name(), nextName, nameToParam.keySet()});
|
||||
continue;
|
||||
}
|
||||
compositeOf.add(param);
|
||||
}
|
||||
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), SearchParamTypeEnum.COMPOSITE, compositeOf);
|
||||
theResourceDef.addSearchParam(param);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, RuntimeResourceDefinition> getIdToResourceDefinition() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
|
@ -22,30 +24,29 @@ import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public class RuntimeSearchParam {
|
||||
|
||||
private String myDescription;
|
||||
private String myName;
|
||||
private String myPath;
|
||||
private SearchParamTypeEnum myParamType;
|
||||
// private List<String> myPathParts;
|
||||
private String myPath;
|
||||
private List<RuntimeSearchParam> myCompositeOf;
|
||||
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, SearchParamTypeEnum theParamType) {
|
||||
this(theName, theDescription, thePath, theParamType, null);
|
||||
}
|
||||
|
||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, SearchParamTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf) {
|
||||
super();
|
||||
myName = theName;
|
||||
myDescription = theDescription;
|
||||
myPath=thePath;
|
||||
myParamType=theParamType;
|
||||
// myPathParts = Arrays.asList(thePath.split("\\."));
|
||||
myPath = thePath;
|
||||
myParamType = theParamType;
|
||||
myCompositeOf = theCompositeOf;
|
||||
}
|
||||
|
||||
public SearchParamTypeEnum getParamType() {
|
||||
return myParamType;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return myPath;
|
||||
public List<RuntimeSearchParam> getCompositeOf() {
|
||||
return myCompositeOf;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
|
@ -56,5 +57,12 @@ public class RuntimeSearchParam {
|
|||
return myName;
|
||||
}
|
||||
|
||||
public SearchParamTypeEnum getParamType() {
|
||||
return myParamType;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return myPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,10 @@ public @interface SearchParamDefinition {
|
|||
|
||||
/**
|
||||
* If the parameter is of type "composite", this parameter lists the names of the parameters
|
||||
* which this parameter is a composite of. E.g. "name-value-token" is a composite of "name" and "value-token"
|
||||
* which this parameter is a composite of. E.g. "name-value-token" is a composite of "name" and "value-token".
|
||||
* <p>
|
||||
* If the parameter is not a composite, this parameter must be empty
|
||||
* </p>
|
||||
*/
|
||||
String[] compositeOf() default {};
|
||||
|
||||
|
|
|
@ -16,26 +16,6 @@
|
|||
|
||||
package ca.uhn.fhir.model.dstu.resource;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -63,13 +43,8 @@ import ca.uhn.fhir.model.dstu.composite.RatioDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.SampledDataDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ObservationInterpretationCodesEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ObservationRelationshipTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ObservationReliabilityEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ObservationStatusEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeableConceptDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
@ -113,7 +88,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.name</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="name", path="Observation.name", description="The name of the observation type", type="token")
|
||||
@SearchParamDefinition(name="name", path="Observation.name", description="The name of the observation type", type="token" )
|
||||
public static final String SP_NAME = "name";
|
||||
|
||||
/**
|
||||
|
@ -134,7 +109,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.value[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="value-quantity", path="Observation.value[x]", description="The value of the observation, if the value is a Quantity, or a SampledData (just search on the bounds of the values in sampled data)", type="quantity")
|
||||
@SearchParamDefinition(name="value-quantity", path="Observation.value[x]", description="The value of the observation, if the value is a Quantity, or a SampledData (just search on the bounds of the values in sampled data)", type="quantity" )
|
||||
public static final String SP_VALUE_QUANTITY = "value-quantity";
|
||||
|
||||
/**
|
||||
|
@ -155,7 +130,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.value[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="value-concept", path="Observation.value[x]", description="The value of the observation, if the value is a CodeableConcept", type="token")
|
||||
@SearchParamDefinition(name="value-concept", path="Observation.value[x]", description="The value of the observation, if the value is a CodeableConcept", type="token" )
|
||||
public static final String SP_VALUE_CONCEPT = "value-concept";
|
||||
|
||||
/**
|
||||
|
@ -176,7 +151,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.value[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="value-date", path="Observation.value[x]", description="The value of the observation, if the value is a Period", type="date")
|
||||
@SearchParamDefinition(name="value-date", path="Observation.value[x]", description="The value of the observation, if the value is a Period", type="date" )
|
||||
public static final String SP_VALUE_DATE = "value-date";
|
||||
|
||||
/**
|
||||
|
@ -197,7 +172,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.value[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="value-string", path="Observation.value[x]", description="The value of the observation, if the value is a string, and also searches in CodeableConcept.text", type="string")
|
||||
@SearchParamDefinition(name="value-string", path="Observation.value[x]", description="The value of the observation, if the value is a string, and also searches in CodeableConcept.text", type="string" )
|
||||
public static final String SP_VALUE_STRING = "value-string";
|
||||
|
||||
/**
|
||||
|
@ -210,27 +185,6 @@ public class Observation extends BaseResource implements IResource {
|
|||
*/
|
||||
public static final StringClientParam VALUE_STRING = new StringClientParam(SP_VALUE_STRING);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>name-value-[x]</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="name-value-[x]", path="name & value-[x]", description="Both name and one of the value parameters", type="composite")
|
||||
public static final String SP_NAME_VALUE_X = "name-value-[x]";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>name-value-[x]</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam NAME_VALUE_X = new CompositeClientParam(SP_NAME_VALUE_X);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>date</b>
|
||||
* <p>
|
||||
|
@ -239,7 +193,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.applies[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="date", path="Observation.applies[x]", description="Obtained date/time. If the obtained element is a period, a date that falls in the period", type="date")
|
||||
@SearchParamDefinition(name="date", path="Observation.applies[x]", description="Obtained date/time. If the obtained element is a period, a date that falls in the period", type="date" )
|
||||
public static final String SP_DATE = "date";
|
||||
|
||||
/**
|
||||
|
@ -260,7 +214,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.status</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="status", path="Observation.status", description="The status of the observation", type="token")
|
||||
@SearchParamDefinition(name="status", path="Observation.status", description="The status of the observation", type="token" )
|
||||
public static final String SP_STATUS = "status";
|
||||
|
||||
/**
|
||||
|
@ -281,7 +235,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.reliability</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="reliability", path="Observation.reliability", description="The reliability of the observation", type="token")
|
||||
@SearchParamDefinition(name="reliability", path="Observation.reliability", description="The reliability of the observation", type="token" )
|
||||
public static final String SP_RELIABILITY = "reliability";
|
||||
|
||||
/**
|
||||
|
@ -302,7 +256,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.subject</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="subject", path="Observation.subject", description="The subject that the observation is about", type="reference")
|
||||
@SearchParamDefinition(name="subject", path="Observation.subject", description="The subject that the observation is about", type="reference" )
|
||||
public static final String SP_SUBJECT = "subject";
|
||||
|
||||
/**
|
||||
|
@ -329,7 +283,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.performer</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="performer", path="Observation.performer", description="Who and/or what performed the observation", type="reference")
|
||||
@SearchParamDefinition(name="performer", path="Observation.performer", description="Who and/or what performed the observation", type="reference" )
|
||||
public static final String SP_PERFORMER = "performer";
|
||||
|
||||
/**
|
||||
|
@ -356,7 +310,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.specimen</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="specimen", path="Observation.specimen", description="", type="reference")
|
||||
@SearchParamDefinition(name="specimen", path="Observation.specimen", description="", type="reference" )
|
||||
public static final String SP_SPECIMEN = "specimen";
|
||||
|
||||
/**
|
||||
|
@ -383,7 +337,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.related.type</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="related-type", path="Observation.related.type", description="", type="token")
|
||||
@SearchParamDefinition(name="related-type", path="Observation.related.type", description="", type="token" )
|
||||
public static final String SP_RELATED_TYPE = "related-type";
|
||||
|
||||
/**
|
||||
|
@ -404,7 +358,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
* Path: <b>Observation.related.target</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="related-target", path="Observation.related.target", description="", type="reference")
|
||||
@SearchParamDefinition(name="related-target", path="Observation.related.target", description="", type="reference" )
|
||||
public static final String SP_RELATED_TARGET = "related-target";
|
||||
|
||||
/**
|
||||
|
@ -424,25 +378,109 @@ public class Observation extends BaseResource implements IResource {
|
|||
public static final Include INCLUDE_RELATED_TARGET = new Include("Observation.related.target");
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>related</b>
|
||||
* Search parameter constant for <b>name-value-quantity</b>
|
||||
* <p>
|
||||
* Description: <b>Related Observations - search on related-type and related-target together</b><br/>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>related-target & related-type</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="related", path="related-target & related-type", description="Related Observations - search on related-type and related-target together", type="composite")
|
||||
public static final String SP_RELATED = "related";
|
||||
@SearchParamDefinition(name="name-value-quantity", path="name & value-[x]", description="Both name and one of the value parameters", type="composite" , compositeOf={ "name", "value-quantity" } )
|
||||
public static final String SP_NAME_VALUE_QUANTITY = "name-value-quantity";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>related</b>
|
||||
* <b>Fluent Client</b> search parameter constant for <b>name-value-quantity</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam<TokenClientParam, QuantityClientParam> NAME_VALUE_QUANTITY = new CompositeClientParam<TokenClientParam, QuantityClientParam>(SP_NAME_VALUE_QUANTITY);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>name-value-concept</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="name-value-concept", path="name & value-[x]", description="Both name and one of the value parameters", type="composite" , compositeOf={ "name", "value-concept" } )
|
||||
public static final String SP_NAME_VALUE_CONCEPT = "name-value-concept";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>name-value-concept</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam<TokenClientParam, TokenClientParam> NAME_VALUE_CONCEPT = new CompositeClientParam<TokenClientParam, TokenClientParam>(SP_NAME_VALUE_CONCEPT);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>name-value-date</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="name-value-date", path="name & value-[x]", description="Both name and one of the value parameters", type="composite" , compositeOf={ "name", "value-date" } )
|
||||
public static final String SP_NAME_VALUE_DATE = "name-value-date";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>name-value-date</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam<TokenClientParam, DateClientParam> NAME_VALUE_DATE = new CompositeClientParam<TokenClientParam, DateClientParam>(SP_NAME_VALUE_DATE);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>name-value-string</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
@SearchParamDefinition(name="name-value-string", path="name & value-[x]", description="Both name and one of the value parameters", type="composite" , compositeOf={ "name", "value-string" } )
|
||||
public static final String SP_NAME_VALUE_STRING = "name-value-string";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>name-value-string</b>
|
||||
* <p>
|
||||
* Description: <b>Both name and one of the value parameters</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>name & value-[x]</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam<TokenClientParam, StringClientParam> NAME_VALUE_STRING = new CompositeClientParam<TokenClientParam, StringClientParam>(SP_NAME_VALUE_STRING);
|
||||
|
||||
/**
|
||||
* Search parameter constant for <b>related-target-related-type</b>
|
||||
* <p>
|
||||
* Description: <b>Related Observations - search on related-type and related-target together</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>related-target & related-type</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam RELATED = new CompositeClientParam(SP_RELATED);
|
||||
@SearchParamDefinition(name="related-target-related-type", path="related-target & related-type", description="Related Observations - search on related-type and related-target together", type="composite" , compositeOf={ "related-target", "related-type" } )
|
||||
public static final String SP_RELATED_TARGET_RELATED_TYPE = "related-target-related-type";
|
||||
|
||||
/**
|
||||
* <b>Fluent Client</b> search parameter constant for <b>related-target-related-type</b>
|
||||
* <p>
|
||||
* Description: <b>Related Observations - search on related-type and related-target together</b><br/>
|
||||
* Type: <b>composite</b><br/>
|
||||
* Path: <b>related-target & related-type</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
public static final CompositeClientParam<ReferenceClientParam, TokenClientParam> RELATED_TARGET_RELATED_TYPE = new CompositeClientParam<ReferenceClientParam, TokenClientParam>(SP_RELATED_TARGET_RELATED_TYPE);
|
||||
|
||||
|
||||
@Child(name="name", type=CodeableConceptDt.class, order=0, min=1, max=1)
|
||||
|
@ -465,7 +503,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
shortDefinition="High, low, normal, etc.",
|
||||
formalDefinition="The assessment made based on the result of the observation."
|
||||
)
|
||||
private BoundCodeableConceptDt<ObservationInterpretationCodesEnum> myInterpretation;
|
||||
private CodeableConceptDt myInterpretation;
|
||||
|
||||
@Child(name="comments", type=StringDt.class, order=3, min=0, max=1)
|
||||
@Description(
|
||||
|
@ -494,14 +532,14 @@ public class Observation extends BaseResource implements IResource {
|
|||
shortDefinition="registered | preliminary | final | amended +",
|
||||
formalDefinition="The status of the result value"
|
||||
)
|
||||
private BoundCodeDt<ObservationStatusEnum> myStatus;
|
||||
private CodeDt myStatus;
|
||||
|
||||
@Child(name="reliability", type=CodeDt.class, order=7, min=1, max=1)
|
||||
@Description(
|
||||
shortDefinition="ok | ongoing | early | questionable | calibrating | error +",
|
||||
formalDefinition="An estimate of the degree to which quality issues have impacted on the value reported"
|
||||
)
|
||||
private BoundCodeDt<ObservationReliabilityEnum> myReliability;
|
||||
private CodeDt myReliability;
|
||||
|
||||
@Child(name="bodySite", type=CodeableConceptDt.class, order=8, min=0, max=1)
|
||||
@Description(
|
||||
|
@ -642,9 +680,9 @@ public class Observation extends BaseResource implements IResource {
|
|||
* The assessment made based on the result of the observation.
|
||||
* </p>
|
||||
*/
|
||||
public BoundCodeableConceptDt<ObservationInterpretationCodesEnum> getInterpretation() {
|
||||
public CodeableConceptDt getInterpretation() {
|
||||
if (myInterpretation == null) {
|
||||
myInterpretation = new BoundCodeableConceptDt<ObservationInterpretationCodesEnum>(ObservationInterpretationCodesEnum.VALUESET_BINDER);
|
||||
myInterpretation = new CodeableConceptDt();
|
||||
}
|
||||
return myInterpretation;
|
||||
}
|
||||
|
@ -657,24 +695,11 @@ public class Observation extends BaseResource implements IResource {
|
|||
* The assessment made based on the result of the observation.
|
||||
* </p>
|
||||
*/
|
||||
public Observation setInterpretation(BoundCodeableConceptDt<ObservationInterpretationCodesEnum> theValue) {
|
||||
public Observation setInterpretation(CodeableConceptDt theValue) {
|
||||
myInterpretation = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>interpretation</b> (High, low, normal, etc.)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The assessment made based on the result of the observation.
|
||||
* </p>
|
||||
*/
|
||||
public Observation setInterpretation(ObservationInterpretationCodesEnum theValue) {
|
||||
getInterpretation().setValueAsEnum(theValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>comments</b> (Comments about result).
|
||||
|
@ -786,8 +811,8 @@ public class Observation extends BaseResource implements IResource {
|
|||
*
|
||||
* </p>
|
||||
*/
|
||||
public Observation setIssued( Date theDate, TemporalPrecisionEnum thePrecision) {
|
||||
myIssued = new InstantDt(theDate, thePrecision);
|
||||
public Observation setIssuedWithMillisPrecision( Date theDate) {
|
||||
myIssued = new InstantDt(theDate);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -799,8 +824,8 @@ public class Observation extends BaseResource implements IResource {
|
|||
*
|
||||
* </p>
|
||||
*/
|
||||
public Observation setIssuedWithMillisPrecision( Date theDate) {
|
||||
myIssued = new InstantDt(theDate);
|
||||
public Observation setIssued( Date theDate, TemporalPrecisionEnum thePrecision) {
|
||||
myIssued = new InstantDt(theDate, thePrecision);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -815,9 +840,9 @@ public class Observation extends BaseResource implements IResource {
|
|||
* The status of the result value
|
||||
* </p>
|
||||
*/
|
||||
public BoundCodeDt<ObservationStatusEnum> getStatus() {
|
||||
public CodeDt getStatus() {
|
||||
if (myStatus == null) {
|
||||
myStatus = new BoundCodeDt<ObservationStatusEnum>(ObservationStatusEnum.VALUESET_BINDER);
|
||||
myStatus = new CodeDt();
|
||||
}
|
||||
return myStatus;
|
||||
}
|
||||
|
@ -830,25 +855,25 @@ public class Observation extends BaseResource implements IResource {
|
|||
* The status of the result value
|
||||
* </p>
|
||||
*/
|
||||
public Observation setStatus(BoundCodeDt<ObservationStatusEnum> theValue) {
|
||||
public Observation setStatus(CodeDt theValue) {
|
||||
myStatus = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>status</b> (registered | preliminary | final | amended +)
|
||||
/**
|
||||
* Sets the value for <b>status</b> (registered | preliminary | final | amended +)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The status of the result value
|
||||
* </p>
|
||||
*/
|
||||
public Observation setStatus(ObservationStatusEnum theValue) {
|
||||
getStatus().setValueAsEnum(theValue);
|
||||
return this;
|
||||
public Observation setStatus( String theCode) {
|
||||
myStatus = new CodeDt(theCode);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>reliability</b> (ok | ongoing | early | questionable | calibrating | error +).
|
||||
* creating it if it does
|
||||
|
@ -859,9 +884,9 @@ public class Observation extends BaseResource implements IResource {
|
|||
* An estimate of the degree to which quality issues have impacted on the value reported
|
||||
* </p>
|
||||
*/
|
||||
public BoundCodeDt<ObservationReliabilityEnum> getReliability() {
|
||||
public CodeDt getReliability() {
|
||||
if (myReliability == null) {
|
||||
myReliability = new BoundCodeDt<ObservationReliabilityEnum>(ObservationReliabilityEnum.VALUESET_BINDER);
|
||||
myReliability = new CodeDt();
|
||||
}
|
||||
return myReliability;
|
||||
}
|
||||
|
@ -874,25 +899,25 @@ public class Observation extends BaseResource implements IResource {
|
|||
* An estimate of the degree to which quality issues have impacted on the value reported
|
||||
* </p>
|
||||
*/
|
||||
public Observation setReliability(BoundCodeDt<ObservationReliabilityEnum> theValue) {
|
||||
public Observation setReliability(CodeDt theValue) {
|
||||
myReliability = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>reliability</b> (ok | ongoing | early | questionable | calibrating | error +)
|
||||
/**
|
||||
* Sets the value for <b>reliability</b> (ok | ongoing | early | questionable | calibrating | error +)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* An estimate of the degree to which quality issues have impacted on the value reported
|
||||
* </p>
|
||||
*/
|
||||
public Observation setReliability(ObservationReliabilityEnum theValue) {
|
||||
getReliability().setValueAsEnum(theValue);
|
||||
return this;
|
||||
public Observation setReliability( String theCode) {
|
||||
myReliability = new CodeDt(theCode);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>bodySite</b> (Observed body part).
|
||||
* creating it if it does
|
||||
|
@ -993,8 +1018,8 @@ public class Observation extends BaseResource implements IResource {
|
|||
* A unique identifier for the simple observation
|
||||
* </p>
|
||||
*/
|
||||
public Observation setIdentifier( IdentifierUseEnum theUse, String theSystem, String theValue, String theLabel) {
|
||||
myIdentifier = new IdentifierDt(theUse, theSystem, theValue, theLabel);
|
||||
public Observation setIdentifier( String theSystem, String theValue) {
|
||||
myIdentifier = new IdentifierDt(theSystem, theValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1006,8 +1031,8 @@ public class Observation extends BaseResource implements IResource {
|
|||
* A unique identifier for the simple observation
|
||||
* </p>
|
||||
*/
|
||||
public Observation setIdentifier( String theSystem, String theValue) {
|
||||
myIdentifier = new IdentifierDt(theSystem, theValue);
|
||||
public Observation setIdentifier( IdentifierUseEnum theUse, String theSystem, String theValue, String theLabel) {
|
||||
myIdentifier = new IdentifierDt(theUse, theSystem, theValue, theLabel);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1324,32 +1349,6 @@ public class Observation extends BaseResource implements IResource {
|
|||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, double theValue, String theSystem, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, long theValue, String theSystem, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, double theValue, String theUnits) {
|
||||
|
@ -1363,19 +1362,6 @@ public class Observation extends BaseResource implements IResource {
|
|||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, long theValue, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( double theValue) {
|
||||
|
@ -1396,6 +1382,45 @@ public class Observation extends BaseResource implements IResource {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, long theValue, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, double theValue, String theSystem, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>low</b> (Low Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the low bound of the reference range. If this is omitted, the low bound of the reference range is assumed to be meaningless. E.g. <2.3
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setLow( QuantityCompararatorEnum theComparator, long theValue, String theSystem, String theUnits) {
|
||||
myLow = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>high</b> (High Range, if relevant).
|
||||
|
@ -1433,32 +1458,6 @@ public class Observation extends BaseResource implements IResource {
|
|||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, double theValue, String theSystem, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, long theValue, String theSystem, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, double theValue, String theUnits) {
|
||||
|
@ -1472,19 +1471,6 @@ public class Observation extends BaseResource implements IResource {
|
|||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, long theValue, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( double theValue) {
|
||||
|
@ -1505,6 +1491,45 @@ public class Observation extends BaseResource implements IResource {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, long theValue, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, double theValue, String theSystem, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for <b>high</b> (High Range, if relevant)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The value of the high bound of the reference range. If this is omitted, the high bound of the reference range is assumed to be meaningless. E.g. >5
|
||||
* </p>
|
||||
*/
|
||||
public ReferenceRange setHigh( QuantityCompararatorEnum theComparator, long theValue, String theSystem, String theUnits) {
|
||||
myHigh = new QuantityDt(theComparator, theValue, theSystem, theUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>meaning</b> (Indicates the meaning/use of this range of this range).
|
||||
|
@ -1588,7 +1613,7 @@ public class Observation extends BaseResource implements IResource {
|
|||
shortDefinition="has-component | has-member | derived-from | sequel-to | replaces | qualified-by | interfered-by",
|
||||
formalDefinition="A code specifying the kind of relationship that exists with the target observation"
|
||||
)
|
||||
private BoundCodeDt<ObservationRelationshipTypeEnum> myType;
|
||||
private CodeDt myType;
|
||||
|
||||
@Child(name="target", order=1, min=1, max=1, type={
|
||||
ca.uhn.fhir.model.dstu.resource.Observation.class })
|
||||
|
@ -1619,9 +1644,9 @@ public class Observation extends BaseResource implements IResource {
|
|||
* A code specifying the kind of relationship that exists with the target observation
|
||||
* </p>
|
||||
*/
|
||||
public BoundCodeDt<ObservationRelationshipTypeEnum> getType() {
|
||||
public CodeDt getType() {
|
||||
if (myType == null) {
|
||||
myType = new BoundCodeDt<ObservationRelationshipTypeEnum>(ObservationRelationshipTypeEnum.VALUESET_BINDER);
|
||||
myType = new CodeDt();
|
||||
}
|
||||
return myType;
|
||||
}
|
||||
|
@ -1634,25 +1659,25 @@ public class Observation extends BaseResource implements IResource {
|
|||
* A code specifying the kind of relationship that exists with the target observation
|
||||
* </p>
|
||||
*/
|
||||
public Related setType(BoundCodeDt<ObservationRelationshipTypeEnum> theValue) {
|
||||
public Related setType(CodeDt theValue) {
|
||||
myType = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>type</b> (has-component | has-member | derived-from | sequel-to | replaces | qualified-by | interfered-by)
|
||||
/**
|
||||
* Sets the value for <b>type</b> (has-component | has-member | derived-from | sequel-to | replaces | qualified-by | interfered-by)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* A code specifying the kind of relationship that exists with the target observation
|
||||
* </p>
|
||||
*/
|
||||
public Related setType(ObservationRelationshipTypeEnum theValue) {
|
||||
getType().setValueAsEnum(theValue);
|
||||
return this;
|
||||
public Related setType( String theCode) {
|
||||
myType = new CodeDt(theCode);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>target</b> (Observation that is related to this one).
|
||||
* creating it if it does
|
||||
|
@ -1687,7 +1712,15 @@ public class Observation extends BaseResource implements IResource {
|
|||
|
||||
}
|
||||
|
||||
public void setStatus(ObservationStatusEnum theFinal) {
|
||||
if (theFinal==null) {
|
||||
getStatus().setValue(null);
|
||||
}else {
|
||||
getStatus().setValue(theFinal.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -35,11 +35,12 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
/**
|
||||
* Represents the FHIR ID type. This is the actual resource ID, meaning the ID that will be used in RESTful URLs, Resource References, etc. to represent a specific instance of a resource.
|
||||
* Represents the FHIR ID type. This is the actual resource ID, meaning the ID that will be used in RESTful URLs,
|
||||
* Resource References, etc. to represent a specific instance of a resource.
|
||||
*
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any other combination of lowercase letters, numerals, "-" and ".", with a length
|
||||
* limit of 36 characters.
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any
|
||||
* other combination of lowercase letters, numerals, "-" and ".", with a length limit of 36 characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* regex: [a-z0-9\-\.]{1,36}
|
||||
|
@ -52,7 +53,7 @@ public class IdDt extends BasePrimitive<String> {
|
|||
private String myResourceType;
|
||||
private String myUnqualifiedId;
|
||||
private String myUnqualifiedVersionId;
|
||||
private String myValue;
|
||||
private volatile String myValue;
|
||||
|
||||
/**
|
||||
* Create a new empty ID
|
||||
|
@ -62,7 +63,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new ID, using a BigDecimal input. Uses {@link BigDecimal#toPlainString()} to generate the string representation.
|
||||
* Create a new ID, using a BigDecimal input. Uses {@link BigDecimal#toPlainString()} to generate the string
|
||||
* representation.
|
||||
*/
|
||||
public IdDt(BigDecimal thePid) {
|
||||
if (thePid != null) {
|
||||
|
@ -80,11 +82,12 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new ID using a string. This String may contain a simple ID (e.g. "1234") or it may contain a complete URL (http://example.com/fhir/Patient/1234).
|
||||
* Create a new ID using a string. This String may contain a simple ID (e.g. "1234") or it may contain a complete
|
||||
* URL (http://example.com/fhir/Patient/1234).
|
||||
*
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any other combination of lowercase letters, numerals, "-" and ".", with a length
|
||||
* limit of 36 characters.
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or
|
||||
* any other combination of lowercase letters, numerals, "-" and ".", with a length limit of 36 characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* regex: [a-z0-9\-\.]{1,36}
|
||||
|
@ -107,13 +110,6 @@ public class IdDt extends BasePrimitive<String> {
|
|||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(BigDecimal theIdPart) {
|
||||
if (theIdPart==null) {
|
||||
throw new NullPointerException("BigDecimal ID can not be null");
|
||||
}
|
||||
return theIdPart.toPlainString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -144,7 +140,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead (this method was deprocated because its name is ambiguous)
|
||||
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead (this method was deprocated because its name is
|
||||
* ambiguous)
|
||||
*/
|
||||
public BigDecimal asBigDecimal() {
|
||||
return getIdPartAsBigDecimal();
|
||||
|
@ -165,7 +162,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
|
||||
* Returns a reference to <code>this</code> IdDt. It is generally not neccesary to use this method but it is
|
||||
* provided for consistency with the rest of the API.
|
||||
*/
|
||||
@Override
|
||||
public IdDt getId() {
|
||||
|
@ -209,18 +207,27 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this ID. Note that this value may be a fully qualified URL, a relative/partial URL, or a simple ID. Use {@link #getIdPart()} to get just the ID portion.
|
||||
* Returns the value of this ID. Note that this value may be a fully qualified URL, a relative/partial URL, or a
|
||||
* simple ID. Use {@link #getIdPart()} to get just the ID portion.
|
||||
*
|
||||
* @see #getIdPart()
|
||||
*/
|
||||
@Override
|
||||
public String getValue() {
|
||||
if (myValue == null && myHaveComponentParts) {
|
||||
if (myUnqualifiedVersionId != null) {
|
||||
myValue = myResourceType + '/' + myUnqualifiedId + '/' + Constants.PARAM_HISTORY + '/' + myUnqualifiedVersionId;
|
||||
} else {
|
||||
myValue = myResourceType + '/' + myUnqualifiedId;
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isNotBlank(myResourceType)) {
|
||||
b.append(myResourceType);
|
||||
b.append('/');
|
||||
}
|
||||
b.append(myUnqualifiedId);
|
||||
if (isNotBlank(myUnqualifiedVersionId)) {
|
||||
b.append('/');
|
||||
b.append(Constants.PARAM_HISTORY);
|
||||
b.append('/');
|
||||
b.append(myUnqualifiedVersionId);
|
||||
}
|
||||
myValue = b.toString();
|
||||
}
|
||||
return myValue;
|
||||
}
|
||||
|
@ -255,7 +262,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the unqualified ID is a valid {@link Long} value (in other words, it consists only of digits)
|
||||
* Returns <code>true</code> if the unqualified ID is a valid {@link Long} value (in other words, it consists only
|
||||
* of digits)
|
||||
*/
|
||||
public boolean isIdPartValidLong() {
|
||||
String id = getIdPart();
|
||||
|
@ -278,7 +286,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Copies the value from the given IdDt to <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
|
||||
* Copies the value from the given IdDt to <code>this</code> IdDt. It is generally not neccesary to use this method
|
||||
* but it is provided for consistency with the rest of the API.
|
||||
*/
|
||||
@Override
|
||||
public void setId(IdDt theId) {
|
||||
|
@ -289,8 +298,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
* Set the value
|
||||
*
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any other combination of lowercase letters, numerals, "-" and ".", with a length
|
||||
* limit of 36 characters.
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or
|
||||
* any other combination of lowercase letters, numerals, "-" and ".", with a length limit of 36 characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* regex: [a-z0-9\-\.]{1,36}
|
||||
|
@ -300,7 +309,7 @@ public class IdDt extends BasePrimitive<String> {
|
|||
public void setValue(String theValue) throws DataFormatException {
|
||||
// TODO: add validation
|
||||
myValue = theValue;
|
||||
myHaveComponentParts=false;
|
||||
myHaveComponentParts = false;
|
||||
if (StringUtils.isBlank(theValue)) {
|
||||
myValue = null;
|
||||
myUnqualifiedId = null;
|
||||
|
@ -337,8 +346,8 @@ public class IdDt extends BasePrimitive<String> {
|
|||
* Set the value
|
||||
*
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any other combination of lowercase letters, numerals, "-" and ".", with a length
|
||||
* limit of 36 characters.
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or
|
||||
* any other combination of lowercase letters, numerals, "-" and ".", with a length limit of 36 characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* regex: [a-z0-9\-\.]{1,36}
|
||||
|
@ -372,9 +381,15 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
}
|
||||
|
||||
public IdDt withResourceType(String theResourceName) {
|
||||
return new IdDt(theResourceName, getIdPart(), getVersionIdPart());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view of this ID as a fully qualified URL, given a server base and resource name (which will only be used if the ID does not already contain those respective parts). Essentially,
|
||||
* because IdDt can contain either a complete URL or a partial one (or even jut a simple ID), this method may be used to translate into a complete URL.
|
||||
* Returns a view of this ID as a fully qualified URL, given a server base and resource name (which will only be
|
||||
* used if the ID does not already contain those respective parts). Essentially, because IdDt can contain either a
|
||||
* complete URL or a partial one (or even jut a simple ID), this method may be used to translate into a complete
|
||||
* URL.
|
||||
*
|
||||
* @param theServerBase
|
||||
* The server base (e.g. "http://example.com/fhir")
|
||||
|
@ -398,29 +413,31 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
retVal.append('/');
|
||||
retVal.append(getIdPart());
|
||||
|
||||
|
||||
if (hasVersionIdPart()) {
|
||||
retVal.append('/');
|
||||
retVal.append(Constants.PARAM_HISTORY);
|
||||
retVal.append('/');
|
||||
retVal.append(getVersionIdPart());
|
||||
retVal.append(getVersionIdPart());
|
||||
}
|
||||
|
||||
|
||||
return retVal.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
||||
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID
|
||||
* noted by theVersion.
|
||||
*
|
||||
* @param theVersion
|
||||
* The actual version string, e.g. "1"
|
||||
* @return A new instance of IdDt which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
||||
* @return A new instance of IdDt which is identical, but refers to the specific version of this resource ID noted
|
||||
* by theVersion.
|
||||
*/
|
||||
public IdDt withVersion(String theVersion) {
|
||||
Validate.notBlank(theVersion, "Version may not be null or empty");
|
||||
|
||||
String existingValue = getValue();
|
||||
|
||||
|
||||
int i = existingValue.indexOf(Constants.PARAM_HISTORY);
|
||||
String value;
|
||||
if (i > 1) {
|
||||
|
@ -432,8 +449,11 @@ public class IdDt extends BasePrimitive<String> {
|
|||
return new IdDt(value + '/' + Constants.PARAM_HISTORY + '/' + theVersion);
|
||||
}
|
||||
|
||||
public IdDt withResourceType(String theResourceName) {
|
||||
return new IdDt(theResourceName, getIdPart(), getVersionIdPart());
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(BigDecimal theIdPart) {
|
||||
if (theIdPart == null) {
|
||||
throw new NullPointerException("BigDecimal ID can not be null");
|
||||
}
|
||||
return theIdPart.toPlainString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,6 +59,18 @@ public class InstantDt extends BaseDateTimeDt {
|
|||
setTimeZone(theCalendar.getTimeZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DateTimeDt using an existing value. <b>Use this constructor with caution</b>,
|
||||
* as it may create more precision than warranted (since for example it is possible to pass in
|
||||
* a DateTime with only a year, and this constructor will convert to an InstantDt with
|
||||
* milliseconds precision).
|
||||
*/
|
||||
public InstantDt(BaseDateTimeDt theDateTime) {
|
||||
setValue(theDateTime.getValue());
|
||||
setPrecision(DEFAULT_PRECISION);
|
||||
setTimeZone(theDateTime.getTimeZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DateTimeDt
|
||||
*/
|
||||
|
|
|
@ -23,18 +23,55 @@ package ca.uhn.fhir.rest.annotation;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
/**
|
||||
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
||||
*/
|
||||
public @interface OptionalParam {
|
||||
String name();
|
||||
/**
|
||||
* This is the name for the parameter. Generally this should be a
|
||||
* simple string (e.g. "name", or "identifier") which will be the name
|
||||
* of the URL parameter used to populate this method parameter.
|
||||
* <p>
|
||||
* Most resource model classes have constants which may be used to
|
||||
* supply values for this field, e.g. {@link Patient#SP_NAME} or
|
||||
* {@link Observation#SP_DATE}
|
||||
* </p>
|
||||
* <p>
|
||||
* If you wish to specify a parameter for a resource reference which
|
||||
* only accepts a specific chained value, it is also valid to supply
|
||||
* a chained name here, such as "patient.name". It is recommended to
|
||||
* supply this using constants where possible, e.g.
|
||||
* <code>{@link Observation#SP_SUBJECT} + '.' + {@link Patient#SP_IDENTIFIER}</code>
|
||||
* </p>
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param
|
||||
* used to indicate the resource type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this parameter may be
|
||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -23,18 +23,56 @@ package ca.uhn.fhir.rest.annotation;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
/**
|
||||
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
||||
*/
|
||||
public @interface RequiredParam {
|
||||
String name();
|
||||
/**
|
||||
* This is the name for the parameter. Generally this should be a
|
||||
* simple string (e.g. "name", or "identifier") which will be the name
|
||||
* of the URL parameter used to populate this method parameter.
|
||||
* <p>
|
||||
* Most resource model classes have constants which may be used to
|
||||
* supply values for this field, e.g. {@link Patient#SP_NAME} or
|
||||
* {@link Observation#SP_DATE}
|
||||
* </p>
|
||||
* <p>
|
||||
* If you wish to specify a parameter for a resource reference which
|
||||
* only accepts a specific chained value, it is also valid to supply
|
||||
* a chained name here, such as "patient.name". It is recommended to
|
||||
* supply this using constants where possible, e.g.
|
||||
* <code>{@link Observation#SP_SUBJECT} + '.' + {@link Patient#SP_IDENTIFIER}</code>
|
||||
* </p>
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param
|
||||
* used to indicate the resource type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this parameter may be
|
||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ import ca.uhn.fhir.rest.gclient.ISort;
|
|||
import ca.uhn.fhir.rest.gclient.ITransaction;
|
||||
import ca.uhn.fhir.rest.gclient.ITransactionTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IUntypedQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdate;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateTyped;
|
||||
import ca.uhn.fhir.rest.method.DeleteMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HistoryMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HttpDeleteClientInvocation;
|
||||
|
@ -77,7 +79,6 @@ import ca.uhn.fhir.rest.method.MethodUtil;
|
|||
import ca.uhn.fhir.rest.method.ReadMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.TransactionMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.UpdateMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
@ -278,7 +279,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public MethodOutcome update(IdDt theIdDt, IResource theResource) {
|
||||
BaseHttpClientInvocation invocation = UpdateMethodBinding.createUpdateInvocation(theResource, theIdDt, null, myContext);
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createUpdateInvocation(theResource, null, theIdDt, myContext);
|
||||
if (isKeepResponses()) {
|
||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
@ -344,6 +345,24 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return (T) this;
|
||||
}
|
||||
|
||||
protected IResource parseResourceBody(String theResourceBody) {
|
||||
EncodingEnum encoding = null;
|
||||
for (int i = 0; i < theResourceBody.length() && encoding == null; i++) {
|
||||
switch (theResourceBody.charAt(i)) {
|
||||
case '<':
|
||||
encoding = EncodingEnum.XML;
|
||||
break;
|
||||
case '{':
|
||||
encoding = EncodingEnum.JSON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("FHIR client can't determine resource encoding");
|
||||
}
|
||||
return encoding.newParser(myContext).parseResource(theResourceBody);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T encodedJson() {
|
||||
|
@ -419,23 +438,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
@Override
|
||||
public MethodOutcome execute() {
|
||||
if (myResource == null) {
|
||||
EncodingEnum encoding = null;
|
||||
for (int i = 0; i < myResourceBody.length() && encoding == null; i++) {
|
||||
switch (myResourceBody.charAt(i)) {
|
||||
case '<':
|
||||
encoding = EncodingEnum.XML;
|
||||
break;
|
||||
case '{':
|
||||
encoding = EncodingEnum.JSON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("FHIR client can't determine resource encoding");
|
||||
}
|
||||
myResource = encoding.newParser(myContext).parseResource(myResourceBody);
|
||||
myResource = parseResourceBody(myResourceBody);
|
||||
}
|
||||
|
||||
myId = getPreferredId(myResource, myId);
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
|
@ -448,6 +454,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ICreateTyped resource(IResource theResource) {
|
||||
Validate.notNull(theResource, "Resource can not be null");
|
||||
|
@ -475,6 +482,76 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateTyped, MethodOutcome> implements IUpdate, IUpdateTyped {
|
||||
|
||||
private IdDt myId;
|
||||
private String myResourceBody;
|
||||
private IResource myResource;
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
if (myResource == null) {
|
||||
myResource = parseResourceBody(myResourceBody);
|
||||
}
|
||||
if (myId == null) {
|
||||
myId = myResource.getId();
|
||||
}
|
||||
if (myId==null || myId.hasIdPart() == false) {
|
||||
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||
|
||||
Map<String, List<String>> params = new HashMap<String, List<String>>();
|
||||
return invoke(params, binding, invocation);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped resource(IResource theResource) {
|
||||
Validate.notNull(theResource, "Resource can not be null");
|
||||
myResource = theResource;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped resource(String theResourceBody) {
|
||||
Validate.notBlank(theResourceBody, "Body can not be null or blank");
|
||||
myResourceBody = theResourceBody;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped withId(IdDt theId) {
|
||||
if (theId == null) {
|
||||
throw new NullPointerException("theId can not be null");
|
||||
}
|
||||
if (theId.hasIdPart()==false) {
|
||||
throw new NullPointerException("theId must not be blank and must contain an ID, found: "+theId.getValue());
|
||||
}
|
||||
myId = theId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped withId(String theId) {
|
||||
if (theId == null) {
|
||||
throw new NullPointerException("theId can not be null");
|
||||
}
|
||||
if (isBlank(theId)) {
|
||||
throw new NullPointerException("theId must not be blank and must contain an ID, found: "+theId);
|
||||
}
|
||||
myId=new IdDt(theId);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, OperationOutcome> implements IDelete, IDeleteTyped {
|
||||
|
||||
|
@ -924,4 +1001,17 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
protected String getPreferredId(IResource theResource, String theId) {
|
||||
if (isNotBlank(theId)) {
|
||||
return theId;
|
||||
}
|
||||
return theResource.getId().getIdPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdate update() {
|
||||
return new UpdateInternal();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.gclient.IGetPage;
|
|||
import ca.uhn.fhir.rest.gclient.IGetTags;
|
||||
import ca.uhn.fhir.rest.gclient.ITransaction;
|
||||
import ca.uhn.fhir.rest.gclient.IUntypedQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdate;
|
||||
|
||||
public interface IGenericClient {
|
||||
/**
|
||||
|
@ -268,4 +269,9 @@ public interface IGenericClient {
|
|||
*/
|
||||
IDelete delete();
|
||||
|
||||
/**
|
||||
* Fluent method for the "update" operation, which performs a logical delete on a server resource
|
||||
*/
|
||||
IUpdate update();
|
||||
|
||||
}
|
||||
|
|
|
@ -21,23 +21,25 @@ package ca.uhn.fhir.rest.gclient;
|
|||
*/
|
||||
|
||||
/**
|
||||
* Composite params are not yet supported - This is a placeholder. Help welcome!
|
||||
*
|
||||
* TODO: implement
|
||||
* Composite parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class CompositeClientParam {
|
||||
public class CompositeClientParam<A extends IParam, B extends IParam> implements IParam {
|
||||
|
||||
private String myName;
|
||||
|
||||
public CompositeClientParam(String theName) {
|
||||
// TODO Auto-generated constructor stub
|
||||
myName=theName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composite params are not yet supported - This is a placeholder. Help welcome!
|
||||
*
|
||||
* TODO: implement
|
||||
*/
|
||||
public void notYetSupported() {
|
||||
//nothig
|
||||
|
||||
@Override
|
||||
public String getParamName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public ICompositeWithLeft<B> withLeft(ICriterion<A> theLeft) {
|
||||
return new CompositeCriterion<A,B>(myName, theLeft);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public class CompositeCriterion<A extends IParam, B extends IParam> implements ICompositeWithLeft<B>, ICriterion<B>, ICriterionInternal {
|
||||
|
||||
private ICriterion<B> myRight;
|
||||
private String myName;
|
||||
private ICriterion<A> myLeft;
|
||||
|
||||
public CompositeCriterion(String theName, ICriterion<A> theLeft) {
|
||||
myName = theName;
|
||||
myLeft = theLeft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion<B> withRight(ICriterion<B> theRight) {
|
||||
myRight = theRight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterValue() {
|
||||
ICriterionInternal left = (ICriterionInternal) myLeft;
|
||||
ICriterionInternal right = (ICriterionInternal) myRight;
|
||||
return defaultString(left.getParameterValue()) + '$' + defaultString(right.getParameterValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,10 +22,10 @@ package ca.uhn.fhir.rest.gclient;
|
|||
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CompositeClientParam} instead. That class is identical to this one but was renamed to reduct
|
||||
* @deprecated Use {@link CompositeClientParam} instead. That class is identical to this one but was renamed to reduce
|
||||
* confusing duplicate names in the API. This class will be removed in a future release.
|
||||
*/
|
||||
public class CompositeParam extends CompositeClientParam {
|
||||
public class CompositeParam<A extends IParam, B extends IParam> extends CompositeClientParam<A,B> {
|
||||
|
||||
public CompositeParam(String theParamName) {
|
||||
super(theParamName);
|
||||
|
|
|
@ -61,7 +61,7 @@ public class DateClientParam implements IParam {
|
|||
return new DateWithPrefix("");
|
||||
}
|
||||
|
||||
private class Criterion implements ICriterion, ICriterionInternal {
|
||||
private class Criterion implements ICriterion<DateClientParam>, ICriterionInternal {
|
||||
|
||||
private String myValue;
|
||||
|
||||
|
@ -89,35 +89,35 @@ public class DateClientParam implements IParam {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ICriterion day(Date theValue) {
|
||||
public ICriterion<DateClientParam> day(Date theValue) {
|
||||
DateTimeDt dt = new DateTimeDt(theValue);
|
||||
dt.setPrecision(TemporalPrecisionEnum.DAY);
|
||||
return new Criterion(myPrefix + dt.getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion day(String theValue) {
|
||||
public ICriterion<DateClientParam> day(String theValue) {
|
||||
DateTimeDt dt = new DateTimeDt(theValue);
|
||||
dt.setPrecision(TemporalPrecisionEnum.DAY);
|
||||
return new Criterion(myPrefix + dt.getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion now() {
|
||||
public ICriterion<DateClientParam> now() {
|
||||
DateTimeDt dt = new DateTimeDt();
|
||||
dt.setPrecision(TemporalPrecisionEnum.DAY);
|
||||
return new Criterion(myPrefix + dt.getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion second(Date theValue) {
|
||||
public ICriterion<DateClientParam> second(Date theValue) {
|
||||
DateTimeDt dt = new DateTimeDt(theValue);
|
||||
dt.setPrecision(TemporalPrecisionEnum.DAY);
|
||||
return new Criterion(myPrefix + dt.getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion second(String theValue) {
|
||||
public ICriterion<DateClientParam> second(String theValue) {
|
||||
DateTimeDt dt = new DateTimeDt(theValue);
|
||||
dt.setPrecision(TemporalPrecisionEnum.DAY);
|
||||
return new Criterion(myPrefix + dt.getValueAsString());
|
||||
|
@ -127,15 +127,15 @@ public class DateClientParam implements IParam {
|
|||
|
||||
public interface IDateSpecifier {
|
||||
|
||||
ICriterion day(Date theValue);
|
||||
ICriterion<DateClientParam> day(Date theValue);
|
||||
|
||||
ICriterion day(String theValue);
|
||||
ICriterion<DateClientParam> day(String theValue);
|
||||
|
||||
ICriterion now();
|
||||
ICriterion<DateClientParam> now();
|
||||
|
||||
ICriterion second(Date theValue);
|
||||
ICriterion<DateClientParam> second(Date theValue);
|
||||
|
||||
ICriterion second(String theValue);
|
||||
ICriterion<DateClientParam> second(String theValue);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface ICompositeWithLeft<B extends IParam> {
|
||||
|
||||
ICriterion<B> withRight(ICriterion<B> theRight);
|
||||
|
||||
}
|
|
@ -20,6 +20,6 @@ package ca.uhn.fhir.rest.gclient;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
public interface ICriterion {
|
||||
public interface ICriterion<T extends IParam> {
|
||||
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ import ca.uhn.fhir.model.api.Include;
|
|||
|
||||
public interface IQuery extends IClientExecutable<IQuery,Bundle> {
|
||||
|
||||
IQuery where(ICriterion theCriterion);
|
||||
IQuery where(ICriterion<?> theCriterion);
|
||||
|
||||
IQuery and(ICriterion theCriterion);
|
||||
IQuery and(ICriterion<?> theCriterion);
|
||||
|
||||
IQuery include(Include theIncludeManagingorganization);
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
public interface IUpdate {
|
||||
|
||||
IUpdateTyped resource(IResource theResource);
|
||||
|
||||
IUpdateTyped resource(String theResourceBody);
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
||||
public interface IUpdateTyped extends IClientExecutable<IUpdateTyped, MethodOutcome> {
|
||||
|
||||
IUpdateTyped withId(IdDt theId);
|
||||
|
||||
IUpdateTyped withId(String theId);
|
||||
}
|
|
@ -31,16 +31,16 @@ public class NumberClientParam implements IParam {
|
|||
myParamName = theParamName;
|
||||
}
|
||||
|
||||
public IMatches<ICriterion> exactly() {
|
||||
return new IMatches<ICriterion>() {
|
||||
public IMatches<ICriterion<NumberClientParam>> exactly() {
|
||||
return new IMatches<ICriterion<NumberClientParam>>() {
|
||||
@Override
|
||||
public ICriterion number(long theNumber) {
|
||||
return new StringCriterion(getParamName(), Long.toString(theNumber));
|
||||
public ICriterion<NumberClientParam> number(long theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), Long.toString(theNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion number(String theNumber) {
|
||||
return new StringCriterion(getParamName(), (theNumber));
|
||||
public ICriterion<NumberClientParam> number(String theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), (theNumber));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -50,58 +50,58 @@ public class NumberClientParam implements IParam {
|
|||
return myParamName;
|
||||
}
|
||||
|
||||
public IMatches<ICriterion> greaterThan() {
|
||||
return new IMatches<ICriterion>() {
|
||||
public IMatches<ICriterion<NumberClientParam>> greaterThan() {
|
||||
return new IMatches<ICriterion<NumberClientParam>>() {
|
||||
@Override
|
||||
public ICriterion number(long theNumber) {
|
||||
return new StringCriterion(getParamName(), ">" + Long.toString(theNumber));
|
||||
public ICriterion<NumberClientParam> number(long theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), ">" + Long.toString(theNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion number(String theNumber) {
|
||||
return new StringCriterion(getParamName(), ">" + (theNumber));
|
||||
public ICriterion<NumberClientParam> number(String theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), ">" + (theNumber));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IMatches<ICriterion> greaterThanOrEqual() {
|
||||
return new IMatches<ICriterion>() {
|
||||
public IMatches<ICriterion<NumberClientParam>> greaterThanOrEqual() {
|
||||
return new IMatches<ICriterion<NumberClientParam>>() {
|
||||
@Override
|
||||
public ICriterion number(long theNumber) {
|
||||
return new StringCriterion(getParamName(), ">=" + Long.toString(theNumber));
|
||||
public ICriterion<NumberClientParam> number(long theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), ">=" + Long.toString(theNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion number(String theNumber) {
|
||||
return new StringCriterion(getParamName(), ">=" + (theNumber));
|
||||
public ICriterion<NumberClientParam> number(String theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), ">=" + (theNumber));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IMatches<ICriterion> lessThan() {
|
||||
return new IMatches<ICriterion>() {
|
||||
public IMatches<ICriterion<NumberClientParam>> lessThan() {
|
||||
return new IMatches<ICriterion<NumberClientParam>>() {
|
||||
@Override
|
||||
public ICriterion number(long theNumber) {
|
||||
return new StringCriterion(getParamName(), "<" + Long.toString(theNumber));
|
||||
public ICriterion<NumberClientParam> number(long theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), "<" + Long.toString(theNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion number(String theNumber) {
|
||||
return new StringCriterion(getParamName(), "<" + (theNumber));
|
||||
public ICriterion<NumberClientParam> number(String theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), "<" + (theNumber));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IMatches<ICriterion> lessThanOrEqual() {
|
||||
return new IMatches<ICriterion>() {
|
||||
public IMatches<ICriterion<NumberClientParam>> lessThanOrEqual() {
|
||||
return new IMatches<ICriterion<NumberClientParam>>() {
|
||||
@Override
|
||||
public ICriterion number(long theNumber) {
|
||||
return new StringCriterion(getParamName(), "<=" + Long.toString(theNumber));
|
||||
public ICriterion<NumberClientParam> number(long theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), "<=" + Long.toString(theNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion number(String theNumber) {
|
||||
return new StringCriterion(getParamName(), "<=" + (theNumber));
|
||||
public ICriterion<NumberClientParam> number(String theNumber) {
|
||||
return new StringCriterion<NumberClientParam>(getParamName(), "<=" + (theNumber));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -141,11 +141,11 @@ public class QuantityClientParam implements IParam {
|
|||
|
||||
public interface IAndUnits {
|
||||
|
||||
ICriterion andNoUnits();
|
||||
ICriterion<QuantityClientParam> andNoUnits();
|
||||
|
||||
ICriterion andUnits(String theUnits);
|
||||
ICriterion<QuantityClientParam> andUnits(String theUnits);
|
||||
|
||||
ICriterion andUnits(String theSystem, String theUnits);
|
||||
ICriterion<QuantityClientParam> andUnits(String theSystem, String theUnits);
|
||||
}
|
||||
|
||||
private class AndUnits implements IAndUnits {
|
||||
|
@ -157,18 +157,18 @@ public class QuantityClientParam implements IParam {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ICriterion andNoUnits() {
|
||||
public ICriterion<QuantityClientParam> andNoUnits() {
|
||||
return andUnits(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion andUnits(String theUnits) {
|
||||
public ICriterion<QuantityClientParam> andUnits(String theUnits) {
|
||||
return andUnits(theUnits, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion andUnits(String theSystem, String theUnits) {
|
||||
return new StringCriterion(getParamName(), myToken1 + "|" + defaultString(theSystem) + "|" + defaultString(theUnits));
|
||||
public ICriterion<QuantityClientParam> andUnits(String theSystem, String theUnits) {
|
||||
return new QuantityCriterion(getParamName(), myToken1 , defaultString(theSystem) , defaultString(theUnits));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
class QuantityCriterion implements ICriterion<QuantityClientParam>, ICriterionInternal {
|
||||
|
||||
private String myValue;
|
||||
private String myName;
|
||||
private String mySystem;
|
||||
private String myUnits;
|
||||
|
||||
public QuantityCriterion(String theParamName, String theValue, String theSystem, String theUnits) {
|
||||
myValue = theValue;
|
||||
myName = theParamName;
|
||||
mySystem = theSystem;
|
||||
myUnits = theUnits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterValue() {
|
||||
return ParameterUtil.escape(myValue) + '|' + ParameterUtil.escape(mySystem) + '|' + ParameterUtil.escape(myUnits);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,32 +36,32 @@ public class ReferenceClientParam implements IParam {
|
|||
return myName;
|
||||
}
|
||||
|
||||
public ICriterion hasChainedProperty(ICriterion theICriterion) {
|
||||
return new ReferenceChainCriterion(getParamName(), theICriterion);
|
||||
public ICriterion<ReferenceClientParam> hasChainedProperty(ICriterion<?> theCriterion) {
|
||||
return new ReferenceChainCriterion(getParamName(), theCriterion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the referenced resource if the resource has the given ID (this can be
|
||||
* the logical ID or the absolute URL of the resource)
|
||||
*/
|
||||
public ICriterion hasId(IdDt theId) {
|
||||
return new StringCriterion(getParamName(), theId.getValue());
|
||||
public ICriterion<ReferenceClientParam> hasId(IdDt theId) {
|
||||
return new StringCriterion<ReferenceClientParam>(getParamName(), theId.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the referenced resource if the resource has the given ID (this can be
|
||||
* the logical ID or the absolute URL of the resource)
|
||||
*/
|
||||
public ICriterion hasId(String theId) {
|
||||
return new StringCriterion(getParamName(), theId);
|
||||
public ICriterion<ReferenceClientParam> hasId(String theId) {
|
||||
return new StringCriterion<ReferenceClientParam>(getParamName(), theId);
|
||||
}
|
||||
|
||||
private static class ReferenceChainCriterion implements ICriterion, ICriterionInternal {
|
||||
private static class ReferenceChainCriterion implements ICriterion<ReferenceClientParam>, ICriterionInternal {
|
||||
|
||||
private String myParamName;
|
||||
private ICriterionInternal myWrappedCriterion;
|
||||
|
||||
public ReferenceChainCriterion(String theParamName, ICriterion theWrappedCriterion) {
|
||||
public ReferenceChainCriterion(String theParamName, ICriterion<?> theWrappedCriterion) {
|
||||
myParamName = theParamName;
|
||||
myWrappedCriterion = (ICriterionInternal) theWrappedCriterion;
|
||||
}
|
||||
|
|
|
@ -59,33 +59,33 @@ public class StringClientParam implements IParam {
|
|||
|
||||
public interface IStringMatch {
|
||||
|
||||
ICriterion value(String theValue);
|
||||
ICriterion<StringClientParam> value(String theValue);
|
||||
|
||||
ICriterion value(StringDt theValue);
|
||||
ICriterion<StringClientParam> value(StringDt theValue);
|
||||
|
||||
}
|
||||
|
||||
private class StringExactly implements IStringMatch {
|
||||
@Override
|
||||
public ICriterion value(String theValue) {
|
||||
return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue);
|
||||
public ICriterion<StringClientParam> value(String theValue) {
|
||||
return new StringCriterion<StringClientParam>(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion value(StringDt theValue) {
|
||||
return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue.getValue());
|
||||
public ICriterion<StringClientParam> value(StringDt theValue) {
|
||||
return new StringCriterion<StringClientParam>(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private class StringMatches implements IStringMatch {
|
||||
@Override
|
||||
public ICriterion value(String theValue) {
|
||||
return new StringCriterion(getParamName(), theValue);
|
||||
public ICriterion<StringClientParam> value(String theValue) {
|
||||
return new StringCriterion<StringClientParam>(getParamName(), theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion value(StringDt theValue) {
|
||||
return new StringCriterion(getParamName(), theValue.getValue());
|
||||
public ICriterion<StringClientParam> value(StringDt theValue) {
|
||||
return new StringCriterion<StringClientParam>(getParamName(), theValue.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -20,7 +22,7 @@ package ca.uhn.fhir.rest.gclient;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
class StringCriterion implements ICriterion, ICriterionInternal {
|
||||
class StringCriterion<A extends IParam> implements ICriterion<A>, ICriterionInternal {
|
||||
|
||||
private String myValue;
|
||||
private String myName;
|
||||
|
@ -37,7 +39,7 @@ class StringCriterion implements ICriterion, ICriterionInternal {
|
|||
|
||||
@Override
|
||||
public String getParameterValue() {
|
||||
return myValue;
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
|
||||
/*
|
||||
|
@ -42,27 +43,27 @@ public class TokenClientParam implements IParam {
|
|||
public IMatches exactly() {
|
||||
return new IMatches() {
|
||||
@Override
|
||||
public ICriterion systemAndCode(String theSystem, String theCode) {
|
||||
return new TokenCriterion(getParamName(), theSystem, theCode);
|
||||
public ICriterion<TokenClientParam> systemAndCode(String theSystem, String theCode) {
|
||||
return new TokenCriterion(getParamName(), defaultString(theSystem), theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion systemAndIdentifier(String theSystem, String theCode) {
|
||||
return new TokenCriterion(getParamName(), theSystem, theCode);
|
||||
public ICriterion<TokenClientParam> systemAndIdentifier(String theSystem, String theCode) {
|
||||
return new TokenCriterion(getParamName(), defaultString(theSystem), theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion code(String theCode) {
|
||||
public ICriterion<TokenClientParam> code(String theCode) {
|
||||
return new TokenCriterion(getParamName(), null, theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion identifier(String theIdentifier) {
|
||||
public ICriterion<TokenClientParam> identifier(String theIdentifier) {
|
||||
return new TokenCriterion(getParamName(), null, theIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICriterion identifier(IdentifierDt theIdentifier) {
|
||||
public ICriterion<TokenClientParam> identifier(IdentifierDt theIdentifier) {
|
||||
return new TokenCriterion(getParamName(), theIdentifier.getSystem().getValueAsString(), theIdentifier.getValue().getValue());
|
||||
}
|
||||
};
|
||||
|
@ -78,7 +79,7 @@ public class TokenClientParam implements IParam {
|
|||
* The code
|
||||
* @return A criterion
|
||||
*/
|
||||
ICriterion systemAndCode(String theSystem, String theCode);
|
||||
ICriterion<TokenClientParam> systemAndCode(String theSystem, String theCode);
|
||||
|
||||
/**
|
||||
* Creates a search criterion that matches against the given system and identifier
|
||||
|
@ -89,7 +90,7 @@ public class TokenClientParam implements IParam {
|
|||
* The identifier
|
||||
* @return A criterion
|
||||
*/
|
||||
ICriterion systemAndIdentifier(String theSystem, String theIdentifier);
|
||||
ICriterion<TokenClientParam> systemAndIdentifier(String theSystem, String theIdentifier);
|
||||
|
||||
/**
|
||||
* Creates a search criterion that matches against the given identifier, with no system specified
|
||||
|
@ -98,7 +99,7 @@ public class TokenClientParam implements IParam {
|
|||
* The identifier
|
||||
* @return A criterion
|
||||
*/
|
||||
ICriterion identifier(String theIdentifier);
|
||||
ICriterion<TokenClientParam> identifier(String theIdentifier);
|
||||
|
||||
/**
|
||||
* Creates a search criterion that matches against the given code, with no code system specified
|
||||
|
@ -107,7 +108,7 @@ public class TokenClientParam implements IParam {
|
|||
* The identifier
|
||||
* @return A criterion
|
||||
*/
|
||||
ICriterion code(String theIdentifier);
|
||||
ICriterion<TokenClientParam> code(String theIdentifier);
|
||||
|
||||
/**
|
||||
* Creates a search criterion that matches against the given identifier (system and code if both are present, or whatever is present)
|
||||
|
@ -116,7 +117,7 @@ public class TokenClientParam implements IParam {
|
|||
* The identifier
|
||||
* @return A criterion
|
||||
*/
|
||||
ICriterion identifier(IdentifierDt theIdentifier);
|
||||
ICriterion<TokenClientParam> identifier(IdentifierDt theIdentifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,17 +22,23 @@ package ca.uhn.fhir.rest.gclient;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
class TokenCriterion implements ICriterion, ICriterionInternal {
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
|
||||
class TokenCriterion implements ICriterion<TokenClientParam>, ICriterionInternal {
|
||||
|
||||
private String myValue;
|
||||
private String myName;
|
||||
|
||||
public TokenCriterion(String theName, String theSystem, String theCode) {
|
||||
myName = theName;
|
||||
if (StringUtils.isNotBlank(theSystem)) {
|
||||
myValue = theSystem + "|" + StringUtils.defaultString(theCode);
|
||||
String system = ParameterUtil.escape(theSystem);
|
||||
String code = ParameterUtil.escape(theCode);
|
||||
if (StringUtils.isNotBlank(system)) {
|
||||
myValue = system + "|" + StringUtils.defaultString(code);
|
||||
} else if (system == null) {
|
||||
myValue = StringUtils.defaultString(code);
|
||||
} else {
|
||||
myValue = "|" + StringUtils.defaultString(theCode);
|
||||
myValue = "|" + StringUtils.defaultString(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
class BaseBinder<T> {
|
||||
private Class<? extends IQueryParameterType>[] myCompositeTypes;
|
||||
private Constructor<? extends T> myConstructor;
|
||||
private final Class<? extends T> myType;
|
||||
|
||||
public BaseBinder(Class<? extends T> theType, Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
myType = theType;
|
||||
myCompositeTypes = theCompositeTypes;
|
||||
|
||||
if (myType.equals(CompositeParam.class)) {
|
||||
if (myCompositeTypes.length != 2) {
|
||||
throw new ConfigurationException("Search parameter of type " + myType.getName() + " must have 2 composite types declared in parameter annotation, found " + theCompositeTypes.length);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?>[] types = new Class<?>[myCompositeTypes.length];
|
||||
for (int i = 0; i < myCompositeTypes.length; i++) {
|
||||
types[i] = myCompositeTypes[i].getClass();
|
||||
}
|
||||
myConstructor = myType.getConstructor(types);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ConfigurationException("Query parameter type " + theType.getName() + " has no constructor with types " + Arrays.asList(theCompositeTypes));
|
||||
}
|
||||
}
|
||||
|
||||
public T newInstance() {
|
||||
try {
|
||||
final Object[] args = new Object[myCompositeTypes.length];
|
||||
for (int i = 0; i < myCompositeTypes.length;i++) {
|
||||
args[i] = myCompositeTypes[i];//.newInstance();
|
||||
}
|
||||
|
||||
T dt = myConstructor.newInstance(args);
|
||||
return dt;
|
||||
} catch (final InstantiationException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (final IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (final SecurityException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (final InvocationTargetException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -79,13 +79,15 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
||||
myResourceType = theReturnResourceType;
|
||||
if (theReturnResourceType != null) {
|
||||
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
||||
if (resourceDefAnnotation == null) {
|
||||
throw new ConfigurationException(theReturnResourceType.getCanonicalName() + " has no @" + ResourceDef.class.getSimpleName() + " annotation");
|
||||
if (IResource.class.isAssignableFrom(theReturnResourceType)) {
|
||||
myResourceType = theReturnResourceType;
|
||||
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
||||
if (resourceDefAnnotation == null) {
|
||||
throw new ConfigurationException(theReturnResourceType.getCanonicalName() + " has no @" + ResourceDef.class.getSimpleName() + " annotation");
|
||||
}
|
||||
myResourceName = resourceDefAnnotation.name();
|
||||
}
|
||||
myResourceName = resourceDefAnnotation.name();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +194,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
|
||||
Integer count = RestfulServer.extractCountParameter(theRequest.getServletRequest());
|
||||
|
||||
boolean respondGzip=theRequest.isRespondGzip();
|
||||
boolean respondGzip = theRequest.isRespondGzip();
|
||||
|
||||
IBundleProvider result = invokeServer(theRequest, params);
|
||||
switch (getReturnType()) {
|
||||
|
@ -210,7 +212,6 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*
|
||||
|
|
|
@ -33,6 +33,10 @@ public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContent
|
|||
super(theContext, theResource, theUrlExtension);
|
||||
}
|
||||
|
||||
public HttpPutClientInvocation(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlExtension) {
|
||||
super(theContext,theContents, theIsBundle, theUrlExtension);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestBase createRequest(String url, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(url);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
|
@ -36,6 +36,7 @@ import ca.uhn.fhir.model.api.TagList;
|
|||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.model.api.annotation.TagListParam;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
|
@ -81,6 +82,37 @@ public class MethodUtil {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, String theResourceBody, IdDt theId, FhirContext theContext) {
|
||||
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||
StringBuilder urlBuilder = new StringBuilder();
|
||||
urlBuilder.append(resourceName);
|
||||
urlBuilder.append('/');
|
||||
urlBuilder.append(theId.getIdPart());
|
||||
|
||||
HttpPutClientInvocation retVal;
|
||||
String urlExtension = urlBuilder.toString();
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, urlExtension);
|
||||
} else {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, urlExtension);
|
||||
}
|
||||
|
||||
if (theId.hasVersionIdPart()) {
|
||||
String versionId = theId.getVersionIdPart();
|
||||
if (StringUtils.isNotBlank(versionId)) {
|
||||
urlBuilder.append('/');
|
||||
urlBuilder.append(Constants.PARAM_HISTORY);
|
||||
urlBuilder.append('/');
|
||||
urlBuilder.append(versionId);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_LOCATION, urlBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static void parseClientRequestResourceHeaders(Map<String, List<String>> theHeaders, IResource resource) {
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
|
@ -298,6 +330,7 @@ public class MethodUtil {
|
|||
parameter.setName(((RequiredParam) nextAnnotation).name());
|
||||
parameter.setRequired(true);
|
||||
parameter.setDeclaredTypes(((RequiredParam) nextAnnotation).targetTypes());
|
||||
parameter.setCompositeTypes(((RequiredParam) nextAnnotation).compositeTypes());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
@ -306,6 +339,7 @@ public class MethodUtil {
|
|||
parameter.setName(((OptionalParam) nextAnnotation).name());
|
||||
parameter.setRequired(false);
|
||||
parameter.setDeclaredTypes(((OptionalParam) nextAnnotation).targetTypes());
|
||||
parameter.setCompositeTypes(((OptionalParam) nextAnnotation).compositeTypes());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
|
|
@ -25,14 +25,14 @@ import java.util.List;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterAndBinder implements IParamBinder {
|
||||
private final Class<? extends IQueryParameterAnd<?>> myType;
|
||||
final class QueryParameterAndBinder extends BaseBinder<IQueryParameterAnd<?>> implements IParamBinder {
|
||||
|
||||
QueryParameterAndBinder(Class<? extends IQueryParameterAnd<?>> theType) {
|
||||
myType = theType;
|
||||
QueryParameterAndBinder(Class<? extends IQueryParameterAnd<?>> theType, Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -46,12 +46,8 @@ final class QueryParameterAndBinder implements IParamBinder {
|
|||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterAnd<?> dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
dt = newInstance();
|
||||
dt.setValuesAsQueryTokens(theString);
|
||||
} catch (InstantiationException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (SecurityException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ import java.util.List;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterOrBinder implements IParamBinder {
|
||||
private final Class<? extends IQueryParameterOr<?>> myType;
|
||||
final class QueryParameterOrBinder extends BaseBinder<IQueryParameterOr<?>> implements IParamBinder {
|
||||
|
||||
QueryParameterOrBinder(Class<? extends IQueryParameterOr<?>> theType) {
|
||||
myType = theType;
|
||||
QueryParameterOrBinder(Class<? extends IQueryParameterOr<?>> theType, Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -47,7 +47,7 @@ final class QueryParameterOrBinder implements IParamBinder {
|
|||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterOr<?> dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
dt = newInstance();
|
||||
if (theString.size() == 0 || theString.get(0).size() == 0) {
|
||||
return dt;
|
||||
}
|
||||
|
@ -56,10 +56,6 @@ final class QueryParameterOrBinder implements IParamBinder {
|
|||
}
|
||||
|
||||
dt.setValuesAsQueryTokens(theString.get(0));
|
||||
} catch (InstantiationException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (SecurityException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
|
|
@ -31,11 +31,10 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterTypeBinder implements IParamBinder {
|
||||
private final Class<? extends IQueryParameterType> myType;
|
||||
final class QueryParameterTypeBinder extends BaseBinder<IQueryParameterType> implements IParamBinder {
|
||||
|
||||
QueryParameterTypeBinder(Class<? extends IQueryParameterType> theType) {
|
||||
myType = theType;
|
||||
QueryParameterTypeBinder(Class<? extends IQueryParameterType> theType, Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -53,24 +52,16 @@ final class QueryParameterTypeBinder implements IParamBinder {
|
|||
return null;
|
||||
}
|
||||
|
||||
IQueryParameterType dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
if (theParams.size() == 0 || theParams.get(0).size() == 0) {
|
||||
return dt;
|
||||
}
|
||||
if (theParams.size() > 1 || theParams.get(0).size() > 1) {
|
||||
throw new InvalidRequestException("Multiple values detected");
|
||||
}
|
||||
|
||||
dt.setValueAsQueryToken(theParams.get(0).getQualifier(), value);
|
||||
} catch (InstantiationException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (SecurityException e) {
|
||||
throw new InternalErrorException(e);
|
||||
IQueryParameterType dt = super.newInstance();
|
||||
|
||||
if (theParams.size() == 0 || theParams.get(0).size() == 0) {
|
||||
return dt;
|
||||
}
|
||||
if (theParams.size() > 1 || theParams.get(0).size() > 1) {
|
||||
throw new InvalidRequestException("Multiple values detected");
|
||||
}
|
||||
|
||||
dt.setValueAsQueryToken(theParams.get(0).getQualifier(), value);
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeAndListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeOrListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.DateAndListParam;
|
||||
import ca.uhn.fhir.rest.param.DateOrListParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
|
@ -70,12 +73,46 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
public class SearchParameter extends BaseQueryParameter {
|
||||
|
||||
private static HashMap<Class<?>, SearchParamTypeEnum> ourParamTypes;
|
||||
static {
|
||||
ourParamTypes = new HashMap<Class<?>, SearchParamTypeEnum>();
|
||||
|
||||
ourParamTypes.put(StringParam.class, SearchParamTypeEnum.STRING);
|
||||
ourParamTypes.put(StringOrListParam.class, SearchParamTypeEnum.STRING);
|
||||
ourParamTypes.put(StringAndListParam.class, SearchParamTypeEnum.STRING);
|
||||
|
||||
ourParamTypes.put(TokenParam.class, SearchParamTypeEnum.TOKEN);
|
||||
ourParamTypes.put(TokenOrListParam.class, SearchParamTypeEnum.TOKEN);
|
||||
ourParamTypes.put(TokenAndListParam.class, SearchParamTypeEnum.TOKEN);
|
||||
|
||||
ourParamTypes.put(DateParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateOrListParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateAndListParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateRangeParam.class, SearchParamTypeEnum.DATE);
|
||||
|
||||
ourParamTypes.put(QuantityParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
ourParamTypes.put(QuantityOrListParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
ourParamTypes.put(QuantityAndListParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
|
||||
ourParamTypes.put(NumberParam.class, SearchParamTypeEnum.NUMBER);
|
||||
ourParamTypes.put(NumberOrListParam.class, SearchParamTypeEnum.NUMBER);
|
||||
ourParamTypes.put(NumberAndListParam.class, SearchParamTypeEnum.NUMBER);
|
||||
|
||||
ourParamTypes.put(ReferenceParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
ourParamTypes.put(ReferenceOrListParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
ourParamTypes.put(ReferenceAndListParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
|
||||
ourParamTypes.put(CompositeParam.class, SearchParamTypeEnum.COMPOSITE);
|
||||
ourParamTypes.put(CompositeOrListParam.class, SearchParamTypeEnum.COMPOSITE);
|
||||
ourParamTypes.put(CompositeAndListParam.class, SearchParamTypeEnum.COMPOSITE);
|
||||
}
|
||||
private Class<? extends IQueryParameterType>[] myCompositeTypes;
|
||||
private Class<? extends IResource>[] myDeclaredTypes;
|
||||
private String myDescription;
|
||||
private String myName;
|
||||
private IParamBinder myParamBinder;
|
||||
private SearchParamTypeEnum myParamType;
|
||||
private boolean myRequired;
|
||||
|
||||
private Class<?> myType;
|
||||
|
||||
public SearchParameter() {
|
||||
|
@ -150,8 +187,12 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
return myParamBinder.parse(theString);
|
||||
}
|
||||
|
||||
public void setCompositeTypes(Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
myCompositeTypes = theCompositeTypes;
|
||||
}
|
||||
|
||||
public void setDeclaredTypes(Class<? extends IResource>[] theTypes) {
|
||||
myDeclaredTypes=theTypes;
|
||||
myDeclaredTypes = theTypes;
|
||||
}
|
||||
|
||||
public void setDescription(String theDescription) {
|
||||
|
@ -166,57 +207,27 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
this.myRequired = required;
|
||||
}
|
||||
|
||||
static {
|
||||
ourParamTypes = new HashMap<Class<?>, SearchParamTypeEnum>();
|
||||
|
||||
ourParamTypes.put(StringParam.class, SearchParamTypeEnum.STRING);
|
||||
ourParamTypes.put(StringOrListParam.class, SearchParamTypeEnum.STRING);
|
||||
ourParamTypes.put(StringAndListParam.class, SearchParamTypeEnum.STRING);
|
||||
|
||||
ourParamTypes.put(TokenParam.class, SearchParamTypeEnum.TOKEN);
|
||||
ourParamTypes.put(TokenOrListParam.class, SearchParamTypeEnum.TOKEN);
|
||||
ourParamTypes.put(TokenAndListParam.class, SearchParamTypeEnum.TOKEN);
|
||||
|
||||
ourParamTypes.put(DateParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateOrListParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateAndListParam.class, SearchParamTypeEnum.DATE);
|
||||
ourParamTypes.put(DateRangeParam.class, SearchParamTypeEnum.DATE);
|
||||
|
||||
ourParamTypes.put(QuantityParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
ourParamTypes.put(QuantityOrListParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
ourParamTypes.put(QuantityAndListParam.class, SearchParamTypeEnum.QUANTITY);
|
||||
|
||||
ourParamTypes.put(NumberParam.class, SearchParamTypeEnum.NUMBER);
|
||||
ourParamTypes.put(NumberOrListParam.class, SearchParamTypeEnum.NUMBER);
|
||||
ourParamTypes.put(NumberAndListParam.class, SearchParamTypeEnum.NUMBER);
|
||||
|
||||
ourParamTypes.put(ReferenceParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
ourParamTypes.put(ReferenceOrListParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
ourParamTypes.put(ReferenceAndListParam.class, SearchParamTypeEnum.REFERENCE);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void setType(final Class<?> type, Class<? extends Collection<?>> theInnerCollectionType, Class<? extends Collection<?>> theOuterCollectionType) {
|
||||
this.myType = type;
|
||||
if (IQueryParameterType.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterTypeBinder((Class<? extends IQueryParameterType>) type);
|
||||
myParamBinder = new QueryParameterTypeBinder((Class<? extends IQueryParameterType>) type, myCompositeTypes);
|
||||
} else if (IQueryParameterOr.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterOrBinder((Class<? extends IQueryParameterOr<?>>) type);
|
||||
myParamBinder = new QueryParameterOrBinder((Class<? extends IQueryParameterOr<?>>) type,myCompositeTypes);
|
||||
} else if (IQueryParameterAnd.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterAndBinder((Class<? extends IQueryParameterAnd<?>>) type);
|
||||
myParamBinder = new QueryParameterAndBinder((Class<? extends IQueryParameterAnd<?>>) type, myCompositeTypes);
|
||||
} else if (String.class.equals(type)) {
|
||||
myParamBinder = new StringBinder();
|
||||
myParamType=SearchParamTypeEnum.STRING;
|
||||
myParamType = SearchParamTypeEnum.STRING;
|
||||
} else {
|
||||
throw new ConfigurationException("Unsupported data type for parameter: " + type.getCanonicalName());
|
||||
}
|
||||
|
||||
if (myParamType==null) {
|
||||
myParamType=ourParamTypes.get(type);
|
||||
if (myParamType == null) {
|
||||
myParamType = ourParamTypes.get(type);
|
||||
}
|
||||
|
||||
if (myParamType!=null) {
|
||||
|
||||
if (myParamType != null) {
|
||||
// ok
|
||||
} else if (StringDt.class.isAssignableFrom(type)) {
|
||||
myParamType = SearchParamTypeEnum.STRING;
|
||||
|
|
|
@ -26,8 +26,6 @@ import java.lang.reflect.Method;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -42,10 +40,9 @@ import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
private Integer myVersionIdParameterIndex;
|
||||
|
||||
public UpdateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
|
@ -112,13 +109,15 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
|
|||
throw new NullPointerException("ID can not be null");
|
||||
}
|
||||
|
||||
IdDt versionIdDt = null;
|
||||
if (myVersionIdParameterIndex != null) {
|
||||
versionIdDt = (IdDt) theArgs[myVersionIdParameterIndex];
|
||||
IdDt versionIdDt = (IdDt) theArgs[myVersionIdParameterIndex];
|
||||
if (idDt.hasVersionIdPart() == false) {
|
||||
idDt = idDt.withVersion(versionIdDt.getIdPart());
|
||||
}
|
||||
}
|
||||
FhirContext context = getContext();
|
||||
|
||||
HttpPutClientInvocation retVal = createUpdateInvocation(theResource, idDt, versionIdDt, context);
|
||||
HttpPutClientInvocation retVal = MethodUtil.createUpdateInvocation(theResource, null,idDt, context);
|
||||
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
IParameter nextParam = getParameters().get(idx);
|
||||
|
@ -128,40 +127,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, IdDt idDt, IdDt versionIdDt, FhirContext context) {
|
||||
String resourceName = context.getResourceDefinition(theResource).getName();
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(idDt.getIdPart());
|
||||
HttpPutClientInvocation retVal = new HttpPutClientInvocation(context, theResource, urlExtension.toString());
|
||||
|
||||
if (idDt.hasVersionIdPart()) {
|
||||
String versionId = idDt.getVersionIdPart();
|
||||
if (StringUtils.isNotBlank(versionId)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
// b.append('/');
|
||||
b.append(urlExtension);
|
||||
b.append("/_history/");
|
||||
b.append(versionId);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_LOCATION, b.toString());
|
||||
}
|
||||
} else if (versionIdDt != null) {
|
||||
String versionId = versionIdDt.getValue();
|
||||
if (StringUtils.isNotBlank(versionId)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
// b.append('/');
|
||||
b.append(urlExtension);
|
||||
b.append("/_history/");
|
||||
b.append(versionId);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_LOCATION, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
MethodUtil.addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public class CompositeAndListParam<A extends IQueryParameterType, B extends IQueryParameterType> extends BaseAndListParam<CompositeOrListParam<A,B>> {
|
||||
|
||||
private Class<A> myLeftType;
|
||||
private Class<B> myRightType;
|
||||
|
||||
public CompositeAndListParam(Class<A> theLeftType, Class<B> theRightType) {
|
||||
super();
|
||||
myLeftType = theLeftType;
|
||||
myRightType = theRightType;
|
||||
}
|
||||
|
||||
@Override
|
||||
CompositeOrListParam<A,B> newInstance() {
|
||||
return new CompositeOrListParam<A,B>(myLeftType, myRightType);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public class CompositeOrListParam<A extends IQueryParameterType, B extends IQueryParameterType> extends BaseOrListParam<CompositeParam<A,B>> {
|
||||
|
||||
private Class<A> myLeftType;
|
||||
private Class<B> myRightType;
|
||||
|
||||
public CompositeOrListParam(Class<A> theLeftType, Class<B> theRightType) {
|
||||
super();
|
||||
myLeftType = theLeftType;
|
||||
myRightType = theRightType;
|
||||
}
|
||||
|
||||
@Override
|
||||
CompositeParam<A,B> newInstance() {
|
||||
return new CompositeParam<A,B>(myLeftType, myRightType);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> implements IQueryParameterType {
|
||||
|
||||
private A myLeftType;
|
||||
private B myRightType;
|
||||
|
||||
public CompositeParam(A theLeftInstance, B theRightInstance) {
|
||||
myLeftType = theLeftInstance;
|
||||
myRightType = theRightInstance;
|
||||
}
|
||||
|
||||
public CompositeParam(Class<A> theLeftType, Class<B> theRightType) {
|
||||
Validate.notNull(theLeftType);
|
||||
Validate.notNull(theRightType);
|
||||
try {
|
||||
myLeftType = theLeftType.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigurationException("Failed to instantiate type: " + myLeftType, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ConfigurationException("Failed to instantiate type: " + myLeftType, e);
|
||||
}
|
||||
try {
|
||||
myRightType = theRightType.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigurationException("Failed to instantiate type: " + myRightType, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ConfigurationException("Failed to instantiate type: " + myRightType, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the left value for this parameter (the first of two parameters in this composite)
|
||||
*/
|
||||
public A getLeftValue() {
|
||||
return myLeftType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the right value for this parameter (the second of two parameters in this composite)
|
||||
*/
|
||||
public B getRightValue() {
|
||||
return myRightType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (myLeftType != null) {
|
||||
b.append(myLeftType.getValueAsQueryToken());
|
||||
}
|
||||
b.append('$');
|
||||
if (myRightType != null) {
|
||||
b.append(myRightType.getValueAsQueryToken());
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (isBlank(theValue)) {
|
||||
myLeftType.setValueAsQueryToken(theQualifier, "");
|
||||
myRightType.setValueAsQueryToken(theQualifier, "");
|
||||
} else {
|
||||
List<String> parts = ParameterUtil.splitParameterString(theValue, '$', false);
|
||||
if (parts.size() > 2) {
|
||||
throw new InvalidRequestException("Invalid value for composite parameter (only one '$' is valid for this parameter, others must be escaped). Value was: " + theValue);
|
||||
}
|
||||
myLeftType.setValueAsQueryToken(theQualifier, parts.get(0));
|
||||
if (parts.size() > 1) {
|
||||
myRightType.setValueAsQueryToken(theQualifier, parts.get(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.model.api.IQueryParameterOr;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -162,4 +163,12 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
public InstantDt getValueAsInstantDt() {
|
||||
return new InstantDt(getValue());
|
||||
}
|
||||
|
||||
public DateTimeDt getValueAsDateTimeDt() {
|
||||
return new DateTimeDt(getValueAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,23 +52,21 @@ public class ParameterUtil {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public static Integer findSinceParameterIndex(Method theMethod) {
|
||||
// return findParamIndex(theMethod, Since.class);
|
||||
// }
|
||||
|
||||
public static int nonEscapedIndexOf(String theString, char theCharacter) {
|
||||
for (int i =0; i < theString.length(); i++) {
|
||||
if (theString.charAt(i)==theCharacter) {
|
||||
if (i == 0 || theString.charAt(i-1) != '\\') {
|
||||
for (int i = 0; i < theString.length(); i++) {
|
||||
if (theString.charAt(i) == theCharacter) {
|
||||
if (i == 0 || theString.charAt(i - 1) != '\\') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
public static Object fromInstant(Class<?> theType, InstantDt theArgument) {
|
||||
if (theType.equals(InstantDt.class)) {
|
||||
if (theArgument == null) {
|
||||
|
@ -138,19 +136,28 @@ public class ParameterUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static List<String> splitParameterString(String theInput, boolean theUnescapeComponents){
|
||||
static List<String> splitParameterString(String theInput, boolean theUnescapeComponents) {
|
||||
return splitParameterString(theInput, ',', theUnescapeComponents);
|
||||
}
|
||||
|
||||
static List<String> splitParameterString(String theInput, char theDelimiter, boolean theUnescapeComponents) {
|
||||
ArrayList<String> retVal = new ArrayList<String>();
|
||||
if (theInput!=null) {
|
||||
if (theInput != null) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < theInput.length(); i++) {
|
||||
char next = theInput.charAt(i);
|
||||
if (next == ',') {
|
||||
if (i == 0 || theInput.charAt(i-1) != '\\') {
|
||||
if (next == theDelimiter) {
|
||||
if (i == 0) {
|
||||
b.append(next);
|
||||
} else {
|
||||
if (b.length() > 0) {
|
||||
retVal.add(b.toString());
|
||||
b.setLength(0);
|
||||
char prevChar = theInput.charAt(i - 1);
|
||||
if (prevChar == '\\') {
|
||||
b.append(next);
|
||||
} else {
|
||||
if (b.length() > 0) {
|
||||
retVal.add(b.toString());
|
||||
b.setLength(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -161,28 +168,27 @@ public class ParameterUtil {
|
|||
retVal.add(b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (theUnescapeComponents) {
|
||||
for (int i = 0; i < retVal.size();i++) {
|
||||
retVal.set(i,unescape(retVal.get(i)));
|
||||
for (int i = 0; i < retVal.size(); i++) {
|
||||
retVal.set(i, unescape(retVal.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Escapes a string according to the rules for parameter escaping specified
|
||||
* in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
|
||||
* Escapes a string according to the rules for parameter escaping specified in the <a
|
||||
* href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
|
||||
*/
|
||||
public static String escape(String theValue) {
|
||||
if (theValue == null) {
|
||||
return theValue;
|
||||
}
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < theValue.length();i++) {
|
||||
|
||||
for (int i = 0; i < theValue.length(); i++) {
|
||||
char next = theValue.charAt(i);
|
||||
switch (next) {
|
||||
case '$':
|
||||
|
@ -194,31 +200,31 @@ public class ParameterUtil {
|
|||
b.append(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes a string according to the rules for parameter escaping specified
|
||||
* in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
|
||||
* Unescapes a string according to the rules for parameter escaping specified in the <a
|
||||
* href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping Section</a>
|
||||
*/
|
||||
public static String unescape(String theValue) {
|
||||
if (theValue == null) {
|
||||
return theValue;
|
||||
}
|
||||
if (theValue.indexOf('\\')==-1) {
|
||||
if (theValue.indexOf('\\') == -1) {
|
||||
return theValue;
|
||||
}
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < theValue.length();i++) {
|
||||
|
||||
for (int i = 0; i < theValue.length(); i++) {
|
||||
char next = theValue.charAt(i);
|
||||
if (next == '\\') {
|
||||
if (i == theValue.length()-1) {
|
||||
if (i == theValue.length() - 1) {
|
||||
b.append(next);
|
||||
} else {
|
||||
switch (theValue.charAt(i+1)) {
|
||||
switch (theValue.charAt(i + 1)) {
|
||||
case '$':
|
||||
case ',':
|
||||
case '|':
|
||||
|
@ -231,7 +237,7 @@ public class ParameterUtil {
|
|||
b.append(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
|
|||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class StringParam implements IQueryParameterType {
|
||||
|
@ -61,7 +62,7 @@ public class StringParam implements IQueryParameterType {
|
|||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
return myValue;
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -91,7 +92,7 @@ public class StringParam implements IQueryParameterType {
|
|||
} else {
|
||||
setExact(false);
|
||||
}
|
||||
myValue = theValue;
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,4 +105,8 @@ public class StringParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -44,8 +45,20 @@ public class TokenOrListParam extends BaseOrListParam<TokenParam> {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method which adds a token to this OR list
|
||||
* using the system and code from a coding
|
||||
*/
|
||||
public void add(CodingDt theCodingDt) {
|
||||
add(new TokenParam(theCodingDt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method which adds a token to this OR list
|
||||
* using the system and value from an identifier
|
||||
*/
|
||||
public void add(IdentifierDt theIdentifierDt) {
|
||||
add(new TokenParam(theIdentifierDt));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class TokenParam implements IQueryParameterType {
|
||||
|
@ -61,7 +63,21 @@ public class TokenParam implements IQueryParameterType {
|
|||
* @param theCodingDt The coding
|
||||
*/
|
||||
public TokenParam(CodingDt theCodingDt) {
|
||||
this(theCodingDt.getSystem().getValue().toASCIIString(), theCodingDt.getCode().getValue());
|
||||
this(toSystemValue(theCodingDt.getSystem()), theCodingDt.getCode().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which copies the {@link IdentifierDt#getSystem() system} and {@link IdentifierDt#getValue() value} from a {@link IdentifierDt}
|
||||
* instance and adds it as a parameter
|
||||
*
|
||||
* @param theCodingDt The coding
|
||||
*/
|
||||
public TokenParam(IdentifierDt theIdentifierDt) {
|
||||
this(toSystemValue(theIdentifierDt.getSystem()), theIdentifierDt.getValue().getValue());
|
||||
}
|
||||
|
||||
private static String toSystemValue(UriDt theSystem) {
|
||||
return theSystem.getValueAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -418,7 +418,7 @@ public class RestfulServer extends HttpServlet {
|
|||
IdDt versionId = null;
|
||||
String operation = null;
|
||||
|
||||
String requestPath = requestFullPath.substring(servletContextPath.length() + servletPath.length());
|
||||
String requestPath = requestFullPath.substring(escapedLength(servletContextPath) + escapedLength(servletPath));
|
||||
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
|
||||
requestPath = requestPath.substring(1);
|
||||
}
|
||||
|
@ -599,6 +599,20 @@ public class RestfulServer extends HttpServlet {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Count length of URL string, but treating unescaped sequences (e.g. ' ') as their unescaped equivalent (%20)
|
||||
*/
|
||||
private int escapedLength(String theServletPath) {
|
||||
int delta = 0;
|
||||
for(int i =0;i<theServletPath.length();i++) {
|
||||
char next = theServletPath.charAt(i);
|
||||
if (next == ' ') {
|
||||
delta = delta + 2;
|
||||
}
|
||||
}
|
||||
return theServletPath.length()+delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the server. Note that this method is final to avoid accidentally introducing bugs in implementations, but subclasses may put initialization code in {@link #initialize()}, which is
|
||||
* called immediately before beginning initialization of the restful server's internal init.
|
||||
|
|
|
@ -22,7 +22,9 @@ package ca.uhn.fhir.util;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
|
@ -153,7 +155,21 @@ public class FhirTerser {
|
|||
}
|
||||
BaseRuntimeElementDefinition<?> childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
|
||||
if (childElementDef == null) {
|
||||
throw new DataFormatException("Found value of type[" + nextValue.getClass().getSimpleName() + "] which is not valid for field[" + nextChild.getElementName() + "] in " + childDef.getName());
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("Found value of type[");
|
||||
b.append(nextValue.getClass().getSimpleName());
|
||||
b.append("] which is not valid for field[");
|
||||
b.append(nextChild.getElementName());
|
||||
b.append("] in ");
|
||||
b.append(childDef.getName());
|
||||
b.append(" - Valid types: ");
|
||||
for (Iterator<String> iter = new TreeSet<String>(nextChild.getValidChildNames()).iterator(); iter.hasNext();) {
|
||||
b.append(nextChild.getChildByName(iter.next()).getImplementingClass().getSimpleName());
|
||||
if (iter.hasNext()) {
|
||||
b.append(", ");
|
||||
}
|
||||
}
|
||||
throw new DataFormatException(b.toString());
|
||||
}
|
||||
getAllChildElementsOfType(nextValue, childElementDef, theType, theList);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
|
@ -55,6 +56,25 @@ client.create()
|
|||
//END SNIPPET: create
|
||||
}
|
||||
{
|
||||
//START SNIPPET: update
|
||||
Patient patient = new Patient();
|
||||
// ..populate the patient object..
|
||||
patient.addIdentifier("urn:system", "12345");
|
||||
patient.addName().addFamily("Smith").addGiven("John");
|
||||
|
||||
// To update a resource, it should have an ID set (if the resource object
|
||||
// comes from the results of a previous read or search, it will already
|
||||
// have one though)
|
||||
patient.setId("Patient/123");
|
||||
|
||||
// Invoke the server create method (and send pretty-printed JSON encoding to the server
|
||||
// instead of the default which is non-pretty printed XML)
|
||||
client.update()
|
||||
.resource(patient)
|
||||
.execute();
|
||||
//END SNIPPET: update
|
||||
}
|
||||
{
|
||||
//START SNIPPET: conformance
|
||||
// Retrieve the server's conformance statement and print its description
|
||||
Conformance conf = client.conformance();
|
||||
|
@ -97,6 +117,16 @@ response = client.search()
|
|||
.execute();
|
||||
//END SNIPPET: searchAdv
|
||||
|
||||
//START SNIPPET: searchComposite
|
||||
response = client.search()
|
||||
.forResource("Observation")
|
||||
.where(Observation.NAME_VALUE_DATE
|
||||
.withLeft(Observation.NAME.exactly().code("FOO$BAR"))
|
||||
.withRight(Observation.VALUE_DATE.exactly().day("2001-01-01"))
|
||||
)
|
||||
.execute();
|
||||
//END SNIPPET: searchComposite
|
||||
|
||||
//START SNIPPET: searchPaging
|
||||
if (response.getLinkNext().isEmpty() == false) {
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ import ca.uhn.fhir.rest.api.SortSpec;
|
|||
import ca.uhn.fhir.rest.client.ITestClient;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
|
@ -285,6 +286,24 @@ public List<Patient> searchByNamedQuery(@RequiredParam(name="someparam") StringP
|
|||
}
|
||||
//END SNIPPET: searchNamedQuery
|
||||
|
||||
//START SNIPPET: searchComposite
|
||||
@Search()
|
||||
public List<Observation> searchByComposite(
|
||||
@RequiredParam(name=Observation.SP_NAME_VALUE_DATE, compositeTypes= {TokenParam.class, DateParam.class})
|
||||
CompositeParam<TokenParam, DateParam> theParam) {
|
||||
// Each of the two values in the composite param are accessible separately.
|
||||
// In the case of Observation's name-value-date, the left is a string and
|
||||
// the right is a date.
|
||||
TokenParam observationName = theParam.getLeftValue();
|
||||
DateParam observationValue = theParam.getRightValue();
|
||||
|
||||
List<Observation> retVal = new ArrayList<Observation>();
|
||||
// ...populate...
|
||||
return retVal;
|
||||
}
|
||||
//END SNIPPET: searchComposite
|
||||
|
||||
|
||||
//START SNIPPET: searchIdentifierParam
|
||||
@Search()
|
||||
public List<Patient> searchByIdentifier(@RequiredParam(name=Patient.SP_IDENTIFIER) TokenParam theId) {
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
</subsection>
|
||||
|
||||
<subsection name="Type - Search/Query">
|
||||
|
||||
<p>
|
||||
The following example shows how to query using the generic client:
|
||||
</p>
|
||||
|
@ -97,6 +98,8 @@
|
|||
<param name="file"
|
||||
value="src/site/example/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<h4>Search - Paging</h4>
|
||||
<p>
|
||||
If the server supports paging results, the client has a page method
|
||||
which can be used to load subsequent pages.
|
||||
|
@ -106,6 +109,21 @@
|
|||
<param name="file"
|
||||
value="src/site/example/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<h4>Search - Composite Parameters</h4>
|
||||
<p>
|
||||
If a composite parameter is being searched on, the parameter
|
||||
takes a "left" and "right" operand, each of which is
|
||||
a parameter from the resource being seached. The following example shows the
|
||||
syntax.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="searchComposite" />
|
||||
<param name="file"
|
||||
value="src/site/example/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<h4>Search - Query Options</h4>
|
||||
<p>
|
||||
The fluent search also has methods for sorting, limiting, specifying
|
||||
JSON encoding, etc.
|
||||
|
@ -115,6 +133,7 @@
|
|||
<param name="file"
|
||||
value="src/site/example/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Instance - Delete">
|
||||
|
@ -129,6 +148,23 @@
|
|||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Instance - Update">
|
||||
<p>
|
||||
Updating a resource is similar to creating one, except that
|
||||
an ID must be supplied since you are updating a previously
|
||||
existing resource instance.
|
||||
</p>
|
||||
<p>
|
||||
The following example shows how to perform an update
|
||||
operation using the generic client:
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="update" />
|
||||
<param name="file"
|
||||
value="src/site/example/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Server - Conformance">
|
||||
<p>
|
||||
To retrieve the server's conformance statement, simply call the <code>conformance()</code>
|
||||
|
@ -157,7 +193,7 @@
|
|||
<section name="The Annotation-Driven Client">
|
||||
|
||||
<p>
|
||||
HAPI also provides a second style of client caled the annotation-driven client.
|
||||
HAPI also provides a second style of client, called the <b>annotation-driven</b> client.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -727,6 +727,34 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Search Parameters: Composite">
|
||||
|
||||
<p>
|
||||
Composite search parameters incorporate two parameters in a single
|
||||
value. Each of those parameters will themselves have a parameter type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the following example, Observation.name-value-date is shown. This parameter
|
||||
is a composite of a string and a date. Note that the composite parameter types
|
||||
(StringParam and DateParam) must be specified in both the annotation's
|
||||
<code>compositeTypes</code> field, as well as the generic types for the
|
||||
<code>CompositeParam</code> method parameter itself.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="searchComposite" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Observation?name-value-date=PROCTIME$2001-02-02</code>
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Combining Multiple Parameters">
|
||||
|
||||
<p>
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
|
|
|
@ -28,7 +28,6 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
|
@ -113,8 +112,11 @@ public class JsonParserTest {
|
|||
" }" +
|
||||
"}";
|
||||
//@formatter:on
|
||||
IResource res = ourCtx.newJsonParser().parseResource(text);
|
||||
|
||||
Patient res = (Patient) ourCtx.newJsonParser().parseResource(text);
|
||||
String value = res.getText().getDiv().getValueAsString();
|
||||
|
||||
assertNull(value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
@ -45,6 +46,7 @@ import ca.uhn.fhir.model.api.TagList;
|
|||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
|
@ -58,6 +60,7 @@ import ca.uhn.fhir.rest.annotation.Search;
|
|||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
|
@ -771,7 +774,7 @@ public class ClientTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSearchComposite() throws Exception {
|
||||
public void testSearchOrList() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
|
@ -944,6 +947,28 @@ public class ClientTest {
|
|||
assertEquals("PRP1660", resource.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByCompositeParam() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
StringParam str = new StringParam("FOO$BAR");
|
||||
DateParam date = new DateParam("2001-01-01");
|
||||
client.getObservationByNameValueDate(new CompositeParam<StringParam, DateParam>(str, date));
|
||||
|
||||
assertEquals("http://foo/Observation?" + Observation.SP_NAME_VALUE_DATE + "=" + URLEncoder.encode("FOO\\$BAR$2001-01-01","UTF-8"), capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithStringIncludes() throws Exception {
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.junit.Assert.*;
|
|||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -15,6 +16,7 @@ import org.apache.http.ProtocolVersion;
|
|||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
|
@ -41,6 +43,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
|||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class GenericClientTest {
|
||||
|
||||
|
@ -138,6 +141,68 @@ public class GenericClientTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Exception {
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier("foo:bar", "12345");
|
||||
p1.addName().addFamily("Smith").addGiven("John");
|
||||
TagList list = new TagList();
|
||||
list.addTag("http://hl7.org/fhir/tag", "urn:happytag", "This is a happy resource");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p1, list);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
try {
|
||||
client.update().resource(p1).execute();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
// should happen because no ID set
|
||||
}
|
||||
|
||||
assertEquals(0, capt.getAllValues().size());
|
||||
|
||||
p1.setId("44");
|
||||
client.update().resource(p1).execute();
|
||||
|
||||
assertEquals(1, capt.getAllValues().size());
|
||||
|
||||
MethodOutcome outcome = client.update().resource(p1).execute();
|
||||
assertEquals("44", outcome.getId().getIdPart());
|
||||
assertEquals("22", outcome.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(2, capt.getAllValues().size());
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/44", capt.getValue().getURI().toString());
|
||||
assertEquals("PUT", capt.getValue().getMethod());
|
||||
Header catH = capt.getValue().getFirstHeader("Category");
|
||||
assertNotNull(Arrays.asList(capt.getValue().getAllHeaders()).toString(), catH);
|
||||
assertEquals("urn:happytag; label=\"This is a happy resource\"; scheme=\"http://hl7.org/fhir/tag\"", catH.getValue());
|
||||
|
||||
/*
|
||||
* Try fluent options
|
||||
*/
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
client.update().resource(p1).withId("123").execute();
|
||||
assertEquals(3, capt.getAllValues().size());
|
||||
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(2).getURI().toString());
|
||||
|
||||
String resourceText = "<Patient xmlns=\"http://hl7.org/fhir\"> </Patient>";
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
client.update().resource(resourceText).withId("123").execute();
|
||||
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(3).getURI().toString());
|
||||
assertEquals(resourceText, IOUtils.toString(((HttpPut)capt.getAllValues().get(3)).getEntity().getContent()));
|
||||
assertEquals(4, capt.getAllValues().size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
|
@ -362,6 +427,45 @@ public class GenericClientTest {
|
|||
|
||||
assertEquals("http://example.com/fhir/Patient?identifier=http%3A%2F%2Fexample.com%2Ffhir%7CZZZ", capt.getValue().getURI().toString());
|
||||
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
//@formatter:off
|
||||
response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.IDENTIFIER.exactly().code("ZZZ"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?identifier=ZZZ", capt.getAllValues().get(1).getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testSearchByComposite() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Observation")
|
||||
.where(Observation.NAME_VALUE_DATE
|
||||
.withLeft(Observation.NAME.exactly().code("FOO$BAR"))
|
||||
.withRight(Observation.VALUE_DATE.exactly().day("2001-01-01"))
|
||||
)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://foo/Observation?" + Observation.SP_NAME_VALUE_DATE + "=" + URLEncoder.encode("FOO\\$BAR$2001-01-01","UTF-8"), capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
@ -26,6 +27,7 @@ import ca.uhn.fhir.rest.annotation.Update;
|
|||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
|
@ -40,7 +42,10 @@ public interface ITestClient extends IBasicClient {
|
|||
|
||||
@Search()
|
||||
public List<Patient> getPatientByDateRange(@RequiredParam(name = "dateRange") DateRangeParam theIdentifiers);
|
||||
|
||||
|
||||
@Search(type=Observation.class)
|
||||
public Bundle getObservationByNameValueDate(@RequiredParam(name = Observation.SP_NAME_VALUE_DATE, compositeTypes= {StringParam.class,DateParam.class}) CompositeParam<StringParam, DateParam> theIdentifiers);
|
||||
|
||||
@Search()
|
||||
public List<Patient> getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);
|
||||
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.param.CompositeAndListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeOrListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class CompositeParameterTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
|
||||
@Test
|
||||
public void testSearchWithDateValue() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_DATE + "=" + URLEncoder.encode("foo\\$bar$2001-01-01", "UTF-8"));
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
List<BundleEntry> entries = ourCtx.newXmlParser().parseBundle(responseContent).getEntries();
|
||||
assertEquals(1, entries.size());
|
||||
Observation o = (Observation) entries.get(0).getResource();
|
||||
assertEquals("foo$bar", o.getName().getText().getValue());
|
||||
assertEquals("2001-01-01", ((DateTimeDt) o.getApplies()).getValueAsString().substring(0, 10));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleValue() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_STRING + "=" + URLEncoder.encode("l1$r1,l2$r2", "UTF-8") + "&" + Observation.SP_NAME_VALUE_STRING + "=" + URLEncoder.encode("l3$r3,l4$r4", "UTF-8"));
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
List<BundleEntry> entries = ourCtx.newXmlParser().parseBundle(responseContent).getEntries();
|
||||
assertEquals(1, entries.size());
|
||||
Observation o = (Observation) entries.get(0).getResource();
|
||||
assertEquals("AND", o.getName().getCoding().get(0).getDisplay().getValue());
|
||||
assertEquals("OR", o.getName().getCoding().get(1).getDisplay().getValue());
|
||||
assertEquals("l1", o.getName().getCoding().get(1).getSystem().getValueAsString());
|
||||
assertEquals("r1", o.getName().getCoding().get(1).getCode().getValue());
|
||||
assertEquals("OR", o.getName().getCoding().get(2).getDisplay().getValue());
|
||||
assertEquals("l2", o.getName().getCoding().get(2).getSystem().getValueAsString());
|
||||
assertEquals("r2", o.getName().getCoding().get(2).getCode().getValue());
|
||||
|
||||
assertEquals("AND", o.getName().getCoding().get(3).getDisplay().getValue());
|
||||
assertEquals("OR", o.getName().getCoding().get(4).getDisplay().getValue());
|
||||
assertEquals("l3", o.getName().getCoding().get(4).getSystem().getValueAsString());
|
||||
assertEquals("r3", o.getName().getCoding().get(4).getCode().getValue());
|
||||
assertEquals("OR", o.getName().getCoding().get(5).getDisplay().getValue());
|
||||
assertEquals("l4", o.getName().getCoding().get(5).getSystem().getValueAsString());
|
||||
assertEquals("r4", o.getName().getCoding().get(5).getCode().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyObservationResourceProvider patientProvider = new DummyObservationResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
ourCtx = servlet.getFhirContext();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
ourCtx = servlet.getFhirContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class DummyObservationResourceProvider implements IResourceProvider {
|
||||
//@formatter:off
|
||||
@Search
|
||||
public List<Observation> findObservation(
|
||||
@RequiredParam(name = Observation.SP_NAME_VALUE_DATE, compositeTypes= { StringParam.class, DateParam.class })
|
||||
CompositeParam<StringParam, DateParam> theParam
|
||||
) {
|
||||
//@formatter:on
|
||||
|
||||
ArrayList<Observation> retVal = new ArrayList<Observation>();
|
||||
|
||||
Observation p = new Observation();
|
||||
p.setId("1");
|
||||
p.setApplies(theParam.getRightValue().getValueAsDateTimeDt());
|
||||
p.getName().setText(theParam.getLeftValue().getValueAsStringDt());
|
||||
retVal.add(p);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
@Search
|
||||
public List<Observation> findObservationNVS(
|
||||
@RequiredParam(name = Observation.SP_NAME_VALUE_STRING, compositeTypes= { StringParam.class, StringParam.class })
|
||||
CompositeAndListParam<StringParam, StringParam> theParam
|
||||
) {
|
||||
//@formatter:on
|
||||
|
||||
ArrayList<Observation> retVal = new ArrayList<Observation>();
|
||||
|
||||
Observation p = new Observation();
|
||||
p.setId("1");
|
||||
for (CompositeOrListParam<StringParam, StringParam> nextAnd : theParam.getValuesAsQueryTokens()) {
|
||||
p.getName().addCoding().getDisplay().setValue("AND");
|
||||
for (CompositeParam<StringParam, StringParam> nextOr : nextAnd.getValuesAsQueryTokens()) {
|
||||
p.getName().addCoding().setDisplay("OR").setSystem(nextOr.getLeftValue().getValue()).setCode(nextOr.getRightValue().getValue());
|
||||
}
|
||||
}
|
||||
retVal.add(p);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Observation.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,8 +2,6 @@ package ca.uhn.fhir.rest.server;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -15,9 +13,10 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
|||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -42,89 +41,103 @@ import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
|||
public class ResfulServerSelfReferenceTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResfulServerSelfReferenceTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
ourCtx = new FhirContext(Patient.class);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
ServerProfileProvider profProvider=new ServerProfileProvider(ourCtx);
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ServletHolder servletHolder = new ServletHolder(new DummyRestfulServer(patientProvider,profProvider));
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/fhir/context/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
@Test
|
||||
public void testContextWithSpace() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
Server server = new Server(port);
|
||||
|
||||
RestfulServer restServer = new RestfulServer();
|
||||
restServer.setFhirContext(ourCtx);
|
||||
restServer.setResourceProviders(new DummyPatientResourceProvider());
|
||||
|
||||
// ServletHandler proxyHandler = new ServletHandler();
|
||||
ServletHolder servletHolder = new ServletHolder(restServer);
|
||||
|
||||
ServletContextHandler ch = new ServletContextHandler();
|
||||
ch.setContextPath("/root ctx/rcp2");
|
||||
ch.addServlet(servletHolder, "/fhir ctx/fcp2/*");
|
||||
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
server.setHandler(ch);
|
||||
server.start();
|
||||
try {
|
||||
|
||||
String baseUri = "http://localhost:" + port + "/root%20ctx/rcp2/fhir%20ctx/fcp2";
|
||||
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
|
||||
} finally {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByParamIdentifier() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
Server hServer = new Server(port);
|
||||
|
||||
String baseUri = "http://localhost:" + ourPort + "/fhir/context";
|
||||
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
ServerProfileProvider profProvider = new ServerProfileProvider(ourCtx);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer server = new RestfulServer();
|
||||
server.setFhirContext(ourCtx);
|
||||
server.setResourceProviders(patientProvider, profProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(server);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/fhir/context/*");
|
||||
hServer.setHandler(proxyHandler);
|
||||
hServer.start();
|
||||
try {
|
||||
String baseUri = "http://localhost:" + port + "/fhir/context";
|
||||
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
Patient patient = (Patient) bundle.getEntries().get(0).getResource();
|
||||
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
|
||||
assertEquals(uri, bundle.getLinkSelf().getValue());
|
||||
assertEquals(baseUri, bundle.getLinkBase().getValue());
|
||||
Patient patient = (Patient) bundle.getEntries().get(0).getResource();
|
||||
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
|
||||
|
||||
assertEquals(uri, bundle.getLinkSelf().getValue());
|
||||
assertEquals(baseUri, bundle.getLinkBase().getValue());
|
||||
} finally {
|
||||
hServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class DummyRestfulServer extends RestfulServer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Collection<IResourceProvider> myResourceProviders;
|
||||
|
||||
public DummyRestfulServer(IResourceProvider... theResourceProviders) {
|
||||
myResourceProviders = Arrays.asList(theResourceProviders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IResourceProvider> getResourceProviders() {
|
||||
return myResourceProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISecurityManager getSecurityManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
|
@ -161,8 +174,6 @@ public class ResfulServerSelfReferenceTest {
|
|||
return idToPatient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Search()
|
||||
public Patient getPatient(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
for (Patient next : getIdToPatient().values()) {
|
||||
|
@ -174,8 +185,7 @@ public class ResfulServerSelfReferenceTest {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the resource by its identifier
|
||||
*
|
||||
|
@ -195,6 +205,4 @@ public class ResfulServerSelfReferenceTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,6 +13,7 @@ import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
|
||||
public class SearchParameterMap extends HashMap<String, List<List<? extends IQueryParameterType>>> {
|
||||
|
||||
|
@ -20,6 +21,8 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
|
|||
|
||||
private Set<Include> myIncludes;
|
||||
|
||||
private SortSpec mySort;
|
||||
|
||||
public void add(String theName, IQueryParameterAnd<?> theAnd) {
|
||||
if (theAnd == null) {
|
||||
return;
|
||||
|
@ -59,6 +62,10 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
|
|||
get(theName).add(list);
|
||||
}
|
||||
|
||||
public void addInclude(Include theInclude) {
|
||||
getIncludes().add(theInclude);
|
||||
}
|
||||
|
||||
public Set<Include> getIncludes() {
|
||||
if (myIncludes == null) {
|
||||
myIncludes = new HashSet<Include>();
|
||||
|
@ -66,12 +73,16 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
|
|||
return myIncludes;
|
||||
}
|
||||
|
||||
public SortSpec getSort() {
|
||||
return mySort;
|
||||
}
|
||||
|
||||
public void setIncludes(Set<Include> theIncludes) {
|
||||
myIncludes = theIncludes;
|
||||
}
|
||||
|
||||
public void addInclude(Include theInclude) {
|
||||
getIncludes().add(theInclude);
|
||||
public void setSort(SortSpec theSort) {
|
||||
mySort = theSort;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,7 +65,7 @@
|
|||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||
<property name="showSql" value="false" />
|
||||
<property name="showSql" value="true" />
|
||||
<property name="generateDdl" value="true" />
|
||||
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
|
||||
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
|
||||
|
|
|
@ -31,34 +31,34 @@ function generateHapiSearch(json, container) {
|
|||
var nextParam = json.params[i];
|
||||
var paramLine = null;
|
||||
if (nextParam.type == 'string') {
|
||||
paramLine = '.where(new StringParam("' + nextParam.name + '")';
|
||||
paramLine = '.where(new StringClientParam("' + nextParam.name + '")';
|
||||
paramLine += nextParam.qualifier = ':exact' ? '.matchesExactly()' : '.matches()';
|
||||
paramLine += '.value("' + nextParam.value + '"))';
|
||||
} else if (nextParam.type == 'token') {
|
||||
var idx = nextParam.value.indexOf('|');
|
||||
if (idx == -1) {
|
||||
paramLine = '.where(new TokenParam("' + nextParam.name + '").exactly().code("' + nextParam.value + '"))';
|
||||
paramLine = '.where(new TokenClientParam("' + nextParam.name + '").exactly().code("' + nextParam.value + '"))';
|
||||
} else {
|
||||
paramLine = '.where(new TokenParam("' + nextParam.name + '").exactly().systemAndCode("' + nextParam.value.substring(0,idx) + '", "' + nextParam.value.substring(idx+1) + '"))';
|
||||
paramLine = '.where(new TokenClientParam("' + nextParam.name + '").exactly().systemAndCode("' + nextParam.value.substring(0,idx) + '", "' + nextParam.value.substring(idx+1) + '"))';
|
||||
}
|
||||
} else if (nextParam.type == 'number') {
|
||||
paramLine = '.where(new NumberParam("' + nextParam.name + '").exactly().value("' + nextParam.value + '"))';
|
||||
paramLine = '.where(new NumberClientParam("' + nextParam.name + '").exactly().value("' + nextParam.value + '"))';
|
||||
} else if (nextParam.type == 'reference') {
|
||||
if (nextParam.qualifier == '') {
|
||||
if (nextParam.name.indexOf('.') == -1) {
|
||||
paramLine = '.where(new ReferenceParam("' + nextParam.name + '").hasId("' + nextParam.value + '"))';
|
||||
paramLine = '.where(new ReferenceClientParam("' + nextParam.name + '").hasId("' + nextParam.value + '"))';
|
||||
}
|
||||
}
|
||||
} else if (nextParam.type == 'date') {
|
||||
var dateQual = nextParam.value.indexOf('T') == -1 ? 'day' : 'second';
|
||||
if (nextParam.value.substring(0,2) == '>=') {
|
||||
paramLine = '.where(new DateParam("' + nextParam.name + '").afterOrEquals().' + dateQual + '("' + nextParam.value.substring(2) + '"))';
|
||||
paramLine = '.where(new DateClientParam("' + nextParam.name + '").afterOrEquals().' + dateQual + '("' + nextParam.value.substring(2) + '"))';
|
||||
} else if (nextParam.value.substring(0,1) == '>') {
|
||||
paramLine = '.where(new DateParam("' + nextParam.name + '").after().' + dateQual + '("' + nextParam.value.substring(1) + '"))';
|
||||
paramLine = '.where(new DateClientParam("' + nextParam.name + '").after().' + dateQual + '("' + nextParam.value.substring(1) + '"))';
|
||||
} else if (nextParam.value.substring(0,2) == '<=') {
|
||||
paramLine = '.where(new DateParam("' + nextParam.name + '").beforeOrEquals().' + dateQual + '("' + nextParam.value.substring(2) + '"))';
|
||||
paramLine = '.where(new DateClientParam("' + nextParam.name + '").beforeOrEquals().' + dateQual + '("' + nextParam.value.substring(2) + '"))';
|
||||
} else if (nextParam.value.substring(0,1) == '<') {
|
||||
paramLine = '.where(new DateParam("' + nextParam.name + '").before().' + dateQual + '("' + nextParam.value.substring(1) + '"))';
|
||||
paramLine = '.where(new DateClientParam("' + nextParam.name + '").before().' + dateQual + '("' + nextParam.value.substring(1) + '"))';
|
||||
}
|
||||
}
|
||||
if (paramLine != null) {
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
package ca.uhn.fhir.tinder;
|
||||
|
||||
import static org.apache.commons.lang.StringUtils.defaultString;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.ParseException;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
|
@ -25,8 +20,6 @@ import org.apache.maven.project.MavenProject;
|
|||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
|
||||
import ca.uhn.fhir.tinder.model.BaseRootType;
|
||||
import ca.uhn.fhir.tinder.model.Extension;
|
||||
import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet;
|
||||
|
||||
@Mojo(name = "generate-jparest-server", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
|
||||
|
@ -151,7 +144,7 @@ public class TinderJpaRestServerMojo extends AbstractMojo {
|
|||
TinderJpaRestServerMojo mojo = new TinderJpaRestServerMojo();
|
||||
mojo.packageBase = "ca.uhn.test";
|
||||
mojo.baseResourceNames = java.util.Collections.singletonList("observation");
|
||||
mojo.targetDirectory = new File("target/gen");
|
||||
mojo.targetDirectory = new File("target/generated/valuesets");
|
||||
mojo.execute();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ public class SearchParameter {
|
|||
private List<String> myTargetTypes;
|
||||
private String myType;
|
||||
private List<String> myCompositeOf;
|
||||
private List<String> myCompositeTypes;
|
||||
|
||||
public SearchParameter() {
|
||||
|
||||
|
@ -124,4 +125,15 @@ public class SearchParameter {
|
|||
return myCompositeOf;
|
||||
}
|
||||
|
||||
public void setCompositeTypes(List<String> theCompositeTypes) {
|
||||
myCompositeTypes = theCompositeTypes;
|
||||
}
|
||||
|
||||
public List<String> getCompositeTypes() {
|
||||
if (myCompositeTypes == null) {
|
||||
myCompositeTypes = new ArrayList<String>();
|
||||
}
|
||||
return myCompositeTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,13 +14,12 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.tinder.model.AnyChild;
|
||||
import ca.uhn.fhir.tinder.model.BaseElement;
|
||||
import ca.uhn.fhir.tinder.model.BaseRootType;
|
||||
|
@ -261,7 +260,8 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
composite.setDescription(nextCompositeParam.getDescription());
|
||||
composite.setPath(nextCompositeParam.getPath());
|
||||
composite.setType("composite");
|
||||
composite.setCompositeOf(Arrays.asList(part1.getPath(), part2.getPath()));
|
||||
composite.setCompositeOf(Arrays.asList(part1.getName(), part2.getName()));
|
||||
composite.setCompositeTypes(Arrays.asList(WordUtils.capitalize(part1.getType()), WordUtils.capitalize(part2.getType())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public class ${className}ResourceProvider extends JpaResourceProvider<${classNam
|
|||
@Description(shortDefinition="The resource identity")
|
||||
@OptionalParam(name="_id")
|
||||
StringParam theId,
|
||||
#foreach ( $param in $searchParamsWithoutComposite ) #{if}(true) #{end}
|
||||
#foreach ( $param in $searchParams ) #{if}(true) #{end}
|
||||
|
||||
@Description(shortDefinition="${param.description}")
|
||||
#if (${param.type} == 'string' )
|
||||
|
@ -43,16 +43,16 @@ public class ${className}ResourceProvider extends JpaResourceProvider<${classNam
|
|||
DateRangeParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'quantity' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
QuantityDt the${param.nameCapitalized},
|
||||
QuantityAndListParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'number' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
QuantityDt the${param.nameCapitalized},
|
||||
NumberAndListParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'reference' )
|
||||
@OptionalParam(name="${param.name}", targetTypes={ #{foreach}($nextType in ${param.targetTypes}) ${nextType}.class #{if}($foreach.hasNext), #{end} #{end} } )
|
||||
ReferenceParam the${param.nameCapitalized},
|
||||
ReferenceAndListParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'composite' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
ReferenceParam the${param.nameCapitalized},
|
||||
@OptionalParam(name="${param.name}", compositeTypes= { ${param.compositeTypes[0]}Param.class, ${param.compositeTypes[1]}Param.class })
|
||||
CompositeAndListParam<${param.compositeTypes[0]}Param, ${param.compositeTypes[1]}Param> the${param.nameCapitalized},
|
||||
#end
|
||||
#end
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class ${className}ResourceProvider extends JpaResourceProvider<${classNam
|
|||
try {
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
paramMap.add("_id", theId);
|
||||
#foreach ( $param in $searchParamsWithoutComposite )
|
||||
#foreach ( $param in $searchParams )
|
||||
paramMap.add("${param.name}", the${param.nameCapitalized});
|
||||
#end
|
||||
|
||||
|
|
|
@ -60,7 +60,11 @@ public class ${className} extends BaseResource implements IResource {
|
|||
* Path: <b>${param.path}</b><br/>
|
||||
* </p>
|
||||
*/
|
||||
#if( ${param.typeCapitalized} == 'Composite' )
|
||||
public static final CompositeClientParam<${param.compositeTypes[0]}ClientParam, ${param.compositeTypes[1]}ClientParam> ${param.fluentConstantName} = new CompositeClientParam<${param.compositeTypes[0]}ClientParam, ${param.compositeTypes[1]}ClientParam>(${param.constantName});
|
||||
#else
|
||||
public static final ${param.typeCapitalized}ClientParam ${param.fluentConstantName} = new ${param.typeCapitalized}ClientParam(${param.constantName});
|
||||
#end
|
||||
|
||||
#if( ${param.typeCapitalized} == 'Reference' )
|
||||
#foreach ( $include in $param.paths )
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
<dependent-module archiveName="hapi-fhir-base-0.5-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-tester-overlay?includes=**/**&excludes=META-INF/MANIFEST.MF">
|
||||
<dependency-type>consumes</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&excludes=META-INF/MANIFEST.MF">
|
||||
<dependency-type>consumes</dependency-type>
|
||||
</dependent-module>
|
||||
<property name="context-root" value="restful-server-example"/>
|
||||
<property name="java-output-path" value="/restful-server-example/target/classes"/>
|
||||
</wb-module>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<groupId>ca.uhn.hapi.example</groupId>
|
||||
<artifactId>restful-server-example</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.5-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>Sample RESTful Server (HAPI-FHIR)</name>
|
||||
|
@ -17,6 +17,15 @@
|
|||
<version>0.5-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- This dependency is used for the "test page" web app overlay -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>0.5-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- HAPI-FHIR uses Logback for logging support. The logback library is included automatically by Maven as a part of the hapi-fhir-base dependency, but you also need to include a
|
||||
logging library. Logback is used here, but log4j would also be fine. -->
|
||||
<dependency>
|
||||
|
@ -48,6 +57,9 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<!--
|
||||
Tell Maven which Java source version you want to use
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
@ -57,13 +69,33 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
The configuration here tells the WAR plugin to include the test
|
||||
page overlay. You can omit it if you are not using that feature.
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
</overlay>
|
||||
</overlays>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
This plugin is just a part of the HAPI internal build process, you do not
|
||||
need to incude it in your own projects
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
|
Loading…
Reference in New Issue