001/*
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2023 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 org.apache.commons.lang3.builder.EqualsBuilder;
024import org.apache.commons.lang3.builder.HashCodeBuilder;
025import org.apache.commons.lang3.builder.ToStringBuilder;
026import org.apache.commons.lang3.builder.ToStringStyle;
027
028import java.io.Serializable;
029import java.util.ArrayList;
030import java.util.List;
031import javax.annotation.Nonnull;
032import javax.persistence.Column;
033import javax.persistence.Entity;
034import javax.persistence.FetchType;
035import javax.persistence.ForeignKey;
036import javax.persistence.GeneratedValue;
037import javax.persistence.GenerationType;
038import javax.persistence.Id;
039import javax.persistence.JoinColumn;
040import javax.persistence.Lob;
041import javax.persistence.ManyToOne;
042import javax.persistence.OneToMany;
043import javax.persistence.SequenceGenerator;
044import javax.persistence.Table;
045import javax.persistence.Transient;
046import javax.persistence.UniqueConstraint;
047
048import static org.apache.commons.lang3.StringUtils.left;
049import static org.apache.commons.lang3.StringUtils.length;
050
051/*
052 * 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
053 * bork up migration tasks.
054 */
055@Table(
056                name = "TRM_VALUESET_CONCEPT",
057                uniqueConstraints = {
058                        @UniqueConstraint(
059                                        name = "IDX_VS_CONCEPT_CSCD",
060                                        columnNames = {"VALUESET_PID", "SYSTEM_URL", "CODEVAL"}),
061                        @UniqueConstraint(
062                                        name = "IDX_VS_CONCEPT_ORDER",
063                                        columnNames = {"VALUESET_PID", "VALUESET_ORDER"})
064                })
065@Entity()
066public class TermValueSetConcept implements Serializable {
067        private static final long serialVersionUID = 1L;
068
069        @Id()
070        @SequenceGenerator(name = "SEQ_VALUESET_CONCEPT_PID", sequenceName = "SEQ_VALUESET_CONCEPT_PID")
071        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_CONCEPT_PID")
072        @Column(name = "PID")
073        private Long myId;
074
075        @ManyToOne(fetch = FetchType.LAZY)
076        @JoinColumn(
077                        name = "VALUESET_PID",
078                        referencedColumnName = "PID",
079                        nullable = false,
080                        foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID"))
081        private TermValueSet myValueSet;
082
083        @Column(name = "VALUESET_PID", insertable = false, updatable = false, nullable = false)
084        private Long myValueSetPid;
085
086        @Column(name = "INDEX_STATUS", nullable = true)
087        private Long myIndexStatus;
088
089        @Column(name = "VALUESET_ORDER", nullable = false)
090        private int myOrder;
091
092        @Transient
093        private String myValueSetUrl;
094
095        @Transient
096        private String myValueSetName;
097
098        @Column(name = "SOURCE_PID", nullable = true)
099        private Long mySourceConceptPid;
100
101        @Lob
102        @Column(name = "SOURCE_DIRECT_PARENT_PIDS", nullable = true)
103        private String mySourceConceptDirectParentPids;
104
105        @Column(name = "SYSTEM_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
106        private String mySystem;
107
108        @Column(name = "SYSTEM_VER", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
109        private String mySystemVer;
110
111        @Column(name = "CODEVAL", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
112        private String myCode;
113
114        @Column(name = "DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH)
115        private String myDisplay;
116
117        @OneToMany(mappedBy = "myConcept", fetch = FetchType.LAZY)
118        private List<TermValueSetConceptDesignation> myDesignations;
119
120        @Transient
121        private transient Integer myHashCode;
122
123        /**
124         * Constructor
125         */
126        public TermValueSetConcept() {
127                super();
128        }
129
130        public Long getId() {
131                return myId;
132        }
133
134        public TermValueSet getValueSet() {
135                return myValueSet;
136        }
137
138        public TermValueSetConcept setValueSet(TermValueSet theValueSet) {
139                myValueSet = theValueSet;
140                return this;
141        }
142
143        public int getOrder() {
144                return myOrder;
145        }
146
147        public TermValueSetConcept setOrder(int theOrder) {
148                myOrder = theOrder;
149                return this;
150        }
151
152        public String getValueSetUrl() {
153                if (myValueSetUrl == null) {
154                        myValueSetUrl = getValueSet().getUrl();
155                }
156
157                return myValueSetUrl;
158        }
159
160        public String getValueSetName() {
161                if (myValueSetName == null) {
162                        myValueSetName = getValueSet().getName();
163                }
164
165                return myValueSetName;
166        }
167
168        public String getSystem() {
169                return mySystem;
170        }
171
172        public TermValueSetConcept setSystem(@Nonnull String theSystem) {
173                ValidateUtil.isNotBlankOrThrowIllegalArgument(theSystem, "theSystem must not be null or empty");
174                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
175                                theSystem,
176                                TermCodeSystem.MAX_URL_LENGTH,
177                                "System exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSystem));
178                mySystem = theSystem;
179                return this;
180        }
181
182        public String getSystemVersion() {
183                return mySystemVer;
184        }
185
186        public TermValueSetConcept setSystemVersion(String theSystemVersion) {
187                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
188                                theSystemVersion,
189                                TermCodeSystemVersion.MAX_VERSION_LENGTH,
190                                "System version exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): "
191                                                + length(theSystemVersion));
192                mySystemVer = theSystemVersion;
193                return this;
194        }
195
196        public String getCode() {
197                return myCode;
198        }
199
200        public TermValueSetConcept setCode(@Nonnull String theCode) {
201                ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
202                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
203                                theCode,
204                                TermConcept.MAX_CODE_LENGTH,
205                                "Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
206                myCode = theCode;
207                return this;
208        }
209
210        public String getDisplay() {
211                return myDisplay;
212        }
213
214        public TermValueSetConcept setDisplay(String theDisplay) {
215                myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH);
216                return this;
217        }
218
219        public List<TermValueSetConceptDesignation> getDesignations() {
220                if (myDesignations == null) {
221                        myDesignations = new ArrayList<>();
222                }
223
224                return myDesignations;
225        }
226
227        @Override
228        public boolean equals(Object theO) {
229                if (this == theO) return true;
230
231                if (!(theO instanceof TermValueSetConcept)) return false;
232
233                TermValueSetConcept that = (TermValueSetConcept) theO;
234
235                return new EqualsBuilder()
236                                .append(myValueSetPid, that.myValueSetPid)
237                                .append(getSystem(), that.getSystem())
238                                .append(getCode(), that.getCode())
239                                .isEquals();
240        }
241
242        @Override
243        public int hashCode() {
244                if (myHashCode == null) {
245                        myHashCode = new HashCodeBuilder(17, 37)
246                                        .append(myValueSetPid)
247                                        .append(getSystem())
248                                        .append(getCode())
249                                        .toHashCode();
250                }
251                return myHashCode;
252        }
253
254        @Override
255        public String toString() {
256                return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
257                                .append("id", myId)
258                                .append("order", myOrder)
259                                .append("system", mySystem)
260                                .append("code", myCode)
261                                .append("valueSet", myValueSet != null ? myValueSet.getId() : "(null)")
262                                .append("valueSetPid", myValueSetPid)
263                                .append("valueSetUrl", this.getValueSetUrl())
264                                .append("valueSetName", this.getValueSetName())
265                                .append("display", myDisplay)
266                                .append("designationCount", myDesignations != null ? myDesignations.size() : "(null)")
267                                .append("parentPids", mySourceConceptDirectParentPids)
268                                .toString();
269        }
270
271        public Long getIndexStatus() {
272                return myIndexStatus;
273        }
274
275        public void setIndexStatus(Long theIndexStatus) {
276                myIndexStatus = theIndexStatus;
277        }
278
279        public void setSourceConceptPid(Long theSourceConceptPid) {
280                mySourceConceptPid = theSourceConceptPid;
281        }
282
283        public void setSourceConceptDirectParentPids(String theSourceConceptDirectParentPids) {
284                mySourceConceptDirectParentPids = theSourceConceptDirectParentPids;
285        }
286}