diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java index 7511f23fd20..b4972e3e99d 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java @@ -8,9 +8,10 @@ import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; +import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; -import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; +import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4; import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; @@ -78,10 +79,10 @@ public class JpaServerDemo extends RestfulServer { systemProvider.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); } else if (fhirVersion == FhirVersionEnum.DSTU3) { systemProvider.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); - systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class)); + systemProvider.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); } else if (fhirVersion == FhirVersionEnum.R4) { systemProvider.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); - systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class)); + systemProvider.add(myAppCtx.getBean(TerminologyUploaderProviderR4.class)); } else { throw new IllegalStateException(); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermConceptDesignationDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermConceptDesignationDao.java new file mode 100644 index 00000000000..ad7ca7265d4 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermConceptDesignationDao.java @@ -0,0 +1,28 @@ +package ca.uhn.fhir.jpa.dao.data; + +import ca.uhn.fhir.jpa.entity.TermConceptDesignation; +import org.springframework.data.jpa.repository.JpaRepository; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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% + */ + +public interface ITermConceptDesignationDao extends JpaRepository { + // nothing +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java index ca2ef4ace87..ff799c97dc1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java @@ -81,6 +81,9 @@ public class TermConcept implements Serializable { @FieldBridge(impl = TermConceptPropertyFieldBridge.class) private Collection myProperties; + @OneToMany(mappedBy = "myConcept", orphanRemoval = true) + private Collection myDesignations; + @Id() @SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID") @@ -123,6 +126,13 @@ public class TermConcept implements Serializable { } } + public TermConceptDesignation addDesignation() { + TermConceptDesignation designation = new TermConceptDesignation(); + designation.setConcept(this); + getDesignations().add(designation); + return designation; + } + private TermConceptProperty addProperty(@Nonnull TermConceptPropertyTypeEnum thePropertyType, @Nonnull String thePropertyName, @Nonnull String thePropertyValue) { Validate.notBlank(thePropertyName); @@ -189,6 +199,29 @@ public class TermConcept implements Serializable { } } + public List getCodingProperties(String thePropertyName) { + List retVal = new ArrayList<>(); + for (TermConceptProperty next : getProperties()) { + if (thePropertyName.equals(next.getKey())) { + if (next.getType() == TermConceptPropertyTypeEnum.CODING) { + Coding coding = new Coding(); + coding.setSystem(next.getCodeSystem()); + coding.setCode(next.getValue()); + coding.setDisplay(next.getDisplay()); + retVal.add(coding); + } + } + } + return retVal; + } + + public Collection getDesignations() { + if (myDesignations == null) { + myDesignations = new ArrayList<>(); + } + return myDesignations; + } + public String getDisplay() { return myDisplay; } @@ -231,6 +264,14 @@ public class TermConcept implements Serializable { return myProperties; } + public Integer getSequence() { + return mySequence; + } + + public void setSequence(Integer theSequence) { + mySequence = theSequence; + } + public List getStringProperties(String thePropertyName) { List retVal = new ArrayList<>(); for (TermConceptProperty next : getProperties()) { @@ -243,30 +284,6 @@ public class TermConcept implements Serializable { return retVal; } - public List getCodingProperties(String thePropertyName) { - List retVal = new ArrayList<>(); - for (TermConceptProperty next : getProperties()) { - if (thePropertyName.equals(next.getKey())) { - if (next.getType() == TermConceptPropertyTypeEnum.CODING) { - Coding coding = new Coding(); - coding.setSystem(next.getCodeSystem()); - coding.setCode(next.getValue()); - coding.setDisplay(next.getDisplay()); - retVal.add(coding); - } - } - } - return retVal; - } - - public Integer getSequence() { - return mySequence; - } - - public void setSequence(Integer theSequence) { - mySequence = theSequence; - } - public String getStringProperty(String thePropertyName) { List properties = getStringProperties(thePropertyName); if (properties.size() > 0) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java new file mode 100644 index 00000000000..51b64484155 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java @@ -0,0 +1,103 @@ +package ca.uhn.fhir.jpa.entity; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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.*; +import java.io.Serializable; + +@Entity +@Table(name = "TRM_CONCEPT_DESIG", uniqueConstraints = { +}, indexes = { +}) +public class TermConceptDesignation implements Serializable { + + private static final long serialVersionUID = 1L; + @ManyToOne + @JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT")) + private TermConcept myConcept; + @Id() + @SequenceGenerator(name = "SEQ_CONCEPT_DESIG_PID", sequenceName = "SEQ_CONCEPT_DESIG_PID") + @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID") + @Column(name = "PID") + private Long myId; + @Column(name = "LANG", length = 50, nullable = true) + private String myLanguage; + @Column(name = "USE_SYSTEM", length = 50, nullable = true) + private String myUseSystem; + @Column(name = "USE_CODE", length = 50, nullable = true) + private String myUseCode; + @Column(name = "USE_DISPLAY", length = 50, nullable = true) + private String myUseDisplay; + @Column(name = "VAL", length = 50, nullable = false) + private String myValue; + + public String getLanguage() { + return myLanguage; + } + + public TermConceptDesignation setLanguage(String theLanguage) { + myLanguage = theLanguage; + return this; + } + + public String getUseCode() { + return myUseCode; + } + + public TermConceptDesignation setUseCode(String theUseCode) { + myUseCode = theUseCode; + return this; + } + + public String getUseDisplay() { + return myUseDisplay; + } + + public TermConceptDesignation setUseDisplay(String theUseDisplay) { + myUseDisplay = theUseDisplay; + return this; + } + + public String getUseSystem() { + return myUseSystem; + } + + public TermConceptDesignation setUseSystem(String theUseSystem) { + myUseSystem = theUseSystem; + return this; + } + + public String getValue() { + return myValue; + } + + public TermConceptDesignation setValue(String theValue) { + myValue = theValue; + return this; + } + + public TermConceptDesignation setConcept(TermConcept theConcept) { + myConcept = theConcept; + return this; + } + + +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyFieldBridge.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyFieldBridge.java index 5a13b78000f..d10a1ac9734 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyFieldBridge.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyFieldBridge.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.entity; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 org.apache.lucene.document.Document; import org.hibernate.search.bridge.FieldBridge; import org.hibernate.search.bridge.LuceneOptions; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyTypeEnum.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyTypeEnum.java index 14762936e45..49062476c44 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyTypeEnum.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptPropertyTypeEnum.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.entity; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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% + */ + /** * @see TermConceptProperty#getType() * @see TermConceptProperty#MAX_PROPTYPE_ENUM_LENGTH diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java index d66d635482b..6438da856c7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.provider.dstu3; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider; import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/TerminologyUploaderProviderR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/TerminologyUploaderProviderR4.java index 054123924cf..303a981a3d7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/TerminologyUploaderProviderR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/TerminologyUploaderProviderR4.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.provider.r4; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider; import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index d8da82784de..79e90e4ba36 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -78,6 +78,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc @Autowired protected ITermConceptPropertyDao myConceptPropertyDao; @Autowired + protected ITermConceptDesignationDao myConceptDesignationDao; + @Autowired protected FhirContext myContext; @PersistenceContext(type = PersistenceContextType.TRANSACTION) protected EntityManager myEntityManager; @@ -103,6 +105,28 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc contains.setCode(theConcept.getCode()); contains.setSystem(theCodeSystem); contains.setDisplay(theConcept.getDisplay()); + for (TermConceptDesignation nextDesignation : theConcept.getDesignations()) { + contains + .addDesignation() + .setValue(nextDesignation.getValue()) + .getUse() + .setSystem(nextDesignation.getUseSystem()) + .setCode(nextDesignation.getUseCode()) + .setDisplay(nextDesignation.getUseDisplay()); + } + } + } + + private void addConceptsToList(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set theAddedCodes, String theSystem, List theConcept) { + for (CodeSystem.ConceptDefinitionComponent next : theConcept) { + if (!theAddedCodes.contains(next.getCode())) { + theAddedCodes.add(next.getCode()); + ValueSet.ValueSetExpansionContainsComponent contains = theExpansionComponent.addContains(); + contains.setCode(next.getCode()); + contains.setSystem(theSystem); + contains.setDisplay(next.getDisplay()); + } + addConceptsToList(theExpansionComponent, theAddedCodes, theSystem, next.getConcept()); } } @@ -162,10 +186,12 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc myCodeSystemDao.save(cs); myCodeSystemDao.flush(); + int i = 0; for (TermCodeSystemVersion next : myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystem.getPid())) { myConceptParentChildLinkDao.deleteByCodeSystemVersion(next.getPid()); for (TermConcept nextConcept : myConceptDao.findByCodeSystemVersion(next.getPid())) { myConceptPropertyDao.delete(nextConcept.getProperties()); + myConceptDesignationDao.delete(nextConcept.getDesignations()); myConceptDao.delete(nextConcept); } if (next.getCodeSystem().getCurrentVersion() == next) { @@ -173,10 +199,15 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc myCodeSystemDao.save(next.getCodeSystem()); } myCodeSystemVersionDao.delete(next); + + if (i % 1000 == 0) { + myEntityManager.flush(); + } } myCodeSystemVersionDao.deleteForCodeSystem(theCodeSystem); myCodeSystemDao.delete(theCodeSystem); + myEntityManager.flush(); } private int ensureParentsSaved(Collection theParents) { @@ -223,11 +254,13 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc haveIncludeCriteria = true; TermConcept code = findCode(system, nextCode); if (code != null) { - addedCodes.add(nextCode); - ValueSet.ValueSetExpansionContainsComponent contains = expansionComponent.addContains(); - contains.setCode(nextCode); - contains.setSystem(system); - contains.setDisplay(code.getDisplay()); + addCodeIfNotAlreadyAdded(system, expansionComponent, addedCodes, code); +// +// addedCodes.add(nextCode); +// ValueSet.ValueSetExpansionContainsComponent contains = expansionComponent.addContains(); +// contains.setCode(nextCode); +// contains.setSystem(system); +// contains.setDisplay(code.getDisplay()); } } } @@ -511,6 +544,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc myConceptPropertyDao.save(next); } + for (TermConceptDesignation next : theConcept.getDesignations()) { + myConceptDesignationDao.save(next); + } + } private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IRecordHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IRecordHandler.java index 314a6a65cf1..35e0b65f34b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IRecordHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IRecordHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 org.apache.commons.csv.CSVRecord; public interface IRecordHandler { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseHandler.java index f35c5e6c5da..9dbc98dc6c7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseHandler.java @@ -1,8 +1,29 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IRecordHandler; import org.hl7.fhir.r4.model.ConceptMap; +import org.hl7.fhir.r4.model.ContactPoint; import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.ValueSet; @@ -65,7 +86,7 @@ abstract class BaseHandler implements IRecordHandler { } - void addConceptMapEntry(ConceptMapping theMapping) { + void addConceptMapEntry(ConceptMapping theMapping, String theCopyright) { if (isBlank(theMapping.getSourceCode())) { return; } @@ -79,6 +100,13 @@ abstract class BaseHandler implements IRecordHandler { conceptMap.setId(theMapping.getConceptMapId()); conceptMap.setUrl(theMapping.getConceptMapUri()); conceptMap.setName(theMapping.getConceptMapName()); + conceptMap.setPublisher("Regentrief Institute, Inc."); + conceptMap.addContact() + .setName("Regentrief Institute, Inc.") + .addTelecom() + .setSystem(ContactPoint.ContactPointSystem.URL) + .setValue("https://loinc.org"); + conceptMap.setCopyright(theCopyright); myIdToConceptMaps.put(theMapping.getConceptMapId(), conceptMap); myConceptMaps.add(conceptMap); } else { @@ -144,6 +172,13 @@ abstract class BaseHandler implements IRecordHandler { vs.setId(theValueSetId); vs.setName(theValueSetName); vs.setStatus(Enumerations.PublicationStatus.ACTIVE); + vs.setPublisher("Regenstrief Institute, Inc."); + vs.addContact() + .setName("Regenstrief Institute, Inc.") + .addTelecom() + .setSystem(ContactPoint.ContactPointSystem.URL) + .setValue("https://loinc.org"); + vs.setCopyright("This content from LOINC® is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at https://loinc.org/license/"); myIdToValueSet.put(theValueSetId, vs); myValueSets.add(vs); } else { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseLoincTop2000LabResultsHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseLoincTop2000LabResultsHandler.java index ac5d5cdffac..8e431107827 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseLoincTop2000LabResultsHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/BaseLoincTop2000LabResultsHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; import ca.uhn.fhir.jpa.term.IRecordHandler; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListHandler.java index bde2ad61f12..29a174827c2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListLinkHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListLinkHandler.java index cda7bdce357..f16ed0cbed8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListLinkHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincAnswerListLinkHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincDocumentOntologyHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincDocumentOntologyHandler.java index 7916e06ba1e..09ff81684de 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincDocumentOntologyHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincDocumentOntologyHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; @@ -15,8 +35,8 @@ import static org.apache.commons.lang3.StringUtils.trim; public class LoincDocumentOntologyHandler extends BaseHandler implements IRecordHandler { - public static final String DOCUMENT_ONTOLOGY_CODES_VS_ID = "DOCUMENT-ONTOLOGY-CODES-VS"; - public static final String DOCUMENT_ONTOLOGY_CODES_VS_URI = "http://loinc.org/document-ontology-codes"; + public static final String DOCUMENT_ONTOLOGY_CODES_VS_ID = "loinc-document-ontology"; + public static final String DOCUMENT_ONTOLOGY_CODES_VS_URI = "http://loinc.org/vs/loinc-document-ontology"; public static final String DOCUMENT_ONTOLOGY_CODES_VS_NAME = "LOINC Document Ontology Codes"; private final Map myCode2Concept; private final TermCodeSystemVersion myCodeSystemVersion; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHandler.java index b2d95452c9b..be3597489f9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IRecordHandler; @@ -37,6 +57,13 @@ public class LoincHandler implements IRecordHandler { TermConcept concept = new TermConcept(myCodeSystemVersion, code); concept.setDisplay(display); + if (!display.equalsIgnoreCase(shortName)) { + concept + .addDesignation() + .setUseDisplay("ShortName") + .setValue(shortName); + } + for (String nextPropertyName : myPropertyNames) { if (!theRecord.toMap().containsKey(nextPropertyName)) { continue; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHierarchyHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHierarchyHandler.java index b550dadf466..02373716541 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHierarchyHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincHierarchyHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincIeeeMedicalDeviceCodeHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincIeeeMedicalDeviceCodeHandler.java index 1375bcea03e..a15bc66332c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincIeeeMedicalDeviceCodeHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincIeeeMedicalDeviceCodeHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; import ca.uhn.fhir.jpa.term.IRecordHandler; @@ -18,6 +38,7 @@ public class LoincIeeeMedicalDeviceCodeHandler extends BaseHandler implements IR public static final String LOINC_IEEE_CM_ID = "LOINC-IEEE-MEDICAL-DEVICE-CM"; public static final String LOINC_IEEE_CM_URI = "http://loinc.org/fhir/loinc-ieee-device-code-mappings"; public static final String LOINC_IEEE_CM_NAME = "LOINC/IEEE Device Code Mappings"; + private static final String CM_COPYRIGHT = "This content from LOINC® is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at https://loinc.org/license/. The LOINC/IEEE Medical Device Code Mapping Table contains content from IEEE (http://ieee.org), copyright © 2017 IEEE."; /** * Constructor @@ -48,7 +69,8 @@ public class LoincIeeeMedicalDeviceCodeHandler extends BaseHandler implements IR .setTargetCodeSystem(targetCodeSystemUri) .setTargetCode(ieeeCode) .setTargetDisplay(ieeeDisplayName) - .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL)); + .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL), + CM_COPYRIGHT); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincImagingDocumentCodeHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincImagingDocumentCodeHandler.java index 4c58e6187e0..ffae5fa14c7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincImagingDocumentCodeHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincImagingDocumentCodeHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; import ca.uhn.fhir.jpa.term.IRecordHandler; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartHandler.java index 3dadb4e0e04..bfcd1aea80d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IRecordHandler; @@ -9,6 +29,7 @@ import org.hl7.fhir.r4.model.ValueSet; import java.util.HashMap; import java.util.Map; +import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.trim; public class LoincPartHandler implements IRecordHandler { @@ -30,15 +51,23 @@ public class LoincPartHandler implements IRecordHandler { String partTypeName = trim(theRecord.get("PartTypeName")); String partName = trim(theRecord.get("PartName")); String partDisplayName = trim(theRecord.get("PartDisplayName")); - String status = trim(theRecord.get("Status")); - if (!"ACTIVE".equals(status)) { - return; - } + // Per Dan's note, we include deprecated parts +// String status = trim(theRecord.get("Status")); +// if (!"ACTIVE".equals(status)) { +// return; +// } TermConcept concept = new TermConcept(myCodeSystemVersion, partNumber); concept.setDisplay(partName); + if (isNotBlank(partDisplayName)) { + concept.addDesignation() + .setConcept(concept) + .setUseDisplay("PartDisplayName") + .setValue(partDisplayName); + } + myCode2Concept.put(partDisplayName, concept); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartLinkHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartLinkHandler.java index fe92e66b347..5ec6963bd84 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartLinkHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartLinkHandler.java @@ -1,20 +1,39 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IRecordHandler; import org.apache.commons.csv.CSVRecord; -import org.hl7.fhir.r4.model.ValueSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; import java.util.Map; import static org.apache.commons.lang3.StringUtils.trim; public class LoincPartLinkHandler implements IRecordHandler { + private static final Logger ourLog = LoggerFactory.getLogger(LoincPartLinkHandler.class); private final Map myCode2Concept; private final TermCodeSystemVersion myCodeSystemVersion; @@ -33,11 +52,11 @@ public class LoincPartLinkHandler implements IRecordHandler { TermConcept loincConcept = myCode2Concept.get(loincNumber); TermConcept partConcept = myCode2Concept.get(partNumber); - if (loincConcept==null) { + if (loincConcept == null) { ourLog.warn("No loinc code: {}", loincNumber); return; } - if (partConcept==null) { + if (partConcept == null) { ourLog.warn("No part code: {}", partNumber); return; } @@ -45,5 +64,4 @@ public class LoincPartLinkHandler implements IRecordHandler { // For now we're ignoring these } -private static final Logger ourLog = LoggerFactory.getLogger(LoincPartLinkHandler.class); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartRelatedCodeMappingHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartRelatedCodeMappingHandler.java index e0198caacfb..627048108f7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartRelatedCodeMappingHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincPartRelatedCodeMappingHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; @@ -18,8 +38,9 @@ import static org.apache.commons.lang3.StringUtils.trim; public class LoincPartRelatedCodeMappingHandler extends BaseHandler implements IRecordHandler { public static final String LOINC_PART_MAP_ID = "LOINC-PART-MAP"; - public static final String LOINC_PART_MAP_URI = "http://loinc.org/fhir/loinc-part-map"; + public static final String LOINC_PART_MAP_URI = "http://loinc.org/cm/loinc-parts-to-snomed-ct"; public static final String LOINC_PART_MAP_NAME = "LOINC Part Map"; + private static final String CM_COPYRIGHT = "This content from LOINC® is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at https://loinc.org/license/. The LOINC Part File, LOINC/SNOMED CT Expression Association and Map Sets File, RELMA database and associated search index files include SNOMED Clinical Terms (SNOMED CT®) which is used by permission of the International Health Terminology Standards Development Organisation (IHTSDO) under license. All rights are reserved. SNOMED CT® was originally created by The College of American Pathologists. “SNOMED” and “SNOMED CT” are registered trademarks of the IHTSDO. Use of SNOMED CT content is subject to the terms and conditions set forth in the SNOMED CT Affiliate License Agreement. It is the responsibility of those implementing this product to ensure they are appropriately licensed and for more information on the license, including how to register as an Affiliate Licensee, please refer to http://www.snomed.org/snomed-ct/get-snomed-ct or info@snomed.org. Under the terms of the Affiliate License, use of SNOMED CT in countries that are not IHTSDO Members is subject to reporting and fee payment obligations. However, IHTSDO agrees to waive the requirements to report and pay fees for use of SNOMED CT content included in the LOINC Part Mapping and LOINC Term Associations for purposes that support or enable more effective use of LOINC. This material includes content from the US Edition to SNOMED CT, which is developed and maintained by the U.S. National Library of Medicine and is available to authorized UMLS Metathesaurus Licensees from the UTS Downloads site at https://uts.nlm.nih.gov."; private final Map myCode2Concept; private final TermCodeSystemVersion myCodeSystemVersion; private final List myConceptMaps; @@ -76,7 +97,9 @@ public class LoincPartRelatedCodeMappingHandler extends BaseHandler implements I .setTargetDisplay(extCodeDisplayName) .setTargetCodeSystemVersion(extCodeSystemVersion) .setEquivalence(equivalence) - .setCopyright(extCodeSystemCopyrightNotice)); + .setCopyright(extCodeSystemCopyrightNotice), + CM_COPYRIGHT + ); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincRsnaPlaybookHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincRsnaPlaybookHandler.java index 7f1efd71e15..b2b7ba74631 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincRsnaPlaybookHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincRsnaPlaybookHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; @@ -17,17 +37,27 @@ import static org.apache.commons.lang3.StringUtils.trim; public class LoincRsnaPlaybookHandler extends BaseHandler implements IRecordHandler { - public static final String RSNA_CODES_VS_ID = "RSNA-LOINC-CODES-VS"; - public static final String RSNA_CODES_VS_URI = "http://loinc.org/rsna-codes"; - public static final String RSNA_CODES_VS_NAME = "RSNA Playbook"; + public static final String RSNA_CODES_VS_ID = "loinc-rsna-radiology-playbook"; + public static final String RSNA_CODES_VS_URI = "http://loinc.org/vs/loinc-rsna-radiology-playbook"; + public static final String RSNA_CODES_VS_NAME = "LOINC/RSNA Radiology Playbook"; public static final String RID_MAPPING_CM_ID = "LOINC-TO-RID-CODES-CM"; public static final String RID_MAPPING_CM_URI = "http://loinc.org/rid-codes"; public static final String RID_MAPPING_CM_NAME = "RSNA Playbook RID Codes Mapping"; - public static final String RID_CS_URI = "http://rid"; + public static final String RID_CS_URI = "http://www.radlex.org"; public static final String RPID_MAPPING_CM_ID = "LOINC-TO-RPID-CODES-CM"; public static final String RPID_MAPPING_CM_URI = "http://loinc.org/rpid-codes"; public static final String RPID_MAPPING_CM_NAME = "RSNA Playbook RPID Codes Mapping"; - public static final String RPID_CS_URI = "http://rpid"; + /* + * About these being the same - Per Dan: + * We had some discussion about this, and both + * RIDs (RadLex clinical terms) and RPIDs (Radlex Playbook Ids) + * belong to the same "code system" since they will never collide. + * The codesystem uri is "http://www.radlex.org". FYI, that's + * now listed on the FHIR page: + * https://www.hl7.org/fhir/terminologies-systems.html + */ + public static final String RPID_CS_URI = RID_CS_URI; + private static final String CM_COPYRIGHT = "This content from LOINC® is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at https://loinc.org/license/. The LOINC/RSNA Radiology Playbook and the LOINC Part File contain content from RadLex® (http://rsna.org/RadLex.aspx), copyright © 2005-2017, The Radiological Society of North America, Inc., available at no cost under the license at http://www.rsna.org/uploadedFiles/RSNA/Content/Informatics/RadLex_License_Agreement_and_Terms_of_Use_V2_Final.pdf."; private final Map myCode2Concept; private final TermCodeSystemVersion myCodeSystemVersion; private final Set myPropertyNames; @@ -118,7 +148,8 @@ public class LoincRsnaPlaybookHandler extends BaseHandler implements IRecordHand .setTargetCodeSystem(RID_CS_URI) .setTargetCode(rid) .setTargetDisplay(preferredName) - .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL)); + .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL), + CM_COPYRIGHT); } // LOINC Term -> Radlex RPID code mappings @@ -134,7 +165,8 @@ public class LoincRsnaPlaybookHandler extends BaseHandler implements IRecordHand .setTargetCodeSystem(RPID_CS_URI) .setTargetCode(rpid) .setTargetDisplay(longName) - .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL)); + .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL), + CM_COPYRIGHT); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsSiHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsSiHandler.java index 7b0310a76f0..8930694a490 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsSiHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsSiHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ValueSet; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsUsHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsUsHandler.java index 70f369b1f0f..1068349bf1b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsUsHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincTop2000LabResultsUsHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ValueSet; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincUniversalOrderSetHandler.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincUniversalOrderSetHandler.java index 34208471bd9..71439449f02 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincUniversalOrderSetHandler.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/loinc/LoincUniversalOrderSetHandler.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.loinc; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; import ca.uhn.fhir.jpa.term.IRecordHandler; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerConcept.java index 42b080df729..c1fbdb30aa9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerConcept.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.snomedct; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.term.IRecordHandler; import org.apache.commons.csv.CSVRecord; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerDescription.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerDescription.java index e7ef13c41db..2aa2ebc8fd8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerDescription.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerDescription.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.snomedct; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.term.IRecordHandler; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerRelationship.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerRelationship.java index 171c5e16a8c..cc58cecba43 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerRelationship.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/snomedct/SctHandlerRelationship.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.term.snomedct; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java index 1b6e270875e..6639e4bf878 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java @@ -281,6 +281,7 @@ public abstract class BaseJpaTest { @Override public Void doInTransaction(TransactionStatus theStatus) { entityManager.createQuery("DELETE from " + TermConceptProperty.class.getSimpleName() + " d").executeUpdate(); + entityManager.createQuery("DELETE from " + TermConceptDesignation.class.getSimpleName() + " d").executeUpdate(); entityManager.createQuery("DELETE from " + TermConcept.class.getSimpleName() + " d").executeUpdate(); for (TermCodeSystem next : entityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) { next.setCurrentVersion(null); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3CodeSystemTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3CodeSystemTest.java index e0b580fd79a..ded3314ee5a 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3CodeSystemTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3CodeSystemTest.java @@ -271,5 +271,10 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst TestUtil.clearAllStaticFieldsForUnitTest(); } + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } + } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3Test.java index abd83f128cf..60b94ec3d2c 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3Test.java @@ -134,7 +134,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs @Test public void testUploadMissingUrl() throws Exception { byte[] packageBytes = createSctZip(); - + try { ourClient .operation() @@ -207,7 +207,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs assertThat(((IntegerType)respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1)); } - + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java index 9e795d95be6..0fe0e96b7d6 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java @@ -56,6 +56,11 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test { TermConcept childAAB = new TermConcept(cs, "childAAB"); childAAB.addPropertyString("propA", "valueAAB"); childAAB.addPropertyString("propB", "foo"); + childAAB.addDesignation() + .setUseSystem("D1S") + .setUseCode("D1C") + .setUseDisplay("D1D") + .setValue("D1V"); childAA.addChild(childAAB, RelationshipTypeEnum.ISA); TermConcept childAB = new TermConcept(cs, "childAB"); @@ -193,6 +198,31 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test { assertThat(codes, containsInAnyOrder("ParentA", "childAAA", "childAAB", "childAA", "childAB", "ParentB")); } + @Test + public void testPropertiesAndDesignationsPreservedInExpansion() { + createCodeSystem(); + + List codes; + + ValueSet vs = new ValueSet(); + ValueSet.ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(CS_URL); + include.addConcept().setCode("childAAB"); + ValueSet outcome = myTermSvc.expandValueSet(vs); + + codes = toCodesContains(outcome.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("childAAB")); + + ValueSet.ValueSetExpansionContainsComponent concept = outcome.getExpansion().getContains().get(0); + assertEquals("childAAB", concept.getCode()); + assertEquals("http://example.com/my_code_system", concept.getSystem()); + assertEquals(null, concept.getDisplay()); + assertEquals("D1S", concept.getDesignation().get(0).getUse().getSystem()); + assertEquals("D1C", concept.getDesignation().get(0).getUse().getCode()); + assertEquals("D1D", concept.getDesignation().get(0).getUse().getDisplay()); + assertEquals("D1V", concept.getDesignation().get(0).getValue()); + } + @Test public void testFindCodesAbove() { IIdType id = createCodeSystem(); diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java index 184ae74ac78..a70c9399b8b 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java @@ -8,9 +8,10 @@ import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; +import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; -import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; +import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.rest.api.EncodingEnum; @@ -50,6 +51,13 @@ public class TestRestfulServer extends RestfulServer { private AnnotationConfigWebApplicationContext myAppCtx; + @Override + public void destroy() { + super.destroy(); + ourLog.info("Server is shutting down"); + myAppCtx.destroy(); + } + @SuppressWarnings("unchecked") @Override protected void initialize() throws ServletException { @@ -74,79 +82,79 @@ public class TestRestfulServer extends RestfulServer { ETagSupportEnum etagSupport; String baseUrlProperty; List plainProviders = new ArrayList(); - + switch (fhirVersionParam.trim().toUpperCase()) { - case "TDL2": - case "DSTU2": { - myAppCtx = new AnnotationConfigWebApplicationContext(); - myAppCtx.setServletConfig(getServletConfig()); - myAppCtx.setParent(parentAppCtx); - if ("TDL2".equals(fhirVersionParam.trim().toUpperCase())) { - myAppCtx.register(TdlDstu2Config.class); - baseUrlProperty = FHIR_BASEURL_TDL2; - } else { - myAppCtx.register(TestDstu2Config.class, WebsocketDispatcherConfig.class); - baseUrlProperty = FHIR_BASEURL_DSTU2; + case "TDL2": + case "DSTU2": { + myAppCtx = new AnnotationConfigWebApplicationContext(); + myAppCtx.setServletConfig(getServletConfig()); + myAppCtx.setParent(parentAppCtx); + if ("TDL2".equals(fhirVersionParam.trim().toUpperCase())) { + myAppCtx.register(TdlDstu2Config.class); + baseUrlProperty = FHIR_BASEURL_TDL2; + } else { + myAppCtx.register(TestDstu2Config.class, WebsocketDispatcherConfig.class); + baseUrlProperty = FHIR_BASEURL_DSTU2; + } + myAppCtx.refresh(); + setFhirContext(FhirContext.forDstu2()); + beans = myAppCtx.getBean("myResourceProvidersDstu2", List.class); + plainProviders.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); + systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); + etagSupport = ETagSupportEnum.ENABLED; + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription(implDesc); + setServerConformanceProvider(confProvider); + break; } - myAppCtx.refresh(); - setFhirContext(FhirContext.forDstu2()); - beans = myAppCtx.getBean("myResourceProvidersDstu2", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); - systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); - etagSupport = ETagSupportEnum.ENABLED; - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, myAppCtx.getBean(DaoConfig.class)); - confProvider.setImplementationDescription(implDesc); - setServerConformanceProvider(confProvider); - break; - } - case "TDL3": - case "DSTU3": { - myAppCtx = new AnnotationConfigWebApplicationContext(); - myAppCtx.setServletConfig(getServletConfig()); - myAppCtx.setParent(parentAppCtx); - if ("TDL3".equals(fhirVersionParam.trim().toUpperCase())) { - myAppCtx.register(TdlDstu3Config.class); - baseUrlProperty = FHIR_BASEURL_TDL3; - } else { - myAppCtx.register(TestDstu3Config.class, WebsocketDispatcherConfig.class); - baseUrlProperty = FHIR_BASEURL_DSTU3; + case "TDL3": + case "DSTU3": { + myAppCtx = new AnnotationConfigWebApplicationContext(); + myAppCtx.setServletConfig(getServletConfig()); + myAppCtx.setParent(parentAppCtx); + if ("TDL3".equals(fhirVersionParam.trim().toUpperCase())) { + myAppCtx.register(TdlDstu3Config.class); + baseUrlProperty = FHIR_BASEURL_TDL3; + } else { + myAppCtx.register(TestDstu3Config.class, WebsocketDispatcherConfig.class); + baseUrlProperty = FHIR_BASEURL_DSTU3; + } + myAppCtx.refresh(); + setFhirContext(FhirContext.forDstu3()); + beans = myAppCtx.getBean("myResourceProvidersDstu3", List.class); + plainProviders.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); + systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); + etagSupport = ETagSupportEnum.ENABLED; + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription(implDesc); + setServerConformanceProvider(confProvider); + plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); + break; } - myAppCtx.refresh(); - setFhirContext(FhirContext.forDstu3()); - beans = myAppCtx.getBean("myResourceProvidersDstu3", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); - systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); - etagSupport = ETagSupportEnum.ENABLED; - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class)); - confProvider.setImplementationDescription(implDesc); - setServerConformanceProvider(confProvider); - plainProviders.add(myAppCtx.getBean(TerminologyUploaderProvider.class)); - break; + case "R4": { + myAppCtx = new AnnotationConfigWebApplicationContext(); + myAppCtx.setServletConfig(getServletConfig()); + myAppCtx.setParent(parentAppCtx); + myAppCtx.register(TestR4Config.class, WebsocketDispatcherConfig.class); + baseUrlProperty = FHIR_BASEURL_R4; + myAppCtx.refresh(); + setFhirContext(FhirContext.forR4()); + beans = myAppCtx.getBean("myResourceProvidersR4", List.class); + plainProviders.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); + systemDao = myAppCtx.getBean("mySystemDaoR4", IFhirSystemDao.class); + etagSupport = ETagSupportEnum.ENABLED; + JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription(implDesc); + setServerConformanceProvider(confProvider); + plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderR4.class)); + break; + } + default: + throw new ServletException("Unknown FHIR version specified in init-param[FhirVersion]: " + fhirVersionParam); } - case "R4": { - myAppCtx = new AnnotationConfigWebApplicationContext(); - myAppCtx.setServletConfig(getServletConfig()); - myAppCtx.setParent(parentAppCtx); - myAppCtx.register(TestR4Config.class, WebsocketDispatcherConfig.class); - baseUrlProperty = FHIR_BASEURL_R4; - myAppCtx.refresh(); - setFhirContext(FhirContext.forR4()); - beans = myAppCtx.getBean("myResourceProvidersR4", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); - systemDao = myAppCtx.getBean("mySystemDaoR4", IFhirSystemDao.class); - etagSupport = ETagSupportEnum.ENABLED; - JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, myAppCtx.getBean(DaoConfig.class)); - confProvider.setImplementationDescription(implDesc); - setServerConformanceProvider(confProvider); - plainProviders.add(myAppCtx.getBean(TerminologyUploaderProvider.class)); - break; - } - default: - throw new ServletException("Unknown FHIR version specified in init-param[FhirVersion]: " + fhirVersionParam); - } - + /* - * On the DSTU2 endpoint, we want to enable ETag support + * On the DSTU2 endpoint, we want to enable ETag support */ setETagSupport(etagSupport); @@ -155,9 +163,9 @@ public class TestRestfulServer extends RestfulServer { */ FhirContext ctx = getFhirContext(); ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); - + /* - * The resource and system providers (which actually implement the various FHIR + * The resource and system providers (which actually implement the various FHIR * operations in this server) are all retrieved from the spring context above * and are provided to the server here. */ @@ -187,17 +195,17 @@ public class TestRestfulServer extends RestfulServer { responseHighlighterInterceptor.setShowRequestHeaders(false); responseHighlighterInterceptor.setShowResponseHeaders(true); registerInterceptor(responseHighlighterInterceptor); - + registerInterceptor(new BanUnsupportedHttpMethodsInterceptor()); - + /* * Default to JSON with pretty printing */ setDefaultPrettyPrint(true); setDefaultResponseEncoding(EncodingEnum.JSON); - + /* - * The server's base URL (e.g. http://fhirtest.uhn.ca/baseDstu2) is + * The server's base URL (e.g. http://fhirtest.uhn.ca/baseDstu2) is * pulled from a system property, which is helpful if you want to try * hosting your own copy of this server. */ @@ -210,12 +218,12 @@ public class TestRestfulServer extends RestfulServer { } } setServerAddressStrategy(new MyHardcodedServerAddressStrategy(baseUrl)); - + /* - * Spool results to the database + * Spool results to the database */ setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class)); - + /* * Load interceptors for the server from Spring */ @@ -226,13 +234,6 @@ public class TestRestfulServer extends RestfulServer { } - @Override - public void destroy() { - super.destroy(); - ourLog.info("Server is shutting down"); - myAppCtx.destroy(); - } - /** * The public server is deployed to http://fhirtest.uhn.ca and the JEE webserver * where this FHIR server is deployed is actually fronted by an Apache HTTPd instance, @@ -248,7 +249,7 @@ public class TestRestfulServer extends RestfulServer { public String determineServerBase(ServletContext theServletContext, HttpServletRequest theRequest) { /* * This is a bit of a hack, but we want to support both HTTP and HTTPS seamlessly - * so we have the outer httpd proxy relay requests to the Java container on + * so we have the outer httpd proxy relay requests to the Java container on * port 28080 for http and 28081 for https. */ String retVal = super.determineServerBase(theServletContext, theRequest); @@ -257,8 +258,8 @@ public class TestRestfulServer extends RestfulServer { } return retVal; } - + } - - + + } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java index 9e7ec5170de..f3acbc931ea 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java @@ -1,7 +1,7 @@ package ca.uhn.fhirtest.interceptor; import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider; -import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; +import ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException; import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor; @@ -16,8 +16,8 @@ import static org.apache.commons.lang3.StringUtils.isBlank; public class PublicSecurityInterceptor extends AuthorizationInterceptor { - private HashSet myTokens; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PublicSecurityInterceptor.class); + private HashSet myTokens; public PublicSecurityInterceptor() { String passwordsString = System.getProperty("fhir.tdlpass"); @@ -34,7 +34,7 @@ public class PublicSecurityInterceptor extends AuthorizationInterceptor { if (isBlank(authHeader)) { return new RuleBuilder() .deny().operation().named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING).onServer().andThen() - .deny().operation().named(TerminologyUploaderProvider.UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andThen() + .deny().operation().named(BaseTerminologyUploaderProvider.UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andThen() .allowAll() .build(); } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1e5d2924c82..1e41560b15d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -6,6 +6,36 @@ HAPI FHIR Changelog + + + When performing a FHIR resource update in the JPA server + where the update happens within a transaction, and the + resource being updated contains placeholder IDs, and + the resource has not actually changed, a new version was + created even though there was not actually any change. + This particular combination of circumstances seems very + specific and improbable, but it is quite common for some + types of solutions (e.g. mapping HL7v2 data) so this + fix can prevent significant wasted space in some cases. + + + JPA server index tables did not have a column length specified + on the resource type column. This caused the default of 255 to + be used, which wasted a lot of space since resource names are all + less than 30 chars long and a single resource can have 10-100+ + index rows depending on configuration. This has now been set + to a much more sensible 30. + + + The LOINC uploader for the JPA Terminology Server has been + significantly beefed up so that it now takes in the full + set of LOINC distribution artifacts, and creates not only + the LOINC CodeSystem but a complete set of concept properties, + a number of LOINC ValueSets, and a number of LOINC ConceptMaps. + This work was sponsored by the Regenstrief Institute. Thanks + to Regenstrief for their support! + + This release corrects an inefficiency in the JPA Server, but requires a schema