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.util.ValidateUtil;
025import jakarta.annotation.Nonnull;
026import jakarta.persistence.Column;
027import jakarta.persistence.Entity;
028import jakarta.persistence.ForeignKey;
029import jakarta.persistence.GeneratedValue;
030import jakarta.persistence.GenerationType;
031import jakarta.persistence.Id;
032import jakarta.persistence.IdClass;
033import jakarta.persistence.Index;
034import jakarta.persistence.JoinColumn;
035import jakarta.persistence.JoinColumns;
036import jakarta.persistence.ManyToOne;
037import jakarta.persistence.OneToMany;
038import jakarta.persistence.SequenceGenerator;
039import jakarta.persistence.Table;
040import org.apache.commons.lang3.Validate;
041import org.apache.commons.lang3.builder.EqualsBuilder;
042import org.apache.commons.lang3.builder.HashCodeBuilder;
043import org.apache.commons.lang3.builder.ToStringBuilder;
044import org.apache.commons.lang3.builder.ToStringStyle;
045
046import java.io.Serializable;
047import java.util.ArrayList;
048import java.util.List;
049
050import static org.apache.commons.lang3.StringUtils.left;
051import static org.apache.commons.lang3.StringUtils.length;
052
053@Entity
054@Table(
055                name = "TRM_CONCEPT_MAP_GRP_ELEMENT",
056                indexes = {
057                        @Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE"),
058                        @Index(name = "FK_TCMGELEMENT_GROUP", columnList = "CONCEPT_MAP_GROUP_PID")
059                })
060@IdClass(IdAndPartitionId.class)
061public class TermConceptMapGroupElement extends BasePartitionable implements Serializable {
062        private static final long serialVersionUID = 1L;
063
064        @Id()
065        @SequenceGenerator(name = "SEQ_CONCEPT_MAP_GRP_ELM_PID", sequenceName = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
066        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
067        @Column(name = "PID")
068        private Long myId;
069
070        @ManyToOne()
071        @JoinColumns(
072                        value = {
073                                @JoinColumn(
074                                                name = "CONCEPT_MAP_GROUP_PID",
075                                                insertable = false,
076                                                updatable = false,
077                                                nullable = false,
078                                                referencedColumnName = "PID"),
079                                @JoinColumn(
080                                                name = "PARTITION_ID",
081                                                referencedColumnName = "PARTITION_ID",
082                                                insertable = false,
083                                                updatable = false,
084                                                nullable = false)
085                        },
086                        foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP"))
087        private TermConceptMapGroup myConceptMapGroup;
088
089        @Column(name = "CONCEPT_MAP_GROUP_PID", nullable = false)
090        private Long myConceptMapGroupPid;
091
092        @Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
093        private String myCode;
094
095        @Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DISP_LENGTH)
096        private String myDisplay;
097
098        @OneToMany(mappedBy = "myConceptMapGroupElement")
099        private List<TermConceptMapGroupElementTarget> myConceptMapGroupElementTargets;
100
101        @Column(name = "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
102        private String myConceptMapUrl;
103
104        @Column(name = "SYSTEM_URL", nullable = true, length = TermCodeSystem.MAX_URL_LENGTH)
105        private String mySystem;
106
107        @Column(name = "SYSTEM_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
108        private String mySystemVersion;
109
110        @Column(name = "VALUESET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
111        private String myValueSet;
112
113        public String getCode() {
114                return myCode;
115        }
116
117        public TermConceptMapGroupElement setCode(@Nonnull String theCode) {
118                ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
119                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
120                                theCode,
121                                TermConcept.MAX_CODE_LENGTH,
122                                "Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
123                myCode = theCode;
124                return this;
125        }
126
127        public TermConceptMapGroup getConceptMapGroup() {
128                return myConceptMapGroup;
129        }
130
131        public TermConceptMapGroupElement setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) {
132                myConceptMapGroup = theTermConceptMapGroup;
133                myConceptMapGroupPid = theTermConceptMapGroup.getId();
134                Validate.notNull(myConceptMapGroupPid, "ConceptMapGroupPid must not be null");
135                setPartitionId(theTermConceptMapGroup.getPartitionId());
136                return this;
137        }
138
139        public List<TermConceptMapGroupElementTarget> getConceptMapGroupElementTargets() {
140                if (myConceptMapGroupElementTargets == null) {
141                        myConceptMapGroupElementTargets = new ArrayList<>();
142                }
143
144                return myConceptMapGroupElementTargets;
145        }
146
147        public String getConceptMapUrl() {
148                if (myConceptMapUrl == null) {
149                        myConceptMapUrl = getConceptMapGroup().getConceptMap().getUrl();
150                }
151                return myConceptMapUrl;
152        }
153
154        public String getDisplay() {
155                return myDisplay;
156        }
157
158        public TermConceptMapGroupElement setDisplay(String theDisplay) {
159                myDisplay = left(theDisplay, TermConcept.MAX_DISP_LENGTH);
160                return this;
161        }
162
163        public Long getId() {
164                return myId;
165        }
166
167        public String getSystem() {
168                if (mySystem == null) {
169                        mySystem = getConceptMapGroup().getSource();
170                }
171                return mySystem;
172        }
173
174        public String getSystemVersion() {
175                if (mySystemVersion == null) {
176                        mySystemVersion = getConceptMapGroup().getSourceVersion();
177                }
178                return mySystemVersion;
179        }
180
181        public String getValueSet() {
182                if (myValueSet == null) {
183                        myValueSet = getConceptMapGroup().getSourceValueSet();
184                }
185                return myValueSet;
186        }
187
188        @Override
189        public boolean equals(Object o) {
190                if (this == o) return true;
191
192                if (!(o instanceof TermConceptMapGroupElement)) return false;
193
194                TermConceptMapGroupElement that = (TermConceptMapGroupElement) o;
195
196                return new EqualsBuilder()
197                                .append(getCode(), that.getCode())
198                                .append(getSystem(), that.getSystem())
199                                .append(getSystemVersion(), that.getSystemVersion())
200                                .isEquals();
201        }
202
203        @Override
204        public int hashCode() {
205                return new HashCodeBuilder(17, 37)
206                                .append(getCode())
207                                .append(getSystem())
208                                .append(getSystemVersion())
209                                .toHashCode();
210        }
211
212        @Override
213        public String toString() {
214                return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
215                                .append("myId", myId)
216                                .append(
217                                                myConceptMapGroup != null
218                                                                ? ("myConceptMapGroup - id=" + myConceptMapGroup.getId())
219                                                                : ("myConceptMapGroup=(null)"))
220                                .append("myCode", myCode)
221                                .append("myDisplay", myDisplay)
222                                .append(
223                                                myConceptMapGroupElementTargets != null
224                                                                ? ("myConceptMapGroupElementTargets - size=" + myConceptMapGroupElementTargets.size())
225                                                                : ("myConceptMapGroupElementTargets=(null)"))
226                                .append("myConceptMapUrl", this.getConceptMapUrl())
227                                .append("mySystem", this.getSystem())
228                                .append("mySystemVersion", this.getSystemVersion())
229                                .append("myValueSet", this.getValueSet())
230                                .toString();
231        }
232}