From 6d93cbcaae4a3a95ba9c5bc1dd9145262996a2c3 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Tue, 13 Oct 2015 09:18:34 -0400 Subject: [PATCH] Get content search working correctly --- .../java/ca/uhn/fhir/parser/JsonParser.java | 10 +- .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 125 +++++++++++------- .../ca/uhn/fhir/jpa/dao/FhirSearchDao.java | 2 +- .../BaseResourceIndexedSearchParam.java | 2 + .../fhir/jpa/entity/ResourceHistoryTag.java | 2 + .../ResourceIndexedSearchParamCoords.java | 3 +- .../ResourceIndexedSearchParamDate.java | 3 +- .../ResourceIndexedSearchParamNumber.java | 2 + .../ResourceIndexedSearchParamQuantity.java | 2 + .../ResourceIndexedSearchParamString.java | 17 ++- .../ResourceIndexedSearchParamToken.java | 2 + .../entity/ResourceIndexedSearchParamUri.java | 2 + .../ca/uhn/fhir/jpa/entity/ResourceTable.java | 31 +++-- .../search/IndexNonDeletedInterceptor.java | 2 +- .../dao/FhirResourceDaoDstu2SearchFtTest.java | 55 +++++++- .../test/resources/META-INF/persistence.xml | 2 +- ...hapi-fhir-server-database-config-dstu2.xml | 2 +- .../src/main/webapp/WEB-INF/web.xml | 1 + .../uhn/fhir/parser/JsonParserDstu2Test.java | 7 + .../uhn/fhir/parser/XmlParserDstu2Test.java | 7 + src/changes/changes.xml | 4 + 21 files changed, 204 insertions(+), 79 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index 4c7874afebe..d1b924dcccd 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -800,8 +800,14 @@ public class JsonParser extends BaseParser implements IParser { if (theResource instanceof IBaseBinary) { IBaseBinary bin = (IBaseBinary) theResource; - theEventWriter.write("contentType", bin.getContentType()); - theEventWriter.write("content", bin.getContentAsBase64()); + String contentType = bin.getContentType(); + if (isNotBlank(contentType)) { + theEventWriter.write("contentType", contentType); + } + String contentAsBase64 = bin.getContentAsBase64(); + if (isNotBlank(contentAsBase64)) { + theEventWriter.write("content", contentAsBase64); + } } else { encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theContainedResource, new CompositeChildElement(resDef)); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 8924445613c..76d1c87531b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -52,8 +52,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; +import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; @@ -695,7 +697,11 @@ public abstract class BaseHapiFhirDao implements IDao { } } - for (ResourceTag next : new ArrayList(theEntity.getTags())) { + ArrayList existingTags = new ArrayList(); + if (theEntity.isHasTags()) { + existingTags.addAll(theEntity.getTags()); + } + for (ResourceTag next : existingTags) { TagDefinition nextDef = next.getTag(); if (!allDefs.contains(nextDef)) { if (shouldDroppedTagBeRemovedOnUpdate(theEntity, next)) { @@ -1224,23 +1230,38 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setVersion(theEntity.getVersion() + 1); } - boolean paramsStringPopulated = theEntity.isParamsStringPopulated(); - boolean paramsTokenPopulated = theEntity.isParamsTokenPopulated(); - boolean paramsNumberPopulated = theEntity.isParamsNumberPopulated(); - boolean paramsQuantityPopulated = theEntity.isParamsQuantityPopulated(); - boolean paramsDatePopulated = theEntity.isParamsDatePopulated(); - boolean paramsCoordsPopulated = theEntity.isParamsCoordsPopulated(); - boolean paramsUriPopulated = theEntity.isParamsUriPopulated(); - boolean hasLinks = theEntity.isHasLinks(); - - Collection paramsString = new ArrayList(theEntity.getParamsString()); // TODO: use the isPopulated method to decide whether to call this - Collection paramsToken = new ArrayList(theEntity.getParamsToken()); - Collection paramsNumber = new ArrayList(theEntity.getParamsNumber()); - Collection paramsQuantity = new ArrayList(theEntity.getParamsQuantity()); - Collection paramsDate = new ArrayList(theEntity.getParamsDate()); - Collection paramsUri = new ArrayList(theEntity.getParamsUri()); - Collection paramsCoords = new ArrayList(theEntity.getParamsCoords()); - Collection resourceLinks = new ArrayList(theEntity.getResourceLinks()); + Collection paramsString = new ArrayList(); + if (theEntity.isParamsStringPopulated()) { + paramsString.addAll(theEntity.getParamsString()); + } + Collection paramsToken = new ArrayList(); + if (theEntity.isParamsTokenPopulated()) { + paramsToken.addAll(theEntity.getParamsToken()); + } + Collection paramsNumber = new ArrayList(); + if (theEntity.isParamsNumberPopulated()) { + paramsNumber.addAll(theEntity.getParamsNumber()); + } + Collection paramsQuantity = new ArrayList(); + if (theEntity.isParamsQuantityPopulated()) { + paramsQuantity.addAll(theEntity.getParamsQuantity()); + } + Collection paramsDate = new ArrayList(); + if (theEntity.isParamsDatePopulated()) { + paramsDate.addAll(theEntity.getParamsDate()); + } + Collection paramsUri = new ArrayList(); + if (theEntity.isParamsUriPopulated()) { + paramsUri.addAll(theEntity.getParamsUri()); + } + Collection paramsCoords = new ArrayList(); + if (theEntity.isParamsCoordsPopulated()) { + paramsCoords.addAll(theEntity.getParamsCoords()); + } + Collection resourceLinks = new ArrayList(); + if (theEntity.isHasLinks()) { + resourceLinks.addAll(theEntity.getResourceLinks()); + } Set stringParams = null; Set tokenParams = null; @@ -1264,6 +1285,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setDeleted(theDeletedTimestampOrNull); theEntity.setUpdated(theDeletedTimestampOrNull); theEntity.setNarrativeTextParsedIntoWords(null); + theEntity.setContentTextParsedIntoWords(null); } else { @@ -1313,6 +1335,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setHasLinks(links.isEmpty() == false); theEntity.setIndexStatus(INDEX_STATUS_INDEXED); theEntity.setNarrativeTextParsedIntoWords(parseNarrativeTextIntoWords(theResource)); + theEntity.setContentTextParsedIntoWords(parseContentTextIntoWords(theResource)); } else { @@ -1342,76 +1365,60 @@ public abstract class BaseHapiFhirDao implements IDao { if (thePerformIndexing) { - if (paramsStringPopulated) { - for (ResourceIndexedSearchParamString next : paramsString) { - myEntityManager.remove(next); - } + for (ResourceIndexedSearchParamString next : paramsString) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamString next : stringParams) { myEntityManager.persist(next); } - if (paramsTokenPopulated) { - for (ResourceIndexedSearchParamToken next : paramsToken) { - myEntityManager.remove(next); - } + for (ResourceIndexedSearchParamToken next : paramsToken) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamToken next : tokenParams) { myEntityManager.persist(next); } - if (paramsNumberPopulated) { - for (ResourceIndexedSearchParamNumber next : paramsNumber) { - myEntityManager.remove(next); - } + for (ResourceIndexedSearchParamNumber next : paramsNumber) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamNumber next : numberParams) { myEntityManager.persist(next); } - if (paramsQuantityPopulated) { - for (ResourceIndexedSearchParamQuantity next : paramsQuantity) { - myEntityManager.remove(next); - } + for (ResourceIndexedSearchParamQuantity next : paramsQuantity) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamQuantity next : quantityParams) { myEntityManager.persist(next); } // Store date SP's - if (paramsDatePopulated) { - for (ResourceIndexedSearchParamDate next : paramsDate) { - myEntityManager.remove(next); - } + for (ResourceIndexedSearchParamDate next : paramsDate) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamDate next : dateParams) { myEntityManager.persist(next); } // Store URI SP's - if (paramsUriPopulated) { - for (ResourceIndexedSearchParamUri next : paramsUri) { - myEntityManager.remove(next); - } + 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 : paramsCoords) { + myEntityManager.remove(next); } for (ResourceIndexedSearchParamCoords next : coordsParams) { myEntityManager.persist(next); } - if (hasLinks) { - for (ResourceLink next : resourceLinks) { - myEntityManager.remove(next); - } + for (ResourceLink next : resourceLinks) { + myEntityManager.remove(next); } for (ResourceLink next : links) { myEntityManager.persist(next); @@ -1419,6 +1426,8 @@ public abstract class BaseHapiFhirDao implements IDao { } // if thePerformIndexing + theEntity = myEntityManager.merge(theEntity); + myEntityManager.flush(); if (theResource != null) { @@ -1502,4 +1511,20 @@ public abstract class BaseHapiFhirDao implements IDao { return b.toString(); } + private String parseContentTextIntoWords(IResource theResource) { + StringBuilder b = new StringBuilder(); + @SuppressWarnings("rawtypes") + List childElements = getContext().newTerser().getAllPopulatedChildElementsOfType(theResource, IPrimitiveType.class); + for (@SuppressWarnings("rawtypes") IPrimitiveType nextType : childElements) { + String nextValue = nextType.getValueAsString(); + if (isNotBlank(nextValue)) { + if (b.length() > 0 && b.charAt(b.length() - 1) != ' ') { + b.append(' '); + } + b.append(nextValue); + } + } + return b.toString(); + } + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java index eb60e1dec87..4f92f31a489 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java @@ -44,7 +44,7 @@ public class FhirSearchDao extends BaseHapiFhirDao implements ISe BooleanJunction bool = qb.bool(); List> contentAndTerms = theParams.remove(Constants.PARAM_CONTENT); - addTextSearch(qb, bool, contentAndTerms, "myParamsString.myValueComplete"); + addTextSearch(qb, bool, contentAndTerms, "myContentText"); List> textAndTerms = theParams.remove(Constants.PARAM_TEXT); addTextSearch(qb, bool, textAndTerms, "myNarrativeText"); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java index b32de2932e1..34e227e93b2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java @@ -30,6 +30,7 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MappedSuperclass; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; @MappedSuperclass @@ -50,6 +51,7 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable { @ManyToOne(optional = false) @JoinColumn(name = "RES_ID", referencedColumnName="RES_ID") + @ContainedIn private ResourceTable myResource; @Field diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java index 633520119c4..66b1d1e0d39 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.entity; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; @@ -31,6 +32,7 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; +@Embeddable @Entity @Table(name = "HFJ_HISTORY_TAG") public class ResourceHistoryTag extends BaseTag implements Serializable { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java index b1ae0695232..2aff3e51ecd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.entity; */ import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; @@ -29,9 +30,9 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.hibernate.search.annotations.Field; -import org.hibernate.search.annotations.Indexed; //@formatter:off +@Embeddable @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 = { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java index 62b372fc60f..904c8e92f64 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.entity; import java.util.Date; import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.Temporal; @@ -33,9 +34,9 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.hibernate.search.annotations.Field; -import org.hibernate.search.annotations.Indexed; //@formatter:off +@Embeddable @Entity @Table(name = "HFJ_SPIDX_DATE" /*, indexes= {@Index(name="IDX_SP_DATE", columnList= "SP_VALUE_LOW,SP_VALUE_HIGH")}*/) @org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_DATE", indexes= { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java index 34d99264ce2..db7f1532b5a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.entity; import java.math.BigDecimal; import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; @@ -38,6 +39,7 @@ import org.hibernate.search.annotations.NumericField; import ca.uhn.fhir.jpa.util.BigDecimalNumericFieldBridge; //@formatter:off +@Embeddable @Entity @Table(name = "HFJ_SPIDX_NUMBER" /*, indexes= {@Index(name="IDX_SP_NUMBER", columnList="SP_VALUE")}*/ ) @org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_NUMBER", indexes= { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamQuantity.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamQuantity.java index 5fcbfeb5f6c..1836d3c427e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamQuantity.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamQuantity.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.entity; import java.math.BigDecimal; import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; @@ -38,6 +39,7 @@ import org.hibernate.search.annotations.NumericField; import ca.uhn.fhir.jpa.util.BigDecimalNumericFieldBridge; //@formatter:off +@Embeddable @Entity @Table(name = "HFJ_SPIDX_QUANTITY" /*, indexes= {@Index(name="IDX_SP_NUMBER", columnList="SP_VALUE")}*/ ) @org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_QUANTITY", indexes= { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java index 6cb4406e1ff..11bf98d28dd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java @@ -21,7 +21,10 @@ package ca.uhn.fhir.jpa.entity; */ import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; import org.apache.commons.lang3.StringUtils; @@ -29,9 +32,10 @@ import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; -import org.hibernate.search.annotations.Indexed; +@Embeddable @Entity @Table(name = "HFJ_SPIDX_STRING"/* , indexes= {@Index(name="IDX_SP_STRING", columnList="SP_VALUE_NORMALIZED")} */) @org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_STRING", indexes = { @@ -49,10 +53,12 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP @Column(name = "SP_VALUE_NORMALIZED", length = MAX_LENGTH, nullable = true) private String myValueNormalized; - @Column(name="SP_VALUE_EXACT", insertable=false, updatable=false) - @Field - private String myValueComplete; - + @ManyToOne(optional = false) + @JoinColumn(name = "RES_ID", referencedColumnName="RES_ID", insertable=false, updatable=false) + @ContainedIn + private ResourceTable myResourceTable; + + public ResourceIndexedSearchParamString() { } @@ -103,7 +109,6 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP throw new IllegalArgumentException("Value is too long: " + theValueExact.length()); } myValueExact = theValueExact; - myValueComplete = theValueExact; } public void setValueNormalized(String theValueNormalized) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java index 79164dc37db..05a8e9497bd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.entity; */ import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; @@ -32,6 +33,7 @@ import org.apache.commons.lang3.builder.ToStringStyle; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Indexed; +@Embeddable @Entity @Table(name = "HFJ_SPIDX_TOKEN" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */) @org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_TOKEN", indexes = { @org.hibernate.annotations.Index(name = "IDX_SP_TOKEN", columnNames = { "RES_TYPE", "SP_NAME", "SP_SYSTEM", "SP_VALUE" }), diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamUri.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamUri.java index 51b0409c681..5e3adeca952 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamUri.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamUri.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.entity; */ import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Table; @@ -33,6 +34,7 @@ import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Indexed; //@formatter:off +@Embeddable @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 = { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java index ab83a201cde..e2a45038ea6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java @@ -49,7 +49,7 @@ import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; //@formatter:off -@Indexed(interceptor=IndexNonDeletedInterceptor.class) +@Indexed(/*interceptor=IndexNonDeletedInterceptor.class*/) @Entity @Table(name = "HFJ_RESOURCE", uniqueConstraints = {}, indexes= { @Index(name = "IDX_RES_DATE", columnList="RES_UPDATED"), @@ -86,55 +86,56 @@ public class ResourceTable extends BaseHasResource implements Serializable { /** * Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB */ - @Column(name = "SP_NARRATIVE_TEXT", length = Integer.MAX_VALUE - 1) + @Column(name = "SP_NARRATIVE_TEXT", length = Integer.MAX_VALUE - 1, nullable=true) @Lob @Field() private String myNarrativeText; + /** + * Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB + */ + @Column(name = "SP_CONTENT_TEXT", length = Integer.MAX_VALUE - 1, nullable=true) + @Lob + @Field() + private String myContentText; + @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsCoords; @Column(name = "SP_COORDS_PRESENT") private boolean myParamsCoordsPopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsDate; @Column(name = "SP_DATE_PRESENT") private boolean myParamsDatePopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsNumber; @Column(name = "SP_NUMBER_PRESENT") private boolean myParamsNumberPopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsQuantity; @Column(name = "SP_QUANTITY_PRESENT") private boolean myParamsQuantityPopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsString; @Column(name = "SP_STRING_PRESENT") private boolean myParamsStringPopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsToken; @Column(name = "SP_TOKEN_PRESENT") private boolean myParamsTokenPopulated; @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) - @IndexedEmbedded private Collection myParamsUri; @Column(name = "SP_URI_PRESENT") @@ -324,6 +325,10 @@ public class ResourceTable extends BaseHasResource implements Serializable { myNarrativeText = theNarrativeText; } + public void setContentTextParsedIntoWords(String theContentText) { + myContentText = theContentText; + } + public void setParamsCoords(Collection theParamsCoords) { if (!isParamsTokenPopulated() && theParamsCoords.isEmpty()) { return; @@ -447,10 +452,12 @@ public class ResourceTable extends BaseHasResource implements Serializable { retVal.setDeleted(getDeleted()); retVal.setForcedId(getForcedId()); - for (ResourceTag next : getTags()) { - retVal.addTag(next); + if (isHasTags()) { + for (ResourceTag next : getTags()) { + retVal.addTag(next); + } } - + return retVal; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/IndexNonDeletedInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/IndexNonDeletedInterceptor.java index e708e6bca0d..d960832fac2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/IndexNonDeletedInterceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/IndexNonDeletedInterceptor.java @@ -33,6 +33,6 @@ public class IndexNonDeletedInterceptor implements EntityIndexingInterceptorDIVAAA"); + patient.addName().addGiven("NAMEAAA"); + IIdType pId1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless(); + + map = new SearchParameterMap(); + map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); + + map = new SearchParameterMap(); + map.add(Constants.PARAM_TEXT, new StringParam("DIVAAA")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); + + /* + * Reindex + */ + + patient = new Patient(); + patient.setId(pId1); + patient.getText().setDiv("
DIVBBB
"); + patient.addName().addGiven("NAMEBBB"); + myPatientDao.update(patient); + + map = new SearchParameterMap(); + map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty()); + + map = new SearchParameterMap(); + map.add(Patient.SP_NAME, new StringParam("NAMEBBB")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); + + map = new SearchParameterMap(); + map.add(Constants.PARAM_CONTENT, new StringParam("NAMEBBB")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); + + map = new SearchParameterMap(); + map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB")); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); + + + } + @Test public void testSearchWithChainedParams() { String methodName = "testSearchWithChainedParams"; @@ -55,12 +104,12 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test { List patients; SearchParameterMap params; - + params = new SearchParameterMap(); - params.add(Constants.PARAM_CONTENT, new StringParam("fulltext")); + params.add(Constants.PARAM_CONTENT, new StringParam("fulltext")); patients = toUnqualifiedVersionlessIds(myPatientDao.search(params)); assertThat(patients, containsInAnyOrder(pId1)); - + params = new SearchParameterMap(); params.add(Constants.PARAM_CONTENT, new StringParam("FULLTEXT")); patients = toUnqualifiedVersionlessIds(myObservationDao.search(params)); diff --git a/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml b/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml index 59fbba085d6..2497241c875 100644 --- a/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml +++ b/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml @@ -37,7 +37,7 @@ - + diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/hapi-fhir-server-database-config-dstu2.xml b/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/hapi-fhir-server-database-config-dstu2.xml index 8548212f96a..9c14d15cbc9 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/hapi-fhir-server-database-config-dstu2.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/hapi-fhir-server-database-config-dstu2.xml @@ -55,7 +55,7 @@ - + diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/web.xml b/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/web.xml index cdc1bc19c05..a249ede17ca 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/web.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/web.xml @@ -17,6 +17,7 @@ classpath:hapi-fhir-server-resourceproviders-dstu1.xml classpath:hapi-fhir-server-resourceproviders-dstu2.xml classpath:fhir-spring-subscription-config-dstu2.xml + classpath:fhir-spring-search-config-dstu2.xml diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java index 2444b3c836d..3039780664f 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java @@ -65,6 +65,13 @@ public class JsonParserDstu2Test { ourLog.info(encoded); assertThat(encoded, containsString("\"div\":\"" + expected.replace("\"", "\\\"") + "\"")); } + + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newJsonParser().encodeResourceToString(new Binary()); + assertEquals("{\"resourceType\":\"Binary\"}", output); + } @Test public void testNamespacePreservationParse() throws Exception { diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java index 6f1a76f9a7f..1d156a7572a 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java @@ -123,6 +123,13 @@ public class XmlParserDstu2Test { assertArrayEquals(new byte[] { 1, 2, 3, 4 }, bin.getContent()); } + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newXmlParser().encodeResourceToString(new Binary()); + assertEquals("", output); + } + @Test public void testContainedResourceInExtensionUndeclared() { diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9ae912f2e6a..5b9999c28a3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -170,6 +170,10 @@ number of unneeded dependencies. Thanks to Thomas Andersen for the pull request! + + Fix a crash when encoding a Binary resource in JSON encoding + if the resource has no content-type +