It should not be possible to search for deleted resources using the _tag, _id, _profile, or _security search parameters

This commit is contained in:
jamesagnew 2015-09-13 09:42:41 -04:00
parent 48ee2cbee8
commit 780fc871cb
14 changed files with 810 additions and 581 deletions

View File

@ -533,13 +533,15 @@ public class JsonParser extends BaseParser implements IParser {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
if (gen != null) {
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
if (narr != null && !narr.isEmpty()) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, nextChildElem);
continue;
if (narr.getDiv().isEmpty()) {
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
if (narr != null && !narr.isEmpty()) {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, nextChildElem);
continue;
}
}
}
} else if (nextChild instanceof RuntimeChildContainedResources) {
@ -1237,7 +1239,6 @@ public class JsonParser extends BaseParser implements IParser {
// theState.endingElement();
// }
@Override
public TagList parseTagList(Reader theReader) {
JsonReader reader = Json.createReader(theReader);

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.cli;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.cli.CommandLine;
@ -16,6 +17,8 @@ public class App {
static {
ourCommands = new ArrayList<BaseCommand>();
ourCommands.add(new RunServerCommand());
Collections.sort(ourCommands);
}
public static void main(String[] theArgs) {

View File

@ -7,7 +7,7 @@ import org.apache.commons.cli.ParseException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.IGenericClient;
public class BaseCommand {
public abstract class BaseCommand implements Comparable<BaseCommand> {
public BaseCommand() {
super();
@ -18,18 +18,15 @@ public class BaseCommand {
return fhirClient;
}
public Options getOptions() {
return null;
}
public abstract Options getOptions();
public String getCommandName() {
// TODO Auto-generated method stub
return null;
}
public abstract String getCommandName();
public void run(CommandLine theCommandLine) throws ParseException {
// TODO Auto-generated method stub
public abstract void run(CommandLine theCommandLine) throws ParseException;
@Override
public int compareTo(BaseCommand theO) {
return getCommandName().compareTo(theO.getCommandName());
}
}

View File

@ -977,15 +977,15 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
ourLog.error(msg, e);
throw new DataFormatException(msg, e);
}
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());
ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion()));
@ -1068,46 +1068,46 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
@SuppressWarnings("unchecked")
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
protected ResourceTable updateEntity(final IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
if (entity.getPublished() == null) {
entity.setPublished(new Date());
if (theEntity.getPublished() == null) {
theEntity.setPublished(new Date());
}
if (theResource != null) {
validateResourceForStorage((T) theResource);
String resourceType = myContext.getResourceDefinition(theResource).getName();
if (isNotBlank(entity.getResourceType()) && !entity.getResourceType().equals(resourceType)) {
throw new UnprocessableEntityException("Existing resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + entity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) {
throw new UnprocessableEntityException("Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
}
}
if (theUpdateHistory) {
final ResourceHistoryTable historyEntry = entity.toHistory();
final ResourceHistoryTable historyEntry = theEntity.toHistory();
myEntityManager.persist(historyEntry);
}
if (theUpdateVersion) {
entity.setVersion(entity.getVersion() + 1);
theEntity.setVersion(theEntity.getVersion() + 1);
}
boolean paramsStringPopulated = entity.isParamsStringPopulated();
boolean paramsTokenPopulated = entity.isParamsTokenPopulated();
boolean paramsNumberPopulated = entity.isParamsNumberPopulated();
boolean paramsQuantityPopulated = entity.isParamsQuantityPopulated();
boolean paramsDatePopulated = entity.isParamsDatePopulated();
boolean paramsCoordsPopulated = entity.isParamsCoordsPopulated();
boolean paramsUriPopulated = entity.isParamsUriPopulated();
boolean hasLinks = entity.isHasLinks();
boolean paramsStringPopulated = theEntity.isParamsStringPopulated();
boolean paramsTokenPopulated = theEntity.isParamsTokenPopulated();
boolean paramsNumberPopulated = theEntity.isParamsNumberPopulated();
boolean paramsQuantityPopulated = theEntity.isParamsQuantityPopulated();
boolean paramsDatePopulated = theEntity.isParamsDatePopulated();
boolean paramsCoordsPopulated = theEntity.isParamsCoordsPopulated();
boolean paramsUriPopulated = theEntity.isParamsUriPopulated();
boolean hasLinks = theEntity.isHasLinks();
Collection<ResourceIndexedSearchParamString> paramsString = new ArrayList<ResourceIndexedSearchParamString>(entity.getParamsString());
Collection<ResourceIndexedSearchParamToken> paramsToken = new ArrayList<ResourceIndexedSearchParamToken>(entity.getParamsToken());
Collection<ResourceIndexedSearchParamNumber> paramsNumber = new ArrayList<ResourceIndexedSearchParamNumber>(entity.getParamsNumber());
Collection<ResourceIndexedSearchParamQuantity> paramsQuantity = new ArrayList<ResourceIndexedSearchParamQuantity>(entity.getParamsQuantity());
Collection<ResourceIndexedSearchParamDate> paramsDate = new ArrayList<ResourceIndexedSearchParamDate>(entity.getParamsDate());
Collection<ResourceIndexedSearchParamUri> paramsUri = new ArrayList<ResourceIndexedSearchParamUri>(entity.getParamsUri());
Collection<ResourceIndexedSearchParamCoords> paramsCoords = new ArrayList<ResourceIndexedSearchParamCoords>(entity.getParamsCoords());
Collection<ResourceLink> resourceLinks = new ArrayList<ResourceLink>(entity.getResourceLinks());
Collection<ResourceIndexedSearchParamString> paramsString = new ArrayList<ResourceIndexedSearchParamString>(theEntity.getParamsString());
Collection<ResourceIndexedSearchParamToken> paramsToken = new ArrayList<ResourceIndexedSearchParamToken>(theEntity.getParamsToken());
Collection<ResourceIndexedSearchParamNumber> paramsNumber = new ArrayList<ResourceIndexedSearchParamNumber>(theEntity.getParamsNumber());
Collection<ResourceIndexedSearchParamQuantity> paramsQuantity = new ArrayList<ResourceIndexedSearchParamQuantity>(theEntity.getParamsQuantity());
Collection<ResourceIndexedSearchParamDate> paramsDate = new ArrayList<ResourceIndexedSearchParamDate>(theEntity.getParamsDate());
Collection<ResourceIndexedSearchParamUri> paramsUri = new ArrayList<ResourceIndexedSearchParamUri>(theEntity.getParamsUri());
Collection<ResourceIndexedSearchParamCoords> paramsCoords = new ArrayList<ResourceIndexedSearchParamCoords>(theEntity.getParamsCoords());
Collection<ResourceLink> resourceLinks = new ArrayList<ResourceLink>(theEntity.getResourceLinks());
List<ResourceIndexedSearchParamString> stringParams = null;
List<ResourceIndexedSearchParamToken> tokenParams = null;
@ -1128,27 +1128,27 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
uriParams = Collections.emptyList();
coordsParams = Collections.emptyList();
links = Collections.emptyList();
entity.setDeleted(theDeletedTimestampOrNull);
entity.setUpdated(theDeletedTimestampOrNull);
theEntity.setDeleted(theDeletedTimestampOrNull);
theEntity.setUpdated(theDeletedTimestampOrNull);
} else {
entity.setDeleted(null);
theEntity.setDeleted(null);
if (thePerformIndexing) {
stringParams = extractSearchParamStrings(entity, theResource);
numberParams = extractSearchParamNumber(entity, theResource);
quantityParams = extractSearchParamQuantity(entity, theResource);
dateParams = extractSearchParamDates(entity, theResource);
uriParams = extractSearchParamUri(entity, theResource);
coordsParams = extractSearchParamCoords(entity, theResource);
stringParams = extractSearchParamStrings(theEntity, theResource);
numberParams = extractSearchParamNumber(theEntity, theResource);
quantityParams = extractSearchParamQuantity(theEntity, theResource);
dateParams = extractSearchParamDates(theEntity, theResource);
uriParams = extractSearchParamUri(theEntity, theResource);
coordsParams = extractSearchParamCoords(theEntity, theResource);
// ourLog.info("Indexing resource: {}", entity.getId());
ourLog.trace("Storing string indexes: {}", stringParams);
tokenParams = new ArrayList<ResourceIndexedSearchParamToken>();
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(entity, theResource)) {
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theEntity, theResource)) {
if (next instanceof ResourceIndexedSearchParamToken) {
tokenParams.add((ResourceIndexedSearchParamToken) next);
} else {
@ -1156,49 +1156,49 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
}
links = extractResourceLinks(entity, theResource);
populateResourceIntoEntity(theResource, entity);
links = extractResourceLinks(theEntity, theResource);
populateResourceIntoEntity(theResource, theEntity);
entity.setUpdated(new Date());
entity.setLanguage(theResource.getLanguage().getValue());
entity.setParamsString(stringParams);
entity.setParamsStringPopulated(stringParams.isEmpty() == false);
entity.setParamsToken(tokenParams);
entity.setParamsTokenPopulated(tokenParams.isEmpty() == false);
entity.setParamsNumber(numberParams);
entity.setParamsNumberPopulated(numberParams.isEmpty() == false);
entity.setParamsQuantity(quantityParams);
entity.setParamsQuantityPopulated(quantityParams.isEmpty() == false);
entity.setParamsDate(dateParams);
entity.setParamsDatePopulated(dateParams.isEmpty() == false);
entity.setParamsUri(uriParams);
entity.setParamsUriPopulated(uriParams.isEmpty() == false);
entity.setParamsCoords(coordsParams);
entity.setParamsCoordsPopulated(coordsParams.isEmpty() == false);
entity.setResourceLinks(links);
entity.setHasLinks(links.isEmpty() == false);
entity.setIndexStatus(INDEX_STATUS_INDEXED);
theEntity.setUpdated(new Date());
theEntity.setLanguage(theResource.getLanguage().getValue());
theEntity.setParamsString(stringParams);
theEntity.setParamsStringPopulated(stringParams.isEmpty() == false);
theEntity.setParamsToken(tokenParams);
theEntity.setParamsTokenPopulated(tokenParams.isEmpty() == false);
theEntity.setParamsNumber(numberParams);
theEntity.setParamsNumberPopulated(numberParams.isEmpty() == false);
theEntity.setParamsQuantity(quantityParams);
theEntity.setParamsQuantityPopulated(quantityParams.isEmpty() == false);
theEntity.setParamsDate(dateParams);
theEntity.setParamsDatePopulated(dateParams.isEmpty() == false);
theEntity.setParamsUri(uriParams);
theEntity.setParamsUriPopulated(uriParams.isEmpty() == false);
theEntity.setParamsCoords(coordsParams);
theEntity.setParamsCoordsPopulated(coordsParams.isEmpty() == false);
theEntity.setResourceLinks(links);
theEntity.setHasLinks(links.isEmpty() == false);
theEntity.setIndexStatus(INDEX_STATUS_INDEXED);
} else {
populateResourceIntoEntity(theResource, entity);
entity.setUpdated(new Date());
entity.setLanguage(theResource.getLanguage().getValue());
entity.setIndexStatus(null);
populateResourceIntoEntity(theResource, theEntity);
theEntity.setUpdated(new Date());
theEntity.setLanguage(theResource.getLanguage().getValue());
theEntity.setIndexStatus(null);
}
}
if (entity.getId() == null) {
myEntityManager.persist(entity);
if (theEntity.getId() == null) {
myEntityManager.persist(theEntity);
if (entity.getForcedId() != null) {
myEntityManager.persist(entity.getForcedId());
if (theEntity.getForcedId() != null) {
myEntityManager.persist(theEntity.getForcedId());
}
} else {
entity = myEntityManager.merge(entity);
theEntity = myEntityManager.merge(theEntity);
}
if (thePerformIndexing) {
@ -1283,10 +1283,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
myEntityManager.flush();
if (theResource != null) {
theResource.setId(entity.getIdDt());
theResource.setId(theEntity.getIdDt());
}
return entity;
return theEntity;
}
/**

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.INDEX_NOT_FOUND;
/*
* #%L
* HAPI FHIR JPA Server
@ -287,12 +288,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
Predicate typePredicate = builder.equal(from.get("myResourceType"), myResourceName);
Predicate langPredicate = from.get("myLanguage").as(String.class).in(values);
Predicate masterCodePredicate = builder.and(typePredicate, langPredicate);
Predicate notDeletedPredicate = builder.isNull(from.get("myDeleted"));
if (thePids.size() > 0) {
Predicate inPids = (from.get("myId").in(thePids));
cq.where(builder.and(masterCodePredicate, inPids));
cq.where(builder.and(masterCodePredicate, inPids, notDeletedPredicate));
} else {
cq.where(masterCodePredicate);
cq.where(builder.and(masterCodePredicate, notDeletedPredicate));
}
TypedQuery<Long> q = myEntityManager.createQuery(cq);
@ -376,6 +378,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
andPredicates.add(builder.or(orPredicates.toArray(new Predicate[0])));
}
From<ResourceTag, ResourceTable> defJoin = from.join("myResource");
Predicate notDeletedPredicatePrediate = builder.isNull(defJoin.get("myDeleted"));
andPredicates.add(notDeletedPredicatePrediate);
Predicate masterCodePredicate = builder.and(andPredicates.toArray(new Predicate[0]));
if (pids.size() > 0) {
@ -1261,11 +1267,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
if (theId.hasVersionIdPart() && Long.parseLong(theId.getVersionIdPart()) != entity.getVersion()) {
throw new InvalidRequestException("Trying to update " + theId + " but this is not the current version");
}
verifyOkToDelete(entity);
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType());
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
ResourceTable savedEntity = updateEntity(null, entity, true, new Date());
notifyWriteCompleted();
@ -1274,6 +1282,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return toMethodOutcome(savedEntity, null);
}
private void verifyOkToDelete(ResourceTable theEntity) {
TypedQuery<ResourceLink> query = myEntityManager.createQuery("SELECT l FROM ResourceLink l WHERE l.myTargetResourcePid = :target_pid", ResourceLink.class);
query.setParameter("target_pid", theEntity.getId());
query.setMaxResults(1);
List<ResourceLink> resultList = query.getResultList();
if (resultList.isEmpty()) {
return;
}
ResourceLink link = resultList.get(0);
String targetId = theEntity.getIdDt().toUnqualifiedVersionless().getValue();
String sourceId = link.getSourceResource().getIdDt().toUnqualifiedVersionless().getValue();
String sourcePath = link.getSourcePath();
throw new PreconditionFailedException("Unable to delete " + targetId + " because at least one resource has a reference to this resource. First reference found was resource " + sourceId + " in path " + sourcePath );
}
@Override
public DaoMethodOutcome deleteByUrl(String theUrl) {
StopWatch w = new StopWatch();
@ -1288,6 +1313,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
Long pid = resource.iterator().next();
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
verifyOkToDelete(entity);
// Notify interceptors
IdDt idToDelete = entity.getIdDt();
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType());
@ -1369,6 +1396,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
protected abstract List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef);
@Override
public Class<T> getResourceType() {
return myResourceType;
}
@ -2126,18 +2154,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
for (IQueryParameterType next : nextValue) {
String value = next.getValueAsQueryToken();
IIdType valueId = new IdDt(value);
try {
long valueLong = translateForcedIdToPid(valueId);
joinPids.add(valueLong);
BaseHasResource entity = readEntity(valueId);
if (entity.getDeleted() != null) {
continue;
}
joinPids.add(entity.getId());
} catch (ResourceNotFoundException e) {
// This isn't an error, just means no result found
}
}
if (joinPids.isEmpty()) {
continue;
return new HashSet<Long>();
}
}
pids = addPredicateId(pids, joinPids);
if (pids.isEmpty()) {
return new HashSet<Long>();
@ -2250,9 +2283,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
}
private DaoMethodOutcome toMethodOutcome(final ResourceTable theEntity, IResource theResource) {
DaoMethodOutcome retVal = toMethodOutcome((BaseHasResource)theEntity, theResource);
retVal.setEntity(theEntity);
return retVal;
}
private DaoMethodOutcome toMethodOutcome(final BaseHasResource theEntity, IResource theResource) {
DaoMethodOutcome outcome = new DaoMethodOutcome();
outcome.setId(theEntity.getIdDt());
outcome.setEntity(theEntity);
outcome.setResource(theResource);
if (theResource != null) {
theResource.setId(theEntity.getIdDt());

View File

@ -90,6 +90,10 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
getIncludes().add(theInclude);
}
public void addRevInclude(Include theInclude) {
getRevIncludes().add(theInclude);
}
public Integer getCount() {
return myCount;
}
@ -106,6 +110,9 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
}
public Set<Include> getRevIncludes() {
if (myRevIncludes == null) {
myRevIncludes = new HashSet<Include>();
}
return myRevIncludes;
}

View File

@ -41,16 +41,15 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.Constants;
@Entity
@Table(name = "HFJ_RES_VER", uniqueConstraints = {@UniqueConstraint(name="IDX_RES_VER_ALL", columnNames = { "RES_ID", "RES_TYPE", "RES_VER" })})
@org.hibernate.annotations.Table(appliesTo="HFJ_RES_VER", indexes= {@Index(name="IDX_RES_VER_DATE", columnNames= {"RES_UPDATED"})})
@Table(name = "HFJ_RES_VER", uniqueConstraints = { @UniqueConstraint(name = "IDX_RES_VER_ALL", columnNames = { "RES_ID", "RES_TYPE", "RES_VER" }) })
@org.hibernate.annotations.Table(appliesTo = "HFJ_RES_VER", indexes = { @Index(name = "IDX_RES_VER_DATE", columnNames = { "RES_UPDATED" }) })
public class ResourceHistoryTable extends BaseHasResource implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="PID")
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "PID")
private Long myId;
@Column(name = "RES_ID")
@ -87,13 +86,14 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
return historyTag;
}
@Override
public Long getId() {
return myId;
}
@Override
public IdDt getIdDt() {
Object id = getForcedId()==null? getResourceId() : getForcedId().getForcedId();
Object id = getForcedId() == null ? getResourceId() : getForcedId().getForcedId();
return new IdDt(getResourceType() + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
}
@ -101,11 +101,12 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
return myResourceId;
}
@Override
public String getResourceType() {
return myResourceType;
}
@Override
public Collection<ResourceHistoryTag> getTags() {
if (myTags == null) {
myTags = new ArrayList<ResourceHistoryTag>();
@ -132,11 +133,11 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
}
public void setResourceType(String theResourceType) {
myResourceType=theResourceType;
myResourceType = theResourceType;
}
public void setVersion(long theVersion) {
myResourceVersion=theVersion;
myResourceVersion = theVersion;
}
}

View File

@ -46,7 +46,7 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
public ResourceIndexedSearchParamCoords() {
}
public ResourceIndexedSearchParamCoords(String theName, String theUri, double theLatitude, double theLongitude) {
public ResourceIndexedSearchParamCoords(String theName, double theLatitude, double theLongitude) {
setParamName(theName);
setLatitude(theLatitude);
setLongitude(theLongitude);

View File

@ -141,16 +141,19 @@ public class ResourceTable extends BaseHasResource implements Serializable {
@Column(name = "RES_VER")
private long myVersion;
@Override
public ResourceTag addTag(TagDefinition theTag) {
ResourceTag tag = new ResourceTag(this, theTag);
getTags().add(tag);
return tag;
}
@Override
public Long getId() {
return myId;
}
@Override
public IdDt getIdDt() {
Object id = getForcedId() == null ? myId : getForcedId().getForcedId();
return new IdDt(myResourceType + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + myVersion);
@ -224,10 +227,12 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myResourceLinks;
}
@Override
public String getResourceType() {
return myResourceType;
}
@Override
public Collection<ResourceTag> getTags() {
if (myTags == null) {
myTags = new HashSet<ResourceTag>();
@ -235,6 +240,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myTags;
}
@Override
public long getVersion() {
return myVersion;
}
@ -428,4 +434,5 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return retVal;
}
}

View File

@ -2,6 +2,8 @@ package ca.uhn.fhir.jpa.dao;
import static org.mockito.Mockito.mock;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@ -34,6 +36,7 @@ import ca.uhn.fhir.jpa.entity.ResourceLink;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.ResourceTag;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
@ -46,6 +49,7 @@ import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
//@formatter:off
@ -57,6 +61,8 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
//@formatter:on
public class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired
protected DaoConfig myDaoConfig;
@Autowired
@Qualifier("myDeviceDaoDstu2")
protected IFhirResourceDao<Device> myDeviceDao;
@ -66,6 +72,8 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired
@Qualifier("myEncounterDaoDstu2")
protected IFhirResourceDao<Encounter> myEncounterDao;
@PersistenceContext()
protected EntityManager myEntityManager;
@Autowired
protected FhirContext myFhirCtx;
protected IServerInterceptor myInterceptor;
@ -79,9 +87,6 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myOrganizationDaoDstu2")
protected IFhirResourceDao<Organization> myOrganizationDao;
@Autowired
@Qualifier("myValueSetDaoDstu2")
protected IFhirResourceDao<ValueSet> myValueSetDao;
@Autowired
@Qualifier("myPatientDaoDstu2")
protected IFhirResourceDao<Patient> myPatientDao;
@Autowired
@ -94,14 +99,32 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myQuestionnaireResponseDaoDstu2")
protected IFhirResourceDao<QuestionnaireResponse> myQuestionnaireResponseDao;
@Autowired
@Qualifier("myResourceProvidersDstu2")
protected Object myResourceProviders;
@Autowired
@Qualifier("mySystemDaoDstu2")
protected IFhirSystemDao<Bundle> mySystemDao;
@Autowired
protected DaoConfig myDaoConfig;
@Qualifier("mySystemProviderDstu2")
protected JpaSystemProviderDstu2 mySystemProvider;
@Autowired
protected PlatformTransactionManager myTxManager;
@PersistenceContext()
protected EntityManager myEntityManager;
@Autowired
@Qualifier("myValueSetDaoDstu2")
protected IFhirResourceDao<ValueSet> myValueSetDao;
@Before
public void beforeCreateInterceptor() {
myInterceptor = mock(IServerInterceptor.class);
myDaoConfig.setInterceptors(myInterceptor);
}
@Before
@Transactional()
public void beforePurgeDatabase() {
final EntityManager entityManager = this.myEntityManager;
purgeDatabase(entityManager, myTxManager);
}
/**
* Just so that JUnit doesn't complain about no test methods in this class
@ -110,53 +133,44 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
public void doNothing() {
// nothing
}
@Before
@Transactional()
public void beforePurgeDatabase() {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager) {
TransactionTemplate txTemplate = new TransactionTemplate(theTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
entityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
entityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
return null;
}
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d").executeUpdate();
return null;
}
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d").executeUpdate();
return null;
}
});
}
@Before
public void beforeCreateInterceptor() {
myInterceptor = mock(IServerInterceptor.class);
myDaoConfig.setInterceptors(myInterceptor);
}
}

View File

@ -4,6 +4,7 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
@ -42,6 +43,7 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.model.api.IQueryParameterType;
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.Tag;
import ca.uhn.fhir.model.api.TagList;
@ -67,6 +69,7 @@ import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
@ -107,46 +110,44 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
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
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) {
int retVal = defaultString(theO1.getScheme()).compareTo(defaultString(theO2.getScheme()));
if (retVal == 0) {
retVal = defaultString(theO1.getTerm()).compareTo(defaultString(theO2.getTerm()));
}
return retVal;
}
});
thePublished.clear();
for (Tag next : tags) {
thePublished.add(next);
}
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());
}
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 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;
}
@Test
public void testChoiceParamConcept() {
Observation o1 = new Observation();
@ -314,48 +315,6 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
}
@Test
public void testCreateWithInvalidReferenceNoId() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("Organization/");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource ID"));
}
}
@Test
public void testCreateWithReferenceBadType() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("Blah/123");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Invalid resource reference"));
}
}
@Test
public void testCreateWithReferenceNoType() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("123");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource type"));
}
}
@Test
public void testCreateWithIfNoneExistBasic() {
String methodName = "testCreateWithIfNoneExistBasic";
@ -422,6 +381,48 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testCreateWithInvalidReferenceNoId() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("Organization/");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource ID"));
}
}
@Test
public void testCreateWithReferenceBadType() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("Blah/123");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Invalid resource reference"));
}
}
@Test
public void testCreateWithReferenceNoType() {
Patient p = new Patient();
p.addName().addFamily("Hello");
p.getManagingOrganization().setReference("123");
try {
myPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Does not contain resource type"));
}
}
@Test
public void testDatePeriodParamEndOnly() {
{
@ -623,6 +624,81 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testCantSearchForDeletedResourceByLanguageOrTag() {
String methodName = "testCantSearchForDeletedResourceByLanguageOrTag";
Organization org = new Organization();
org.setLanguage(new CodeDt("EN_ca"));
org.setName(methodName);
TagList tl = new TagList();
tl.add(new Tag(methodName, methodName));
ResourceMetadataKeyEnum.TAG_LIST.put(org, tl);
IIdType orgId = myOrganizationDao.create(org).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add("_language", new StringParam("EN_ca"));
assertEquals(1, myOrganizationDao.search(map).size());
map = new SearchParameterMap();
map.add("_tag", new TokenParam(methodName, methodName));
assertEquals(1, myOrganizationDao.search(map).size());
myOrganizationDao.delete(orgId);
map = new SearchParameterMap();
map.add("_language", new StringParam("EN_ca"));
assertEquals(0, myOrganizationDao.search(map).size());
map = new SearchParameterMap();
map.add("_tag", new TokenParam(methodName, methodName));
assertEquals(0, myOrganizationDao.search(map).size());
}
@Test
public void testDeleteFailsIfIncomingLinks() {
String methodName = "testDeleteFailsIfIncomingLinks";
Organization org = new Organization();
org.setName(methodName);
IIdType orgId = myOrganizationDao.create(org).getId().toUnqualifiedVersionless();
Patient patient = new Patient();
patient.addName().addFamily(methodName);
patient.getManagingOrganization().setReference(orgId);
IIdType patId = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add("_id", new StringParam(orgId.getIdPart()));
map.addRevInclude(new Include("*"));
List<IIdType> found = toUnqualifiedVersionlessIds(myOrganizationDao.search(map));
assertThat(found, contains(orgId, patId));
try {
myOrganizationDao.delete(orgId);
fail();
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("Unable to delete Organization/" + orgId.getIdPart() + " because at least one resource has a reference to this resource. First reference found was resource Patient/" + patId.getIdPart() + " in path Patient.managingOrganization"));
}
myPatientDao.delete(patId);
map = new SearchParameterMap();
map.add("_id", new StringParam(orgId.getIdPart()));
map.addRevInclude(new Include("*"));
found = toUnqualifiedVersionlessIds(myOrganizationDao.search(map));
assertThat(found, contains(orgId));
myOrganizationDao.delete(orgId);
map = new SearchParameterMap();
map.add("_id", new StringParam(orgId.getIdPart()));
map.addRevInclude(new Include("*"));
found = toUnqualifiedVersionlessIds(myOrganizationDao.search(map));
assertThat(found, empty());
}
@Test
public void testDeleteThenUndelete() {
Patient patient = new Patient();
@ -717,6 +793,155 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertNotEquals(idv1, idv2);
}
@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;
int halfSize = 50;
int fullSize = 100;
for (int i = 0; i < fullSize; i++) {
if (i == halfSize) {
Thread.sleep(fullSize);
middleDate = new Date();
Thread.sleep(fullSize);
}
patient.setId(id);
patient.getName().get(0).getFamily().get(0).setValue(methodName + "_i");
myPatientDao.update(patient);
}
// By instance
IBundleProvider history = myPatientDao.history(id, null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - 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);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(middleDate);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(middleDate);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
/*
* Now delete the most recent version and make sure everything still works
*/
myPatientDao.delete(id.toVersionless());
fullSize++;
halfSize++;
// By instance
history = myPatientDao.history(id, null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(null);
assertEquals(fullSize + 1, history.size());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - 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);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By type
history = myPatientDao.history(middleDate);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
// By server
history = mySystemDao.history(middleDate);
assertEquals(halfSize, history.size());
for (int i = 0; i < halfSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
String actual = history.getResources(i, i + 1).get(0).getIdElement().getValue();
assertEquals(expected, actual);
}
}
@Test
public void testHistoryWithDeletedResource() throws Exception {
String methodName = "testHistoryWithDeletedResource";
@ -745,80 +970,6 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
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
public void testIdParam() {
Patient patient = new Patient();
@ -891,6 +1042,141 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
}
@Test
public void testInstanceMetaOperations() {
String methodName = "testMetaRead";
IIdType id;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue(methodName);
TagList tagList = new TagList();
tagList.addTag("tag_scheme1", "tag_code1", "tag_display1");
tagList.addTag("tag_scheme2", "tag_code2", "tag_display2");
ResourceMetadataKeyEnum.TAG_LIST.put(patient, tagList);
List<BaseCodingDt> securityLabels = new ArrayList<BaseCodingDt>();
securityLabels.add(new CodingDt().setSystem("seclabel_sys1").setCode("seclabel_code1").setDisplay("seclabel_dis1"));
securityLabels.add(new CodingDt().setSystem("seclabel_sys2").setCode("seclabel_code2").setDisplay("seclabel_dis2"));
ResourceMetadataKeyEnum.SECURITY_LABELS.put(patient, securityLabels);
ArrayList<IdDt> profiles = new ArrayList<IdDt>();
profiles.add(new IdDt("http://profile/1"));
profiles.add(new IdDt("http://profile/2"));
ResourceMetadataKeyEnum.PROFILES.put(patient, profiles);
id = myPatientDao.create(patient).getId();
}
assertTrue(id.hasVersionIdPart());
/*
* Create a second version
*/
Patient pt = myPatientDao.read(id);
pt.addName().addFamily("anotherName");
myPatientDao.update(pt);
/*
* Meta-Delete on previous version
*/
MetaDt meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
MetaDt newMeta = myPatientDao.metaDeleteOperation(id.withVersion("1"), meta);
assertEquals(1, newMeta.getProfile().size());
assertEquals(1, newMeta.getSecurity().size());
assertEquals(1, newMeta.getTag().size());
assertEquals("tag_code2", newMeta.getTag().get(0).getCode());
assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode());
/*
* Meta Read on Version
*/
meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(1, meta.getProfile().size());
assertEquals(1, meta.getSecurity().size());
assertEquals(1, meta.getTag().size());
assertEquals("tag_code2", meta.getTag().get(0).getCode());
assertEquals("http://profile/2", meta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", meta.getSecurity().get(0).getCode());
/*
* Meta-read on Version 2
*/
meta = myPatientDao.metaGetOperation(id.withVersion("2"));
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
/*
* Meta-read on latest version
*/
meta = myPatientDao.metaGetOperation(id.toVersionless());
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
assertEquals("2", meta.getVersionId());
/*
* Meta-Add on previous version
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaAddOperation(id.withVersion("1"), meta);
assertEquals(2, newMeta.getProfile().size());
assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size());
/*
* Meta Read on Version
*/
meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
assertEquals("1", meta.getVersionId());
/*
* Meta delete on latest
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaDeleteOperation(id.toVersionless(), meta);
assertEquals(1, newMeta.getProfile().size());
assertEquals(1, newMeta.getSecurity().size());
assertEquals(1, newMeta.getTag().size());
assertEquals("tag_code2", newMeta.getTag().get(0).getCode());
assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode());
/*
* Meta-Add on latest version
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaAddOperation(id.toVersionless(), meta);
assertEquals(2, newMeta.getProfile().size());
assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size());
assertEquals("2", newMeta.getVersionId());
}
/**
* See #196
*/
@ -1217,138 +1503,42 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testInstanceMetaOperations() {
String methodName = "testMetaRead";
IIdType id;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue(methodName);
TagList tagList = new TagList();
tagList.addTag("tag_scheme1", "tag_code1", "tag_display1");
tagList.addTag("tag_scheme2", "tag_code2", "tag_display2");
ResourceMetadataKeyEnum.TAG_LIST.put(patient, tagList);
public void testReadWithDeletedResource() {
String methodName = "testReadWithDeletedResource";
List<BaseCodingDt> securityLabels = new ArrayList<BaseCodingDt>();
securityLabels.add(new CodingDt().setSystem("seclabel_sys1").setCode("seclabel_code1").setDisplay("seclabel_dis1"));
securityLabels.add(new CodingDt().setSystem("seclabel_sys2").setCode("seclabel_code2").setDisplay("seclabel_dis2"));
ResourceMetadataKeyEnum.SECURITY_LABELS.put(patient, securityLabels);
Patient patient = new Patient();
patient.addName().addFamily(methodName);
IIdType id = myPatientDao.create(patient).getId().toVersionless();
myPatientDao.delete(id);
ArrayList<IdDt> profiles = new ArrayList<IdDt>();
profiles.add(new IdDt("http://profile/1"));
profiles.add(new IdDt("http://profile/2"));
ResourceMetadataKeyEnum.PROFILES.put(patient, profiles);
id = myPatientDao.create(patient).getId();
try {
myPatientDao.read(id);
fail();
} catch (ResourceGoneException e) {
// good
}
assertTrue(id.hasVersionIdPart());
patient.setId(id);
patient.addAddress().addLine("AAA");
myPatientDao.update(patient);
/*
* Create a second version
*/
Patient p;
Patient pt = myPatientDao.read(id);
pt.addName().addFamily("anotherName");
myPatientDao.update(pt);
p = myPatientDao.read(id);
assertEquals(1, (p).getName().size());
/*
* Meta-Delete on previous version
*/
p = myPatientDao.read(id.withVersion("1"));
assertEquals(1, (p).getName().size());
MetaDt meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
MetaDt newMeta = myPatientDao.metaDeleteOperation(id.withVersion("1"), meta);
assertEquals(1, newMeta.getProfile().size());
assertEquals(1, newMeta.getSecurity().size());
assertEquals(1, newMeta.getTag().size());
assertEquals("tag_code2", newMeta.getTag().get(0).getCode());
assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode());
/*
* Meta Read on Version
*/
meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(1, meta.getProfile().size());
assertEquals(1, meta.getSecurity().size());
assertEquals(1, meta.getTag().size());
assertEquals("tag_code2", meta.getTag().get(0).getCode());
assertEquals("http://profile/2", meta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", meta.getSecurity().get(0).getCode());
/*
* Meta-read on Version 2
*/
meta = myPatientDao.metaGetOperation(id.withVersion("2"));
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
/*
* Meta-read on latest version
*/
meta = myPatientDao.metaGetOperation(id.toVersionless());
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
assertEquals("2", meta.getVersionId());
/*
* Meta-Add on previous version
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaAddOperation(id.withVersion("1"), meta);
assertEquals(2, newMeta.getProfile().size());
assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size());
/*
* Meta Read on Version
*/
meta = myPatientDao.metaGetOperation(id.withVersion("1"));
assertEquals(2, meta.getProfile().size());
assertEquals(2, meta.getSecurity().size());
assertEquals(2, meta.getTag().size());
assertEquals("1", meta.getVersionId());
/*
* Meta delete on latest
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaDeleteOperation(id.toVersionless(), meta);
assertEquals(1, newMeta.getProfile().size());
assertEquals(1, newMeta.getSecurity().size());
assertEquals(1, newMeta.getTag().size());
assertEquals("tag_code2", newMeta.getTag().get(0).getCode());
assertEquals("http://profile/2", newMeta.getProfile().get(0).getValue());
assertEquals("seclabel_code2", newMeta.getSecurity().get(0).getCode());
/*
* Meta-Add on latest version
*/
meta = new MetaDt();
meta.addTag().setSystem("tag_scheme1").setCode("tag_code1");
meta.addProfile("http://profile/1");
meta.addSecurity().setSystem("seclabel_sys1").setCode("seclabel_code1");
newMeta = myPatientDao.metaAddOperation(id.toVersionless(), meta);
assertEquals(2, newMeta.getProfile().size());
assertEquals(2, newMeta.getSecurity().size());
assertEquals(2, newMeta.getTag().size());
assertEquals("2", newMeta.getVersionId());
try {
myPatientDao.read(id.withVersion("2"));
fail();
} catch (ResourceGoneException e) {
// good
}
p = myPatientDao.read(id.withVersion("3"));
assertEquals(1, (p).getName().size());
}
@Test
@ -1989,6 +2179,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Cat", published.get(1).getTerm());
assertEquals("Kittens", published.get(1).getLabel());
assertEquals("http://foo", published.get(1).getScheme());
List<BaseCodingDt> secLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved);
sortCodings(secLabels);
assertEquals(2, secLabels.size());
@ -2001,19 +2192,24 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
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/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
assertEquals("http://profile/1", profiles.get(0).getValue());
assertEquals("http://profile/2", profiles.get(1).getValue());
List<Patient> search = toList(myPatientDao.search(Patient.SP_IDENTIFIER, patient.getIdentifierFirstRep()));
assertEquals(1, search.size());
retrieved = search.get(0);
published = (TagList) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
sort(published);
assertEquals("Dog", published.get(0).getTerm());
assertEquals("Puppies", published.get(0).getLabel());
assertEquals(null, published.get(0).getScheme());
assertEquals("Cat", published.get(1).getTerm());
assertEquals("Kittens", published.get(1).getLabel());
assertEquals("http://foo", published.get(1).getScheme());
secLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved);
sortCodings(secLabels);
assertEquals(2, secLabels.size());
assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
assertEquals("seclabel:code:1", secLabels.get(0).getCodeElement().getValue());
@ -2021,25 +2217,32 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("seclabel:sys:2", secLabels.get(1).getSystemElement().getValue());
assertEquals("seclabel:code:2", secLabels.get(1).getCodeElement().getValue());
assertEquals("seclabel:dis:2", secLabels.get(1).getDisplayElement().getValue());
assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size());
assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue());
assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
profiles = ResourceMetadataKeyEnum.PROFILES.get(retrieved);
profiles = sortIds(profiles);
assertEquals(2, profiles.size());
assertEquals("http://profile/1", profiles.get(0).getValue());
assertEquals("http://profile/2", profiles.get(1).getValue());
myPatientDao.addTag(patientId, TagTypeEnum.TAG, "http://foo", "Cat", "Kittens");
myPatientDao.addTag(patientId, TagTypeEnum.TAG, "http://foo", "Cow", "Calves");
retrieved = myPatientDao.read(patientId);
published = (TagList) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
sort(published);
assertEquals(3, published.size());
assertEquals("Dog", published.get(0).getTerm());
assertEquals("Puppies", published.get(0).getLabel());
assertEquals(null, published.get(0).getScheme());
assertEquals("Cat", published.get(1).getTerm());
assertEquals("Kittens", published.get(1).getLabel());
assertEquals("http://foo", published.get(1).getScheme());
assertEquals("Cow", published.get(2).getTerm());
assertEquals("Calves", published.get(2).getLabel());
assertEquals("http://foo", published.get(2).getScheme());
assertEquals(published.toString(), "Dog", published.get(0).getTerm());
assertEquals(published.toString(), "Puppies", published.get(0).getLabel());
assertEquals(published.toString(), null, published.get(0).getScheme());
assertEquals(published.toString(), "Cat", published.get(1).getTerm());
assertEquals(published.toString(), "Kittens", published.get(1).getLabel());
assertEquals(published.toString(), "http://foo", published.get(1).getScheme());
assertEquals(published.toString(), "Cow", published.get(2).getTerm());
assertEquals(published.toString(), "Calves", published.get(2).getLabel());
assertEquals(published.toString(), "http://foo", published.get(2).getScheme());
secLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(retrieved);
sortCodings(secLabels);
assertEquals(2, secLabels.size());
assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
assertEquals("seclabel:code:1", secLabels.get(0).getCodeElement().getValue());
@ -2047,41 +2250,13 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("seclabel:sys:2", secLabels.get(1).getSystemElement().getValue());
assertEquals("seclabel:code:2", secLabels.get(1).getCodeElement().getValue());
assertEquals("seclabel:dis:2", secLabels.get(1).getDisplayElement().getValue());
assertEquals(2, ResourceMetadataKeyEnum.PROFILES.get(retrieved).size());
assertEquals("http://profile/1", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(0).getValue());
assertEquals("http://profile/2", ResourceMetadataKeyEnum.PROFILES.get(retrieved).get(1).getValue());
}
profiles = ResourceMetadataKeyEnum.PROFILES.get(retrieved);
profiles = sortIds(profiles);
assertEquals(2, profiles.size());
assertEquals("http://profile/1", profiles.get(0).getValue());
assertEquals("http://profile/2", profiles.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

View File

@ -49,16 +49,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
@ -105,26 +101,18 @@ import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.rest.gclient.TokenClientParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class ResourceProviderDstu2Test extends BaseJpaTest {
public class ResourceProviderDstu2Test extends BaseJpaDstu2Test {
private static ClassPathXmlApplicationContext ourAppCtx;
private static IGenericClient ourClient;
private static FhirContext ourCtx = FhirContext.forDstu2();
private static DaoConfig ourDaoConfig;
private static CloseableHttpClient ourHttpClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static int ourPort;
private static Server ourServer;
private static String ourServerBase;
@ -138,28 +126,30 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
private void delete(String theResourceType, String theParamName, String theParamValue) {
Bundle resources;
do {
IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
if (theParamName != null) {
forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
}
resources = forResource.execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
} while (resources.size() > 0);
}
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
ourLog.info("Deleting resource: {}", next.getId());
ourClient.delete().resource(next).execute();
}
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = ourClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// }
@Test
public void testBundleCreate() throws Exception {
@ -172,7 +162,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = client.read().resource(ca.uhn.fhir.model.dstu2.resource.Bundle.class).withId(id).execute();
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
}
@Test
@ -192,7 +182,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testCountParam() throws Exception {
// NB this does not get used- The paging provider has its own limits built in
ourDaoConfig.setHardSearchLimit(100);
myDaoConfig.setHardSearchLimit(100);
List<IBaseResource> resources = new ArrayList<IBaseResource>();
for (int i = 0; i < 100; i++) {
@ -250,7 +240,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = ourCtx.newXmlParser().encodeResourceToString(pt);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?name=" + methodName);
@ -322,10 +312,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testDeepChaining() {
delete("Location", Location.SP_NAME, "testDeepChainingL1");
delete("Location", Location.SP_NAME, "testDeepChainingL2");
deleteToken("Encounter", Encounter.SP_IDENTIFIER, "urn:foo", "testDeepChainingE1");
Location l1 = new Location();
l1.getNameElement().setValue("testDeepChainingL1");
IIdType l1id = ourClient.create().resource(l1).execute().getId();
@ -365,7 +351,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = ourCtx.newXmlParser().encodeResourceToString(pt);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -409,7 +395,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Patient pt = new Patient();
pt.addName().addFamily(methodName);
pt.addIdentifier().setSystem("http://ghh.org/patient").setValue(methodName);
String resource = ourCtx.newXmlParser().encodeResourceToString(pt);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -491,8 +477,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
*/
@Test
public void testDocumentManifestResources() throws Exception {
ourCtx.getResourceDefinition(Practitioner.class);
ourCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
myFhirCtx.getResourceDefinition(Practitioner.class);
myFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
IGenericClient client = ourClient;
@ -531,7 +517,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testEverythingDoesntRepeatPatient() throws Exception {
ca.uhn.fhir.model.dstu2.resource.Bundle b;
b = ourCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
b = myFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
List<IdDt> ids = new ArrayList<IdDt>();
@ -600,7 +586,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
IdDt patientId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
assertEquals("Patient", patientId.getResourceType());
@ -794,17 +780,28 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
@Test
public void testSaveAndRetrieveExistingNarrative() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSaveAndRetrieveExistingNarrative01");
public void testSaveAndRetrieveExistingNarrativeJson() {
Patient p1 = new Patient();
p1.getText().setStatus(ca.uhn.fhir.model.dstu2.valueset.NarrativeStatusEnum.GENERATED);
p1.getText().getDiv().setValueAsString("<div>HELLO WORLD</div>");
p1.addIdentifier().setSystem("urn:system").setValue("testSaveAndRetrieveExistingNarrative01");
IIdType newId = ourClient.create().resource(p1).execute().getId();
IIdType newId = ourClient.create().resource(p1).encodedJson().execute().getId();
Patient actual = ourClient.read(Patient.class, (UriDt) newId);
Patient actual = ourClient.read().resource(Patient.class).withId(newId).encodedJson().execute();
assertEquals("<div>HELLO WORLD</div>", actual.getText().getDiv().getValueAsString());
}
@Test
public void testSaveAndRetrieveExistingNarrativeXml() {
Patient p1 = new Patient();
p1.getText().setStatus(ca.uhn.fhir.model.dstu2.valueset.NarrativeStatusEnum.GENERATED);
p1.getText().getDiv().setValueAsString("<div>HELLO WORLD</div>");
p1.addIdentifier().setSystem("urn:system").setValue("testSaveAndRetrieveExistingNarrative01");
IIdType newId = ourClient.create().resource(p1).encodedXml().execute().getId();
Patient actual = ourClient.read().resource(Patient.class).withId(newId).encodedXml().execute();
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">HELLO WORLD</div>", actual.getText().getDiv().getValueAsString());
}
@ -856,9 +853,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testSearchByIdentifier() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier01");
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier02");
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testSearchByIdentifier01");
p1.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven01");
@ -888,7 +882,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testSearchByIdentifierWithoutSystem() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "", "testSearchByIdentifierWithoutSystem01");
Patient p1 = new Patient();
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
@ -902,8 +895,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testSearchByResourceChain() {
delete("Organization", Organization.SP_NAME, "testSearchByResourceChainName01");
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByResourceChain01");
Organization o1 = new Organization();
o1.setName("testSearchByResourceChainName01");
@ -1036,7 +1027,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
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);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = myFhirCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp);
matches = bundle.getTotal();
assertThat(matches, greaterThan(0));
@ -1104,8 +1095,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
public void testSearchWithMissing() throws Exception {
ourLog.info("Starting testSearchWithMissing");
delete("Organization", null, null);
String methodName = "testSearchWithMissing";
Organization org = new Organization();
@ -1334,15 +1323,15 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
// Read back directly from the DAO
{
Organization returned = ourOrganizationDao.read(orgId);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
Organization returned = myOrganizationDao.read(orgId);
String val = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
// Read back through the HTTP API
{
Organization returned = ourClient.read(Organization.class, orgId);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
String val = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
@ -1350,8 +1339,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testTryToCreateResourceWithReferenceThatDoesntExist() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testTryToCreateResourceWithReferenceThatDoesntExist01");
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testTryToCreateResourceWithReferenceThatDoesntExist01");
p1.addName().addFamily("testTryToCreateResourceWithReferenceThatDoesntExistFamily01").addGiven("testTryToCreateResourceWithReferenceThatDoesntExistGiven01");
@ -1366,9 +1353,9 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
@Test
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testUpdateRejectsInvalidTypes");
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
@ -1399,7 +1386,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = ourCtx.newXmlParser().encodeResourceToString(pt);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -1434,7 +1421,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = ourCtx.newXmlParser().encodeResourceToString(pt);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -1461,7 +1448,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
String responseString = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
Patient respPt = ourCtx.newXmlParser().parseResource(Patient.class, responseString);
Patient respPt = myFhirCtx.newXmlParser().parseResource(Patient.class, responseString);
assertEquals("2", respPt.getId().getVersionIdPart());
InstantDt updateTime = ResourceMetadataKeyEnum.UPDATED.get(respPt);
@ -1475,8 +1462,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testUpdateWithClientSuppliedIdWhichDoesntExist() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2");
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2");
MethodOutcome outcome = ourClient.update().resource(p1).withId("testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2").execute();
@ -1501,7 +1486,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Parameters input = new Parameters();
input.addParameter().setName("resource").setResource(patient);
String inputStr = ourCtx.newXmlParser().encodeResourceToString(input);
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(input);
ourLog.info(inputStr);
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
@ -1529,7 +1514,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Parameters input = new Parameters();
input.addParameter().setName("resource").setResource(patient);
String inputStr = ourCtx.newXmlParser().encodeResourceToString(input);
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(input);
ourLog.info(inputStr);
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
@ -1556,7 +1541,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Parameters input = new Parameters();
input.addParameter().setName("resource").setResource(patient);
String inputStr = ourCtx.newXmlParser().encodeResourceToString(input);
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(input);
ourLog.info(inputStr);
HttpPost post = new HttpPost(ourServerBase + "/Patient/123/$validate");
@ -1576,7 +1561,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@Test
public void testValueSetExpandOperation() throws IOException {
ValueSet upload = ourCtx.newXmlParser().parseResource(ValueSet.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/extensional-case-2.xml")));
ValueSet upload = myFhirCtx.newXmlParser().parseResource(ValueSet.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/extensional-case-2.xml")));
IIdType vsid = ourClient.create().resource(upload).execute().getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/ValueSet/" + vsid.getIdPart() + "/$expand");
@ -1673,63 +1658,61 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
ourAppCtx.stop();
ourHttpClient.close();
}
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
@After
public void after() {
myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
}
RestfulServer restServer = new RestfulServer(ourCtx);
restServer.setFhirContext(ourCtx);
@SuppressWarnings({ "unchecked", "rawtypes" })
@Before
public void before() throws Exception {
myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
myFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
ourServerBase = "http://localhost:" + ourPort + "/fhir/context";
if (ourServer == null) {
ourPort = RandomServerPortProvider.findFreePort();
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
RestfulServer restServer = new RestfulServer(myFhirCtx);
ourDaoConfig = (DaoConfig) ourAppCtx.getBean(DaoConfig.class);
ourServerBase = "http://localhost:" + ourPort + "/fhir/context";
ourOrganizationDao = (IFhirResourceDao<Organization>) ourAppCtx.getBean("myOrganizationDaoDstu2", IFhirResourceDao.class);
restServer.setResourceProviders((List)myResourceProviders);
List<IResourceProvider> rpsDev = (List<IResourceProvider>) ourAppCtx.getBean("myResourceProvidersDstu2", List.class);
restServer.setResourceProviders(rpsDev);
restServer.getFhirContext().setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
restServer.getFhirContext().setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
restServer.setPlainProviders(mySystemProvider);
JpaSystemProviderDstu2 systemProv = ourAppCtx.getBean(JpaSystemProviderDstu2.class, "mySystemProviderDstu2");
restServer.setPlainProviders(systemProv);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(restServer, mySystemDao);
confProvider.setImplementationDescription("THIS IS THE DESC");
restServer.setServerConformanceProvider(confProvider);
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle> systemDao = ourAppCtx.getBean(IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(restServer, systemDao);
confProvider.setImplementationDescription("THIS IS THE DESC");
restServer.setServerConformanceProvider(confProvider);
restServer.setPagingProvider(new FifoMemoryPagingProvider(10));
restServer.setPagingProvider(new FifoMemoryPagingProvider(10));
Server server = new Server(ourPort);
ourServer = new Server(ourPort);
ServletContextHandler proxyHandler = new ServletContextHandler();
proxyHandler.setContextPath("/");
ServletContextHandler proxyHandler = new ServletContextHandler();
proxyHandler.setContextPath("/");
ServletHolder servletHolder = new ServletHolder();
servletHolder.setServlet(restServer);
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
ServletHolder servletHolder = new ServletHolder();
servletHolder.setServlet(restServer);
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
server.setHandler(proxyHandler);
server.start();
ourServer.setHandler(proxyHandler);
ourServer.start();
ourClient = myFhirCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true));
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true));
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourHttpClient = builder.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourHttpClient = builder.build();
ourServer = server;
}
}
}

View File

@ -186,6 +186,9 @@
JPA server now correctly suppresses contents of deleted resources
in history
</action>
<action type="fix" issue="222">
JPA server returned deleted resources in search results when using the _tag, _id, _profile, or _security search parameters
</action>
</release>
<release version="1.1" date="2015-07-13">
<action type="add">

View File

@ -26,7 +26,7 @@
<li>
<b>Resource Validation</b>
is validation of the parsed (or constructed) resource against
the official FHIR validation rules (e.g. Schema/Schematron).
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet).
</li>
</ul>