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