Skip to content

Commit

Permalink
More work on bugfixing #164 - Support for :missing
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesagnew committed May 1, 2015
1 parent 3fc6958 commit 20a16d6
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private boolean isSystemBlank() {
@Deprecated
@Override
public Boolean getMissing() {
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public void setValueAsQueryToken(String theQualifier, String theParameter) {
@Deprecated
@Override
public Boolean getMissing() {
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public String getQueryParameterQualifier() {
@Deprecated
@Override
public Boolean getMissing() {
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ protected String encode(String theValue) {
@Deprecated
@Override
public Boolean getMissing() {
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public void setMissing(Boolean theMissing) {
public final void setValueAsQueryToken(String theQualifier, String theValue) {
if (Constants.PARAMQUALIFIER_MISSING.equals(theQualifier)) {
myMissing = "true".equals(theValue);
doSetValueAsQueryToken(null, null);
} else {
myMissing = null;
doSetValueAsQueryToken(theQualifier, theValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,11 @@ private void clear() {

@Override
String doGetQueryParameterQualifier() {
return super.getQueryParameterQualifier();
return null;
}

@Override
String doGetValueAsQueryToken() {
if (super.getMissing() != null) {
return super.getValueAsQueryToken();
}

StringBuilder b = new StringBuilder();
if (myApproximate) {
b.append('~');
Expand All @@ -179,11 +175,6 @@ String doGetValueAsQueryToken() {
void doSetValueAsQueryToken(String theQualifier, String theValue) {
clear();

super.setValueAsQueryToken(theQualifier, theValue);
if (getMissing() != null) {
return;
}

if (theValue == null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;

import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -183,7 +183,7 @@ private Set<Long> addPredicateDate(String theParamName, Set<Long> thePids, List<
}

if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
return addPredicateParamMissing(thePids, "myParamsDate");
return addPredicateParamMissing(thePids, "myParamsDate", theParamName, ResourceIndexedSearchParamDate.class);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -193,7 +193,7 @@ private Set<Long> addPredicateDate(String theParamName, Set<Long> thePids, List<

List<Predicate> codePredicates = new ArrayList<Predicate>();
for (IQueryParameterType nextOr : theList) {
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

Expand Down Expand Up @@ -296,7 +296,7 @@ private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, Lis
}

if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
return addPredicateParamMissing(thePids, "myParamsNumber");
return addPredicateParamMissing(thePids, "myParamsNumber", theParamName, ResourceIndexedSearchParamNumber.class);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -308,7 +308,7 @@ private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, Lis
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;

if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

Expand Down Expand Up @@ -365,20 +365,58 @@ private Set<Long> addPredicateNumber(String theParamName, Set<Long> thePids, Lis
return new HashSet<Long>(q.getResultList());
}

private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName) {
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
Root<ResourceTable> from = cq.from(ResourceTable.class);
cq.select(from.get("myId").as(Long.class));
Join<Object, Object> join = from.join(joinName, JoinType.LEFT);

Subquery<Long> subQ = cq.subquery(Long.class);
Root<? extends BaseResourceIndexedSearchParam> subQfrom = subQ.from(theParamTable);
subQ.select(subQfrom.get("myResourcePid").as(Long.class));
subQ.where(builder.equal(subQfrom.get("myParamName"), theParamName));

Predicate joinPredicate = builder.not(builder.in(from.get("myId")).value(subQ));

if (thePids.size() > 0) {
Predicate inPids = (from.get("myId").in(thePids));
cq.where(builder.and(inPids, join.isNull()));
cq.where(builder.and(inPids, joinPredicate));
} else {
cq.where(join.isNull());
cq.where(joinPredicate);
}

TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList());
List<Long> resultList = q.getResultList();
HashSet<Long> retVal = new HashSet<Long>(resultList);
return retVal;
}

private Set<Long> addPredicateParamMissingResourceLink(Set<Long> thePids, String joinName, String theParamName) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
Root<ResourceTable> from = cq.from(ResourceTable.class);
cq.select(from.get("myId").as(Long.class));

Subquery<Long> subQ = cq.subquery(Long.class);
Root<ResourceLink> subQfrom = subQ.from(ResourceLink.class);
subQ.select(subQfrom.get("mySourceResourcePid").as(Long.class));

// subQ.where(builder.equal(subQfrom.get("myParamName"), theParamName));
subQ.where(createResourceLinkPathPredicate(theParamName, builder, subQfrom));

Predicate joinPredicate = builder.not(builder.in(from.get("myId")).value(subQ));

if (thePids.size() > 0) {
Predicate inPids = (from.get("myId").in(thePids));
cq.where(builder.and(inPids, joinPredicate));
} else {
cq.where(joinPredicate);
}

TypedQuery<Long> q = myEntityManager.createQuery(cq);
List<Long> resultList = q.getResultList();
HashSet<Long> retVal = new HashSet<Long>(resultList);
return retVal;
}

private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
Expand All @@ -387,7 +425,7 @@ private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, L
}

if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
return addPredicateParamMissing(thePids, "myParamsQuantity");
return addPredicateParamMissing(thePids, "myParamsQuantity", theParamName, ResourceIndexedSearchParamQuantity.class);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -399,7 +437,7 @@ private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, L
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;

if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

Expand Down Expand Up @@ -505,7 +543,7 @@ private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids,
}

if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
return addPredicateParamMissing(thePids, "myResourceLinks");
return addPredicateParamMissingResourceLink(thePids, "myResourceLinks", theParamName);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -518,7 +556,7 @@ private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids,
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;

if (addPredicateMissingFalseIfPresentForResourceLink(theParamName, from, codePredicates, nextOr)) {
if (addPredicateMissingFalseIfPresentForResourceLink(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

Expand Down Expand Up @@ -586,10 +624,7 @@ private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids,

Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0]));

RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
String path = param.getPath();

Predicate type = builder.equal(from.get("mySourcePath"), path);
Predicate type = createResourceLinkPathPredicate(theParamName, builder, from);
if (pidsToRetain.size() > 0) {
Predicate inPids = (from.get("mySourceResourcePid").in(pidsToRetain));
cq.where(builder.and(type, masterCodePredicate, inPids));
Expand All @@ -601,13 +636,21 @@ private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids,
return new HashSet<Long>(q.getResultList());
}

private Predicate createResourceLinkPathPredicate(String theParamName, CriteriaBuilder builder, Root<? extends ResourceLink> from) {
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
String path = param.getPath();

Predicate type = builder.equal(from.get("mySourcePath"), path);
return type;
}

private Set<Long> addPredicateString(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, "myParamsString");
return addPredicateParamMissing(thePids, "myParamsString", theParamName, ResourceIndexedSearchParamString.class);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -618,7 +661,7 @@ private Set<Long> addPredicateString(String theParamName, Set<Long> thePids, Lis
List<Predicate> codePredicates = new ArrayList<Predicate>();
for (IQueryParameterType nextOr : theList) {
IQueryParameterType theParameter = nextOr;
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

Expand All @@ -641,27 +684,29 @@ private Set<Long> addPredicateString(String theParamName, Set<Long> thePids, Lis
return new HashSet<Long>(q.getResultList());
}

private boolean addPredicateMissingFalseIfPresent(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) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
}
Predicate singleCode = from.get("myId").isNotNull();
codePredicates.add(singleCode);
Predicate name = theBuilder.equal(from.get("myParamName"), theParamName);
codePredicates.add(theBuilder.and(name, singleCode));
missingFalse = true;
}
return missingFalse;
}

private boolean addPredicateMissingFalseIfPresentForResourceLink(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) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
}
Predicate singleCode = from.get("mySourceResource").isNotNull();
codePredicates.add(singleCode);
Predicate name = createResourceLinkPathPredicate(theParamName, theBuilder, from);
codePredicates.add(theBuilder.and(name, singleCode));
missingFalse = true;
}
return missingFalse;
Expand All @@ -673,7 +718,7 @@ private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List
}

if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
return addPredicateParamMissing(thePids, "myParamsToken");
return addPredicateParamMissing(thePids, "myParamsToken", theParamName, ResourceIndexedSearchParamToken.class);
}

CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
Expand All @@ -683,17 +728,17 @@ private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List

List<Predicate> codePredicates = new ArrayList<Predicate>();
for (IQueryParameterType nextOr : theList) {
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
continue;
}

if (nextOr instanceof TokenParam) {
TokenParam id = (TokenParam) nextOr;
if (id.isText()) {
return addPredicateString(theParamName, thePids, theList);
}
}

if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
continue;
}

Predicate singleCode = createPredicateToken(nextOr, theParamName, builder, from);
codePredicates.add(singleCode);
}
Expand Down
Loading

0 comments on commit 20a16d6

Please sign in to comment.