001/* 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.entity; 021 022import ca.uhn.fhir.util.ValidateUtil; 023import jakarta.annotation.Nonnull; 024import jakarta.persistence.Column; 025import jakarta.persistence.Entity; 026import jakarta.persistence.FetchType; 027import jakarta.persistence.ForeignKey; 028import jakarta.persistence.GeneratedValue; 029import jakarta.persistence.GenerationType; 030import jakarta.persistence.Id; 031import jakarta.persistence.JoinColumn; 032import jakarta.persistence.Lob; 033import jakarta.persistence.ManyToOne; 034import jakarta.persistence.OneToMany; 035import jakarta.persistence.SequenceGenerator; 036import jakarta.persistence.Table; 037import jakarta.persistence.Transient; 038import jakarta.persistence.UniqueConstraint; 039import org.apache.commons.lang3.builder.EqualsBuilder; 040import org.apache.commons.lang3.builder.HashCodeBuilder; 041import org.apache.commons.lang3.builder.ToStringBuilder; 042import org.apache.commons.lang3.builder.ToStringStyle; 043import org.hibernate.Length; 044 045import java.io.Serializable; 046import java.util.ArrayList; 047import java.util.List; 048 049import static org.apache.commons.lang3.StringUtils.isNotEmpty; 050import static org.apache.commons.lang3.StringUtils.left; 051import static org.apache.commons.lang3.StringUtils.length; 052 053/* 054 * DM 2019-08-01 - Do not use IDX_VALUESET_CONCEPT_CS_CD or IDX_VALUESET_CONCEPT_CS_CODE; this was previously used as an index so reusing the name will 055 * bork up migration tasks. 056 */ 057@Table( 058 name = "TRM_VALUESET_CONCEPT", 059 uniqueConstraints = { 060 @UniqueConstraint( 061 name = "IDX_VS_CONCEPT_CSCD", 062 columnNames = {"VALUESET_PID", "SYSTEM_URL", "CODEVAL"}), 063 @UniqueConstraint( 064 name = "IDX_VS_CONCEPT_ORDER", 065 columnNames = {"VALUESET_PID", "VALUESET_ORDER"}) 066 }) 067@Entity() 068public class TermValueSetConcept implements Serializable { 069 private static final long serialVersionUID = 1L; 070 071 @Id() 072 @SequenceGenerator(name = "SEQ_VALUESET_CONCEPT_PID", sequenceName = "SEQ_VALUESET_CONCEPT_PID") 073 @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_CONCEPT_PID") 074 @Column(name = "PID") 075 private Long myId; 076 077 @ManyToOne(fetch = FetchType.LAZY) 078 @JoinColumn( 079 name = "VALUESET_PID", 080 referencedColumnName = "PID", 081 nullable = false, 082 foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID")) 083 private TermValueSet myValueSet; 084 085 @Column(name = "VALUESET_PID", insertable = false, updatable = false, nullable = false) 086 private Long myValueSetPid; 087 088 @Column(name = "INDEX_STATUS", nullable = true) 089 private Long myIndexStatus; 090 091 @Column(name = "VALUESET_ORDER", nullable = false) 092 private int myOrder; 093 094 @Transient 095 private String myValueSetUrl; 096 097 @Transient 098 private String myValueSetName; 099 100 @Column(name = "SOURCE_PID", nullable = true) 101 private Long mySourceConceptPid; 102 103 @Deprecated(since = "7.2.0") 104 @Lob 105 @Column(name = "SOURCE_DIRECT_PARENT_PIDS", nullable = true) 106 private String mySourceConceptDirectParentPids; 107 108 @Column(name = "SOURCE_DIRECT_PARENT_PIDS_VC", nullable = true, length = Length.LONG32) 109 private String mySourceConceptDirectParentPidsVc; 110 111 @Column(name = "SYSTEM_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH) 112 private String mySystem; 113 114 @Column(name = "SYSTEM_VER", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH) 115 private String mySystemVer; 116 117 @Column(name = "CODEVAL", nullable = false, length = TermConcept.MAX_CODE_LENGTH) 118 private String myCode; 119 120 @Column(name = "DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH) 121 private String myDisplay; 122 123 @OneToMany(mappedBy = "myConcept", fetch = FetchType.LAZY) 124 private List<TermValueSetConceptDesignation> myDesignations; 125 126 @Transient 127 private transient Integer myHashCode; 128 129 /** 130 * Constructor 131 */ 132 public TermValueSetConcept() { 133 super(); 134 } 135 136 public Long getId() { 137 return myId; 138 } 139 140 public TermValueSet getValueSet() { 141 return myValueSet; 142 } 143 144 public TermValueSetConcept setValueSet(TermValueSet theValueSet) { 145 myValueSet = theValueSet; 146 return this; 147 } 148 149 public int getOrder() { 150 return myOrder; 151 } 152 153 public TermValueSetConcept setOrder(int theOrder) { 154 myOrder = theOrder; 155 return this; 156 } 157 158 public String getValueSetUrl() { 159 if (myValueSetUrl == null) { 160 myValueSetUrl = getValueSet().getUrl(); 161 } 162 163 return myValueSetUrl; 164 } 165 166 public String getValueSetName() { 167 if (myValueSetName == null) { 168 myValueSetName = getValueSet().getName(); 169 } 170 171 return myValueSetName; 172 } 173 174 public String getSystem() { 175 return mySystem; 176 } 177 178 public TermValueSetConcept setSystem(@Nonnull String theSystem) { 179 ValidateUtil.isNotBlankOrThrowIllegalArgument(theSystem, "theSystem must not be null or empty"); 180 ValidateUtil.isNotTooLongOrThrowIllegalArgument( 181 theSystem, 182 TermCodeSystem.MAX_URL_LENGTH, 183 "System exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSystem)); 184 mySystem = theSystem; 185 return this; 186 } 187 188 public String getSystemVersion() { 189 return mySystemVer; 190 } 191 192 public TermValueSetConcept setSystemVersion(String theSystemVersion) { 193 ValidateUtil.isNotTooLongOrThrowIllegalArgument( 194 theSystemVersion, 195 TermCodeSystemVersion.MAX_VERSION_LENGTH, 196 "System version exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): " 197 + length(theSystemVersion)); 198 mySystemVer = theSystemVersion; 199 return this; 200 } 201 202 public String getCode() { 203 return myCode; 204 } 205 206 public TermValueSetConcept setCode(@Nonnull String theCode) { 207 ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty"); 208 ValidateUtil.isNotTooLongOrThrowIllegalArgument( 209 theCode, 210 TermConcept.MAX_CODE_LENGTH, 211 "Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode)); 212 myCode = theCode; 213 return this; 214 } 215 216 public String getDisplay() { 217 return myDisplay; 218 } 219 220 public TermValueSetConcept setDisplay(String theDisplay) { 221 myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH); 222 return this; 223 } 224 225 public List<TermValueSetConceptDesignation> getDesignations() { 226 if (myDesignations == null) { 227 myDesignations = new ArrayList<>(); 228 } 229 230 return myDesignations; 231 } 232 233 @Override 234 public boolean equals(Object theO) { 235 if (this == theO) return true; 236 237 if (!(theO instanceof TermValueSetConcept)) return false; 238 239 TermValueSetConcept that = (TermValueSetConcept) theO; 240 241 return new EqualsBuilder() 242 .append(myValueSetPid, that.myValueSetPid) 243 .append(getSystem(), that.getSystem()) 244 .append(getCode(), that.getCode()) 245 .isEquals(); 246 } 247 248 @Override 249 public int hashCode() { 250 if (myHashCode == null) { 251 myHashCode = new HashCodeBuilder(17, 37) 252 .append(myValueSetPid) 253 .append(getSystem()) 254 .append(getCode()) 255 .toHashCode(); 256 } 257 return myHashCode; 258 } 259 260 @Override 261 public String toString() { 262 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 263 .append("id", myId) 264 .append("order", myOrder) 265 .append("system", mySystem) 266 .append("code", myCode) 267 .append("valueSet", myValueSet != null ? myValueSet.getId() : "(null)") 268 .append("valueSetPid", myValueSetPid) 269 .append("valueSetUrl", this.getValueSetUrl()) 270 .append("valueSetName", this.getValueSetName()) 271 .append("display", myDisplay) 272 .append("designationCount", myDesignations != null ? myDesignations.size() : "(null)") 273 .append("parentPids", getSourceConceptDirectParentPids()) 274 .toString(); 275 } 276 277 public Long getIndexStatus() { 278 return myIndexStatus; 279 } 280 281 public void setIndexStatus(Long theIndexStatus) { 282 myIndexStatus = theIndexStatus; 283 } 284 285 public void setSourceConceptPid(Long theSourceConceptPid) { 286 mySourceConceptPid = theSourceConceptPid; 287 } 288 289 public void setSourceConceptDirectParentPids(String theSourceConceptDirectParentPids) { 290 mySourceConceptDirectParentPids = theSourceConceptDirectParentPids; 291 mySourceConceptDirectParentPidsVc = theSourceConceptDirectParentPids; 292 } 293 294 public String getSourceConceptDirectParentPids() { 295 return isNotEmpty(mySourceConceptDirectParentPidsVc) 296 ? mySourceConceptDirectParentPidsVc 297 : mySourceConceptDirectParentPids; 298 } 299}