Switch JPA server to use new include style
This commit is contained in:
parent
7adf48a38a
commit
596dd664f9
|
@ -236,7 +236,7 @@ public class GenericClientExample {
|
|||
.encodedJson()
|
||||
.where(Patient.BIRTHDATE.beforeOrEquals().day("2012-01-22"))
|
||||
.and(Patient.BIRTHDATE.after().day("2011-01-01"))
|
||||
.include(Patient.INCLUDE_MANAGINGORGANIZATION)
|
||||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.sort().ascending(Patient.BIRTHDATE)
|
||||
.sort().descending(Patient.NAME).limitTo(123)
|
||||
.execute();
|
||||
|
|
|
@ -599,6 +599,22 @@ public List<DiagnosticReport> getDiagnosticReport(
|
|||
}
|
||||
//END SNIPPET: pathSpec
|
||||
|
||||
//START SNIPPET: revInclude
|
||||
@Search()
|
||||
public List<DiagnosticReport> getDiagnosticReport(
|
||||
@RequiredParam(name=DiagnosticReport.SP_IDENTIFIER)
|
||||
TokenParam theIdentifier,
|
||||
|
||||
@IncludeParam()
|
||||
Set<Include> theIncludes,
|
||||
|
||||
@IncludeParam(reverse=true)
|
||||
Set<Include> theReverseIncludes
|
||||
) {
|
||||
|
||||
return new ArrayList<DiagnosticReport>(); // populate this
|
||||
}
|
||||
//END SNIPPET: revInclude
|
||||
|
||||
//START SNIPPET: pathSpecSimple
|
||||
@Search()
|
||||
|
|
|
@ -25,29 +25,38 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
|
||||
/**
|
||||
* Method parameter which is used to indicate a parameter that will
|
||||
* be populated with the "_include" values for a search param.
|
||||
* be populated with the "_include" (or "_revinclude") values for a search param.
|
||||
* The parameter annotated with this annotation is used for either "_include"
|
||||
* or "_revinclude", depending on whether {@link #reverse()} has been
|
||||
* set to <code>true</code> (default is <code>false</code>).
|
||||
*
|
||||
* <p>
|
||||
* Only one parameter may be annotated with this annotation, and that
|
||||
* Only up to two parameters may be annotated with this annotation (one each
|
||||
* for <code>reverse=false</code> and <code>reverse=true</code>. That
|
||||
* parameter should be one of the following:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li><code>Collection<PathSpecification></code></li>
|
||||
* <li><code>List<PathSpecification></code></li>
|
||||
* <li><code>Set<PathSpecification></code></li>
|
||||
* <li><code>Collection<Include></code></li>
|
||||
* <li><code>List<Include></code></li>
|
||||
* <li><code>Set<Include></code></li>
|
||||
* </ul>
|
||||
*
|
||||
* @see Include
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.PARAMETER})
|
||||
public @interface IncludeParam {
|
||||
|
||||
/**
|
||||
* Optional parameter, if provided the server will only allow the values
|
||||
* Optional value, if provided the server will only allow the values
|
||||
* within the given set. If an _include parameter is passed to the server
|
||||
* which does not match any allowed values the server will return an error.
|
||||
* <p>
|
||||
* Values for this parameter takew the form that the FHIR specification
|
||||
* Values for this parameter take the form that the FHIR specification
|
||||
* defines for <code>_include</code> values, namely <code>[Resource Name].[path]</code>.
|
||||
* For example: <code>"Patient.link.other"</code>
|
||||
* or <code>"Encounter.partOf"</code>
|
||||
|
@ -69,4 +78,11 @@ public @interface IncludeParam {
|
|||
*/
|
||||
String[] allow() default {};
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), the values
|
||||
* for this parameter correspond to the <code>_revinclude<code> parameter
|
||||
* instead of the <code>_include<code> parameter.
|
||||
*/
|
||||
boolean reverse() default false;
|
||||
|
||||
}
|
||||
|
|
|
@ -65,4 +65,10 @@ public @interface Operation {
|
|||
* </p>
|
||||
*/
|
||||
boolean idempotent() default false;
|
||||
|
||||
/**
|
||||
* This parameter may be used to specify the parts which will be found in the
|
||||
* response to this operation.
|
||||
*/
|
||||
OperationParam[] returnParameters() default {};
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
@ -36,4 +38,10 @@ public @interface OperationParam {
|
|||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* The type of the parameter. This will only have effect on <code>@OperationParam</code>
|
||||
* annotations specified as values for {@link Operation#returnParameters()}
|
||||
*/
|
||||
Class<? extends IBase> type() default IBase.class;
|
||||
|
||||
}
|
||||
|
|
|
@ -1323,6 +1323,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private String myCompartmentName;
|
||||
private CriterionList myCriterion = new CriterionList();
|
||||
private List<Include> myInclude = new ArrayList<Include>();
|
||||
private List<Include> myRevInclude = new ArrayList<Include>();
|
||||
private Integer myParamLimit;
|
||||
private String myResourceId;
|
||||
private String myResourceName;
|
||||
|
@ -1356,6 +1357,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
addParam(params, Constants.PARAM_INCLUDE, next.getValue());
|
||||
}
|
||||
|
||||
for (Include next : myRevInclude) {
|
||||
addParam(params, Constants.PARAM_REVINCLUDE, next.getValue());
|
||||
}
|
||||
|
||||
for (SortInternal next : mySort) {
|
||||
addParam(params, next.getParamName(), next.getParamValue());
|
||||
}
|
||||
|
@ -1444,6 +1449,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQuery revinclude(Include theInclude) {
|
||||
myRevInclude.add(theInclude);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SortInternal implements ISort {
|
||||
|
|
|
@ -26,7 +26,10 @@ import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
|||
|
||||
public interface IQuery extends IClientExecutable<IQuery, Bundle>, IBaseQuery<IQuery> {
|
||||
|
||||
IQuery include(Include theIncludeManagingorganization);
|
||||
/**
|
||||
* Add an "_include" specification
|
||||
*/
|
||||
IQuery include(Include theInclude);
|
||||
|
||||
ISort sort();
|
||||
|
||||
|
@ -43,4 +46,11 @@ public interface IQuery extends IClientExecutable<IQuery, Bundle>, IBaseQuery<IQ
|
|||
|
||||
IQuery withIdAndCompartment(String theResourceId, String theCompartmentName);
|
||||
|
||||
/**
|
||||
* Add a "_revinclude" specification
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
IQuery revinclude(Include theIncludeTarget);
|
||||
|
||||
}
|
||||
|
|
|
@ -43,9 +43,11 @@ class IncludeParameter extends BaseQueryParameter {
|
|||
private Set<String> myAllow;
|
||||
private Class<? extends Collection<Include>> myInstantiableCollectionType;
|
||||
private Class<?> mySpecType;
|
||||
private boolean myReverse;
|
||||
|
||||
public IncludeParameter(IncludeParam theAnnotation, Class<? extends Collection<Include>> theInstantiableCollectionType, Class<?> theSpecType) {
|
||||
myInstantiableCollectionType = theInstantiableCollectionType;
|
||||
myReverse = theAnnotation.reverse();
|
||||
if (theAnnotation.allow().length > 0) {
|
||||
myAllow = new HashSet<String>();
|
||||
for (String next : theAnnotation.allow()) {
|
||||
|
@ -93,7 +95,7 @@ class IncludeParameter extends BaseQueryParameter {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "_include";
|
||||
return myReverse ? "_revinclude" : "_include";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,10 +133,10 @@ class IncludeParameter extends BaseQueryParameter {
|
|||
}
|
||||
|
||||
String value = nextParamList.get(0);
|
||||
if (myAllow != null) {
|
||||
if (myAllow != null && !myAllow.isEmpty()) {
|
||||
if (!myAllow.contains(value)) {
|
||||
if (!myAllow.contains("*")) {
|
||||
String msg = theContext.getLocalizer().getMessage(IncludeParameter.class, "invalidIncludeNameInRequest", value, new TreeSet<String>(myAllow).toString());
|
||||
String msg = theContext.getLocalizer().getMessage(IncludeParameter.class, "invalidIncludeNameInRequest", value, new TreeSet<String>(myAllow).toString(), getName());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ public class Constants {
|
|||
public static final String PARAM_FORMAT = "_format";
|
||||
public static final String PARAM_HISTORY = "_history";
|
||||
public static final String PARAM_INCLUDE = "_include";
|
||||
public static final String PARAM_REVINCLUDE = "_revinclude";
|
||||
public static final String PARAM_NARRATIVE = "_narrative";
|
||||
public static final String PARAM_PAGINGACTION = "_getpages";
|
||||
public static final String PARAM_PAGINGOFFSET = "_getpagesoffset";
|
||||
|
|
|
@ -14,7 +14,7 @@ ca.uhn.fhir.rest.client.RestfulClientFactory.wrongVersionInConformance=The serve
|
|||
|
||||
ca.uhn.fhir.rest.method.OperationMethodBinding.methodNotSupported=HTTP Method {0} is not allowed for this operation. Allowed method(s): {1}
|
||||
ca.uhn.fhir.rest.method.OperationParamBinder.urlParamNotPrimitive=Can not invoke operation {0} using HTTP GET because parameter {1} is not a primitive datatype
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid _include parameter value: "{0}". Valid values are: {1}
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid {2} parameter value: "{0}". Valid values are: {1}
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.orIncludeInRequest='OR' query parameters (values containing ',') are not supported in _include parameters
|
||||
|
||||
ca.uhn.fhir.rest.method.SearchMethodBinding.invalidSpecialParamName=Method [{0}] in provider [{1}] contains search parameter annotated to use name [{2}] - This name is reserved according to the FHIR specification and can not be used as a search parameter name.
|
||||
|
@ -36,7 +36,7 @@ ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionEntryHasInvalidVerb=Transaction
|
|||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
|
|
|
@ -125,9 +125,9 @@ import ca.uhn.fhir.util.FhirTerser;
|
|||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements IFhirResourceDao<T> {
|
||||
public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirDao implements IFhirResourceDao<T> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDao.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirResourceDao.class);
|
||||
|
||||
@PersistenceContext()
|
||||
private EntityManager myEntityManager;
|
||||
|
@ -703,10 +703,10 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
if (isNotBlank(theResource.getId().getIdPart())) {
|
||||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
if (theResource.getId().isIdPartValidLong()) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
||||
}
|
||||
} else {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getId().getIdPart()));
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getId().getIdPart()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,7 +740,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
if (entity.getForcedId() != null) {
|
||||
try {
|
||||
translateForcedIdToPid(theResource.getId());
|
||||
throw new UnprocessableEntityException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "duplicateCreateForcedId", theResource.getId().getIdPart()));
|
||||
throw new UnprocessableEntityException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "duplicateCreateForcedId", theResource.getId().getIdPart()));
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// good, this ID doesn't exist so we can create it
|
||||
}
|
||||
|
@ -963,7 +963,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
||||
if (resource.isEmpty()) {
|
||||
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "unableToDeleteNotFound", theUrl));
|
||||
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "unableToDeleteNotFound", theUrl));
|
||||
} else if (resource.size() > 1) {
|
||||
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resource.size()));
|
||||
}
|
||||
|
@ -1367,15 +1367,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
for (Include next : theParams.getIncludes()) {
|
||||
for (IResource nextResource : resources) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(nextResource);
|
||||
List<Object> values;
|
||||
if ("*".equals(next.getValue())) {
|
||||
values = new ArrayList<Object>();
|
||||
values.addAll(t.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class));
|
||||
} else if (next.getValue().startsWith(def.getName() + ".")) {
|
||||
values = t.getValues(nextResource, next.getValue());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
List<Object> values = getIncludeValues(t, next, nextResource, def);
|
||||
|
||||
for (Object object : values) {
|
||||
if (object == null) {
|
||||
|
@ -1420,6 +1412,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1439,6 +1432,10 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return search(Collections.singletonMap(theParameterName, theValue));
|
||||
}
|
||||
|
||||
|
||||
protected abstract List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IResource theResource, RuntimeResourceDefinition theResourceDef);
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Long> searchForIds(Map<String, IQueryParameterType> theParams) {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
|
@ -1682,7 +1679,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
entity = readEntityLatestVersion(resourceId);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
if (Character.isDigit(theResource.getId().getIdPart().charAt(0))) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
||||
}
|
||||
return doCreate(theResource, null, true);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirResourceDaoDstu1<T extends IResource> extends BaseFhirResourceDao<T> {
|
||||
|
||||
protected List<Object> getIncludeValues(FhirTerser t, Include next, IResource nextResource, RuntimeResourceDefinition def) {
|
||||
List<Object> values;
|
||||
if ("*".equals(next.getValue())) {
|
||||
values = new ArrayList<Object>();
|
||||
values.addAll(t.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class));
|
||||
} else if (next.getValue().startsWith(def.getName() + ".")) {
|
||||
values = t.getValues(nextResource, next.getValue());
|
||||
} else {
|
||||
values = Collections.emptyList();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirResourceDaoDstu2<T extends IResource> extends BaseFhirResourceDao<T> {
|
||||
|
||||
protected List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IResource theResource, RuntimeResourceDefinition theResourceDef) {
|
||||
List<Object> values;
|
||||
if ("*".equals(theInclude.getValue())) {
|
||||
values = new ArrayList<Object>();
|
||||
values.addAll(theTerser.getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class));
|
||||
} else if (theInclude.getValue().startsWith(theResourceDef.getName() + ":")) {
|
||||
values = new ArrayList<Object>();
|
||||
RuntimeSearchParam sp = theResourceDef.getSearchParam(theInclude.getValue().substring(theInclude.getValue().indexOf(':')+1));
|
||||
StringTokenizer tok = new StringTokenizer(sp.getPath(), "|");
|
||||
while (tok.hasMoreElements()) {
|
||||
String nextPath = tok.nextToken().trim();
|
||||
values.addAll(theTerser.getValues(theResource, nextPath));
|
||||
}
|
||||
} else {
|
||||
values = Collections.emptyList();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
|
@ -96,24 +97,48 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
}
|
||||
}
|
||||
|
||||
@Operation(name="$meta", idempotent=true)
|
||||
public MetaDt meta() {
|
||||
return getDao().metaGetOperation();
|
||||
//@formatter:off
|
||||
@Operation(name="$meta", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
})
|
||||
//@formatter:on
|
||||
public Parameters meta() {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation());
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Operation(name="$meta", idempotent=true)
|
||||
public MetaDt meta(@IdParam IdDt theId) {
|
||||
return getDao().metaGetOperation(theId);
|
||||
//@formatter:off
|
||||
@Operation(name="$meta", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
})
|
||||
//@formatter:on
|
||||
public Parameters meta(@IdParam IdDt theId) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation(theId));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Operation(name="$meta-add", idempotent=true)
|
||||
public MetaDt metaAdd(@IdParam IdDt theId, @OperationParam(name="meta") MetaDt theMeta) {
|
||||
return getDao().metaAddOperation(theId, theMeta);
|
||||
//@formatter:off
|
||||
@Operation(name="$meta-add", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
})
|
||||
//@formatter:on
|
||||
public Parameters metaAdd(@IdParam IdDt theId, @OperationParam(name="meta") MetaDt theMeta) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaAddOperation(theId, theMeta));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Operation(name="$meta-delete", idempotent=true)
|
||||
public MetaDt metaDelete(@IdParam IdDt theId, @OperationParam(name="meta") MetaDt theMeta) {
|
||||
return getDao().metaDeleteOperation(theId, theMeta);
|
||||
//@formatter:off
|
||||
@Operation(name="$meta-delete", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
})
|
||||
//@formatter:on
|
||||
public Parameters metaDelete(@IdParam IdDt theId, @OperationParam(name="meta") MetaDt theMeta) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaDeleteOperation(theId, theMeta));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,15 +24,23 @@ import javax.servlet.http.HttpServletRequest;
|
|||
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
|
||||
public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
|
||||
|
||||
@Operation(name="$meta", idempotent=true)
|
||||
public MetaDt operation() {
|
||||
return getDao().metaGetOperation();
|
||||
//@formatter:off
|
||||
@Operation(name="$meta", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
})
|
||||
//@formatter:on
|
||||
public Parameters operation() {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation());
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Transaction
|
||||
|
|
|
@ -1399,7 +1399,7 @@ public class FhirResourceDaoDstu2Test {
|
|||
// Named include
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Patient.SP_FAMILY, new StringDt("Tester_testSearchWithIncludes_P1"));
|
||||
params.addInclude(Patient.INCLUDE_MANAGINGORGANIZATION);
|
||||
params.addInclude(Patient.INCLUDE_ORGANIZATION);
|
||||
IBundleProvider search = ourPatientDao.search(params);
|
||||
List<IResource> patients = toList(search);
|
||||
assertEquals(2, patients.size());
|
||||
|
@ -1410,7 +1410,7 @@ public class FhirResourceDaoDstu2Test {
|
|||
// Named include with parent
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Patient.SP_FAMILY, new StringDt("Tester_testSearchWithIncludes_P1"));
|
||||
params.addInclude(Patient.INCLUDE_MANAGINGORGANIZATION);
|
||||
params.addInclude(Patient.INCLUDE_ORGANIZATION);
|
||||
params.addInclude(Organization.INCLUDE_PARTOF);
|
||||
IBundleProvider search = ourPatientDao.search(params);
|
||||
List<IResource> patients = toList(search);
|
||||
|
@ -1470,7 +1470,7 @@ public class FhirResourceDaoDstu2Test {
|
|||
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Patient.SP_FAMILY, new StringDt("Tester_testSearchWithIncludesThatHaveTextId_P1"));
|
||||
params.addInclude(Patient.INCLUDE_MANAGINGORGANIZATION);
|
||||
params.addInclude(Patient.INCLUDE_ORGANIZATION);
|
||||
IBundleProvider search = ourPatientDao.search(params);
|
||||
List<IResource> patients = toList(search);
|
||||
assertEquals(2, patients.size());
|
||||
|
|
|
@ -284,7 +284,7 @@ public class ResourceProviderDstu2Test {
|
|||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
|
||||
.include(Patient.INCLUDE_MANAGINGORGANIZATION)
|
||||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
@ -443,7 +443,7 @@ public class ResourceProviderDstu2Test {
|
|||
Bundle res = ourClient.search()
|
||||
.forResource(Encounter.class)
|
||||
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
|
||||
.include(Encounter.INCLUDE_LOCATION_LOCATION)
|
||||
.include(Encounter.INCLUDE_LOCATION)
|
||||
.include(Location.INCLUDE_PARTOF)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
|
|
@ -44,6 +44,7 @@ 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;
|
||||
import ca.uhn.fhir.model.dstu.resource.Provenance;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
@ -668,6 +669,34 @@ public class GenericClientTest {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testSearchWithReverseInclude() 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 = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.encodedJson()
|
||||
.revinclude(Provenance.INCLUDE_TARGET)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(
|
||||
"http://example.com/fhir/Patient?_revinclude=Provenance.target&_format=json",
|
||||
capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
|
||||
|
|
|
@ -60,6 +60,35 @@ public class GenericClientTestDstu2 {
|
|||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testSearchWithReverseInclude() 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 = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.encodedJson()
|
||||
.revinclude(ca.uhn.fhir.model.dstu2.resource.Provenance.INCLUDE_TARGET)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(
|
||||
"http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json",
|
||||
capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
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.hamcrest.Matchers;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class IncludeAndRevincludeParameterTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IncludeAndRevincludeParameterTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static FhirContext ourCtx;
|
||||
private static Set<Include> ourIncludes;
|
||||
private static Set<Include> ourReverseIncludes;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourIncludes = null;
|
||||
ourReverseIncludes = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoIncludes() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=normalInclude");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(ourIncludes, hasSize(0));
|
||||
assertThat(ourReverseIncludes, hasSize(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithBoth() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=normalInclude&_include=A.a&_include=B.b&_revinclude=C.c&_revinclude=D.d");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(ourIncludes, hasSize(2));
|
||||
assertThat(ourReverseIncludes, hasSize(2));
|
||||
assertThat(ourIncludes, containsInAnyOrder(new Include("A.a"), new Include("B.b")));
|
||||
assertThat(ourReverseIncludes, containsInAnyOrder(new Include("C.c"), new Include("D.d")));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
|
||||
ourCtx = new FhirContext();
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setFhirContext(ourCtx);
|
||||
servlet.setResourceProviders(new DummyPatientResourceProvider());
|
||||
servlet.setBundleInclusionRule(BundleInclusionRule.BASED_ON_RESOURCE_PRESENCE);
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Search(queryName = "normalInclude")
|
||||
public List<Patient> normalInclude(
|
||||
@IncludeParam() Set<Include> theIncludes,
|
||||
@IncludeParam(reverse=true) Set<Include> theRevincludes
|
||||
) {
|
||||
ourIncludes = theIncludes;
|
||||
ourReverseIncludes = theRevincludes;
|
||||
return new ArrayList<Patient>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -49,10 +49,10 @@ import ca.uhn.fhir.util.PortUtil;
|
|||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class IncludeTest {
|
||||
public class IncludeDstu2Test {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IncludeTest.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IncludeDstu2Test.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static FhirContext ourCtx;
|
|
@ -42,7 +42,6 @@ public class ValueSetGenerator {
|
|||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetGenerator.class);
|
||||
private List<ValueSetFileDefinition> myResourceValueSetFiles;
|
||||
private Set<ValueSetTm> myMarkedValueSets = new HashSet<ValueSetTm>();
|
||||
|
||||
private Map<String, ValueSetTm> myValueSets = new HashMap<String, ValueSetTm>();
|
||||
private int myValueSetCount;
|
||||
private int myConceptCount;
|
||||
|
|
|
@ -56,7 +56,7 @@ public abstract class BaseRootType extends BaseElement {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public void addSearchParameter(SearchParameter theParam) {
|
||||
public void addSearchParameter(String theVersion, SearchParameter theParam) {
|
||||
getSearchParameters();
|
||||
mySearchParameters.add(theParam);
|
||||
|
||||
|
|
|
@ -9,16 +9,21 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
public class SearchParameter {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParameter.class);
|
||||
private List<String> myCompositeOf;
|
||||
private List<String> myCompositeTypes;
|
||||
private String myDescription;
|
||||
private String myName;
|
||||
private String myPath;
|
||||
private String myResourceName;
|
||||
private List<String> myTargetTypes;
|
||||
private String myType;
|
||||
private List<String> myCompositeOf;
|
||||
private List<String> myCompositeTypes;
|
||||
|
||||
public SearchParameter() {
|
||||
private String myVersion;
|
||||
|
||||
public SearchParameter(String theVersion, String theResourceName) {
|
||||
this.myVersion = theVersion;
|
||||
this.myResourceName = theResourceName;
|
||||
}
|
||||
|
||||
public List<String> getCompositeOf() {
|
||||
|
@ -65,9 +70,18 @@ public class SearchParameter {
|
|||
|
||||
public List<Include> getPaths() {
|
||||
ArrayList<Include> retVal = new ArrayList<Include>();
|
||||
if ("dstu".equals(myVersion)) {
|
||||
for (String next : getPath().split("\\s*\\|\\s*")) {
|
||||
retVal.add(new Include(next));
|
||||
}
|
||||
} else {
|
||||
if (myType == null) {
|
||||
ourLog.warn("Search parameter {} has no type", myName);
|
||||
}
|
||||
if ("resource".equals(myType) || "reference".equals(myType)) {
|
||||
retVal.add(new Include(myResourceName + ":" + myName));
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -126,11 +140,8 @@ public class SearchParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myPath == null) ? 0 : myPath.hashCode());
|
||||
return result;
|
||||
public int compareTo(Include theO) {
|
||||
return myPath.compareTo(theO.myPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,7 +164,8 @@ public class SearchParameter {
|
|||
public String getIncludeName() {
|
||||
String retVal = myPath;
|
||||
retVal = retVal.substring(retVal.indexOf('.') + 1);
|
||||
retVal = retVal.toUpperCase().replace('.', '_').replace("[X]", "");
|
||||
retVal = retVal.substring(retVal.indexOf(':') + 1);
|
||||
retVal = retVal.toUpperCase().replace('.', '_').replace("[X]", "").replace("-", "_");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -164,8 +176,11 @@ public class SearchParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Include theO) {
|
||||
return myPath.compareTo(theO.myPath);
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myPath == null) ? 0 : myPath.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
|
||||
for (int j = 1; j < rows.getLength(); j++) {
|
||||
Element nextRow = (Element) rows.item(j);
|
||||
SearchParameter sp = new SearchParameter();
|
||||
SearchParameter sp = new SearchParameter(getVersion(), theResource.getName());
|
||||
|
||||
sp.setName(cellValue(nextRow, colName));
|
||||
sp.setDescription(cellValue(nextRow, colDesc));
|
||||
|
@ -227,7 +227,7 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
if (sp.getType().equals("composite")) {
|
||||
compositeParams.add(sp);
|
||||
} else {
|
||||
theResource.addSearchParameter(sp);
|
||||
theResource.addSearchParameter(getVersion(), sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,8 +290,8 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
|
||||
for (SearchParameter part1 : compositeOf.get(0)) {
|
||||
for (SearchParameter part2 : compositeOf.get(1)) {
|
||||
SearchParameter composite = new SearchParameter();
|
||||
theResource.addSearchParameter(composite);
|
||||
SearchParameter composite = new SearchParameter(getVersion(), theResource.getName());
|
||||
theResource.addSearchParameter(getVersion(), composite);
|
||||
composite.setName(part1.getName() + "-" + part2.getName());
|
||||
composite.setDescription(nextCompositeParam.getDescription());
|
||||
composite.setPath(nextCompositeParam.getPath());
|
||||
|
|
|
@ -145,7 +145,7 @@ public class ProfileParser extends BaseStructureParser {
|
|||
}
|
||||
|
||||
for (StructureSearchParam nextParam : nextStructure.getSearchParam()) {
|
||||
SearchParameter param = new SearchParameter();
|
||||
SearchParameter param = new SearchParameter(getVersion(), retVal.getName());
|
||||
param.setName(nextParam.getName().getValue());
|
||||
|
||||
String path = defaultString(nextParam.getXpath().getValue());
|
||||
|
@ -154,7 +154,7 @@ public class ProfileParser extends BaseStructureParser {
|
|||
|
||||
param.setType(nextParam.getType().getValue());
|
||||
param.setDescription(nextParam.getDocumentation().getValue());
|
||||
retVal.addSearchParameter(param);
|
||||
retVal.addSearchParameter(getVersion(), param);
|
||||
}
|
||||
|
||||
addResource(retVal);
|
||||
|
|
|
@ -66,9 +66,15 @@ public class ${className}ResourceProvider extends JpaResourceProvider${versionCa
|
|||
@IncludeParam(allow= {
|
||||
#foreach ( $param in $searchParamsReference )
|
||||
#set ( $haveMore = $foreach.hasNext )
|
||||
#if ( $version == 'dstu' )
|
||||
#foreach ( $include in $param.paths )
|
||||
"${include.path}" #{if}($foreach.hasNext || $haveMore), #{end}
|
||||
#end
|
||||
#else
|
||||
#foreach ( $include in $includes )
|
||||
"${include.path}" #{if}($foreach.hasNext || $haveMore), #{end}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#{if}($searchParamsReference.empty == false), #{end}"*"
|
||||
})
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</util:list>
|
||||
|
||||
#foreach ( $res in $resources )
|
||||
<bean id="my${res.name}Dao${versionCapitalized}" class="ca.uhn.fhir.jpa.dao.FhirResourceDao">
|
||||
<bean id="my${res.name}Dao${versionCapitalized}" class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">
|
||||
<property name="resourceType" value="ca.uhn.fhir.model.${version}.resource.${res.declaringClassNameComplete}"/>
|
||||
<property name="context" ref="myFhirContext${versionCapitalized}"/>
|
||||
</bean>
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
<action type="fix" issue="128">
|
||||
Fix regression in 0.9 - Server responds with an HTTP 500 and a NullPointerException instead of an HTTP 400 and a useful error message if the client requests an unknown resource type
|
||||
</action>
|
||||
<action type="add">
|
||||
Add support for
|
||||
<![CDATA[<code>_revinclude</code>]]>
|
||||
parameter in client, server, and JPA.
|
||||
</action>
|
||||
<action type="add">
|
||||
Include constants on resources (such as
|
||||
<![CDATA[<code>Observation.INCLUDE_VALUE_STRING</code>]]>)
|
||||
have been switched in the DSTU2 structures to use
|
||||
the new syntax required in DSTU2: [resource name]:[search param NAME]
|
||||
insead of the DSTU1 style [resource name].[search param PATH]
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.9" date="2015-Mar-14">
|
||||
<action type="add">
|
||||
|
|
|
@ -917,6 +917,22 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Reverse Resource Includes (_revinclude)">
|
||||
|
||||
<p>
|
||||
To add support for reverse includes (via the <code>_revinclude</code> parameter),
|
||||
use the same format as with the <code>_include</code> parameter (shown above)
|
||||
but add <code>reverse=true</code> to the <code>@IncludeParam</code>
|
||||
annotation, as shown below.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="revInclude" />
|
||||
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Named Queries (_query)">
|
||||
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue