Parameter type cleanup from connectathon
This commit is contained in:
parent
5701572e08
commit
1fecb8ad76
|
@ -10,6 +10,16 @@
|
|||
<action type="add">
|
||||
Documentation update, thanks to Suranga Nath Kasthurirathne of the OpenMRS project.
|
||||
</action>
|
||||
<action type="fix">
|
||||
Server implementation was not correctly figuring out its own FHIR Base URL when deployed
|
||||
on Amazon Web Service server. Thanks to Jeffrey Ting and Bill De Beaubien of
|
||||
Systems Made Simple for their help in figuring out this issue!
|
||||
</action>
|
||||
<action type="fix">
|
||||
XML Parser failed to encode fields with both a resource reference child and
|
||||
a primitive type child. Thanks to Jeffrey Ting and Bill De Beaubien of
|
||||
Systems Made Simple for their help in figuring out this issue!
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.6" date="2014-Sep-08" description="This release brings a number of new features and bug fixes!">
|
||||
<!--
|
||||
|
|
|
@ -172,12 +172,14 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
break;
|
||||
|
||||
case UPDATE:
|
||||
if (response.getCreated() == null || Boolean.FALSE.equals(response.getCreated())) {
|
||||
if (response == null || response.getCreated() == null || Boolean.FALSE.equals(response.getCreated())) {
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
} else {
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
}
|
||||
addLocationHeader(theRequest, servletResponse, response);
|
||||
if (response != null && response.getId() != null) {
|
||||
addLocationHeader(theRequest, servletResponse, response);
|
||||
}
|
||||
break;
|
||||
|
||||
case VALIDATE:
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -46,6 +47,8 @@ public abstract class BaseAndListParam<T extends IQueryParameterOr<?>> implement
|
|||
}
|
||||
}
|
||||
|
||||
public abstract SearchParamTypeEnum getSearchParamType();
|
||||
|
||||
abstract T newInstance();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -38,6 +39,11 @@ public class CompositeAndListParam<A extends IQueryParameterType, B extends IQue
|
|||
CompositeOrListParam<A,B> newInstance() {
|
||||
return new CompositeOrListParam<A,B>(myLeftType, myRightType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.COMPOSITE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -28,4 +30,9 @@ public class DateAndListParam extends BaseAndListParam<DateOrListParam> {
|
|||
return new DateOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.DATE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -27,5 +29,10 @@ public class NumberAndListParam extends BaseAndListParam<NumberOrListParam> {
|
|||
NumberOrListParam newInstance() {
|
||||
return new NumberOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.NUMBER;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -28,4 +30,9 @@ public class QuantityAndListParam extends BaseAndListParam<QuantityOrListParam>
|
|||
return new QuantityOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.QUANTITY;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -28,4 +30,10 @@ public class ReferenceAndListParam extends BaseAndListParam<ReferenceOrListParam
|
|||
return new ReferenceOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.REFERENCE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -28,4 +30,9 @@ public class StringAndListParam extends BaseAndListParam<StringOrListParam> {
|
|||
return new StringOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.STRING;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -28,4 +30,10 @@ public class TokenAndListParam extends BaseAndListParam<TokenOrListParam> {
|
|||
return new TokenOrListParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchParamTypeEnum getSearchParamType() {
|
||||
return SearchParamTypeEnum.TOKEN;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -951,6 +951,8 @@ public class RestfulServer extends HttpServlet {
|
|||
if (theServer.getPagingProvider() == null) {
|
||||
numToReturn = theResult.size();
|
||||
resourceList = theResult.getResources(0, numToReturn);
|
||||
validateResourceListNotNull(resourceList);
|
||||
|
||||
} else {
|
||||
IPagingProvider pagingProvider = theServer.getPagingProvider();
|
||||
if (theLimit == null) {
|
||||
|
@ -961,6 +963,7 @@ public class RestfulServer extends HttpServlet {
|
|||
|
||||
numToReturn = Math.min(numToReturn, theResult.size() - theOffset);
|
||||
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
|
||||
validateResourceListNotNull(resourceList);
|
||||
|
||||
if (theSearchId != null) {
|
||||
searchId = theSearchId;
|
||||
|
@ -1012,6 +1015,12 @@ public class RestfulServer extends HttpServlet {
|
|||
return bundle;
|
||||
}
|
||||
|
||||
private static void validateResourceListNotNull(List<IResource> theResourceList) {
|
||||
if (theResourceList == null) {
|
||||
throw new InternalErrorException("IBundleProvider returned a null list of resources - This is not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
public static Bundle createBundleFromResourceList(FhirContext theContext, String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.getAuthorName().setValue(theAuthor);
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.server;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.param.BaseAndListParam;
|
||||
|
@ -39,7 +39,7 @@ import ca.uhn.fhir.rest.param.StringOrListParam;
|
|||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
|
||||
public class SearchParameterMap extends HashMap<String, BaseAndListParam<?>> {
|
||||
public class SearchParameterMap extends LinkedHashMap<String, BaseAndListParam<?>> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
|
|
@ -20,41 +20,41 @@ package ca.uhn.fhir.util;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides server ports
|
||||
*/
|
||||
public class PortUtil {
|
||||
|
||||
private static List<Integer> ourPorts = new ArrayList<Integer>();
|
||||
|
||||
/**
|
||||
* This is really only used for unit tests but is included in the library so it can be reused across modules. Use with caution.
|
||||
*/
|
||||
public static int findFreePort() {
|
||||
ServerSocket server;
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
int port = server.getLocalPort();
|
||||
ourPorts.add(port);
|
||||
server.close();
|
||||
Thread.sleep(500);
|
||||
return port;
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Integer> list() {
|
||||
return ourPorts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides server ports
|
||||
*/
|
||||
public class PortUtil {
|
||||
|
||||
private static List<Integer> ourPorts = new ArrayList<Integer>();
|
||||
|
||||
/**
|
||||
* This is really only used for unit tests but is included in the library so it can be reused across modules. Use with caution.
|
||||
*/
|
||||
public static int findFreePort() {
|
||||
ServerSocket server;
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
int port = server.getLocalPort();
|
||||
ourPorts.add(port);
|
||||
server.close();
|
||||
Thread.sleep(500);
|
||||
return port;
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Integer> list() {
|
||||
return ourPorts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import ca.uhn.fhir.util.ElementUtil;
|
|||
|
||||
@ResourceDef(name="Patient")
|
||||
public class MyObservationWithExtensions extends Patient {
|
||||
|
||||
|
||||
@Extension(url = "urn:patientext:att", definedLocally = false, isModifier = false)
|
||||
@Child(name = "extAtt", order = 0)
|
||||
private AttachmentDt myExtAtt;
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.model.dstu.resource.DiagnosticOrder;
|
|||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
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.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
|
@ -279,6 +280,21 @@ public class UpdateTest {
|
|||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWithNoReturn() throws Exception {
|
||||
|
||||
Organization patient = new Organization();
|
||||
patient.addIdentifier().setValue("002");
|
||||
|
||||
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Organization/001");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
CloseableHttpResponse response = ourClient.execute(httpPost);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
response.close();
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
|
@ -295,7 +311,7 @@ public class UpdateTest {
|
|||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider, ourReportProvider, new ObservationProvider());
|
||||
servlet.setResourceProviders(patientProvider, ourReportProvider, new ObservationProvider(), new OrganizationResourceProvider());
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
|
@ -308,6 +324,23 @@ public class UpdateTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
public static class OrganizationResourceProvider implements IResourceProvider
|
||||
{
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Organization.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam IdDt theId, @ResourceParam Organization theOrganization) {
|
||||
return new MethodOutcome();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DiagnosticReportProvider implements IResourceProvider {
|
||||
private TagList myLastTags;
|
||||
|
||||
|
|
|
@ -374,17 +374,6 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return entity;
|
||||
}
|
||||
|
||||
private void validateGivenIdIsAppropriateToRetrieveResource(IdDt theId, BaseHasResource entity) {
|
||||
if (entity.getForcedId() != null) {
|
||||
if (theId.isIdPartValidLong()) {
|
||||
// This means that the resource with the given numeric ID exists, but it has a "forced ID", meaning that
|
||||
// as far as the outside world is concerned, the given ID doesn't exist (it's just an internal pointer to the
|
||||
// forced ID)
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(IdDt theId, String theScheme, String theTerm) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -564,34 +553,6 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders, List<Predicate> thePredicates) {
|
||||
if (theSort == null || isBlank(theSort.getParamName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(myResourceType);
|
||||
RuntimeSearchParam param = resourceDef.getSearchParam(theSort.getParamName());
|
||||
if (param == null) {
|
||||
throw new InvalidRequestException("Unknown sort parameter '" + theSort.getParamName() + "'");
|
||||
}
|
||||
|
||||
String joinAttrName = "myParamsString";
|
||||
String sortAttrName = "myValueExact";
|
||||
|
||||
switch (param.getParamType()) {
|
||||
case STRING: {
|
||||
From<?, ?> stringJoin = theFrom.join(joinAttrName, JoinType.LEFT);
|
||||
Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName());
|
||||
Predicate pn = theBuilder.isNull(stringJoin.get("myParamName"));
|
||||
thePredicates.add(theBuilder.or(p, pn));
|
||||
theOrders.add(theBuilder.asc(stringJoin.get(sortAttrName)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider search(String theParameterName, IQueryParameterType theValue) {
|
||||
return search(Collections.singletonMap(theParameterName, theValue));
|
||||
|
@ -904,6 +865,51 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return found;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateLanguage(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
if (theList.size() > 1) {
|
||||
throw new InvalidRequestException("Language parameter can not have more than one AND value, found " + theList.size());
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.select(from.get("myId").as(Long.class));
|
||||
|
||||
Set<String> values = new HashSet<String>();
|
||||
for (IQueryParameterType next : theList.get(0)) {
|
||||
if (next instanceof StringParam) {
|
||||
String nextValue = ((StringParam) next).getValue();
|
||||
if (isBlank(nextValue)) {
|
||||
continue;
|
||||
}
|
||||
values.add(nextValue);
|
||||
} else {
|
||||
throw new InternalErrorException("Lanugage parameter must be of type " + StringParam.class.getCanonicalName() + " - Got " + next.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
if (values.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
Predicate typePredicate = builder.equal(from.get("myResourceType"), myResourceName);
|
||||
Predicate langPredicate = from.get("myLanguage").as(String.class).in(values);
|
||||
Predicate masterCodePredicate = builder.and(typePredicate, langPredicate);
|
||||
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myId").in(thePids));
|
||||
cq.where(builder.and(masterCodePredicate, inPids));
|
||||
} else {
|
||||
cq.where(masterCodePredicate);
|
||||
}
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
|
@ -1203,51 +1209,6 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateLanguage(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
if (theList.size() > 1) {
|
||||
throw new InvalidRequestException("Language parameter can not have more than one AND value, found " + theList.size());
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.select(from.get("myId").as(Long.class));
|
||||
|
||||
Set<String> values = new HashSet<String>();
|
||||
for (IQueryParameterType next : theList.get(0)) {
|
||||
if (next instanceof StringParam) {
|
||||
String nextValue = ((StringParam) next).getValue();
|
||||
if (isBlank(nextValue)) {
|
||||
continue;
|
||||
}
|
||||
values.add(nextValue);
|
||||
} else {
|
||||
throw new InternalErrorException("Lanugage parameter must be of type " + StringParam.class.getCanonicalName() + " - Got " + next.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
if (values.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
Predicate typePredicate = builder.equal(from.get("myResourceType"), myResourceName);
|
||||
Predicate langPredicate = from.get("myLanguage").as(String.class).in(values);
|
||||
Predicate masterCodePredicate = builder.and(typePredicate, langPredicate);
|
||||
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myId").in(thePids));
|
||||
cq.where(builder.and(masterCodePredicate, inPids));
|
||||
} else {
|
||||
cq.where(masterCodePredicate);
|
||||
}
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
|
@ -1410,6 +1371,34 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return singleCode;
|
||||
}
|
||||
|
||||
private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders, List<Predicate> thePredicates) {
|
||||
if (theSort == null || isBlank(theSort.getParamName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(myResourceType);
|
||||
RuntimeSearchParam param = resourceDef.getSearchParam(theSort.getParamName());
|
||||
if (param == null) {
|
||||
throw new InvalidRequestException("Unknown sort parameter '" + theSort.getParamName() + "'");
|
||||
}
|
||||
|
||||
String joinAttrName = "myParamsString";
|
||||
String sortAttrName = "myValueExact";
|
||||
|
||||
switch (param.getParamType()) {
|
||||
case STRING: {
|
||||
From<?, ?> stringJoin = theFrom.join(joinAttrName, JoinType.LEFT);
|
||||
Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName());
|
||||
Predicate pn = theBuilder.isNull(stringJoin.get("myParamName"));
|
||||
thePredicates.add(theBuilder.or(p, pn));
|
||||
theOrders.add(theBuilder.asc(stringJoin.get(sortAttrName)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
}
|
||||
|
||||
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IResource> theResourceListToPopulate) {
|
||||
if (theIncludePids.isEmpty()) {
|
||||
return;
|
||||
|
@ -1497,6 +1486,17 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
return qp;
|
||||
}
|
||||
|
||||
private void validateGivenIdIsAppropriateToRetrieveResource(IdDt theId, BaseHasResource entity) {
|
||||
if (entity.getForcedId() != null) {
|
||||
if (theId.isIdPartValidLong()) {
|
||||
// This means that the resource with the given numeric ID exists, but it has a "forced ID", meaning that
|
||||
// as far as the outside world is concerned, the given ID doesn't exist (it's just an internal pointer to the
|
||||
// forced ID)
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateResourceType(BaseHasResource entity) {
|
||||
if (!myResourceName.equals(entity.getResourceType())) {
|
||||
throw new ResourceNotFoundException("Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
|
||||
|
|
|
@ -121,12 +121,6 @@
|
|||
<version>${jetty_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${jetty_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
|
|
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.rest.annotation.Read;
|
|||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -106,13 +107,8 @@ public class PatientResourceProvider implements IResourceProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* The "@Search" annotation indicates that this method supports the search operation. You may have many different method annotated with this annotation, to support many different search criteria.
|
||||
* This example searches by family name.
|
||||
*
|
||||
* @param theIdentifier
|
||||
* This operation takes one parameter which is the search criteria. It is annotated with the "@Required" annotation. This annotation takes one argument, a string containing the name of
|
||||
* the search criteria. The datatype here is StringDt, but there are other possible parameter types depending on the specific search criteria.
|
||||
* @return This method returns a list of Patients. This list may contain multiple matching resources, or it may also be empty.
|
||||
* The "@Create" annotation indicates that this method implements "create=type", which adds a
|
||||
* new instance of a resource to the server.
|
||||
*/
|
||||
@Create()
|
||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient) {
|
||||
|
@ -217,7 +213,8 @@ public class PatientResourceProvider implements IResourceProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* The "@Update" annotation indicates that this method supports replacing an existing resource (by ID) with a new instance of that resource.
|
||||
* The "@Update" annotation indicates that this method supports replacing an existing
|
||||
* resource (by ID) with a new instance of that resource.
|
||||
*
|
||||
* @param theId
|
||||
* This is the ID of the patient to update
|
||||
|
@ -225,7 +222,7 @@ public class PatientResourceProvider implements IResourceProvider {
|
|||
* This is the actual resource to save
|
||||
* @return This method returns a "MethodOutcome"
|
||||
*/
|
||||
@Create()
|
||||
@Update()
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
|
||||
validateResource(thePatient);
|
||||
|
||||
|
|
Loading…
Reference in New Issue