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