Support URI (and prepare for lat/lon search params) in JPA server, and
don't store duplicate tags
This commit is contained in:
parent
b6f6340eb9
commit
97e6073665
|
@ -37,6 +37,8 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
*/
|
||||
public class Tag extends BaseElement implements IElement {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String ATTR_LABEL = "label";
|
||||
public static final String ATTR_SCHEME = "scheme";
|
||||
public static final String ATTR_TERM = "term";
|
||||
|
|
|
@ -633,8 +633,9 @@ class ParserState<T> {
|
|||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
if (myJsonMode) {
|
||||
string(theValue);
|
||||
} else {
|
||||
super.attributeValue(theName, theValue);
|
||||
}
|
||||
super.attributeValue(theName, theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
/build/
|
||||
/target/
|
||||
/target/
|
||||
|
|
|
@ -31,6 +31,9 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
|
||||
IGenericClient client = newClient(ctx);
|
||||
|
||||
int total;
|
||||
int count;
|
||||
|
||||
// String vsContents =
|
||||
// IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/valuesets.xml"),
|
||||
// "UTF-8");
|
||||
|
@ -50,12 +53,8 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
//
|
||||
// ourLog.info("Finished uploading ValueSets");
|
||||
|
||||
String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
|
||||
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||
|
||||
int total;
|
||||
int count;
|
||||
|
||||
// String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
|
||||
// Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||
// total = bundle.getEntry().size();
|
||||
// count = 1;
|
||||
// for (BundleEntryComponent i : bundle.getEntry()) {
|
||||
|
@ -68,6 +67,22 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
// count++;
|
||||
// }
|
||||
|
||||
|
||||
String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v2-tables.xml"), "UTF-8");
|
||||
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||
total = bundle.getEntry().size();
|
||||
count = 1;
|
||||
for (BundleEntryComponent i : bundle.getEntry()) {
|
||||
if (count > 1900) {
|
||||
ValueSet next = (ValueSet) i.getResource();
|
||||
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||
|
||||
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||
client.update().resource(next).execute();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
ourLog.info("Finished uploading ValueSets");
|
||||
|
||||
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
@ -75,12 +90,13 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
total = mappingLocations.length;
|
||||
count = 1;
|
||||
for (Resource i : mappingLocations) {
|
||||
if (count > 140) {
|
||||
StructureDefinition next = ctx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(i.getInputStream(), "UTF-8"));
|
||||
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||
|
||||
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||
client.update().resource(next).execute();
|
||||
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ delete from hfj_spidx_quantity where res_id in (select res_id from hfj_resource
|
|||
delete from hfj_spidx_string where res_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
delete from hfj_spidx_token where res_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
delete from hfj_res_link where src_resource_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
delete from hfj_res_link where target_resource_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
delete from hfj_res_tag where res_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
delete from hfj_resource where res_id in (select res_id from hfj_resource where sp_index_status = 2);
|
||||
|
||||
|
|
|
@ -77,11 +77,13 @@ import ca.uhn.fhir.jpa.entity.ForcedId;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
|
@ -255,10 +257,17 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
return mySearchParamExtractor.extractSearchParamDates(theEntity, theResource);
|
||||
}
|
||||
|
||||
protected ArrayList<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
|
||||
protected List<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamNumber(theEntity, theResource);
|
||||
}
|
||||
|
||||
protected List<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamUri(theEntity, theResource);
|
||||
}
|
||||
protected List<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamCoords(theEntity, theResource);
|
||||
}
|
||||
|
||||
protected List<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantity(theEntity, theResource);
|
||||
}
|
||||
|
@ -611,10 +620,13 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
Set<TagDefinition> allDefs = new HashSet<TagDefinition>();
|
||||
|
||||
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(theResource);
|
||||
if (tagList != null) {
|
||||
for (Tag next : tagList) {
|
||||
TagDefinition tag = getTag(TagTypeEnum.TAG, next.getScheme(), next.getTerm(), next.getLabel());
|
||||
allDefs.add(tag);
|
||||
theEntity.addTag(tag);
|
||||
theEntity.setHasTags(true);
|
||||
}
|
||||
|
@ -624,6 +636,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
if (securityLabels != null) {
|
||||
for (BaseCodingDt next : securityLabels) {
|
||||
TagDefinition tag = getTag(TagTypeEnum.SECURITY_LABEL, next.getSystemElement().getValue(), next.getCodeElement().getValue(), next.getDisplayElement().getValue());
|
||||
allDefs.add(tag);
|
||||
theEntity.addTag(tag);
|
||||
theEntity.setHasTags(true);
|
||||
}
|
||||
|
@ -633,11 +646,24 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
if (profiles != null) {
|
||||
for (IIdType next : profiles) {
|
||||
TagDefinition tag = getTag(TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
||||
allDefs.add(tag);
|
||||
theEntity.addTag(tag);
|
||||
theEntity.setHasTags(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (ResourceTag next : new ArrayList<ResourceTag>(theEntity.getTags())) {
|
||||
TagDefinition nextDef = next.getTag();
|
||||
if (!allDefs.contains(nextDef)) {
|
||||
theEntity.getTags().remove(next);
|
||||
}
|
||||
}
|
||||
if (theEntity.getTags().size() == 0) {
|
||||
theEntity.setHasTags(false);
|
||||
}
|
||||
|
||||
|
||||
String title = ResourceMetadataKeyEnum.TITLE.get(theResource);
|
||||
if (title != null && title.length() > BaseHasResource.MAX_TITLE_LENGTH) {
|
||||
title = title.substring(0, BaseHasResource.MAX_TITLE_LENGTH);
|
||||
|
@ -1065,11 +1091,22 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
entity.setVersion(entity.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();
|
||||
|
||||
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());
|
||||
|
||||
List<ResourceIndexedSearchParamString> stringParams = null;
|
||||
|
@ -1077,6 +1114,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
List<ResourceIndexedSearchParamNumber> numberParams = null;
|
||||
List<ResourceIndexedSearchParamQuantity> quantityParams = null;
|
||||
List<ResourceIndexedSearchParamDate> dateParams = null;
|
||||
List<ResourceIndexedSearchParamUri> uriParams = null;
|
||||
List<ResourceIndexedSearchParamCoords> coordsParams = null;
|
||||
List<ResourceLink> links = null;
|
||||
|
||||
if (theDeletedTimestampOrNull != null) {
|
||||
|
@ -1086,6 +1125,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
numberParams = Collections.emptyList();
|
||||
quantityParams = Collections.emptyList();
|
||||
dateParams = Collections.emptyList();
|
||||
uriParams = Collections.emptyList();
|
||||
coordsParams = Collections.emptyList();
|
||||
links = Collections.emptyList();
|
||||
entity.setDeleted(theDeletedTimestampOrNull);
|
||||
entity.setUpdated(theDeletedTimestampOrNull);
|
||||
|
@ -1100,6 +1141,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
numberParams = extractSearchParamNumber(entity, theResource);
|
||||
quantityParams = extractSearchParamQuantity(entity, theResource);
|
||||
dateParams = extractSearchParamDates(entity, theResource);
|
||||
uriParams = extractSearchParamUri(entity, theResource);
|
||||
coordsParams = extractSearchParamCoords(entity, theResource);
|
||||
|
||||
// ourLog.info("Indexing resource: {}", entity.getId());
|
||||
ourLog.trace("Storing string indexes: {}", stringParams);
|
||||
|
@ -1115,6 +1158,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
links = extractResourceLinks(entity, theResource);
|
||||
populateResourceIntoEntity(theResource, entity);
|
||||
|
||||
entity.setUpdated(new Date());
|
||||
entity.setLanguage(theResource.getLanguage().getValue());
|
||||
entity.setParamsString(stringParams);
|
||||
|
@ -1127,6 +1171,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
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);
|
||||
|
@ -1155,7 +1203,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
if (thePerformIndexing) {
|
||||
|
||||
if (entity.isParamsStringPopulated()) {
|
||||
if (paramsStringPopulated) {
|
||||
for (ResourceIndexedSearchParamString next : paramsString) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
@ -1164,7 +1212,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsTokenPopulated()) {
|
||||
if (paramsTokenPopulated) {
|
||||
for (ResourceIndexedSearchParamToken next : paramsToken) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
@ -1173,7 +1221,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsNumberPopulated()) {
|
||||
if (paramsNumberPopulated) {
|
||||
for (ResourceIndexedSearchParamNumber next : paramsNumber) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
@ -1182,7 +1230,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsQuantityPopulated()) {
|
||||
if (paramsQuantityPopulated) {
|
||||
for (ResourceIndexedSearchParamQuantity next : paramsQuantity) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
@ -1191,7 +1239,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsDatePopulated()) {
|
||||
// Store date SP's
|
||||
if (paramsDatePopulated) {
|
||||
for (ResourceIndexedSearchParamDate next : paramsDate) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
@ -1200,7 +1249,27 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isHasLinks()) {
|
||||
// Store URI SP's
|
||||
if (paramsUriPopulated) {
|
||||
for (ResourceIndexedSearchParamUri next : paramsUri) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamUri next : uriParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
// Store Coords SP's
|
||||
if (paramsCoordsPopulated) {
|
||||
for (ResourceIndexedSearchParamCoords next : paramsCoords) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamCoords next : coordsParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (hasLinks) {
|
||||
for (ResourceLink next : resourceLinks) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -82,6 +83,7 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
|
@ -398,7 +400,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return processMatchUrl(theMatchUrl, getResourceType());
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates,
|
||||
IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
|
@ -412,7 +415,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return missingFalse;
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates,
|
||||
IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
|
@ -501,6 +505,61 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
|
||||
private Set<Long> addPredicateUri(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsUri", theParamName, ResourceIndexedSearchParamUri.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamUri> from = cq.from(ResourceIndexedSearchParamUri.class);
|
||||
cq.select(from.get("myResourcePid").as(Long.class));
|
||||
|
||||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (params instanceof UriParam) {
|
||||
UriParam param = (UriParam) params;
|
||||
|
||||
String value = param.getValue();
|
||||
if (value == null) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
Path<Object> fromObj = from.get("myUri");
|
||||
codePredicates.add(builder.equal(fromObj.as(String.class), value));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid URI type: " + params.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0]));
|
||||
|
||||
Predicate type = builder.equal(from.get("myResourceType"), myResourceName);
|
||||
Predicate name = builder.equal(from.get("myParamName"), theParamName);
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myResourcePid").in(thePids));
|
||||
cq.where(builder.and(type, name, masterCodePredicate, inPids));
|
||||
} else {
|
||||
cq.where(builder.and(type, name, masterCodePredicate));
|
||||
}
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
|
||||
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
|
||||
String resourceType = getContext().getResourceDefinition(getResourceType()).getName();
|
||||
|
||||
|
@ -1064,7 +1123,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
}
|
||||
|
||||
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
|
||||
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
|
||||
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
|
||||
String rawSearchTerm;
|
||||
if (theParameter instanceof TokenParam) {
|
||||
TokenParam id = (TokenParam) theParameter;
|
||||
|
@ -1083,7 +1143,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed ("
|
||||
+ ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
|
||||
}
|
||||
|
||||
String likeExpression = normalizeString(rawSearchTerm);
|
||||
|
@ -1097,7 +1158,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return singleCode;
|
||||
}
|
||||
|
||||
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
|
||||
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
|
||||
From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
|
||||
String code;
|
||||
String system;
|
||||
if (theParameter instanceof TokenParam) {
|
||||
|
@ -1117,10 +1179,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
|
||||
throw new InvalidRequestException(
|
||||
"Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
|
||||
}
|
||||
if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
|
||||
throw new InvalidRequestException(
|
||||
"Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
|
||||
}
|
||||
|
||||
ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>());
|
||||
|
@ -1283,7 +1347,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
if (isNotBlank(theResource.getId().getIdPart())) {
|
||||
if (isValidPid(theResource.getId())) {
|
||||
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");
|
||||
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");
|
||||
}
|
||||
createForcedIdIfNeeded(entity, theResource.getId());
|
||||
|
||||
|
@ -1384,7 +1449,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
final T current = currentTmp;
|
||||
|
||||
String querySring = "SELECT count(h) FROM ResourceHistoryTable h " + "WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE" + " AND h.myUpdated < :END" + (theSince != null ? " AND h.myUpdated >= :SINCE" : "");
|
||||
String querySring = "SELECT count(h) FROM ResourceHistoryTable h " + "WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE" + " AND h.myUpdated < :END"
|
||||
+ (theSince != null ? " AND h.myUpdated >= :SINCE" : "");
|
||||
TypedQuery<Long> countQuery = myEntityManager.createQuery(querySring, Long.class);
|
||||
countQuery.setParameter("PID", translateForcedIdToPid(theId));
|
||||
countQuery.setParameter("RESTYPE", resourceType);
|
||||
|
@ -1422,8 +1488,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
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 " + (theSince != null ? " AND h.myUpdated >= :SINCE" : "") + " ORDER BY h.myUpdated ASC",
|
||||
ResourceHistoryTable.class);
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT h FROM ResourceHistoryTable h WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE AND h.myUpdated < :END "
|
||||
+ (theSince != null ? " AND h.myUpdated >= :SINCE" : "") + " ORDER BY h.myUpdated ASC", ResourceHistoryTable.class);
|
||||
q.setParameter("PID", translateForcedIdToPid(theId));
|
||||
q.setParameter("RESTYPE", resourceType);
|
||||
q.setParameter("END", end.getValue(), TemporalType.TIMESTAMP);
|
||||
|
@ -1509,57 +1575,101 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
}
|
||||
|
||||
private Set<Long> loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes) {
|
||||
/**
|
||||
* THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet())
|
||||
*/
|
||||
private HashSet<Long> loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode) {
|
||||
if (theMatches.size() == 0) {
|
||||
return Collections.emptySet();
|
||||
return new HashSet<Long>();
|
||||
}
|
||||
if (theRevIncludes == null || theRevIncludes.isEmpty()) {
|
||||
return new HashSet<Long>();
|
||||
}
|
||||
String fieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
|
||||
|
||||
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
||||
Collection<Long> nextRoundMatches = theMatches;
|
||||
HashSet<Long> allAdded = new HashSet<Long>();
|
||||
HashSet<Long> original = new HashSet<Long>(theMatches);
|
||||
ArrayList<Include> includes = new ArrayList<Include>(theRevIncludes);
|
||||
|
||||
for (Include nextInclude : theRevIncludes) {
|
||||
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||
if (matchAll) {
|
||||
String sql = "SELECT r FROM ResourceLink r WHERE r.myTargetResourcePid IN (:target_pids)";
|
||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||
q.setParameter("target_pids", theMatches);
|
||||
List<ResourceLink> results = q.getResultList();
|
||||
for (ResourceLink resourceLink : results) {
|
||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||
}
|
||||
} else {
|
||||
int colonIdx = nextInclude.getValue().indexOf(':');
|
||||
if (colonIdx < 2) {
|
||||
continue;
|
||||
}
|
||||
String resType = nextInclude.getValue().substring(0, colonIdx);
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(resType);
|
||||
if (def == null) {
|
||||
ourLog.warn("Unknown resource type in _revinclude=" + nextInclude.getValue());
|
||||
continue;
|
||||
boolean addedSomeThisRound;
|
||||
do {
|
||||
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
||||
|
||||
for (Iterator<Include> iter = includes.iterator(); iter.hasNext();) {
|
||||
Include nextInclude = iter.next();
|
||||
if (nextInclude.isRecurse() == false) {
|
||||
iter.remove();
|
||||
}
|
||||
|
||||
String paramName = nextInclude.getValue().substring(colonIdx + 1);
|
||||
RuntimeSearchParam param = def.getSearchParam(paramName);
|
||||
if (param == null) {
|
||||
ourLog.warn("Unknown param name in _revinclude=" + nextInclude.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String nextPath : param.getPathsSplit()) {
|
||||
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r.myTargetResourcePid IN (:target_pids)";
|
||||
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||
if (matchAll) {
|
||||
String sql;
|
||||
sql = "SELECT r FROM ResourceLink r WHERE r." + fieldName + " IN (:target_pids)";
|
||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||
q.setParameter("src_path", nextPath);
|
||||
q.setParameter("target_pids", theMatches);
|
||||
q.setParameter("target_pids", nextRoundMatches);
|
||||
List<ResourceLink> results = q.getResultList();
|
||||
for (ResourceLink resourceLink : results) {
|
||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||
if (theReverseMode) {
|
||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||
} else {
|
||||
pidsToInclude.add(resourceLink.getTargetResourcePid());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
List<String> paths;
|
||||
if (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
paths = Collections.singletonList(nextInclude.getValue());
|
||||
} else {
|
||||
int colonIdx = nextInclude.getValue().indexOf(':');
|
||||
if (colonIdx < 2) {
|
||||
continue;
|
||||
}
|
||||
String resType = nextInclude.getValue().substring(0, colonIdx);
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(resType);
|
||||
if (def == null) {
|
||||
ourLog.warn("Unknown resource type in include/revinclude=" + nextInclude.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
String paramName = nextInclude.getValue().substring(colonIdx + 1);
|
||||
RuntimeSearchParam param = def.getSearchParam(paramName);
|
||||
if (param == null) {
|
||||
ourLog.warn("Unknown param name in include/revinclude=" + nextInclude.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
paths = param.getPathsSplit();
|
||||
}
|
||||
|
||||
for (String nextPath : paths) {
|
||||
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + fieldName + " IN (:target_pids)";
|
||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||
q.setParameter("src_path", nextPath);
|
||||
q.setParameter("target_pids", nextRoundMatches);
|
||||
List<ResourceLink> results = q.getResultList();
|
||||
for (ResourceLink resourceLink : results) {
|
||||
if (theReverseMode) {
|
||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||
} else {
|
||||
pidsToInclude.add(resourceLink.getTargetResourcePid());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theMatches.addAll(pidsToInclude);
|
||||
return pidsToInclude;
|
||||
for (Long next : pidsToInclude) {
|
||||
if (original.contains(next) == false && allAdded.contains(next) == false) {
|
||||
theMatches.add(next);
|
||||
}
|
||||
}
|
||||
addedSomeThisRound = allAdded.addAll(pidsToInclude);
|
||||
nextRoundMatches = pidsToInclude;
|
||||
} while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound);
|
||||
|
||||
return allAdded;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1757,7 +1867,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
if (entity == null) {
|
||||
if (theId.hasVersionIdPart()) {
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager
|
||||
.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("RTYP", myResourceName);
|
||||
q.setParameter("RVER", Long.parseLong(theId.getVersionIdPart()));
|
||||
|
@ -1927,11 +2038,18 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
// Load _revinclude resources
|
||||
final Set<Long> revIncludedPids;
|
||||
if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) {
|
||||
revIncludedPids = loadReverseIncludes(pids, theParams.getRevIncludes());
|
||||
revIncludedPids = loadReverseIncludes(pids, theParams.getRevIncludes(), true);
|
||||
if (theParams.isEverythingMode()) {
|
||||
revIncludedPids.addAll(loadReverseIncludes(pids, theParams.getIncludes(), false));
|
||||
}
|
||||
} else {
|
||||
revIncludedPids = Collections.emptySet();
|
||||
revIncludedPids = new HashSet<Long>();
|
||||
}
|
||||
|
||||
ourLog.info("Search returned PIDs: {}", pids);
|
||||
|
||||
final int totalCount = pids.size();
|
||||
|
||||
IBundleProvider retVal = new IBundleProvider() {
|
||||
@Override
|
||||
public InstantDt getPublished() {
|
||||
|
@ -1946,73 +2064,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
public List<IBaseResource> doInTransaction(TransactionStatus theStatus) {
|
||||
List<Long> pidsSubList = pids.subList(theFromIndex, theToIndex);
|
||||
|
||||
// Load includes
|
||||
if (!theParams.isEverythingMode()) {
|
||||
pidsSubList = new ArrayList<Long>(pidsSubList);
|
||||
revIncludedPids.addAll(loadReverseIncludes(pidsSubList, theParams.getIncludes(), false));
|
||||
}
|
||||
|
||||
// Execute the query and make sure we return distinct results
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
loadResourcesByPid(pidsSubList, retVal, revIncludedPids);
|
||||
|
||||
/*
|
||||
* Load _include resources - Note that _revincludes are handled differently than _include ones, as
|
||||
* they are counted towards the total count and paged, so they are loaded outside the bundle provider
|
||||
*/
|
||||
if (theParams.getIncludes() != null && theParams.getIncludes().isEmpty() == false) {
|
||||
Set<IIdType> previouslyLoadedPids = new HashSet<IIdType>();
|
||||
for (IBaseResource next : retVal) {
|
||||
previouslyLoadedPids.add(next.getIdElement().toUnqualifiedVersionless());
|
||||
}
|
||||
|
||||
Set<IIdType> includePids = new HashSet<IIdType>();
|
||||
List<IBaseResource> resources = retVal;
|
||||
HashSet<Include> includes = new HashSet<Include>(theParams.getIncludes());
|
||||
do {
|
||||
includePids.clear();
|
||||
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (Include next : new ArrayList<Include>(includes)) {
|
||||
for (IBaseResource nextResource : resources) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(nextResource);
|
||||
List<Object> values = getIncludeValues(t, next, nextResource, def);
|
||||
|
||||
for (Object object : values) {
|
||||
if (object == null) {
|
||||
continue;
|
||||
}
|
||||
if (!(object instanceof BaseResourceReferenceDt)) {
|
||||
throw new InvalidRequestException("Path '" + next.getValue() + "' produced non ResourceReferenceDt value: " + object.getClass());
|
||||
}
|
||||
BaseResourceReferenceDt rr = (BaseResourceReferenceDt) object;
|
||||
if (rr.getReference().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (rr.getReference().isLocal()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IIdType nextId = rr.getReference().toUnqualified();
|
||||
if (!previouslyLoadedPids.contains(nextId)) {
|
||||
includePids.add(nextId);
|
||||
previouslyLoadedPids.add(nextId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only process non-recursive includes once
|
||||
if (!next.isRecurse()) {
|
||||
includes.remove(next);
|
||||
}
|
||||
}
|
||||
|
||||
resources = addResourcesAsIncludesById(retVal, includePids, resources);
|
||||
} while (includePids.size() > 0 && previouslyLoadedPids.size() < getConfig().getIncludeLimit() && includes.size() > 0);
|
||||
|
||||
if (previouslyLoadedPids.size() >= getConfig().getIncludeLimit()) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
Issue issue = oo.addIssue();
|
||||
issue.getSeverity().setValue(OO_SEVERITY_WARN);
|
||||
issue.setDetails("Not all _include resources were actually included as the request surpassed the limit of " + getConfig().getIncludeLimit() + " resources");
|
||||
retVal.add(0, oo);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -2026,7 +2087,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
@Override
|
||||
public int size() {
|
||||
return pids.size();
|
||||
return totalCount;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2175,6 +2236,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
}
|
||||
break;
|
||||
case URI:
|
||||
for (List<? extends IQueryParameterType> nextAnd : nextParamEntry.getValue()) {
|
||||
pids = addPredicateUri(nextParamName, pids, nextAnd);
|
||||
if (pids.isEmpty()) {
|
||||
return new HashSet<Long>();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2190,8 +2259,7 @@ 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) {
|
||||
mySecondaryPrimaryKeyParamName = theSecondaryPrimaryKeyParamName;
|
||||
|
@ -2319,7 +2387,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
if (resourceId.hasResourceType() && !resourceId.getResourceType().equals(getResourceName())) {
|
||||
throw new UnprocessableEntityException("Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]");
|
||||
throw new UnprocessableEntityException(
|
||||
"Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]");
|
||||
}
|
||||
|
||||
// Notify interceptors
|
||||
|
@ -2354,7 +2423,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
private void validateResourceType(BaseHasResource entity) {
|
||||
if (!myResourceName.equals(entity.getResourceType())) {
|
||||
throw new ResourceNotFoundException("Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
|
||||
throw new ResourceNotFoundException(
|
||||
"Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ public abstract class BaseHapiFhirSystemDao<T> extends BaseHapiFhirDao<IBaseReso
|
|||
try {
|
||||
dao.update(resource, null, true);
|
||||
} catch (Exception e) {
|
||||
ourLog.error("Failed to index resource {}: {}", new Object[] { resource.getIdElement(), e.toString() });
|
||||
ourLog.error("Failed to index resource {}: {}", new Object[] { resource.getIdElement(), e.toString(), e });
|
||||
throw new UnprocessableEntityException(Long.toString(resourceTable.getId()));
|
||||
}
|
||||
count++;
|
||||
|
|
|
@ -24,15 +24,19 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
interface ISearchParamExtractor {
|
||||
|
||||
public abstract List<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IResource theResource);
|
||||
|
||||
public abstract List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource);
|
||||
|
||||
public abstract ArrayList<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource);
|
||||
|
@ -43,4 +47,6 @@ interface ISearchParamExtractor {
|
|||
|
||||
public abstract List<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource);
|
||||
|
||||
public abstract List<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IResource theResource);
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -40,11 +41,13 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
|
@ -71,6 +74,11 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
super(theContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IResource theResource) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamDate> retVal = new ArrayList<ResourceIndexedSearchParamDate>();
|
||||
|
@ -123,8 +131,6 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsDatePopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -220,8 +226,6 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -270,8 +274,6 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -358,8 +360,6 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsStringPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -468,9 +468,12 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||
|
||||
}
|
||||
|
||||
theEntity.setParamsTokenPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IResource theResource) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -40,11 +41,13 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
|
@ -81,6 +84,34 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
super(theContext);
|
||||
}
|
||||
|
||||
private void addSearchTerm(ResourceTable theEntity, ArrayList<ResourceIndexedSearchParamString> retVal, String resourceName, String searchTerm) {
|
||||
if (isBlank(searchTerm)) {
|
||||
return;
|
||||
}
|
||||
if (searchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
searchTerm = searchTerm.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
}
|
||||
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseHapiFhirDao.normalizeString(searchTerm), searchTerm);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
private void addStringParam(ResourceTable theEntity, ArrayList<BaseResourceIndexedSearchParam> retVal, RuntimeSearchParam nextSpDef, String value) {
|
||||
if (value.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
value = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseHapiFhirDao.normalizeString(value), value);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IResource theResource) {
|
||||
// TODO: implement
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -138,8 +169,6 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsDatePopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -234,8 +263,6 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -290,8 +317,6 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -373,24 +398,9 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsStringPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void addSearchTerm(ResourceTable theEntity, ArrayList<ResourceIndexedSearchParamString> retVal, String resourceName, String searchTerm) {
|
||||
if (isBlank(searchTerm)) {
|
||||
return;
|
||||
}
|
||||
if (searchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
searchTerm = searchTerm.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
}
|
||||
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseHapiFhirDao.normalizeString(searchTerm), searchTerm);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -542,19 +552,62 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
|
||||
}
|
||||
|
||||
theEntity.setParamsTokenPopulated(retVal.size() > 0);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamUri> retVal = new ArrayList<ResourceIndexedSearchParamUri>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.URI) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
if (isBlank(nextPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Object nextObject : extractValues(nextPath, theResource)) {
|
||||
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
if (nextObject instanceof UriDt) {
|
||||
UriDt nextValue = (UriDt) nextObject;
|
||||
if (isBlank(nextValue.getValue())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ourLog.info("Adding param: {}, {}", resourceName, nextValue.getValue());
|
||||
|
||||
ResourceIndexedSearchParamUri nextEntity = new ResourceIndexedSearchParamUri(resourceName, nextValue.getValue());
|
||||
|
||||
ourLog.info("Added : {}", nextEntity);
|
||||
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void addStringParam(ResourceTable theEntity, ArrayList<BaseResourceIndexedSearchParam> retVal, RuntimeSearchParam nextSpDef, String value) {
|
||||
if (value.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
value = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseHapiFhirDao.normalizeString(value), value);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity,
|
||||
ArrayList<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
|
||||
|
|
|
@ -41,10 +41,10 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer myCount;
|
||||
private boolean myEverythingMode = false;
|
||||
private Set<Include> myIncludes;
|
||||
private DateRangeParam myLastUpdated;
|
||||
private Set<Include> myRevIncludes;
|
||||
|
||||
private SortSpec mySort;
|
||||
|
||||
public void add(String theName, IQueryParameterAnd<?> theAnd) {
|
||||
|
@ -113,10 +113,18 @@ public class SearchParameterMap extends HashMap<String, List<List<? extends IQue
|
|||
return mySort;
|
||||
}
|
||||
|
||||
public boolean isEverythingMode() {
|
||||
return myEverythingMode;
|
||||
}
|
||||
|
||||
public void setCount(Integer theCount) {
|
||||
myCount = theCount;
|
||||
}
|
||||
|
||||
public void setEverythingMode(boolean theConsolidateMatches) {
|
||||
myEverythingMode = theConsolidateMatches;
|
||||
}
|
||||
|
||||
public void setIncludes(Set<Include> theIncludes) {
|
||||
myIncludes = theIncludes;
|
||||
}
|
||||
|
|
|
@ -49,24 +49,28 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
@JoinColumn(name = "RES_ID", referencedColumnName="RES_ID")
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "RES_TYPE", nullable=false)
|
||||
private String myResourceType;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourcePid;
|
||||
protected Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public String getParamName() {
|
||||
return myParamName;
|
||||
}
|
||||
|
||||
public void setParamName(String theName) {
|
||||
myParamName = theName;
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public void setParamName(String theName) {
|
||||
myParamName = theName;
|
||||
}
|
||||
|
||||
public void setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
myResourceType = theResource.getResourceType();
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_COORDS" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_COORDS", indexes = {
|
||||
@org.hibernate.annotations.Index(name = "IDX_SP_COORDS", columnNames = { "RES_TYPE", "SP_NAME", "SP_LATITUDE" })
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 100;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_LATITUDE")
|
||||
public double myLatitude;
|
||||
|
||||
@Column(name = "SP_LONGITUDE")
|
||||
public double myLongitude;
|
||||
|
||||
public ResourceIndexedSearchParamCoords() {
|
||||
}
|
||||
|
||||
public ResourceIndexedSearchParamCoords(String theName, String theUri, double theLatitude, double theLongitude) {
|
||||
setParamName(theName);
|
||||
setLatitude(theLatitude);
|
||||
setLongitude(theLongitude);
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return myLatitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double theLatitude) {
|
||||
myLatitude = theLatitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return myLongitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double theLongitude) {
|
||||
myLongitude = theLongitude;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_URI" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_URI", indexes = {
|
||||
@org.hibernate.annotations.Index(name = "IDX_SP_URI", columnNames = { "RES_TYPE", "SP_NAME", "SP_URI" })
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 256;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_URI", nullable = true, length = MAX_LENGTH)
|
||||
public String myUri;
|
||||
|
||||
public ResourceIndexedSearchParamUri() {
|
||||
}
|
||||
|
||||
public ResourceIndexedSearchParamUri(String theName, String theUri) {
|
||||
setParamName(theName);
|
||||
setUri(theUri);
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return myUri;
|
||||
}
|
||||
|
||||
public void setUri(String theUri) {
|
||||
myUri = StringUtils.defaultIfBlank(theUri, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this);
|
||||
builder.append("id", getId());
|
||||
builder.append("paramName", getParamName());
|
||||
builder.append("uri", myUri);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,9 @@ import static org.apache.commons.lang3.StringUtils.*;
|
|||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
|
@ -76,12 +78,18 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
@OneToMany(mappedBy = "myTargetResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceLink> myIncomingResourceLinks;
|
||||
|
||||
@Column(name = "SP_INDEX_STATUS", nullable=true)
|
||||
@Column(name = "SP_INDEX_STATUS", nullable = true)
|
||||
private Long myIndexStatus;
|
||||
|
||||
@Column(name = "RES_LANGUAGE", length=MAX_LANGUAGE_LENGTH, nullable=true)
|
||||
@Column(name = "RES_LANGUAGE", length = MAX_LANGUAGE_LENGTH, nullable = true)
|
||||
private String myLanguage;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamCoords> myParamsCoords;
|
||||
|
||||
@Column(name = "SP_COORDS_PRESENT")
|
||||
private boolean myParamsCoordsPopulated;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamDate> myParamsDate;
|
||||
|
||||
|
@ -112,7 +120,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
@Column(name = "SP_TOKEN_PRESENT")
|
||||
private boolean myParamsTokenPopulated;
|
||||
|
||||
@Column(name = "RES_PROFILE", length=MAX_PROFILE_LENGTH,nullable=true)
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamUri> myParamsUri;
|
||||
|
||||
@Column(name = "SP_URI_PRESENT")
|
||||
private boolean myParamsUriPopulated;
|
||||
|
||||
@Column(name = "RES_PROFILE", length = MAX_PROFILE_LENGTH, nullable = true)
|
||||
private String myProfile;
|
||||
|
||||
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
|
@ -122,7 +136,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
private String myResourceType;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
|
||||
private Collection<ResourceTag> myTags;
|
||||
private Set<ResourceTag> myTags;
|
||||
|
||||
@Column(name = "RES_VER")
|
||||
private long myVersion;
|
||||
|
@ -151,6 +165,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return myLanguage;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamCoords> getParamsCoords() {
|
||||
if (myParamsCoords == null) {
|
||||
myParamsCoords = new ArrayList<ResourceIndexedSearchParamCoords>();
|
||||
}
|
||||
return myParamsCoords;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamDate> getParamsDate() {
|
||||
if (myParamsDate == null) {
|
||||
myParamsDate = new ArrayList<ResourceIndexedSearchParamDate>();
|
||||
|
@ -166,8 +187,8 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamQuantity> getParamsQuantity() {
|
||||
if(myParamsQuantity==null) {
|
||||
myParamsQuantity=new ArrayList<ResourceIndexedSearchParamQuantity>();
|
||||
if (myParamsQuantity == null) {
|
||||
myParamsQuantity = new ArrayList<ResourceIndexedSearchParamQuantity>();
|
||||
}
|
||||
return myParamsQuantity;
|
||||
}
|
||||
|
@ -186,11 +207,17 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return myParamsToken;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamUri> getParamsUri() {
|
||||
if (myParamsUri == null) {
|
||||
myParamsUri = new ArrayList<ResourceIndexedSearchParamUri>();
|
||||
}
|
||||
return myParamsUri;
|
||||
}
|
||||
|
||||
public String getProfile() {
|
||||
return myProfile;
|
||||
}
|
||||
|
||||
|
||||
public Collection<ResourceLink> getResourceLinks() {
|
||||
if (myResourceLinks == null) {
|
||||
myResourceLinks = new ArrayList<ResourceLink>();
|
||||
|
@ -204,7 +231,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
|
||||
public Collection<ResourceTag> getTags() {
|
||||
if (myTags == null) {
|
||||
myTags = new ArrayList<ResourceTag>();
|
||||
myTags = new HashSet<ResourceTag>();
|
||||
}
|
||||
return myTags;
|
||||
}
|
||||
|
@ -226,6 +253,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return myHasLinks;
|
||||
}
|
||||
|
||||
public boolean isParamsCoordsPopulated() {
|
||||
return myParamsCoordsPopulated;
|
||||
}
|
||||
|
||||
public boolean isParamsDatePopulated() {
|
||||
return myParamsDatePopulated;
|
||||
}
|
||||
|
@ -246,6 +277,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return myParamsTokenPopulated;
|
||||
}
|
||||
|
||||
public boolean isParamsUriPopulated() {
|
||||
return myParamsUriPopulated;
|
||||
}
|
||||
|
||||
public void setHasLinks(boolean theHasLinks) {
|
||||
myHasLinks = theHasLinks;
|
||||
}
|
||||
|
@ -259,12 +294,24 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
}
|
||||
|
||||
public void setLanguage(String theLanguage) {
|
||||
if (defaultString(theLanguage).length()> MAX_LANGUAGE_LENGTH) {
|
||||
if (defaultString(theLanguage).length() > MAX_LANGUAGE_LENGTH) {
|
||||
throw new UnprocessableEntityException("Language exceeds maximum length of " + MAX_LANGUAGE_LENGTH + " chars: " + theLanguage);
|
||||
}
|
||||
myLanguage = theLanguage;
|
||||
}
|
||||
|
||||
public void setParamsCoords(Collection<ResourceIndexedSearchParamCoords> theParamsCoords) {
|
||||
if (!isParamsTokenPopulated() && theParamsCoords.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
getParamsCoords().clear();
|
||||
getParamsCoords().addAll(theParamsCoords);
|
||||
}
|
||||
|
||||
public void setParamsCoordsPopulated(boolean theParamsCoordsPopulated) {
|
||||
myParamsCoordsPopulated = theParamsCoordsPopulated;
|
||||
}
|
||||
|
||||
public void setParamsDate(Collection<ResourceIndexedSearchParamDate> theParamsDate) {
|
||||
if (!isParamsDatePopulated() && theParamsDate.isEmpty()) {
|
||||
return;
|
||||
|
@ -325,8 +372,20 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
myParamsTokenPopulated = theParamsTokenPopulated;
|
||||
}
|
||||
|
||||
public void setParamsUri(Collection<ResourceIndexedSearchParamUri> theParamsUri) {
|
||||
if (!isParamsTokenPopulated() && theParamsUri.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
getParamsUri().clear();
|
||||
getParamsUri().addAll(theParamsUri);
|
||||
}
|
||||
|
||||
public void setParamsUriPopulated(boolean theParamsUriPopulated) {
|
||||
myParamsUriPopulated = theParamsUriPopulated;
|
||||
}
|
||||
|
||||
public void setProfile(String theProfile) {
|
||||
if (defaultString(theProfile).length()> MAX_PROFILE_LENGTH) {
|
||||
if (defaultString(theProfile).length() > MAX_PROFILE_LENGTH) {
|
||||
throw new UnprocessableEntityException("Profile name exceeds maximum length of " + MAX_PROFILE_LENGTH + " chars: " + theProfile);
|
||||
}
|
||||
myProfile = theProfile;
|
||||
|
|
|
@ -29,6 +29,9 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
@Entity
|
||||
@Table(name = "HFJ_RES_TAG")
|
||||
public class ResourceTag extends BaseTag {
|
||||
|
@ -63,6 +66,7 @@ public class ResourceTag extends BaseTag {
|
|||
|
||||
public ResourceTag(ResourceTable theResourceTable, TagDefinition theTag) {
|
||||
myResource = theResourceTable;
|
||||
myResourceId = theResourceTable.getId();
|
||||
setTag(theTag);
|
||||
}
|
||||
|
||||
|
@ -82,4 +86,30 @@ public class ResourceTag extends BaseTag {
|
|||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof ResourceTag)) {
|
||||
return false;
|
||||
}
|
||||
ResourceTag other = (ResourceTag) obj;
|
||||
EqualsBuilder b = new EqualsBuilder();
|
||||
b.append(getResourceId(), other.getResourceId());
|
||||
b.append(getTag(), other.getTag());
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
HashCodeBuilder b = new HashCodeBuilder();
|
||||
b.append(getResourceId());
|
||||
b.append(getTag());
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
|
||||
//@formatter:on
|
||||
|
@ -119,4 +122,28 @@ public class TagDefinition implements Serializable {
|
|||
return new Tag(getSystem(), getCode(), getDisplay());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof TagDefinition)) {
|
||||
return false;
|
||||
}
|
||||
TagDefinition other = (TagDefinition) obj;
|
||||
EqualsBuilder b = new EqualsBuilder();
|
||||
b.append(myId, other.myId);
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
HashCodeBuilder b = new HashCodeBuilder();
|
||||
b.append(myId);
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ public class BaseJpaResourceProviderEncounterDstu2 extends JpaResourceProviderDs
|
|||
|
||||
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setEverythingMode(true);
|
||||
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
||||
ca.uhn.fhir.rest.server.IBundleProvider retVal = getDao().search(paramMap);
|
||||
return retVal;
|
||||
|
|
|
@ -50,6 +50,7 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
|
|||
|
||||
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setEverythingMode(true);
|
||||
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
||||
ca.uhn.fhir.rest.server.IBundleProvider retVal = getDao().search(paramMap);
|
||||
return retVal;
|
||||
|
|
|
@ -23,11 +23,13 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.jpa.entity.ForcedId;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
|
@ -43,6 +45,7 @@ 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.QuestionnaireResponse;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -76,6 +79,9 @@ 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
|
||||
|
@ -127,6 +133,8 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
|
|||
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();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ public class BaseJpaTest {
|
|||
|
||||
protected List<IIdType> toUnqualifiedVersionlessIds(IBundleProvider theFound) {
|
||||
List<IIdType> retVal = new ArrayList<IIdType>();
|
||||
for (IBaseResource next : theFound.getResources(0, theFound.size())) {
|
||||
List<IBaseResource> resources = theFound.getResources(0, theFound.size());
|
||||
for (IBaseResource next : resources) {
|
||||
retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless());
|
||||
}
|
||||
return retVal;
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -46,6 +47,7 @@ import ca.uhn.fhir.model.dstu2.resource.Observation;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
|
@ -651,6 +653,33 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchParamChangesType() {
|
||||
String name = "testSearchParamChangesType";
|
||||
IIdType id;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily(name);
|
||||
id = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(Patient.SP_FAMILY, new StringDt(name));
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
|
||||
assertThat(patients, contains(id));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem(name).setValue(name);
|
||||
patient.setId(id);
|
||||
myPatientDao.update(patient);
|
||||
|
||||
params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(Patient.SP_FAMILY, new StringDt(name));
|
||||
patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
|
||||
assertThat(patients, not(contains(id)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchStringParamReallyLong() {
|
||||
String methodName = "testSearchStringParamReallyLong";
|
||||
|
@ -1002,6 +1031,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
params.add(Organization.SP_RES_ID, new StringDt(orgId.getIdPart()));
|
||||
params.addInclude(Organization.INCLUDE_PARTOF.asRecursive());
|
||||
List<IIdType> resources = toUnqualifiedVersionlessIds(myOrganizationDao.search(params));
|
||||
ourLog.info(resources.toString());
|
||||
assertThat(resources, contains(orgId, parentOrgId, parentParentOrgId));
|
||||
}
|
||||
}
|
||||
|
@ -1308,6 +1338,17 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithUriParam() throws Exception {
|
||||
String methodName = "testSearchWithUriParam";
|
||||
|
||||
ValueSet vs = myFhirCtx.newJsonParser().parseResource(ValueSet.class, IOUtils.toString(FhirResourceDaoDstu2SearchTest.class.getResourceAsStream("/valueset-dstu2.json")));
|
||||
myValueSetDao.update(vs);
|
||||
|
||||
IBundleProvider result = myValueSetDao.search(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type"));
|
||||
assertThat(toUnqualifiedVersionlessIds(result), contains((IIdType)new IdDt("ValueSet/testSearchWithUriParam")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithSecurityAndProfileParams() {
|
||||
String methodName = "testSearchWithSecurityAndProfileParams";
|
||||
|
|
|
@ -15,8 +15,11 @@ import static org.mockito.Matchers.eq;
|
|||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -24,8 +27,10 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
|||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -224,6 +229,82 @@ public class FhirResourceDaoDstu2UpdateTest extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateProfilesIgnored() {
|
||||
String name = "testDuplicateProfilesIgnored";
|
||||
IIdType id;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily(name);
|
||||
|
||||
List<IdDt> tl = new ArrayList<IdDt>();
|
||||
tl.add(new IdDt("http://foo/bar"));
|
||||
tl.add(new IdDt("http://foo/bar"));
|
||||
tl.add(new IdDt("http://foo/bar"));
|
||||
ResourceMetadataKeyEnum.PROFILES.put(patient, tl);
|
||||
|
||||
id = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
// Do a read
|
||||
{
|
||||
Patient patient = myPatientDao.read(id);
|
||||
List<IdDt> tl = ResourceMetadataKeyEnum.PROFILES.get(patient);
|
||||
assertEquals(1, tl.size());
|
||||
assertEquals("http://foo/bar", tl.get(0).getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateModifiesProfiles() {
|
||||
String name = "testUpdateModifiesProfiles";
|
||||
IIdType id;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily(name);
|
||||
|
||||
List<IdDt> tl = new ArrayList<IdDt>();
|
||||
tl.add(new IdDt("http://foo/bar"));
|
||||
ResourceMetadataKeyEnum.PROFILES.put(patient, tl);
|
||||
|
||||
id = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
// Do a read
|
||||
{
|
||||
Patient patient = myPatientDao.read(id);
|
||||
List<IdDt> tl = ResourceMetadataKeyEnum.PROFILES.get(patient);
|
||||
assertEquals(1, tl.size());
|
||||
assertEquals("http://foo/bar", tl.get(0).getValue());
|
||||
}
|
||||
|
||||
// Update
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.setId(id);
|
||||
patient.addName().addFamily(name);
|
||||
|
||||
List<IdDt> tl = new ArrayList<IdDt>();
|
||||
tl.add(new IdDt("http://foo/baz"));
|
||||
ResourceMetadataKeyEnum.PROFILES.put(patient, tl);
|
||||
|
||||
id = myPatientDao.update(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
// Do a read
|
||||
{
|
||||
Patient patient = myPatientDao.read(id);
|
||||
List<IdDt> tl = ResourceMetadataKeyEnum.PROFILES.get(patient);
|
||||
assertEquals(1, tl.size());
|
||||
assertEquals("http://foo/baz", tl.get(0).getValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateUnknownNumericIdFails() {
|
||||
Patient p = new Patient();
|
||||
|
|
|
@ -239,7 +239,6 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
o1.getResourceMetadata().remove(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
o1.setId(o1id);
|
||||
IIdType o1id2 = ourObservationDao.update(o1).getId();
|
||||
assertTrue(o1id2.getVersionIdPart() != null);
|
||||
|
|
|
@ -48,6 +48,7 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryResponse;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
|
@ -72,6 +73,10 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
p.addName().addFamily("family");
|
||||
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl("http://foo");
|
||||
myValueSetDao.create(vs);
|
||||
|
||||
ResourceTable entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
|
||||
@Override
|
||||
public ResourceTable doInTransaction(TransactionStatus theStatus) {
|
||||
|
|
|
@ -556,6 +556,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
|
|||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(240 * 1000);
|
||||
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
|
||||
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
|
|
|
@ -657,8 +657,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
|
||||
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
|
||||
|
||||
// _revinclude's are counted but not _include's
|
||||
assertEquals(3, b.getTotal().intValue());
|
||||
// Should include everything
|
||||
assertEquals(6, b.getTotal().intValue());
|
||||
|
||||
ourLog.info(ids.toString());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,6 +15,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTable</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTable</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
|
|
|
@ -1060,7 +1060,6 @@ public class JsonParserTest {
|
|||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testTotalResultsInJsonBundle() {
|
||||
String json =
|
||||
|
@ -1115,6 +1114,9 @@ public class JsonParserTest {
|
|||
|
||||
IParser jsonParser = ourCtx.newJsonParser();
|
||||
Bundle bundle = jsonParser.parseBundle(json);
|
||||
assertEquals("author-name", bundle.getAuthorName().getValue());
|
||||
assertEquals("uri", bundle.getAuthorUri().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
|
||||
|
|
|
@ -1,778 +0,0 @@
|
|||
<StructureDefinition xmlns="http://hl7.org/fhir">
|
||||
<id value="Supply"/>
|
||||
<meta>
|
||||
<lastUpdated value="2015-07-23T16:50:38.106-04:00"/>
|
||||
</meta>
|
||||
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm">
|
||||
<valueInteger value="1"/>
|
||||
</extension>
|
||||
<url value="http://hl7.org/fhir/StructureDefinition/Supply"/>
|
||||
<name value="Supply"/>
|
||||
<publisher value="Health Level Seven International (Orders and Observations)"/>
|
||||
<contact>
|
||||
<telecom>
|
||||
<system value="other"/>
|
||||
<value value="http://hl7.org/fhir"/>
|
||||
</telecom>
|
||||
</contact>
|
||||
<contact>
|
||||
<telecom>
|
||||
<system value="other"/>
|
||||
<value value="http://www.hl7.org/Special/committees/orders/index.cfm"/>
|
||||
</telecom>
|
||||
</contact>
|
||||
<description value="Base StructureDefinition for Supply Resource"/>
|
||||
<status value="draft"/>
|
||||
<date value="2015-07-23T16:50:38-04:00"/>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<uri value="http://hl7.org/v3"/>
|
||||
<name value="RIM"/>
|
||||
</mapping>
|
||||
<abstract value="false"/>
|
||||
<snapshot>
|
||||
<element>
|
||||
<path value="Supply"/>
|
||||
<short value="A supply - request and provision"/>
|
||||
<definition value="A supply - a request for something, and provision of what is supplied."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="DomainResource"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="Supply[moodCode=RQO]"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.id"/>
|
||||
<short value="Logical id of this artifact"/>
|
||||
<definition value="The logical id of the resource, as used in the url for the resource. Once assigned, this value never changes."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="id"/>
|
||||
</type>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.meta"/>
|
||||
<short value="Metadata about the resource"/>
|
||||
<definition value="The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content may not always be associated with version changes to the resource."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Meta"/>
|
||||
</type>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.implicitRules"/>
|
||||
<short value="A set of rules under which this content was created"/>
|
||||
<definition value="A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="uri"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.language"/>
|
||||
<short value="Language of the resource content"/>
|
||||
<definition value="The base language in which the resource is written."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="code"/>
|
||||
</type>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="A human language"/>
|
||||
<valueSetUri value="http://tools.ietf.org/html/bcp47"/>
|
||||
</binding>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.text"/>
|
||||
<short value="Text summary of the resource, for human interpretation"/>
|
||||
<definition value="A human-readable narrative that contains a summary of the resource, and may be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it "clinically safe" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety."/>
|
||||
<alias value="narrative"/>
|
||||
<alias value="html"/>
|
||||
<alias value="xhtml"/>
|
||||
<alias value="display"/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Narrative"/>
|
||||
</type>
|
||||
<condition value="dom-1"/>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="Act.text?"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.contained"/>
|
||||
<short value="Contained, inline Resources"/>
|
||||
<definition value="These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope."/>
|
||||
<alias value="inline resources"/>
|
||||
<alias value="anonymous resources"/>
|
||||
<alias value="contained resources"/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Resource"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="N/A"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.extension"/>
|
||||
<short value="Additional Content defined by implementations"/>
|
||||
<definition value="May be used to represent additional information that is not part of the basic definition of the resource. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension."/>
|
||||
<alias value="extensions"/>
|
||||
<alias value="user content"/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Extension"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="N/A"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.modifierExtension"/>
|
||||
<short value="Extensions that cannot be ignored"/>
|
||||
<definition value="May be used to represent additional information that is not part of the basic definition of the resource, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions."/>
|
||||
<alias value="extensions"/>
|
||||
<alias value="user content"/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Extension"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="N/A"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.kind"/>
|
||||
<short value="The kind of supply (central, non-stock, etc)"/>
|
||||
<definition value="Category of supply, e.g. central, non-stock, etc. This is used to support work flows associated with the supply process."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="CodeableConcept"/>
|
||||
</type>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Category of supply"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-kind"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".code"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.identifier"/>
|
||||
<short value="Unique identifier"/>
|
||||
<definition value="Unique identifier for this supply request."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Identifier"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".id"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.status"/>
|
||||
<short value="requested | dispensed | received | failed | cancelled"/>
|
||||
<definition value="Status of the supply request."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="code"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Status of the supply"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-status"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".statusCode, also existence of fulfillment events"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.orderedItem"/>
|
||||
<short value="Medication, Substance, or Device requested to be supplied"/>
|
||||
<definition value="The item that is requested to be supplied."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Medication"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Substance"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Device"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PRD].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.patient"/>
|
||||
<short value="Patient for whom the item is supplied"/>
|
||||
<definition value="A link to a resource representing the person whom the ordered item is for."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Patient"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=SBJ].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense"/>
|
||||
<short value="Supply details"/>
|
||||
<definition value="Indicates the details of the dispense event such as the days supply and quantity of a supply dispensed."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="BackboneElement"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".inboundRelationship[typeCode=FLFS].source[classCode=SPLY, moodCode=EVN]"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.id"/>
|
||||
<representation value="xmlAttr"/>
|
||||
<short value="xml:id (or equivalent in JSON)"/>
|
||||
<definition value="unique id for the element within a resource (for internal references)."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="id"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="n/a"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.extension"/>
|
||||
<short value="Additional Content defined by implementations"/>
|
||||
<definition value="May be used to represent additional information that is not part of the basic definition of the element. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension."/>
|
||||
<alias value="extensions"/>
|
||||
<alias value="user content"/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Extension"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="n/a"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.modifierExtension"/>
|
||||
<short value="Extensions that cannot be ignored"/>
|
||||
<definition value="May be used to represent additional information that is not part of the basic definition of the element, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions."/>
|
||||
<alias value="extensions"/>
|
||||
<alias value="user content"/>
|
||||
<alias value="modifiers"/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Extension"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="N/A"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.identifier"/>
|
||||
<short value="External identifier"/>
|
||||
<definition value="Identifier assigned by the dispensing facility when the item(s) is dispensed."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Identifier"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".id"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.status"/>
|
||||
<short value="in-progress | dispensed | abandoned"/>
|
||||
<definition value="A code specifying the state of the dispense event."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="code"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Status of the dispense"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-dispense-status"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".statusCode, also existence of fulfillment events"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.type"/>
|
||||
<short value="Category of dispense event"/>
|
||||
<definition value="Indicates the type of dispensing event that is performed. Examples include: Trial Fill, Completion of Trial, Partial Fill, Emergency Fill, Samples, etc."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="CodeableConcept"/>
|
||||
</type>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="The actual item being supplied"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-item"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".code"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.quantity"/>
|
||||
<short value="Amount dispensed"/>
|
||||
<definition value="The amount of supply that has been dispensed. Includes unit of measure."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Quantity"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".quantity"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.suppliedItem"/>
|
||||
<short value="Medication, Substance, or Device supplied"/>
|
||||
<definition value="Identifies the medication or substance or device being dispensed. This is either a link to a resource representing the details of the item or a simple attribute carrying a code that identifies the item from a known list."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Medication"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Substance"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Device"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PRD].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.supplier"/>
|
||||
<short value="Dispenser"/>
|
||||
<definition value="The individual responsible for dispensing the medication, supplier or device."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Practitioner"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PFM].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.whenPrepared"/>
|
||||
<short value="Dispensing time"/>
|
||||
<definition value="The time the dispense event occurred."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Period"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".effectiveTime.low"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.whenHandedOver"/>
|
||||
<short value="Handover time"/>
|
||||
<definition value="The time the dispensed item was sent or handed to the patient (or agent)."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="dateTime"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".effectiveTime.high"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.destination"/>
|
||||
<short value="Where the Supply was sent"/>
|
||||
<definition value="Identification of the facility/location where the Supply was shipped to, as part of the dispense event."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Location"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=DST].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.receiver"/>
|
||||
<short value="Who collected the Supply"/>
|
||||
<definition value="Identifies the person who picked up the Supply."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Practitioner"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=RCV].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
</snapshot>
|
||||
<differential>
|
||||
<element>
|
||||
<path value="Supply"/>
|
||||
<short value="A supply - request and provision"/>
|
||||
<definition value="A supply - a request for something, and provision of what is supplied."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="DomainResource"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value="Supply[moodCode=RQO]"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.kind"/>
|
||||
<short value="The kind of supply (central, non-stock, etc)"/>
|
||||
<definition value="Category of supply, e.g. central, non-stock, etc. This is used to support work flows associated with the supply process."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="CodeableConcept"/>
|
||||
</type>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Category of supply"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-kind"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".code"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.identifier"/>
|
||||
<short value="Unique identifier"/>
|
||||
<definition value="Unique identifier for this supply request."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Identifier"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".id"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.status"/>
|
||||
<short value="requested | dispensed | received | failed | cancelled"/>
|
||||
<definition value="Status of the supply request."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="code"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Status of the supply"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-status"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".statusCode, also existence of fulfillment events"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.orderedItem"/>
|
||||
<short value="Medication, Substance, or Device requested to be supplied"/>
|
||||
<definition value="The item that is requested to be supplied."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Medication"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Substance"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Device"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PRD].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.patient"/>
|
||||
<short value="Patient for whom the item is supplied"/>
|
||||
<definition value="A link to a resource representing the person whom the ordered item is for."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Patient"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=SBJ].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense"/>
|
||||
<short value="Supply details"/>
|
||||
<definition value="Indicates the details of the dispense event such as the days supply and quantity of a supply dispensed."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".inboundRelationship[typeCode=FLFS].source[classCode=SPLY, moodCode=EVN]"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.identifier"/>
|
||||
<short value="External identifier"/>
|
||||
<definition value="Identifier assigned by the dispensing facility when the item(s) is dispensed."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Identifier"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".id"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.status"/>
|
||||
<short value="in-progress | dispensed | abandoned"/>
|
||||
<definition value="A code specifying the state of the dispense event."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="code"/>
|
||||
</type>
|
||||
<isModifier value="true"/>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="Status of the dispense"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-dispense-status"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".statusCode, also existence of fulfillment events"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.type"/>
|
||||
<short value="Category of dispense event"/>
|
||||
<definition value="Indicates the type of dispensing event that is performed. Examples include: Trial Fill, Completion of Trial, Partial Fill, Emergency Fill, Samples, etc."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="CodeableConcept"/>
|
||||
</type>
|
||||
<binding>
|
||||
<strength value="required"/>
|
||||
<description value="The actual item being supplied"/>
|
||||
<valueSetReference>
|
||||
<reference value="http://hl7.org/fhir/ValueSet/supply-item"/>
|
||||
</valueSetReference>
|
||||
</binding>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".code"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.quantity"/>
|
||||
<short value="Amount dispensed"/>
|
||||
<definition value="The amount of supply that has been dispensed. Includes unit of measure."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Quantity"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".quantity"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.suppliedItem"/>
|
||||
<short value="Medication, Substance, or Device supplied"/>
|
||||
<definition value="Identifies the medication or substance or device being dispensed. This is either a link to a resource representing the details of the item or a simple attribute carrying a code that identifies the item from a known list."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Medication"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Substance"/>
|
||||
</type>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Device"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PRD].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.supplier"/>
|
||||
<short value="Dispenser"/>
|
||||
<definition value="The individual responsible for dispensing the medication, supplier or device."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Practitioner"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=PFM].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.whenPrepared"/>
|
||||
<short value="Dispensing time"/>
|
||||
<definition value="The time the dispense event occurred."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Period"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".effectiveTime.low"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.whenHandedOver"/>
|
||||
<short value="Handover time"/>
|
||||
<definition value="The time the dispensed item was sent or handed to the patient (or agent)."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="dateTime"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".effectiveTime.high"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.destination"/>
|
||||
<short value="Where the Supply was sent"/>
|
||||
<definition value="Identification of the facility/location where the Supply was shipped to, as part of the dispense event."/>
|
||||
<min value="0"/>
|
||||
<max value="1"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Location"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=DST].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
<element>
|
||||
<path value="Supply.dispense.receiver"/>
|
||||
<short value="Who collected the Supply"/>
|
||||
<definition value="Identifies the person who picked up the Supply."/>
|
||||
<min value="0"/>
|
||||
<max value="*"/>
|
||||
<type>
|
||||
<code value="Reference"/>
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/Practitioner"/>
|
||||
</type>
|
||||
<mapping>
|
||||
<identity value="rim"/>
|
||||
<map value=".participation[typeCode=RCV].role"/>
|
||||
</mapping>
|
||||
</element>
|
||||
</differential>
|
||||
</StructureDefinition>
|
File diff suppressed because it is too large
Load Diff
|
@ -137,6 +137,20 @@
|
|||
resources (really only useful after indexes change or bugs are
|
||||
fixed)
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server did not correctly index search parameters
|
||||
of type "URI". Thanks to David Hay for reporting! Note that if you are using the JPA server, this change means that
|
||||
there are two new tables added to the database schema. Updating existing resources in the database may fail unless you
|
||||
set default values for the resource
|
||||
table by issuing a SQL command similar to the following (false may be 0 or something else, depending on the database platform in use)
|
||||
<![CDATA[<br/><code>update hfj_resource set sp_coords_present = false;<br/>
|
||||
update hfj_resource set sp_uri_present = false;</code>]]>
|
||||
</action>
|
||||
<action type="fix">
|
||||
FIx issue in JPA server where profile declarations, tags, and
|
||||
security labels were not always properly removed by an update that
|
||||
was trying to remove them. Also don't store duplicates.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.1" date="2015-07-13">
|
||||
<action type="add">
|
||||
|
|
1
sync.sh
1
sync.sh
|
@ -10,6 +10,7 @@ for i in $(find $FHIRTRUNK/build/source/datatypes | grep xml | grep -v spreadshe
|
|||
|
||||
cp $FHIRTRUNK/build/publish/valuesets.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/
|
||||
cp $FHIRTRUNK/build/publish/v3-codesystems.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/
|
||||
cp $FHIRTRUNK/build/publish/v2-codesystems.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/
|
||||
|
||||
# Schematron
|
||||
rm hapi-fhir-structures-dstu2/src/main/resources/ca/uhn/fhir/model/dstu2/schema/*.sch
|
||||
|
|
Loading…
Reference in New Issue