001/* 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 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.jpa.model.entity.BasePartitionable; 023import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId; 024import ca.uhn.fhir.jpa.model.entity.ResourceTable; 025import ca.uhn.fhir.util.ValidateUtil; 026import jakarta.annotation.Nonnull; 027import jakarta.persistence.Column; 028import jakarta.persistence.Entity; 029import jakarta.persistence.EnumType; 030import jakarta.persistence.Enumerated; 031import jakarta.persistence.FetchType; 032import jakarta.persistence.ForeignKey; 033import jakarta.persistence.GeneratedValue; 034import jakarta.persistence.GenerationType; 035import jakarta.persistence.Id; 036import jakarta.persistence.IdClass; 037import jakarta.persistence.Index; 038import jakarta.persistence.JoinColumn; 039import jakarta.persistence.JoinColumns; 040import jakarta.persistence.ManyToOne; 041import jakarta.persistence.OneToMany; 042import jakarta.persistence.SequenceGenerator; 043import jakarta.persistence.Table; 044import jakarta.persistence.Temporal; 045import jakarta.persistence.TemporalType; 046import jakarta.persistence.Transient; 047import jakarta.persistence.UniqueConstraint; 048import org.apache.commons.lang3.builder.EqualsBuilder; 049import org.apache.commons.lang3.builder.ToStringBuilder; 050import org.apache.commons.lang3.builder.ToStringStyle; 051import org.hibernate.annotations.ColumnDefault; 052import org.hibernate.annotations.JdbcTypeCode; 053import org.hibernate.type.SqlTypes; 054 055import java.io.Serializable; 056import java.util.ArrayList; 057import java.util.Date; 058import java.util.List; 059 060import static org.apache.commons.lang3.StringUtils.left; 061import static org.apache.commons.lang3.StringUtils.length; 062 063@Table( 064 name = "TRM_VALUESET", 065 uniqueConstraints = { 066 @UniqueConstraint( 067 name = "IDX_VALUESET_URL", 068 columnNames = {"PARTITION_ID", "URL", "VER"}) 069 }, 070 indexes = { 071 // must have same name that indexed FK or SchemaMigrationTest complains because H2 sets this index 072 // automatically 073 @Index(name = "FK_TRMVALUESET_RES", columnList = "RES_ID") 074 }) 075@Entity() 076@IdClass(IdAndPartitionId.class) 077public class TermValueSet extends BasePartitionable implements Serializable { 078 public static final int MAX_EXPANSION_STATUS_LENGTH = 50; 079 public static final int MAX_NAME_LENGTH = 200; 080 public static final int MAX_URL_LENGTH = 200; 081 public static final int MAX_VER_LENGTH = 200; 082 private static final long serialVersionUID = 1L; 083 084 @Id() 085 @SequenceGenerator(name = "SEQ_VALUESET_PID", sequenceName = "SEQ_VALUESET_PID") 086 @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_PID") 087 @Column(name = "PID") 088 private Long myId; 089 090 @Column(name = "URL", nullable = false, length = MAX_URL_LENGTH) 091 private String myUrl; 092 093 @Column(name = "VER", nullable = true, length = MAX_VER_LENGTH) 094 private String myVersion; 095 096 @ManyToOne() 097 @JoinColumns( 098 value = { 099 @JoinColumn( 100 name = "RES_ID", 101 referencedColumnName = "RES_ID", 102 nullable = false, 103 insertable = false, 104 updatable = false), 105 @JoinColumn( 106 name = "PARTITION_ID", 107 referencedColumnName = "PARTITION_ID", 108 nullable = false, 109 insertable = false, 110 updatable = false) 111 }, 112 foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES")) 113 private ResourceTable myResource; 114 115 @Column(name = "RES_ID", nullable = false) 116 private Long myResourcePid; 117 118 @Column(name = "VSNAME", nullable = true, length = MAX_NAME_LENGTH) 119 private String myName; 120 121 @OneToMany(mappedBy = "myValueSet", fetch = FetchType.LAZY) 122 private List<TermValueSetConcept> myConcepts; 123 124 @Column(name = "TOTAL_CONCEPTS", nullable = false) 125 @ColumnDefault("0") 126 private Long myTotalConcepts; 127 128 @Column(name = "TOTAL_CONCEPT_DESIGNATIONS", nullable = false) 129 @ColumnDefault("0") 130 private Long myTotalConceptDesignations; 131 132 @Enumerated(EnumType.STRING) 133 @JdbcTypeCode(SqlTypes.VARCHAR) 134 @Column(name = "EXPANSION_STATUS", nullable = false, length = MAX_EXPANSION_STATUS_LENGTH) 135 private TermValueSetPreExpansionStatusEnum myExpansionStatus; 136 137 @Temporal(TemporalType.TIMESTAMP) 138 @Column(name = "EXPANDED_AT", nullable = true) 139 private Date myExpansionTimestamp; 140 141 @Transient 142 private transient Integer myHashCode; 143 144 public TermValueSet() { 145 super(); 146 myExpansionStatus = TermValueSetPreExpansionStatusEnum.NOT_EXPANDED; 147 myTotalConcepts = 0L; 148 myTotalConceptDesignations = 0L; 149 } 150 151 public Date getExpansionTimestamp() { 152 return myExpansionTimestamp; 153 } 154 155 public void setExpansionTimestamp(Date theExpansionTimestamp) { 156 myExpansionTimestamp = theExpansionTimestamp; 157 } 158 159 public Long getId() { 160 return myId; 161 } 162 163 public IdAndPartitionId getPartitionedId() { 164 return IdAndPartitionId.forId(myId, this); 165 } 166 167 public String getUrl() { 168 return myUrl; 169 } 170 171 public TermValueSet setUrl(@Nonnull String theUrl) { 172 ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty"); 173 ValidateUtil.isNotTooLongOrThrowIllegalArgument( 174 theUrl, MAX_URL_LENGTH, "URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl)); 175 myUrl = theUrl; 176 return this; 177 } 178 179 public ResourceTable getResource() { 180 return myResource; 181 } 182 183 public TermValueSet setResource(ResourceTable theResource) { 184 myResource = theResource; 185 myResourcePid = theResource.getId().getId(); 186 setPartitionId(theResource.getPartitionId()); 187 return this; 188 } 189 190 public String getName() { 191 return myName; 192 } 193 194 public TermValueSet setName(String theName) { 195 myName = left(theName, MAX_NAME_LENGTH); 196 return this; 197 } 198 199 public List<TermValueSetConcept> getConcepts() { 200 if (myConcepts == null) { 201 myConcepts = new ArrayList<>(); 202 } 203 204 return myConcepts; 205 } 206 207 public Long getTotalConcepts() { 208 return myTotalConcepts; 209 } 210 211 public TermValueSet setTotalConcepts(Long theTotalConcepts) { 212 myTotalConcepts = theTotalConcepts; 213 return this; 214 } 215 216 public TermValueSet decrementTotalConcepts() { 217 if (myTotalConcepts > 0) { 218 myTotalConcepts--; 219 } 220 return this; 221 } 222 223 public TermValueSet incrementTotalConcepts() { 224 myTotalConcepts++; 225 return this; 226 } 227 228 public Long getTotalConceptDesignations() { 229 return myTotalConceptDesignations; 230 } 231 232 public TermValueSet setTotalConceptDesignations(Long theTotalConceptDesignations) { 233 myTotalConceptDesignations = theTotalConceptDesignations; 234 return this; 235 } 236 237 public TermValueSet decrementTotalConceptDesignations() { 238 if (myTotalConceptDesignations > 0) { 239 myTotalConceptDesignations--; 240 } 241 return this; 242 } 243 244 public TermValueSet incrementTotalConceptDesignations() { 245 myTotalConceptDesignations++; 246 return this; 247 } 248 249 public TermValueSetPreExpansionStatusEnum getExpansionStatus() { 250 return myExpansionStatus; 251 } 252 253 public void setExpansionStatus(TermValueSetPreExpansionStatusEnum theExpansionStatus) { 254 myExpansionStatus = theExpansionStatus; 255 } 256 257 public String getVersion() { 258 return myVersion; 259 } 260 261 public TermValueSet setVersion(String theVersion) { 262 ValidateUtil.isNotTooLongOrThrowIllegalArgument( 263 theVersion, 264 MAX_VER_LENGTH, 265 "Version exceeds maximum length (" + MAX_VER_LENGTH + "): " + length(theVersion)); 266 myVersion = theVersion; 267 return this; 268 } 269 270 @Override 271 public boolean equals(Object theO) { 272 if (this == theO) return true; 273 274 if (!(theO instanceof TermValueSet)) return false; 275 276 TermValueSet that = (TermValueSet) theO; 277 278 return new EqualsBuilder().append(getUrl(), that.getUrl()).isEquals(); 279 } 280 281 @Override 282 public int hashCode() { 283 if (myHashCode == null) { 284 myHashCode = getUrl().hashCode(); 285 } 286 return myHashCode; 287 } 288 289 @Override 290 public String toString() { 291 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 292 .append("id", myId) 293 .append("url", myUrl) 294 .append("version", myVersion) 295 .append("resourcePid", myResourcePid) 296 .append("name", myName) 297 .append(myConcepts != null ? ("conceptCount=" + myConcepts.size()) : ("concepts=(null)")) 298 .append("totalConcepts", myTotalConcepts) 299 .append("totalConceptDesignations", myTotalConceptDesignations) 300 .append("expansionStatus", myExpansionStatus) 301 .append(myResource != null ? ("resId=" + myResource) : ("resource=(null)")) 302 .toString(); 303 } 304}