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.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.Index;
032import jakarta.persistence.JoinColumn;
033import jakarta.persistence.ManyToOne;
034import jakarta.persistence.OneToMany;
035import jakarta.persistence.OneToOne;
036import jakarta.persistence.SequenceGenerator;
037import jakarta.persistence.Table;
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;
043
044import java.io.Serializable;
045import java.util.ArrayList;
046import java.util.Collection;
047
048import static org.apache.commons.lang3.StringUtils.length;
049
050@Table(
051                name = "TRM_CODESYSTEM_VER",
052                // Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this)
053                uniqueConstraints = {
054                        @UniqueConstraint(
055                                        name = TermCodeSystemVersion.IDX_CODESYSTEM_AND_VER,
056                                        columnNames = {"CODESYSTEM_PID", "CS_VERSION_ID"})
057                },
058                indexes = {
059                        @Index(name = "FK_CODESYSVER_RES_ID", columnList = "RES_ID"),
060                        @Index(name = "FK_CODESYSVER_CS_ID", columnList = "CODESYSTEM_PID")
061                })
062@Entity()
063public class TermCodeSystemVersion implements Serializable {
064        public static final String IDX_CODESYSTEM_AND_VER = "IDX_CODESYSTEM_AND_VER";
065        public static final int MAX_VERSION_LENGTH = 200;
066        private static final long serialVersionUID = 1L;
067
068        @OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")
069        private Collection<TermConcept> myConcepts;
070
071        @Id()
072        @SequenceGenerator(name = "SEQ_CODESYSTEMVER_PID", sequenceName = "SEQ_CODESYSTEMVER_PID")
073        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEMVER_PID")
074        @Column(name = "PID")
075        private Long myId;
076
077        @OneToOne(fetch = FetchType.LAZY)
078        @JoinColumn(
079                        name = "RES_ID",
080                        referencedColumnName = "RES_ID",
081                        nullable = false,
082                        updatable = false,
083                        foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
084        private ResourceTable myResource;
085
086        @Column(name = "RES_ID", nullable = false, insertable = false, updatable = false)
087        private Long myResourcePid;
088
089        @Column(name = "CS_VERSION_ID", nullable = true, updatable = true, length = MAX_VERSION_LENGTH)
090        private String myCodeSystemVersionId;
091
092        /**
093         * This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
094         * issued. It should be made non-nullable at some point.
095         */
096        @ManyToOne(fetch = FetchType.LAZY)
097        @JoinColumn(
098                        name = "CODESYSTEM_PID",
099                        referencedColumnName = "PID",
100                        nullable = true,
101                        foreignKey = @ForeignKey(name = "FK_CODESYSVER_CS_ID"))
102        private TermCodeSystem myCodeSystem;
103
104        @Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
105        private Long myCodeSystemPid;
106
107        @SuppressWarnings("unused")
108        @OneToOne(mappedBy = "myCurrentVersion", optional = true, fetch = FetchType.LAZY)
109        private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny;
110
111        @Column(name = "CS_DISPLAY", nullable = true, updatable = true, length = MAX_VERSION_LENGTH)
112        private String myCodeSystemDisplayName;
113
114        /**
115         * Constructor
116         */
117        public TermCodeSystemVersion() {
118                super();
119        }
120
121        public TermCodeSystem getCodeSystem() {
122                return myCodeSystem;
123        }
124
125        public TermCodeSystemVersion setCodeSystem(TermCodeSystem theCodeSystem) {
126                myCodeSystem = theCodeSystem;
127                return this;
128        }
129
130        public String getCodeSystemVersionId() {
131                return myCodeSystemVersionId;
132        }
133
134        public TermCodeSystemVersion setCodeSystemVersionId(String theCodeSystemVersionId) {
135                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
136                                theCodeSystemVersionId,
137                                MAX_VERSION_LENGTH,
138                                "Version ID exceeds maximum length (" + MAX_VERSION_LENGTH + "): " + length(theCodeSystemVersionId));
139                myCodeSystemVersionId = theCodeSystemVersionId;
140                return this;
141        }
142
143        public Collection<TermConcept> getConcepts() {
144                if (myConcepts == null) {
145                        myConcepts = new ArrayList<>();
146                }
147                return myConcepts;
148        }
149
150        public Long getPid() {
151                return myId;
152        }
153
154        public ResourceTable getResource() {
155                return myResource;
156        }
157
158        public TermCodeSystemVersion setResource(ResourceTable theResource) {
159                myResource = theResource;
160                return this;
161        }
162
163        public TermCodeSystemVersion setId(Long theId) {
164                myId = theId;
165                return this;
166        }
167
168        @Override
169        public boolean equals(Object theO) {
170                if (this == theO) {
171                        return true;
172                }
173
174                if (theO == null || getClass() != theO.getClass()) {
175                        return false;
176                }
177
178                TermCodeSystemVersion that = (TermCodeSystemVersion) theO;
179
180                return new EqualsBuilder()
181                                .append(myCodeSystemVersionId, that.myCodeSystemVersionId)
182                                .append(myCodeSystemPid, that.myCodeSystemPid)
183                                .isEquals();
184        }
185
186        @Override
187        public int hashCode() {
188                HashCodeBuilder b = new HashCodeBuilder(17, 37);
189                b.append(myCodeSystemVersionId);
190                b.append(myCodeSystemPid);
191                return b.toHashCode();
192        }
193
194        public String getCodeSystemDisplayName() {
195                return myCodeSystemDisplayName;
196        }
197
198        public void setCodeSystemDisplayName(String theCodeSystemDisplayName) {
199                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
200                                theCodeSystemDisplayName,
201                                MAX_VERSION_LENGTH,
202                                "Version ID exceeds maximum length (" + MAX_VERSION_LENGTH + "): " + length(theCodeSystemDisplayName));
203                myCodeSystemDisplayName = theCodeSystemDisplayName;
204        }
205
206        public TermConcept addConcept() {
207                TermConcept concept = new TermConcept();
208                concept.setCodeSystemVersion(this);
209                getConcepts().add(concept);
210                return concept;
211        }
212
213        @Override
214        public String toString() {
215                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
216                b.append("pid", myId);
217                b.append("displayName", myCodeSystemDisplayName);
218                b.append("codeSystemResourcePid", myResourcePid);
219                b.append("codeSystemPid", myCodeSystemPid);
220                b.append("codeSystemVersionId", myCodeSystemVersionId);
221                return b.toString();
222        }
223
224        TermCodeSystemVersion setCodeSystemPidForUnitTest(long theCodeSystemPid) {
225                myCodeSystemPid = theCodeSystemPid;
226                return this;
227        }
228}