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.jpa.model.entity.ResourceTable;
025import ca.uhn.fhir.util.ValidateUtil;
026import jakarta.annotation.Nonnull;
027import jakarta.persistence.Column;
028import jakarta.persistence.Entity;
029import jakarta.persistence.ForeignKey;
030import jakarta.persistence.GeneratedValue;
031import jakarta.persistence.GenerationType;
032import jakarta.persistence.Id;
033import jakarta.persistence.IdClass;
034import jakarta.persistence.Index;
035import jakarta.persistence.JoinColumn;
036import jakarta.persistence.JoinColumns;
037import jakarta.persistence.ManyToOne;
038import jakarta.persistence.OneToMany;
039import jakarta.persistence.SequenceGenerator;
040import jakarta.persistence.Table;
041import jakarta.persistence.UniqueConstraint;
042import org.apache.commons.lang3.builder.ToStringBuilder;
043import org.apache.commons.lang3.builder.ToStringStyle;
044
045import java.io.Serializable;
046import java.util.ArrayList;
047import java.util.List;
048
049import static org.apache.commons.lang3.StringUtils.length;
050
051@Entity
052@Table(
053                name = "TRM_CONCEPT_MAP",
054                uniqueConstraints = {
055                        @UniqueConstraint(
056                                        name = "IDX_CONCEPT_MAP_URL",
057                                        columnNames = {"PARTITION_ID", "URL", "VER"})
058                },
059                indexes = {
060                        // must have same name that indexed FK or SchemaMigrationTest complains because H2 sets this index
061                        // automatically
062                        @Index(name = "FK_TRMCONCEPTMAP_RES", columnList = "RES_ID")
063                })
064@IdClass(IdAndPartitionId.class)
065public class TermConceptMap extends BasePartitionable implements Serializable {
066        private static final long serialVersionUID = 1L;
067
068        static final int MAX_URL_LENGTH = 200;
069        public static final int MAX_VER_LENGTH = 200;
070
071        /**
072         * Constructor
073         */
074        public TermConceptMap() {
075                super();
076        }
077
078        @Id()
079        @SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID")
080        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_PID")
081        @Column(name = "PID")
082        private Long myId;
083
084        @ManyToOne()
085        @JoinColumns(
086                        value = {
087                                @JoinColumn(
088                                                name = "RES_ID",
089                                                referencedColumnName = "RES_ID",
090                                                nullable = false,
091                                                insertable = false,
092                                                updatable = false),
093                                @JoinColumn(
094                                                name = "PARTITION_ID",
095                                                referencedColumnName = "PARTITION_ID",
096                                                nullable = false,
097                                                insertable = false,
098                                                updatable = false)
099                        },
100                        foreignKey = @ForeignKey(name = "FK_TRMCONCEPTMAP_RES"))
101        private ResourceTable myResource;
102
103        @Column(name = "RES_ID", nullable = false)
104        private Long myResourcePid;
105
106        @Column(name = "SOURCE_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
107        private String mySource;
108
109        @Column(name = "TARGET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
110        private String myTarget;
111
112        @Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
113        private String myUrl;
114
115        @Column(name = "VER", nullable = true, length = MAX_VER_LENGTH)
116        private String myVersion;
117
118        @OneToMany(mappedBy = "myConceptMap")
119        private List<TermConceptMapGroup> myConceptMapGroups;
120
121        public List<TermConceptMapGroup> getConceptMapGroups() {
122                if (myConceptMapGroups == null) {
123                        myConceptMapGroups = new ArrayList<>();
124                }
125
126                return myConceptMapGroups;
127        }
128
129        public Long getId() {
130                return myId;
131        }
132
133        public ResourceTable getResource() {
134                return myResource;
135        }
136
137        public TermConceptMap setResource(ResourceTable theResource) {
138                myResource = theResource;
139                myResourcePid = theResource.getId().getId();
140                setPartitionId(theResource.getPartitionId());
141                return this;
142        }
143
144        public String getSource() {
145                return mySource;
146        }
147
148        public TermConceptMap setSource(String theSource) {
149                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
150                                theSource,
151                                TermValueSet.MAX_URL_LENGTH,
152                                "Source exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theSource));
153                mySource = theSource;
154                return this;
155        }
156
157        public String getTarget() {
158                return myTarget;
159        }
160
161        public TermConceptMap setTarget(String theTarget) {
162                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
163                                theTarget,
164                                TermValueSet.MAX_URL_LENGTH,
165                                "Target exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theTarget));
166                myTarget = theTarget;
167                return this;
168        }
169
170        public String getUrl() {
171                return myUrl;
172        }
173
174        public TermConceptMap setUrl(@Nonnull String theUrl) {
175                ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty");
176                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
177                                theUrl, MAX_URL_LENGTH, "URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl));
178                myUrl = theUrl;
179                return this;
180        }
181
182        public String getVersion() {
183                return myVersion;
184        }
185
186        public TermConceptMap setVersion(String theVersion) {
187                ValidateUtil.isNotTooLongOrThrowIllegalArgument(
188                                theVersion,
189                                MAX_VER_LENGTH,
190                                "Version exceeds maximum length (" + MAX_VER_LENGTH + "): " + length(theVersion));
191                myVersion = theVersion;
192                return this;
193        }
194
195        @Override
196        public String toString() {
197                return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
198                                .append("myId", myId)
199                                .append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
200                                .append("myResourcePid", myResourcePid)
201                                .append("mySource", mySource)
202                                .append("myTarget", myTarget)
203                                .append("myUrl", myUrl)
204                                .append("myVersion", myVersion)
205                                .append(
206                                                myConceptMapGroups != null
207                                                                ? ("myConceptMapGroups - size=" + myConceptMapGroups.size())
208                                                                : ("myConceptMapGroups=(null)"))
209                                .toString();
210        }
211}