Work on subscriptions, and correct indexing of codes in JPA

This commit is contained in:
jamesagnew 2015-10-01 08:56:17 -04:00
parent 9664174b6a
commit 900c93949a
10 changed files with 296 additions and 101 deletions

View File

@ -37,25 +37,20 @@ public class BoundCodeDt<T extends Enum<?>> extends CodeDt {
public BoundCodeDt() { public BoundCodeDt() {
// nothing // nothing
} }
public BoundCodeDt(IValueSetEnumBinder<T> theBinder) { public BoundCodeDt(IValueSetEnumBinder<T> theBinder) {
Validate.notNull(theBinder, "theBinder must not be null"); Validate.notNull(theBinder, "theBinder must not be null");
myBinder = theBinder; myBinder = theBinder;
} }
public BoundCodeDt(IValueSetEnumBinder<T> theBinder, T theValue) { public BoundCodeDt(IValueSetEnumBinder<T> theBinder, T theValue) {
Validate.notNull(theBinder, "theBinder must not be null"); Validate.notNull(theBinder, "theBinder must not be null");
myBinder = theBinder; myBinder = theBinder;
setValueAsEnum(theValue); setValueAsEnum(theValue);
} }
public void setValueAsEnum(T theValue) { public IValueSetEnumBinder<T> getBinder() {
Validate.notNull(myBinder, "This object does not have a binder. Constructor BoundCodeDt() should not be called!"); return myBinder;
if (theValue==null) {
setValue(null);
} else {
setValue(myBinder.toCodeString(theValue));
}
} }
public T getValueAsEnum() { public T getValueAsEnum() {
@ -66,4 +61,13 @@ public class BoundCodeDt<T extends Enum<?>> extends CodeDt {
} }
return retVal; return retVal;
} }
public void setValueAsEnum(T theValue) {
Validate.notNull(myBinder, "This object does not have a binder. Constructor BoundCodeDt() should not be called!");
if (theValue==null) {
setValue(null);
} else {
setValue(myBinder.toCodeString(theValue));
}
}
} }

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src/test/java"> <classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes> <attributes>
<attribute name="optional" value="true"/> <attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" path="src/test/resources"/> <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="src" path="src/main/java"> <classpathentry kind="src" path="src/main/java">
<attributes> <attributes>
<attribute name="optional" value="true"/> <attribute name="optional" value="true"/>

View File

@ -52,6 +52,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.model.api.IDatatype; import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IPrimitiveDatatype; import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
import ca.uhn.fhir.model.base.composite.BaseHumanNameDt; import ca.uhn.fhir.model.base.composite.BaseHumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.AddressDt; import ca.uhn.fhir.model.dstu2.composite.AddressDt;
import ca.uhn.fhir.model.dstu2.composite.BoundCodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.BoundCodeableConceptDt;
@ -71,6 +72,7 @@ import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.RestfulSecurityServiceEnum; import ca.uhn.fhir.model.dstu2.valueset.RestfulSecurityServiceEnum;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt; import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.IntegerDt; import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.model.primitive.UriDt;
@ -79,7 +81,7 @@ import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISearchParamExtractor { public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISearchParamExtractor {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorDstu2.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorDstu2.class);
public SearchParamExtractorDstu2(FhirContext theContext) { public SearchParamExtractorDstu2(FhirContext theContext) {
super(theContext); super(theContext);
} }
@ -115,7 +117,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource) * @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/ */
@Override @Override
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) { public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
@ -175,7 +178,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource) * @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/ */
@Override @Override
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) { public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
@ -222,12 +226,17 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
nextValue = newValue; nextValue = newValue;
/* /*
* @SuppressWarnings("unchecked") PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>>) * @SuppressWarnings("unchecked") PhysicsUnit<? extends
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if (unit.isCompatible(UCUM.DAY)) { * org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends
* org.unitsofmeasurement.quantity.Quantity<?>>)
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if
* (unit.isCompatible(UCUM.DAY)) {
* *
* @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit = (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY); * @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit =
* double dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt newValue = new DurationDt(); newValue.setSystem(UCUM_NS); * (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY); double
* newValue.setCode(UCUM.DAY.getSymbol()); newValue.setValue(dayValue); nextValue=newValue; } * dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt newValue =
* new DurationDt(); newValue.setSystem(UCUM_NS); newValue.setCode(UCUM.DAY.getSymbol());
* newValue.setValue(dayValue); nextValue=newValue; }
*/ */
} }
} }
@ -269,7 +278,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource) * @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/ */
@Override @Override
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) { public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) {
@ -303,8 +313,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
continue; continue;
} }
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(), ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(), nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
nextEntity.setResource(theEntity); nextEntity.setResource(theEntity);
retVal.add(nextEntity); retVal.add(nextEntity);
} else { } else {
@ -323,7 +332,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource) * @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/ */
@Override @Override
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IResource theResource) { public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IResource theResource) {
@ -404,7 +414,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource) * @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/ */
@Override @Override
public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) { public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) {
@ -464,11 +475,11 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
systems.add(system); systems.add(system);
codes.add(value); codes.add(value);
} }
if (isNotBlank(nextValue.getType().getText())) { if (isNotBlank(nextValue.getType().getText())) {
addStringParam(theEntity, retVal, nextSpDef, nextValue.getType().getText()); addStringParam(theEntity, retVal, nextSpDef, nextValue.getType().getText());
} }
} else if (nextObject instanceof ContactPointDt) { } else if (nextObject instanceof ContactPointDt) {
ContactPointDt nextValue = (ContactPointDt) nextObject; ContactPointDt nextValue = (ContactPointDt) nextObject;
if (nextValue.isEmpty()) { if (nextValue.isEmpty()) {
@ -481,6 +492,14 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
} }
systems.add(nextValue.getSystemElement().getValueAsString()); systems.add(nextValue.getSystemElement().getValueAsString());
codes.add(nextValue.getValueElement().getValue()); codes.add(nextValue.getValueElement().getValue());
} else if (nextObject instanceof BoundCodeDt) {
BoundCodeDt<?> obj = (BoundCodeDt<?>) nextObject;
String system = extractSystem(obj);
String code = obj.getValue();
if (isNotBlank(code)) {
systems.add(system);
codes.add(code);
}
} else if (nextObject instanceof IPrimitiveDatatype<?>) { } else if (nextObject instanceof IPrimitiveDatatype<?>) {
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject; IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
if (nextValue.isEmpty()) { if (nextValue.isEmpty()) {
@ -503,7 +522,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef); extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
} else if (nextObject instanceof RestSecurity) { } else if (nextObject instanceof RestSecurity) {
// Conformance.security search param points to something kind of useless right now - This should probably be fixed. // Conformance.security search param points to something kind of useless right now - This should probably
// be fixed.
RestSecurity sec = (RestSecurity) nextObject; RestSecurity sec = (RestSecurity) nextObject;
for (BoundCodeableConceptDt<RestfulSecurityServiceEnum> nextCC : sec.getService()) { for (BoundCodeableConceptDt<RestfulSecurityServiceEnum> nextCC : sec.getService()) {
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef); extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
@ -588,9 +608,9 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
} }
ourLog.trace("Adding param: {}, {}", resourceName, nextValue.getValue()); ourLog.trace("Adding param: {}, {}", resourceName, nextValue.getValue());
ResourceIndexedSearchParamUri nextEntity = new ResourceIndexedSearchParamUri(resourceName, nextValue.getValue()); ResourceIndexedSearchParamUri nextEntity = new ResourceIndexedSearchParamUri(resourceName, nextValue.getValue());
nextEntity.setResource(theEntity); nextEntity.setResource(theEntity);
retVal.add(nextEntity); retVal.add(nextEntity);
} else { } else {
@ -605,17 +625,14 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
return retVal; return retVal;
} }
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity,
Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
for (CodingDt nextCoding : theCodeableConcept.getCoding()) { for (CodingDt nextCoding : theCodeableConcept.getCoding()) {
extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding); extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding);
} }
} }
private void extractTokensFromCoding(List<String> theSystems, List<String> theCodes, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, private void extractTokensFromCoding(List<String> theSystems, List<String> theCodes, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef, CodingDt nextCoding) {
RuntimeSearchParam theParameterDef, CodingDt nextCoding) {
if (nextCoding != null && !nextCoding.isEmpty()) { if (nextCoding != null && !nextCoding.isEmpty()) {
String nextSystem = nextCoding.getSystemElement().getValueAsString(); String nextSystem = nextCoding.getSystemElement().getValueAsString();
@ -632,4 +649,12 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
} }
} }
private static <T extends Enum<?>> String extractSystem(BoundCodeDt<T> theBoundCode) {
if (theBoundCode.getValueAsEnum() != null) {
IValueSetEnumBinder<T> binder = theBoundCode.getBinder();
return binder.toSystemString(theBoundCode.getValueAsEnum());
}
return null;
}
} }

View File

@ -8,6 +8,8 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass; import org.junit.AfterClass;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
public class BaseJpaTest { public class BaseJpaTest {
@ -35,6 +37,16 @@ public class BaseJpaTest {
return retVal; return retVal;
} }
protected List<IIdType> toUnqualifiedVersionlessIds(Bundle theFound) {
List<IIdType> retVal = new ArrayList<IIdType>();
for (Entry next : theFound.getEntry()) {
// if (next.getResource()!= null) {
retVal.add(next.getResource().getId().toUnqualifiedVersionless());
// }
}
return retVal;
}
protected List<IIdType> toUnqualifiedVersionlessIds(List<IBaseResource> theFound) { protected List<IIdType> toUnqualifiedVersionlessIds(List<IBaseResource> theFound) {
List<IIdType> retVal = new ArrayList<IIdType>(); List<IIdType> retVal = new ArrayList<IIdType>();
for (IBaseResource next : theFound) { for (IBaseResource next : theFound) {

View File

@ -56,9 +56,12 @@ import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner; import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.Substance; import ca.uhn.fhir.model.dstu2.resource.Substance;
import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum; import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
@ -100,6 +103,19 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
assertEquals(0, results.size()); assertEquals(0, results.size());
} }
@Test
public void testCodeSearch() {
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
IIdType id = mySubscriptionDao.create(subs).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add(Subscription.SP_TYPE, new TokenParam(null, SubscriptionChannelTypeEnum.WEBSOCKET.getCode()));
map.add(Subscription.SP_STATUS, new TokenParam(null, SubscriptionStatusEnum.ACTIVE.getCode()));
assertThat(toUnqualifiedVersionlessIds(mySubscriptionDao.search(map)), contains(id));
}
@Test @Test
public void testIndexNoDuplicatesString() { public void testIndexNoDuplicatesString() {

View File

@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder; import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
@ -69,12 +70,15 @@ import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire; import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum; import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum; import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -104,6 +108,53 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode()); assertEquals(200, resp.getStatusLine().getStatusCode());
} }
@Test
public void testCodeSearch() {
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
IIdType id = ourClient.create().resource(subs).execute().getId().toUnqualifiedVersionless();
//@formatter:off
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().code(SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().code(SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), contains(id));
//@formatter:off
resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().systemAndCode(SubscriptionChannelTypeEnum.WEBSOCKET.getSystem(), SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().systemAndCode(SubscriptionStatusEnum.ACTIVE.getSystem(), SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), contains(id));
//@formatter:off
resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().systemAndCode(SubscriptionChannelTypeEnum.WEBSOCKET.getSystem(), SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().systemAndCode("foo", SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), empty());
}
// private void delete(String theResourceType, String theParamName, String theParamValue) { // private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources; // Bundle resources;
// do { // do {

View File

@ -1,10 +1,19 @@
package ca.uhn.fhirtest.mvc; package ca.uhn.fhirtest.mvc;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.to.BaseController; import ca.uhn.fhir.to.BaseController;
import ca.uhn.fhir.to.model.HomeRequest; import ca.uhn.fhir.to.model.HomeRequest;
@ -21,6 +30,28 @@ public class SubscriptionPlaygroundController extends BaseController {
ourLog.info(logPrefix(theModel) + "Displayed subscriptions playground page"); ourLog.info(logPrefix(theModel) + "Displayed subscriptions playground page");
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor);
//@formatter:off
Bundle resp = client
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().code(SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().code(SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(Bundle.class)
.execute();
//@formatter:off
List<Subscription> subscriptions = new ArrayList<Subscription>();
for (Entry next : resp.getEntry()) {
if (next.getResource() instanceof Subscription) {
subscriptions.add((Subscription) next.getResource());
}
}
theModel.put("subscriptions", subscriptions);
return "subscriptions"; return "subscriptions";
} }

View File

@ -36,7 +36,10 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Subscription Creation -->
<div id="subscription_creation">
<!-- Nav tabs --> <!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist"> <ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#wss" <li role="presentation" class="active"><a href="#wss"
@ -48,33 +51,29 @@
<!-- Tab panes --> <!-- Tab panes -->
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="wss">...1</div>
<!-- Static Websocket -->
<div role="tabpanel" class="tab-pane active" id="wss">
<table class="table table-striped table-condensed">
<tr>
<td>ID</td>
<td>Criteria</td>
<td></td>
</tr>
<tr th:each="subscription : ${subscriptions}">
<td th:text="${subscription.id.toUnqualified()}"/>
<td th:text="${subscription.criteria}"/>
<td>
<button type="button" class="btn btn-default btn-primary btn-block" id="dws_create" th:onclick="'dwsCreate(\'' + ${subscription.id.getIdPart()} + '\');'"><i class="glyphicon glyphicon-cog"></i> Subscribe</button>
</td>
</tr>
</table>
</div>
<!-- Dynamic WebSocket --> <!-- Dynamic WebSocket -->
<div role="tabpanel" class="tab-pane" id="wsd"> <div role="tabpanel" class="tab-pane" id="wsd">
<script type="text/javascript">
function dwsCreate() {
try {
var socket = new WebSocket("ws://localhost:8888/websocket/dstu2");
alert('Socket Status: '+socket.readyState);
socket.onopen = function() {
alert("Opening Socket: " + socket.readyState);
socket.send("bind Observation?");
}
socket.onmessage = function(msg) {
alert("New message: " + msg);
}
socket.onerror = function(error) {
alert("error: " + error);
}
} catch (exception) {
alert('Error'+exception);
}
return false;
}
</script>
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
Enter a criteria in the text box below and then click subscribe to Enter a criteria in the text box below and then click subscribe to
@ -93,38 +92,84 @@
</div> </div>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<button type="button" class="btn btn-default btn-primary btn-block" id="dws_create" onclick="dwsCreate();"><i class="glyphicon glyphicon-cog"></i> Subscribe</button> <button type="button" class="btn btn-default btn-primary btn-block" id="dws_create" onclick="dwsCreate(document.getElementById('dws_criteria').value, true);"><i class="glyphicon glyphicon-cog"></i> Subscribe</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Dynamic Subscription Results -->
<div class="panel panel-default"> <!-- Subscription Results -->
<div class="panel panel-default" style="display:none;" id="resultsDiv">
<div class="panel-heading">Subscription Results</div> <div class="panel-heading">Subscription Results</div>
<div class="panel-body"> <ul class="list-group" id="subscription_status_list">
<p>
This will be status...
</p>
</div>
<!-- List group -->
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul> </ul>
</div> </div>
</div> </div>
<script type="text/javascript">
function messageStatus(message) {
var listItem = $('<li />', { 'class': 'list-group-item' });
listItem.append($('<div class="glyphicon glyphicon-info-sign" style="width: 20px;"/>'));
listItem.append($('<span>' + message + '</span>'));
$('#subscription_status_list').append(listItem);
}
function messageIn(message, remainder) {
var listItem = $('<li />', { 'class': 'list-group-item' });
listItem.append($('<div class="glyphicon glyphicon-download" style="width: 20px;"/>'));
listItem.append($('<span>' + message + '</span>'));
if (remainder) {
listItem.append($('<p>(' + remainder + ' bytes)</p>'));
listItem.append($('<pre style="display:none;"/>').text(remainder));
}
$('#subscription_status_list').append(listItem);
}
function dwsCreate(bindArgument, dynamic) {
$('#resultsDiv').css("display","");
$('#subscription_creation').hide();
try {
var url = "ws://fhirtest.uhn.ca/websocket/dstu2";
messageStatus("Connecting to: " + url);
var socket = new WebSocket(url);
socket.onopen = function() {
messageStatus("Connected to: " + url);
$('#subscription_status_list')
.append(
$('<li />', { 'class': 'list-group-item' })
.append($('<div class="glyphicon glyphicon-upload" style="width: 20px;"/>'))
.append($('<span>bind ' + bindArgument + '</span>'))
);
socket.send("bind " + bindArgument);
}
// This function is called when a new message comes from the server
socket.onmessage = function(msg) {
var data = msg.data;
var remainder = null;
if (data.indexOf('\n') != -1) {
data = data.substring(0, data.indexOf('\n'));
remainder = data.substring(data.indexOf('\n') + 1);
}
messageIn(data, remainder);
}
socket.onerror = function(error) {
messageStatus("Error: " + error);
}
} catch (exception) {
messageStatus("Error: " + exception);
}
return false;
}
</script>
</div> </div>
</div> </div>
</div>
</form> </form>

View File

@ -12,6 +12,9 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.dstu.resource.Organization; import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient; import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.client.IGenericClient;
@ -21,7 +24,7 @@ public class UhnFhirTestApp {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
int myPort = 8888; int myPort = 8888;
String base = "http://localhost:" + myPort + "/base"; String base = "http://localhost:" + myPort + "/baseDstu2";
// new File("target/testdb").mkdirs(); // new File("target/testdb").mkdirs();
System.setProperty("fhir.db.location", "./target/testdb"); System.setProperty("fhir.db.location", "./target/testdb");
@ -47,13 +50,13 @@ public class UhnFhirTestApp {
// base = "http://spark.furore.com/fhir"; // base = "http://spark.furore.com/fhir";
if (true) { if (true) {
FhirContext ctx = new FhirContext(); FhirContext ctx = FhirContext.forDstu2();
IGenericClient client = ctx.newRestfulGenericClient(base); IGenericClient client = ctx.newRestfulGenericClient(base);
// client.setLogRequestAndResponse(true); // client.setLogRequestAndResponse(true);
Organization o1 = new Organization(); Organization o1 = new Organization();
o1.getName().setValue("Some Org"); o1.getName().setValue("Some Org");
MethodOutcome create = client.create(o1); MethodOutcome create = client.create().resource(o1).execute();
IdDt orgId = (IdDt) create.getId(); IdDt orgId = (IdDt) create.getId();
Patient p1 = new Patient(); Patient p1 = new Patient();
@ -64,11 +67,14 @@ public class UhnFhirTestApp {
TagList list = new TagList(); TagList list = new TagList();
list.addTag("http://hl7.org/fhir/tag", "urn:happytag", "This is a happy resource"); list.addTag("http://hl7.org/fhir/tag", "urn:happytag", "This is a happy resource");
ResourceMetadataKeyEnum.TAG_LIST.put(p1, list); ResourceMetadataKeyEnum.TAG_LIST.put(p1, list);
client.create(p1); client.create().resource(p1).execute();
List<IResource> resources = ctx.newJsonParser().parseBundle(IOUtils.toString(UhnFhirTestApp.class.getResourceAsStream("/bundle.json"))).toListOfResources();
// client.transaction().withResources(resources).execute();
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
client.create().resource(subs).execute();
// for (int i = 0; i < 1000; i++) { // for (int i = 0; i < 1000; i++) {
// //
// Patient p = (Patient) resources.get(0); // Patient p = (Patient) resources.get(0);
@ -78,22 +84,22 @@ public class UhnFhirTestApp {
// client.transaction(resources); // client.transaction(resources);
// } // }
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
client.create(p1); client.create().resource(p1).execute();
} }

View File

@ -106,6 +106,11 @@
did not have latest valueset definitions applied. Thanks did not have latest valueset definitions applied. Thanks
to Bill de Beaubien for reporting! to Bill de Beaubien for reporting!
</action> </action>
<action type="fix">
JPA server can now successfully search for tokens pointing at code values
(values with no explicit system but an implied one, such as Patient.gender)
even if the system is supplied in the query.
</action>
</release> </release>
<release version="1.2" date="2015-09-18"> <release version="1.2" date="2015-09-18">
<action type="add"> <action type="add">