JPA server now correctly suppresses contents of deleted resources

in history
This commit is contained in:
jamesagnew 2015-09-12 09:45:12 -04:00
parent e2bc9336f9
commit 48ee2cbee8
9 changed files with 381 additions and 179 deletions

View File

@ -19,8 +19,7 @@ package ca.uhn.fhir.model.api;
* limitations under the License. * limitations under the License.
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,7 +34,6 @@ import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.primitive.DecimalDt; import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum; import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@ -74,6 +72,8 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<InstantDt> DELETED_AT = new ResourceMetadataKeyEnum<InstantDt>("DELETED_AT") { public static final ResourceMetadataKeyEnum<InstantDt> DELETED_AT = new ResourceMetadataKeyEnum<InstantDt>("DELETED_AT") {
private static final long serialVersionUID = 1L;
@Override @Override
public InstantDt get(IResource theResource) { public InstantDt get(IResource theResource) {
return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), DELETED_AT); return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), DELETED_AT);
@ -96,6 +96,8 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<DecimalDt> ENTRY_SCORE = new ResourceMetadataKeyEnum<DecimalDt>("ENTRY_SCORE") { public static final ResourceMetadataKeyEnum<DecimalDt> ENTRY_SCORE = new ResourceMetadataKeyEnum<DecimalDt>("ENTRY_SCORE") {
private static final long serialVersionUID = 1L;
@Override @Override
public DecimalDt get(IResource theResource) { public DecimalDt get(IResource theResource) {
return getDecimalFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_SCORE); return getDecimalFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_SCORE);
@ -119,6 +121,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<BundleEntrySearchModeEnum> ENTRY_SEARCH_MODE = new ResourceMetadataKeyEnum<BundleEntrySearchModeEnum>("ENTRY_SEARCH_MODE") { public static final ResourceMetadataKeyEnum<BundleEntrySearchModeEnum> ENTRY_SEARCH_MODE = new ResourceMetadataKeyEnum<BundleEntrySearchModeEnum>("ENTRY_SEARCH_MODE") {
private static final long serialVersionUID = 1L;
@Override @Override
public BundleEntrySearchModeEnum get(IResource theResource) { public BundleEntrySearchModeEnum get(IResource theResource) {
return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_SEARCH_MODE, BundleEntrySearchModeEnum.class, BundleEntrySearchModeEnum.VALUESET_BINDER); return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_SEARCH_MODE, BundleEntrySearchModeEnum.class, BundleEntrySearchModeEnum.VALUESET_BINDER);
@ -144,6 +147,8 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
*/ */
public static final ResourceMetadataKeyEnum<BundleEntryTransactionMethodEnum> ENTRY_TRANSACTION_METHOD = new ResourceMetadataKeyEnum<BundleEntryTransactionMethodEnum>( public static final ResourceMetadataKeyEnum<BundleEntryTransactionMethodEnum> ENTRY_TRANSACTION_METHOD = new ResourceMetadataKeyEnum<BundleEntryTransactionMethodEnum>(
"ENTRY_TRANSACTION_OPERATION") { "ENTRY_TRANSACTION_OPERATION") {
private static final long serialVersionUID = 1L;
@Override @Override
public BundleEntryTransactionMethodEnum get(IResource theResource) { public BundleEntryTransactionMethodEnum get(IResource theResource) {
return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_TRANSACTION_METHOD, BundleEntryTransactionMethodEnum.class, return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_TRANSACTION_METHOD, BundleEntryTransactionMethodEnum.class,
@ -165,6 +170,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<String> LINK_ALTERNATE = new ResourceMetadataKeyEnum<String>("LINK_ALTERNATE") { public static final ResourceMetadataKeyEnum<String> LINK_ALTERNATE = new ResourceMetadataKeyEnum<String>("LINK_ALTERNATE") {
private static final long serialVersionUID = 1L;
@Override @Override
public String get(IResource theResource) { public String get(IResource theResource) {
return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_ALTERNATE); return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_ALTERNATE);
@ -185,6 +191,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<String> LINK_SEARCH = new ResourceMetadataKeyEnum<String>("LINK_SEARCH") { public static final ResourceMetadataKeyEnum<String> LINK_SEARCH = new ResourceMetadataKeyEnum<String>("LINK_SEARCH") {
private static final long serialVersionUID = 1L;
@Override @Override
public String get(IResource theResource) { public String get(IResource theResource) {
return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_SEARCH); return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_SEARCH);
@ -203,6 +210,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<IdDt> PREVIOUS_ID = new ResourceMetadataKeyEnum<IdDt>("PREVIOUS_ID") { public static final ResourceMetadataKeyEnum<IdDt> PREVIOUS_ID = new ResourceMetadataKeyEnum<IdDt>("PREVIOUS_ID") {
private static final long serialVersionUID = 1L;
@Override @Override
public IdDt get(IResource theResource) { public IdDt get(IResource theResource) {
return getIdFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PREVIOUS_ID); return getIdFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PREVIOUS_ID);
@ -222,6 +230,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<List<IdDt>> PROFILES = new ResourceMetadataKeyEnum<List<IdDt>>("PROFILES") { public static final ResourceMetadataKeyEnum<List<IdDt>> PROFILES = new ResourceMetadataKeyEnum<List<IdDt>>("PROFILES") {
private static final long serialVersionUID = 1L;
@Override @Override
public List<IdDt> get(IResource theResource) { public List<IdDt> get(IResource theResource) {
return getIdListFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PROFILES); return getIdListFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PROFILES);
@ -245,6 +254,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* @see InstantDt * @see InstantDt
*/ */
public static final ResourceMetadataKeyEnum<InstantDt> PUBLISHED = new ResourceMetadataKeyEnum<InstantDt>("PUBLISHED") { public static final ResourceMetadataKeyEnum<InstantDt> PUBLISHED = new ResourceMetadataKeyEnum<InstantDt>("PUBLISHED") {
private static final long serialVersionUID = 1L;
@Override @Override
public InstantDt get(IResource theResource) { public InstantDt get(IResource theResource) {
return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PUBLISHED); return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), PUBLISHED);
@ -257,6 +267,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
}; };
public static final ResourceMetadataKeyEnum<List<BaseCodingDt>> SECURITY_LABELS = new ResourceMetadataKeyEnum<List<BaseCodingDt>>("SECURITY_LABELS") { public static final ResourceMetadataKeyEnum<List<BaseCodingDt>> SECURITY_LABELS = new ResourceMetadataKeyEnum<List<BaseCodingDt>>("SECURITY_LABELS") {
private static final long serialVersionUID = 1L;
@Override @Override
public List<BaseCodingDt> get(IResource resource) { public List<BaseCodingDt> get(IResource resource) {
Object obj = resource.getResourceMetadata().get(SECURITY_LABELS); Object obj = resource.getResourceMetadata().get(SECURITY_LABELS);
@ -264,6 +275,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
return null; return null;
} else { } else {
try { try {
@SuppressWarnings("unchecked")
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) obj; List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) obj;
if (securityLabels.isEmpty()) if (securityLabels.isEmpty())
return null; return null;
@ -294,6 +306,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* @see TagList * @see TagList
*/ */
public static final ResourceMetadataKeyEnum<TagList> TAG_LIST = new ResourceMetadataKeyEnum<TagList>("TAG_LIST") { public static final ResourceMetadataKeyEnum<TagList> TAG_LIST = new ResourceMetadataKeyEnum<TagList>("TAG_LIST") {
private static final long serialVersionUID = 1L;
@Override @Override
public TagList get(IResource theResource) { public TagList get(IResource theResource) {
Object retValObj = theResource.getResourceMetadata().get(TAG_LIST); Object retValObj = theResource.getResourceMetadata().get(TAG_LIST);
@ -323,6 +336,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<String> TITLE = new ResourceMetadataKeyEnum<String>("TITLE") { public static final ResourceMetadataKeyEnum<String> TITLE = new ResourceMetadataKeyEnum<String>("TITLE") {
private static final long serialVersionUID = 1L;
@Override @Override
public String get(IResource theResource) { public String get(IResource theResource) {
return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), TITLE); return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), TITLE);
@ -344,6 +358,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* @see InstantDt * @see InstantDt
*/ */
public static final ResourceMetadataKeyEnum<InstantDt> UPDATED = new ResourceMetadataKeyEnum<InstantDt>("UPDATED") { public static final ResourceMetadataKeyEnum<InstantDt> UPDATED = new ResourceMetadataKeyEnum<InstantDt>("UPDATED") {
private static final long serialVersionUID = 1L;
@Override @Override
public InstantDt get(IResource theResource) { public InstantDt get(IResource theResource) {
return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), UPDATED); return getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), UPDATED);
@ -362,6 +377,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
* </p> * </p>
*/ */
public static final ResourceMetadataKeyEnum<String> VERSION = new ResourceMetadataKeyEnum<String>("VERSION") { public static final ResourceMetadataKeyEnum<String> VERSION = new ResourceMetadataKeyEnum<String>("VERSION") {
private static final long serialVersionUID = 1L;
@Override @Override
public String get(IResource theResource) { public String get(IResource theResource) {
return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), VERSION); return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), VERSION);
@ -383,6 +399,7 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
*/ */
@Deprecated @Deprecated
public static final ResourceMetadataKeyEnum<IdDt> VERSION_ID = new ResourceMetadataKeyEnum<IdDt>("VERSION_ID") { public static final ResourceMetadataKeyEnum<IdDt> VERSION_ID = new ResourceMetadataKeyEnum<IdDt>("VERSION_ID") {
private static final long serialVersionUID = 1L;
@Override @Override
public IdDt get(IResource theResource) { public IdDt get(IResource theResource) {
return getIdFromMetadataOrNullIfNone(theResource.getResourceMetadata(), VERSION_ID); return getIdFromMetadataOrNullIfNone(theResource.getResourceMetadata(), VERSION_ID);
@ -519,26 +536,6 @@ public abstract class ResourceMetadataKeyEnum<T> implements Serializable {
+ InstantDt.class.getCanonicalName()); + InstantDt.class.getCanonicalName());
} }
private static StringDt getStringDtFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<StringDt> theKey) {
Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) {
return null;
} else if (retValObj instanceof String) {
if (StringUtils.isBlank((String) retValObj)) {
return null;
}
return new StringDt((String) retValObj);
} else if (retValObj instanceof StringDt) {
if (((StringDt) retValObj).isEmpty()) {
return null;
} else {
return (StringDt) retValObj;
}
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected "
+ InstantDt.class.getCanonicalName());
}
private static String getStringFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<String> theKey) { private static String getStringFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<String> theKey) {
Object retValObj = theResourceMetadata.get(theKey); Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) { if (retValObj == null) {

View File

@ -498,7 +498,11 @@ public abstract class BaseParser implements IParser {
List<IBase> entryResources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry); List<IBase> entryResources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry);
if (entryResources != null && entryResources.size() > 0) { if (entryResources != null && entryResources.size() > 0) {
IBaseResource res = (IBaseResource) entryResources.get(0); IBaseResource res = (IBaseResource) entryResources.get(0);
String versionId = res.getIdElement().getVersionIdPart();
res.setId(value.getValueAsString()); res.setId(value.getValueAsString());
if (isNotBlank(versionId) && res.getIdElement().hasVersionIdPart() == false) {
res.setId(res.getIdElement().withVersion(versionId));
}
} }
} }
} }

View File

@ -100,6 +100,7 @@ import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
@ -940,6 +941,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
return toResource(type.getImplementingClass(), theEntity); return toResource(type.getImplementingClass(), theEntity);
} }
@SuppressWarnings("unchecked")
protected <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity) { protected <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity) {
String resourceText = null; String resourceText = null;
switch (theEntity.getEncoding()) { switch (theEntity.getEncoding()) {
@ -975,7 +977,15 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
ourLog.error(msg, e); ourLog.error(msg, e);
throw new DataFormatException(msg, e); throw new DataFormatException(msg, e);
} }
IResource res = (IResource) retVal; IResource res = (IResource) retVal;
if (theEntity.getDeleted() != null) {
res = (IResource) myContext.getResourceDefinition(theResourceType).newInstance();
retVal = (R) res;
ResourceMetadataKeyEnum.DELETED_AT.put(res, new InstantDt(theEntity.getDeleted()));
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.put(res, BundleEntryTransactionMethodEnum.DELETE);
}
res.setId(theEntity.getIdDt()); res.setId(theEntity.getIdDt());
ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion())); ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion()));
@ -986,10 +996,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
ResourceMetadataKeyEnum.TITLE.put(res, theEntity.getTitle()); ResourceMetadataKeyEnum.TITLE.put(res, theEntity.getTitle());
} }
if (theEntity.getDeleted() != null) {
ResourceMetadataKeyEnum.DELETED_AT.put(res, new InstantDt(theEntity.getDeleted()));
}
Collection<? extends BaseTag> tags = theEntity.getTags(); Collection<? extends BaseTag> tags = theEntity.getTags();
if (theEntity.isHasTags()) { if (theEntity.isHasTags()) {
TagList tagList = new TagList(); TagList tagList = new TagList();

View File

@ -397,8 +397,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return processMatchUrl(theMatchUrl, getResourceType()); return processMatchUrl(theMatchUrl, getResourceType());
} }
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
IQueryParameterType nextOr) {
boolean missingFalse = false; boolean missingFalse = false;
if (nextOr.getMissing() != null) { if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) { if (nextOr.getMissing().booleanValue() == true) {
@ -412,8 +411,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return missingFalse; return missingFalse;
} }
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
IQueryParameterType nextOr) {
boolean missingFalse = false; boolean missingFalse = false;
if (nextOr.getMissing() != null) { if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) { if (nextOr.getMissing().booleanValue() == true) {
@ -502,7 +500,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateUri(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) { private Set<Long> addPredicateUri(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
if (theList == null || theList.isEmpty()) { if (theList == null || theList.isEmpty()) {
return thePids; return thePids;
@ -556,7 +553,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) { private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
String resourceType = getContext().getResourceDefinition(getResourceType()).getName(); String resourceType = getContext().getResourceDefinition(getResourceType()).getName();
@ -1108,8 +1104,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
} }
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
String rawSearchTerm; String rawSearchTerm;
if (theParameter instanceof TokenParam) { if (theParameter instanceof TokenParam) {
TokenParam id = (TokenParam) theParameter; TokenParam id = (TokenParam) theParameter;
@ -1128,8 +1123,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) { if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
+ ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
} }
String likeExpression = normalizeString(rawSearchTerm); String likeExpression = normalizeString(rawSearchTerm);
@ -1143,8 +1137,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return singleCode; return singleCode;
} }
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
String code; String code;
String system; String system;
if (theParameter instanceof TokenParam) { if (theParameter instanceof TokenParam) {
@ -1164,12 +1157,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) { if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException( throw new InvalidRequestException("Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
"Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
} }
if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) { if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException( throw new InvalidRequestException("Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
"Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
} }
ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>()); ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>());
@ -1332,8 +1323,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
if (isNotBlank(theResource.getId().getIdPart())) { if (isNotBlank(theResource.getId().getIdPart())) {
if (isValidPid(theResource.getId())) { if (isValidPid(theResource.getId())) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException("This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
"This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
} }
createForcedIdIfNeeded(entity, theResource.getId()); createForcedIdIfNeeded(entity, theResource.getId());
@ -1434,8 +1424,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
final T current = currentTmp; final T current = currentTmp;
String querySring = "SELECT count(h) FROM ResourceHistoryTable h " + "WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE" + " AND h.myUpdated < :END" StringBuilder B = new StringBuilder();
+ (theSince != null ? " AND h.myUpdated >= :SINCE" : ""); B.append("SELECT count(h) FROM ResourceHistoryTable h ");
B.append("WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE");
B.append(" AND h.myUpdated < :END");
B.append((theSince != null ? " AND h.myUpdated >= :SINCE" : ""));
String querySring = B.toString();
TypedQuery<Long> countQuery = myEntityManager.createQuery(querySring, Long.class); TypedQuery<Long> countQuery = myEntityManager.createQuery(querySring, Long.class);
countQuery.setParameter("PID", translateForcedIdToPid(theId)); countQuery.setParameter("PID", translateForcedIdToPid(theId));
countQuery.setParameter("RESTYPE", resourceType); countQuery.setParameter("RESTYPE", resourceType);
@ -1473,8 +1468,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
retVal.add(current); retVal.add(current);
} }
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT h FROM ResourceHistoryTable h WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE AND h.myUpdated < :END " StringBuilder b = new StringBuilder();
+ (theSince != null ? " AND h.myUpdated >= :SINCE" : "") + " ORDER BY h.myUpdated ASC", ResourceHistoryTable.class); b.append("SELECT h FROM ResourceHistoryTable h WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE AND h.myUpdated < :END ");
b.append((theSince != null ? " AND h.myUpdated >= :SINCE" : ""));
b.append(" ORDER BY h.myUpdated DESC");
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery(b.toString(), ResourceHistoryTable.class);
q.setParameter("PID", translateForcedIdToPid(theId)); q.setParameter("PID", translateForcedIdToPid(theId));
q.setParameter("RESTYPE", resourceType); q.setParameter("RESTYPE", resourceType);
q.setParameter("END", end.getValue(), TemporalType.TIMESTAMP); q.setParameter("END", end.getValue(), TemporalType.TIMESTAMP);
@ -1734,9 +1732,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
myEntityManager.merge(entity); myEntityManager.merge(entity);
myEntityManager.flush(); myEntityManager.flush();
ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() }); ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() });
return metaGetOperation(theResourceId); return metaGetOperation(theResourceId);
} }
@ -1771,7 +1769,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
retVal.setLastUpdated(entity.getUpdated()); retVal.setLastUpdated(entity.getUpdated());
retVal.setVersionId(Long.toString(entity.getVersion())); retVal.setVersionId(Long.toString(entity.getVersion()));
return retVal; return retVal;
} }
@ -1853,8 +1851,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
if (entity == null) { if (entity == null) {
if (theId.hasVersionIdPart()) { if (theId.hasVersionIdPart()) {
TypedQuery<ResourceHistoryTable> q = myEntityManager TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
q.setParameter("RID", pid); q.setParameter("RID", pid);
q.setParameter("RTYP", myResourceName); q.setParameter("RTYP", myResourceName);
q.setParameter("RVER", Long.parseLong(theId.getVersionIdPart())); q.setParameter("RVER", Long.parseLong(theId.getVersionIdPart()));
@ -2245,7 +2242,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
/** /**
* If set, the given param will be treated as a secondary primary key, and multiple resources will not be able to share the same value. * If set, the given param will be treated as a secondary primary key, and multiple resources will not be able to
* share the same value.
*/ */
public void setSecondaryPrimaryKeyParamName(String theSecondaryPrimaryKeyParamName) { public void setSecondaryPrimaryKeyParamName(String theSecondaryPrimaryKeyParamName) {
mySecondaryPrimaryKeyParamName = theSecondaryPrimaryKeyParamName; mySecondaryPrimaryKeyParamName = theSecondaryPrimaryKeyParamName;
@ -2373,8 +2371,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
if (resourceId.hasResourceType() && !resourceId.getResourceType().equals(getResourceName())) { if (resourceId.hasResourceType() && !resourceId.getResourceType().equals(getResourceName())) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException("Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]");
"Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]");
} }
// Notify interceptors // Notify interceptors
@ -2409,8 +2406,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
private void validateResourceType(BaseHasResource entity) { private void validateResourceType(BaseHasResource entity) {
if (!myResourceName.equals(entity.getResourceType())) { if (!myResourceName.equals(entity.getResourceType())) {
throw new ResourceNotFoundException( throw new ResourceNotFoundException("Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
"Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
} }
} }

View File

@ -1,13 +1,12 @@
package ca.uhn.fhir.jpa.dao; package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -22,9 +21,9 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -32,12 +31,10 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains; import org.hamcrest.core.StringContains;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@ -45,10 +42,9 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.TagTypeEnum; import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
@ -62,15 +58,12 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Device; import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport; import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.Encounter; import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire; import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum; import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum; import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum; import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
@ -85,17 +78,12 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -110,26 +98,6 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2Test.class);
@Before
public void before() {
deleteAll(myPatientDao);
deleteAll(myObservationDao);
deleteAll(myOrganizationDao);
deleteAll(myDiagnosticReportDao);
deleteAll(myEncounterDao);
FhirSystemDaoDstu2Test.doDeleteEverything(mySystemDao);
reset(myInterceptor);
}
private void deleteAll(IFhirResourceDao<?> dao) {
IBundleProvider find = dao.search(new SearchParameterMap());
List<IBaseResource> res = find.getResources(0, find.size());
for (IBaseResource next : res) {
dao.delete(next.getIdElement());
}
}
private List<String> extractNames(IBundleProvider theSearch) { private List<String> extractNames(IBundleProvider theSearch) {
ArrayList<String> retVal = new ArrayList<String>(); ArrayList<String> retVal = new ArrayList<String>();
for (IBaseResource next : theSearch.getResources(0, theSearch.size())) { for (IBaseResource next : theSearch.getResources(0, theSearch.size())) {
@ -139,6 +107,46 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
return retVal; return retVal;
} }
@Test
public void testReadWithDeletedResource() {
String methodName = "testReadWithDeletedResource";
Patient patient = new Patient();
patient.addName().addFamily(methodName);
IIdType id = myPatientDao.create(patient).getId().toVersionless();
myPatientDao.delete(id);
try {
myPatientDao.read(id);
fail();
} catch (ResourceGoneException e) {
// good
}
patient.setId(id);
patient.addAddress().addLine("AAA");
myPatientDao.update(patient);
Patient p;
p = myPatientDao.read(id);
assertEquals(1, (p).getName().size());
p = myPatientDao.read(id.withVersion("1"));
assertEquals(1, (p).getName().size());
try {
myPatientDao.read(id.withVersion("2"));
fail();
} catch (ResourceGoneException e) {
// good
}
p = myPatientDao.read(id.withVersion("3"));
assertEquals(1, (p).getName().size());
}
@Test @Test
public void testChoiceParamConcept() { public void testChoiceParamConcept() {
Observation o1 = new Observation(); Observation o1 = new Observation();
@ -230,8 +238,8 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
@Test @Test
public void testCreateOperationOutcome() { public void testCreateOperationOutcome() {
/* /*
* If any of this ever fails, it means that one of the OperationOutcome issue severity codes has changed code value across versions. We store the string as a constant, so something will need to * If any of this ever fails, it means that one of the OperationOutcome issue severity codes has changed code
* be fixed. * value across versions. We store the string as a constant, so something will need to be fixed.
*/ */
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR); assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR);
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.ERROR.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR); assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.ERROR.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR);
@ -709,6 +717,108 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertNotEquals(idv1, idv2); assertNotEquals(idv1, idv2);
} }
@Test
public void testHistoryWithDeletedResource() throws Exception {
String methodName = "testHistoryWithDeletedResource";
Patient patient = new Patient();
patient.addName().addFamily(methodName);
IIdType id = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
myPatientDao.delete(id);
patient.setId(id);
myPatientDao.update(patient);
IBundleProvider history = myPatientDao.history(id, null);
assertEquals(3, history.size());
List<IBaseResource> entries = history.getResources(0, 3);
ourLog.info("" + ResourceMetadataKeyEnum.UPDATED.get((IResource) entries.get(0)));
ourLog.info("" + ResourceMetadataKeyEnum.UPDATED.get((IResource) entries.get(1)));
ourLog.info("" + ResourceMetadataKeyEnum.UPDATED.get((IResource) entries.get(2)));
assertEquals(id.withVersion("3"), entries.get(0).getIdElement());
assertEquals(id.withVersion("2"), entries.get(1).getIdElement());
assertEquals(id.withVersion("1"), entries.get(2).getIdElement());
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get((IResource) entries.get(0)));
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get((IResource) entries.get(1)));
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get((IResource) entries.get(2)));
}
@Test
public void testHistoryOverMultiplePages() throws Exception {
String methodName = "testHistoryOverMultiplePages";
Patient patient = new Patient();
patient.addName().addFamily(methodName);
IIdType id = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
Date middleDate = null;
for (int i = 0; i < 100; i++) {
if (i == 50) {
Thread.sleep(100);
middleDate = new Date();
Thread.sleep(100);
}
patient.setId(id);
patient.getName().get(0).getFamily().get(0).setValue(methodName + "_i");
myPatientDao.update(patient);
}
// By instance
IBundleProvider history = myPatientDao.history(id, null);
for (int i = 0; i < 100; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(null);
for (int i = 0; i < 100; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(null);
for (int i = 0; i < 100; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
/*
* With since date
*/
// By instance
history = myPatientDao.history(id, middleDate);
for (int i = 0; i < 50; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(middleDate);
for (int i = 0; i < 50; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(middleDate);
for (int i = 0; i < 50; i++) {
String expected = id.withVersion(Integer.toString(101 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
}
@Test @Test
public void testIdParam() { public void testIdParam() {
Patient patient = new Patient(); Patient patient = new Patient();
@ -1130,21 +1240,21 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
id = myPatientDao.create(patient).getId(); id = myPatientDao.create(patient).getId();
} }
assertTrue(id.hasVersionIdPart()); assertTrue(id.hasVersionIdPart());
/* /*
* Create a second version * Create a second version
*/ */
Patient pt = myPatientDao.read(id); Patient pt = myPatientDao.read(id);
pt.addName().addFamily("anotherName"); pt.addName().addFamily("anotherName");
myPatientDao.update(pt); myPatientDao.update(pt);
/* /*
* Meta-Delete on previous version * Meta-Delete on previous version
*/ */
MetaDt meta = new MetaDt(); MetaDt meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1"); meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1"); meta.addProfile("http://profile/1");
@ -1156,11 +1266,11 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("tag_code2", newMeta.getTag().get(0).getCode()); assertEquals("tag_code2", newMeta.getTag().get(0).getCode());
assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue()); assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode()); assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode());
/* /*
* Meta Read on Version * Meta Read on Version
*/ */
meta = myPatientDao.metaGetOperation(id.withVersion("1")); meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(1, meta.getProfile().size()); assertEquals(1, meta.getProfile().size());
assertEquals(1, meta.getSecurity().size()); assertEquals(1, meta.getSecurity().size());
@ -1168,7 +1278,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("tag_code2", meta.getTag().get(0).getCode()); assertEquals("tag_code2", meta.getTag().get(0).getCode());
assertEquals("http://profile/2", meta.getProfile().get(0).getValue()); assertEquals("http://profile/2", meta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", meta.getSecurity().get(0).getCode()); assertEquals("seclabel_code2", meta.getSecurity().get(0).getCode());
/* /*
* Meta-read on Version 2 * Meta-read on Version 2
*/ */
@ -1189,7 +1299,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
/* /*
* Meta-Add on previous version * Meta-Add on previous version
*/ */
meta = new MetaDt(); meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1"); meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1"); meta.addProfile("http://profile/1");
@ -1198,11 +1308,11 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals(2, newMeta.getProfile().size()); assertEquals(2, newMeta.getProfile().size());
assertEquals(2, newMeta.getSecurity().size()); assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size()); assertEquals(2, newMeta.getTag().size());
/* /*
* Meta Read on Version * Meta Read on Version
*/ */
meta = myPatientDao.metaGetOperation(id.withVersion("1")); meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(2, meta.getProfile().size()); assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size()); assertEquals(2, meta.getSecurity().size());
@ -1228,7 +1338,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
/* /*
* Meta-Add on latest version * Meta-Add on latest version
*/ */
meta = new MetaDt(); meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1"); meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1"); meta.addProfile("http://profile/1");
@ -1238,7 +1348,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals(2, newMeta.getSecurity().size()); assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size()); assertEquals(2, newMeta.getTag().size());
assertEquals("2", newMeta.getVersionId()); assertEquals("2", newMeta.getVersionId());
} }
@Test @Test
@ -1859,7 +1969,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
securityLabels.add(new CodingDt().setSystem("seclabel:sys:2").setCode("seclabel:code:2").setDisplay("seclabel:dis:2")); securityLabels.add(new CodingDt().setSystem("seclabel:sys:2").setCode("seclabel:code:2").setDisplay("seclabel:dis:2"));
ResourceMetadataKeyEnum.SECURITY_LABELS.put(patient, securityLabels); ResourceMetadataKeyEnum.SECURITY_LABELS.put(patient, securityLabels);
ArrayList<IdDt> profiles = new ArrayList<IdDt>(); List<IdDt> profiles = new ArrayList<IdDt>();
profiles.add(new IdDt("http://profile/1")); profiles.add(new IdDt("http://profile/1"));
profiles.add(new IdDt("http://profile/2")); profiles.add(new IdDt("http://profile/2"));
ResourceMetadataKeyEnum.PROFILES.put(patient, profiles); ResourceMetadataKeyEnum.PROFILES.put(patient, profiles);
@ -1871,6 +1981,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
Patient retrieved = myPatientDao.read(patientId); Patient retrieved = myPatientDao.read(patientId);
TagList published = (TagList) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST); TagList published = (TagList) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
sort(published);
assertEquals(2, published.size()); assertEquals(2, published.size());
assertEquals("Dog", published.get(0).getTerm()); assertEquals("Dog", published.get(0).getTerm());
assertEquals("Puppies", published.get(0).getLabel()); assertEquals("Puppies", published.get(0).getLabel());
@ -1878,14 +1989,18 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Cat", published.get(1).getTerm()); assertEquals("Cat", published.get(1).getTerm());
assertEquals("Kittens", published.get(1).getLabel()); assertEquals("Kittens", published.get(1).getLabel());
assertEquals("http://foo", published.get(1).getScheme()); assertEquals("http://foo", published.get(1).getScheme());
assertEquals(2, ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).size()); List<BaseCodingDt> secLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved);
assertEquals("seclabel:sys:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getSystemElement().getValue()); sortCodings(secLabels);
assertEquals("seclabel:code:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getCodeElement().getValue()); assertEquals(2, secLabels.size());
assertEquals("seclabel:dis:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getDisplayElement().getValue()); assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
assertEquals("seclabel:sys:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getSystemElement().getValue()); assertEquals("seclabel:code:1", secLabels.get(0).getCodeElement().getValue());
assertEquals("seclabel:code:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getCodeElement().getValue()); assertEquals("seclabel:dis:1", secLabels.get(0).getDisplayElement().getValue());
assertEquals("seclabel:dis:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getDisplayElement().getValue()); assertEquals("seclabel:sys:2", secLabels.get(1).getSystemElement().getValue());
assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size()); assertEquals("seclabel:code:2", secLabels.get(1).getCodeElement().getValue());
assertEquals("seclabel:dis:2", secLabels.get(1).getDisplayElement().getValue());
profiles = ResourceMetadataKeyEnum.PROFILES.get(retrieved);
profiles = sortIds(profiles);
assertEquals(2, profiles.size());
assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue()); assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue());
assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue()); assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
@ -1899,13 +2014,13 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Cat", published.get(1).getTerm()); assertEquals("Cat", published.get(1).getTerm());
assertEquals("Kittens", published.get(1).getLabel()); assertEquals("Kittens", published.get(1).getLabel());
assertEquals("http://foo", published.get(1).getScheme()); assertEquals("http://foo", published.get(1).getScheme());
assertEquals(2, ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).size()); assertEquals(2, secLabels.size());
assertEquals("seclabel:sys:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getSystemElement().getValue()); assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
assertEquals("seclabel:code:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getCodeElement().getValue()); assertEquals("seclabel:code:1", secLabels.get(0).getCodeElement().getValue());
assertEquals("seclabel:dis:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getDisplayElement().getValue()); assertEquals("seclabel:dis:1", secLabels.get(0).getDisplayElement().getValue());
assertEquals("seclabel:sys:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getSystemElement().getValue()); assertEquals("seclabel:sys:2", secLabels.get(1).getSystemElement().getValue());
assertEquals("seclabel:code:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getCodeElement().getValue()); assertEquals("seclabel:code:2", secLabels.get(1).getCodeElement().getValue());
assertEquals("seclabel:dis:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getDisplayElement().getValue()); assertEquals("seclabel:dis:2", secLabels.get(1).getDisplayElement().getValue());
assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size()); assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size());
assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue()); assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue());
assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue()); assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
@ -1925,19 +2040,50 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Cow", published.get(2).getTerm()); assertEquals("Cow", published.get(2).getTerm());
assertEquals("Calves", published.get(2).getLabel()); assertEquals("Calves", published.get(2).getLabel());
assertEquals("http://foo", published.get(2).getScheme()); assertEquals("http://foo", published.get(2).getScheme());
assertEquals(2, ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).size()); assertEquals(2, secLabels.size());
assertEquals("seclabel:sys:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getSystemElement().getValue()); assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
assertEquals("seclabel:code:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getCodeElement().getValue()); assertEquals("seclabel:code:1", secLabels.get(0).getCodeElement().getValue());
assertEquals("seclabel:dis:1", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(0).getDisplayElement().getValue()); assertEquals("seclabel:dis:1", secLabels.get(0).getDisplayElement().getValue());
assertEquals("seclabel:sys:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getSystemElement().getValue()); assertEquals("seclabel:sys:2", secLabels.get(1).getSystemElement().getValue());
assertEquals("seclabel:code:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getCodeElement().getValue()); assertEquals("seclabel:code:2", secLabels.get(1).getCodeElement().getValue());
assertEquals("seclabel:dis:2", ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved).get(1).getDisplayElement().getValue()); assertEquals("seclabel:dis:2", secLabels.get(1).getDisplayElement().getValue());
assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size()); assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size());
assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue()); assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue());
assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue()); assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
} }
private List<IdDt> sortIds(List<IdDt> theProfiles) {
ArrayList<IdDt> retVal = new ArrayList<IdDt>(theProfiles);
Collections.sort(retVal, new Comparator<IdDt>() {
@Override
public int compare(IdDt theO1, IdDt theO2) {
return theO1.getValue().compareTo(theO2.getValue());
}});
return retVal;
}
private void sortCodings(List<BaseCodingDt> theSecLabels) {
Collections.sort(theSecLabels, new Comparator<BaseCodingDt>() {
@Override
public int compare(BaseCodingDt theO1, BaseCodingDt theO2) {
return theO1.getSystemElement().getValue().compareTo(theO2.getSystemElement().getValue());
}});
}
private void sort(TagList thePublished) {
ArrayList<Tag> tags = new ArrayList<Tag>(thePublished);
Collections.sort(tags, new Comparator<Tag>() {
@Override
public int compare(Tag theO1, Tag theO2) {
return defaultString(theO1.getScheme()).compareTo(defaultString(theO2.getScheme()));
}});
thePublished.clear();
for (Tag next : tags) {
thePublished.add(next);
}
}
@Test @Test
public void testTokenParamWhichIsTooLong() { public void testTokenParamWhichIsTooLong() {

View File

@ -101,6 +101,7 @@ import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
@ -424,7 +425,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
} }
/* /*
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to make sure that works too.. * Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to
* make sure that works too..
*/ */
Socket sock = new Socket(); Socket sock = new Socket();
sock.setSoTimeout(3000); sock.setSoTimeout(3000);
@ -685,6 +687,30 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
} }
} }
@Test
public void testHistoryWithDeletedResource() {
String methodName = "testHistoryWithDeletedResource";
Patient patient = new Patient();
patient.addName().addFamily(methodName);
IIdType id = ourClient.create().resource(patient).execute().getId().toVersionless();
ourClient.delete().resourceById(id).execute();
patient.setId(id);
ourClient.update().resource(patient).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle history = ourClient.history().onInstance(id).andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).prettyPrint().summaryMode(SummaryEnum.DATA).execute();
assertEquals(3, history.getEntry().size());
assertEquals(id.withVersion("3"), history.getEntry().get(0).getResource().getId());
assertEquals(1, ((Patient) history.getEntry().get(0).getResource()).getName().size());
assertEquals(id.withVersion("2"), history.getEntry().get(1).getResource().getId());
assertEquals(HTTPVerbEnum.DELETE, history.getEntry().get(1).getRequest().getMethodElement().getValueAsEnum());
assertEquals(0, ((Patient) history.getEntry().get(1).getResource()).getName().size());
assertEquals(id.withVersion("1"), history.getEntry().get(2).getResource().getId());
assertEquals(1, ((Patient) history.getEntry().get(2).getResource()).getName().size());
}
/** /**
* See issue #52 * See issue #52
*/ */
@ -703,6 +729,21 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
} }
@Test
public void testMetadata() throws Exception {
HttpGet get = new HttpGet(ourServerBase + "/metadata");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
String resp = IOUtils.toString(response.getEntity().getContent());
ourLog.info(resp);
assertEquals(200, response.getStatusLine().getStatusCode());
assertThat(resp, stringContainsInOrder("THIS IS THE DESC"));
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
response.close();
}
}
@Test @Test
public void testMetaOperations() throws Exception { public void testMetaOperations() throws Exception {
String methodName = "testMetaOperations"; String methodName = "testMetaOperations";
@ -838,7 +879,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class) .returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute(); .execute();
//@formatter:on //@formatter:on
assertEquals(1, actual.getEntry().size()); assertEquals(1, actual.getEntry().size());
assertEquals(ourServerBase + "/Patient/" + p1Id.getIdPart(), actual.getEntry().get(0).getFullUrl()); assertEquals(ourServerBase + "/Patient/" + p1Id.getIdPart(), actual.getEntry().get(0).getFullUrl());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
@ -853,8 +894,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01"); p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId(); IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint() Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint().execute();
.execute();
assertEquals(1, actual.size()); assertEquals(1, actual.size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
@ -989,6 +1029,19 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
} }
} }
private void testSearchReturnsResults(String search) throws IOException, ClientProtocolException {
int matches;
HttpGet get = new HttpGet(ourServerBase + search);
CloseableHttpResponse response = ourHttpClient.execute(get);
String resp = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(resp);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp);
matches = bundle.getTotal();
assertThat(matches, greaterThan(0));
}
@Test @Test
public void testSearchReturnsSearchDate() throws Exception { public void testSearchReturnsSearchDate() throws Exception {
Date before = new Date(); Date before = new Date();
@ -1047,33 +1100,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE)); assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
} }
@Test
public void testSearchWithTextInexactMatch() throws Exception {
Observation obs = new Observation();
obs.getCode().setText("THIS_IS_THE_TEXT");
obs.getCode().addCoding().setSystem("SYSTEM").setCode("CODE").setDisplay("THIS_IS_THE_DISPLAY");
ourClient.create().resource(obs).execute();
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_TEXT");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_");
testSearchReturnsResults("/Observation?code%3Atext=this_is_the_");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_DISPLAY");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_disp");
}
private void testSearchReturnsResults(String search) throws IOException, ClientProtocolException {
int matches;
HttpGet get = new HttpGet(ourServerBase + search);
CloseableHttpResponse response = ourHttpClient.execute(get);
String resp = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(resp);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp);
matches = bundle.getTotal();
assertThat(matches, greaterThan(0));
}
@Test @Test
public void testSearchWithMissing() throws Exception { public void testSearchWithMissing() throws Exception {
ourLog.info("Starting testSearchWithMissing"); ourLog.info("Starting testSearchWithMissing");
@ -1153,6 +1179,20 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
checkParamMissing(Observation.SP_DATE); checkParamMissing(Observation.SP_DATE);
} }
@Test
public void testSearchWithTextInexactMatch() throws Exception {
Observation obs = new Observation();
obs.getCode().setText("THIS_IS_THE_TEXT");
obs.getCode().addCoding().setSystem("SYSTEM").setCode("CODE").setDisplay("THIS_IS_THE_DISPLAY");
ourClient.create().resource(obs).execute();
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_TEXT");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_");
testSearchReturnsResults("/Observation?code%3Atext=this_is_the_");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_DISPLAY");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_disp");
}
/** /**
* See #198 * See #198
*/ */
@ -1281,7 +1321,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
//@formatter:om //@formatter:om
} }
/** /**
* Test for issue #60 * Test for issue #60
*/ */
@ -1637,21 +1677,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
ourHttpClient.close(); ourHttpClient.close();
} }
@Test
public void testMetadata() throws Exception {
HttpGet get = new HttpGet(ourServerBase + "/metadata");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
String resp = IOUtils.toString(response.getEntity().getContent());
ourLog.info(resp);
assertEquals(200, response.getStatusLine().getStatusCode());
assertThat(resp, stringContainsInOrder("THIS IS THE DESC"));
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
response.close();
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@BeforeClass @BeforeClass
public static void beforeClass() throws Exception { public static void beforeClass() throws Exception {

View File

@ -51,6 +51,7 @@ import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.server.AddProfileTagEnum; import ca.uhn.fhir.rest.server.AddProfileTagEnum;
import ca.uhn.fhir.rest.server.BundleInclusionRule; import ca.uhn.fhir.rest.server.BundleInclusionRule;
@ -147,6 +148,10 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
if (next.getId().hasBaseUrl()) { if (next.getId().hasBaseUrl()) {
entry.setFullUrl(next.getId().getValue()); entry.setFullUrl(next.getId().getValue());
} }
BundleEntryTransactionMethodEnum httpVerb = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(next);
if (httpVerb != null) {
entry.getRequest().getMethodElement().setValueAsString(httpVerb.getCode());
}
} }
/* /*
@ -238,6 +243,10 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
} while (references.isEmpty() == false); } while (references.isEmpty() == false);
Entry entry = myBundle.addEntry().setResource(next); Entry entry = myBundle.addEntry().setResource(next);
BundleEntryTransactionMethodEnum httpVerb = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(next);
if (httpVerb != null) {
entry.getRequest().getMethodElement().setValueAsString(httpVerb.getCode());
}
populateBundleEntryFullUrl(next, entry); populateBundleEntryFullUrl(next, entry);
BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next); BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next);

View File

@ -92,6 +92,21 @@ public class XmlParserDstu2Test {
private static final FhirContext ourCtx = FhirContext.forDstu2(); private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
@Test
public void testParseBundleWithResourceId() {
//@formatter:off
String input = "<Bundle xmlns=\"http://hl7.org/fhir\">"
+ "<entry><fullUrl value=\"http://localhost:58402/fhir/context/Patient/1\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><id value=\"1\"/><meta><versionId value=\"3\"/><lastUpdated value=\"2015-09-11T23:35:43.273-04:00\"/></meta><name><family value=\"testHistoryWithDeletedResource\"/></name></Patient></resource></entry>"
+ "<entry><fullUrl value=\"http://localhost:58402/fhir/context/Patient/1\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><id value=\"1\"/><meta><versionId value=\"2\"/><lastUpdated value=\"2015-09-11T23:35:42.849-04:00\"/></meta><name><family value=\"testHistoryWithDeletedResource\"/></name></Patient></resource></entry>"
+ "<entry><fullUrl value=\"http://localhost:58402/fhir/context/Patient/1\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><id value=\"1\"/><meta><versionId value=\"1\"/><lastUpdated value=\"2015-09-11T23:35:42.295-04:00\"/></meta><name><family value=\"testHistoryWithDeletedResource\"/></name></Patient></resource></entry>"
+ "</Bundle>\n";
//@formatter:on
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, input);
assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/3", bundle.getEntry().get(0).getResource().getId().getValue());
assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/2", bundle.getEntry().get(1).getResource().getId().getValue());
assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/1", bundle.getEntry().get(2).getResource().getId().getValue());
}
@Test @Test
public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() { public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() {

View File

@ -182,6 +182,10 @@
RestfulServer now supports dynamically adding and removing resource providers RestfulServer now supports dynamically adding and removing resource providers
at runtime. Thanks to Bill Denton for adding this. at runtime. Thanks to Bill Denton for adding this.
</action> </action>
<action type="add">
JPA server now correctly suppresses contents of deleted resources
in history
</action>
</release> </release>
<release version="1.1" date="2015-07-13"> <release version="1.1" date="2015-07-13">
<action type="add"> <action type="add">