001package ca.uhn.fhir.jpa.entity;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server
006 * %%
007 * Copyright (C) 2014 - 2022 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.jpa.model.entity.BasePartitionable;
024import ca.uhn.fhir.jpa.model.entity.ResourceTable;
025import ca.uhn.fhir.mdm.api.IMdmLink;
026import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
027import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
028import org.apache.commons.lang3.builder.ToStringBuilder;
029
030import javax.persistence.Column;
031import javax.persistence.Entity;
032import javax.persistence.EnumType;
033import javax.persistence.Enumerated;
034import javax.persistence.FetchType;
035import javax.persistence.ForeignKey;
036import javax.persistence.GeneratedValue;
037import javax.persistence.GenerationType;
038import javax.persistence.Id;
039import javax.persistence.Index;
040import javax.persistence.JoinColumn;
041import javax.persistence.ManyToOne;
042import javax.persistence.SequenceGenerator;
043import javax.persistence.Table;
044import javax.persistence.Temporal;
045import javax.persistence.TemporalType;
046import javax.persistence.UniqueConstraint;
047import java.util.Date;
048
049@Entity
050@Table(name = "MPI_LINK", uniqueConstraints = {
051        // TODO GGG DROP this index, and instead use the below one
052        @UniqueConstraint(name = "IDX_EMPI_PERSON_TGT", columnNames = {"PERSON_PID", "TARGET_PID"}),
053        // v---- this one
054        //TODO GGG revisit adding this: @UniqueConstraint(name = "IDX_EMPI_GR_TGT", columnNames = {"GOLDEN_RESOURCE_PID", "TARGET_PID"}),
055        //TODO GGG Should i make individual indices for PERSON/TARGET?
056}, indexes = {
057        @Index(name = "IDX_EMPI_MATCH_TGT_VER", columnList = "MATCH_RESULT, TARGET_PID, VERSION")
058})
059public class MdmLink extends BasePartitionable implements IMdmLink {
060        public static final int VERSION_LENGTH = 16;
061        private static final int MATCH_RESULT_LENGTH = 16;
062        private static final int LINK_SOURCE_LENGTH = 16;
063        public static final int SOURCE_TYPE_LENGTH = 40;
064
065        @SequenceGenerator(name = "SEQ_EMPI_LINK_ID", sequenceName = "SEQ_EMPI_LINK_ID")
066        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_EMPI_LINK_ID")
067        @Id
068        @Column(name = "PID")
069        private Long myId;
070
071        @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
072        @JoinColumn(name = "GOLDEN_RESOURCE_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_GOLDEN_RESOURCE"), insertable=false, updatable=false, nullable=false)
073        private ResourceTable myGoldenResource;
074
075        @Column(name = "GOLDEN_RESOURCE_PID", nullable=false)
076        private Long myGoldenResourcePid;
077
078        @Deprecated
079        @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
080        @JoinColumn(name = "PERSON_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_PERSON"), insertable=false, updatable=false, nullable=false)
081        private ResourceTable myPerson;
082
083        @Deprecated
084        @Column(name = "PERSON_PID", nullable=false)
085        private Long myPersonPid;
086
087        @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
088        @JoinColumn(name = "TARGET_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_TARGET"), insertable=false, updatable=false, nullable=false)
089        private ResourceTable mySource;
090
091        @Column(name = "TARGET_PID", updatable=false, nullable=false)
092        private Long mySourcePid;
093
094        @Column(name = "MATCH_RESULT", nullable = false)
095        @Enumerated(EnumType.ORDINAL)
096        private MdmMatchResultEnum myMatchResult;
097
098        @Column(name = "LINK_SOURCE", nullable = false)
099        @Enumerated(EnumType.ORDINAL)
100        private MdmLinkSourceEnum myLinkSource;
101
102        @Temporal(TemporalType.TIMESTAMP)
103        @Column(name = "CREATED", nullable = false)
104        private Date myCreated;
105
106        @Temporal(TemporalType.TIMESTAMP)
107        @Column(name = "UPDATED", nullable = false)
108        private Date myUpdated;
109
110        @Column(name = "VERSION", nullable = false, length = VERSION_LENGTH)
111        private String myVersion;
112
113        /** This link was created as a result of an eid match **/
114        @Column(name = "EID_MATCH")
115        private Boolean myEidMatch;
116
117        /** This link created a new person **/
118        @Column(name = "NEW_PERSON")
119        private Boolean myHadToCreateNewGoldenResource;
120
121        @Column(name = "VECTOR")
122        private Long myVector;
123
124        @Column(name = "SCORE")
125        private Double myScore;
126
127        //TODO GGG GL-1340
128        @Column(name = "RULE_COUNT")
129        private Long myRuleCount;
130
131        public MdmLink() {}
132
133        public MdmLink(String theVersion) {
134                myVersion = theVersion;
135        }
136
137        @Column(name = "TARGET_TYPE", nullable = true, length = SOURCE_TYPE_LENGTH)
138        private String myMdmSourceType;
139
140        public Long getId() {
141                return myId;
142        }
143
144        public MdmLink setId(Long theId) {
145                myId = theId;
146                return this;
147        }
148
149        public ResourceTable getGoldenResource() {
150                return myGoldenResource;
151        }
152
153        public MdmLink setGoldenResource(ResourceTable theGoldenResource) {
154                myGoldenResource = theGoldenResource;
155                myGoldenResourcePid = theGoldenResource.getId();
156
157                myPerson = theGoldenResource;
158                myPersonPid = theGoldenResource.getId();
159
160                return this;
161        }
162
163        public Long getGoldenResourcePid() {
164                return myGoldenResourcePid;
165        }
166
167        /**
168         * @deprecated  Use {@link #setGoldenResourcePid(Long)} instead
169         */
170        @Deprecated
171        public MdmLink setPersonPid(Long thePersonPid) {
172                myPersonPid = thePersonPid;
173                return this;
174        }
175
176        public MdmLink setGoldenResourcePid(Long theGoldenResourcePid) {
177                setPersonPid(theGoldenResourcePid);
178
179                myGoldenResourcePid = theGoldenResourcePid;
180                return this;
181        }
182
183        public ResourceTable getSource() {
184                return mySource;
185        }
186
187        public MdmLink setSource(ResourceTable theSource) {
188                mySource = theSource;
189                mySourcePid = theSource.getId();
190                return this;
191        }
192
193        public Long getSourcePid() {
194                return mySourcePid;
195        }
196
197        public MdmLink setSourcePid(Long theSourcePid) {
198                mySourcePid = theSourcePid;
199                return this;
200        }
201
202        public MdmMatchResultEnum getMatchResult() {
203                return myMatchResult;
204        }
205
206        public MdmLink setMatchResult(MdmMatchResultEnum theMatchResult) {
207                myMatchResult = theMatchResult;
208                return this;
209        }
210
211        public boolean isNoMatch() {
212                return myMatchResult == MdmMatchResultEnum.NO_MATCH;
213        }
214
215        public boolean isMatch() {
216                return myMatchResult == MdmMatchResultEnum.MATCH;
217        }
218
219        public boolean isPossibleMatch() {
220                return myMatchResult == MdmMatchResultEnum.POSSIBLE_MATCH;
221        }
222
223        public boolean isRedirect() {
224                return myMatchResult == MdmMatchResultEnum.REDIRECT;
225        }
226
227        public boolean isPossibleDuplicate() {
228                return myMatchResult == MdmMatchResultEnum.POSSIBLE_DUPLICATE;
229        }
230
231        public MdmLinkSourceEnum getLinkSource() {
232                return myLinkSource;
233        }
234
235        public MdmLink setLinkSource(MdmLinkSourceEnum theLinkSource) {
236                myLinkSource = theLinkSource;
237                return this;
238        }
239
240        public boolean isAuto() {
241                return myLinkSource == MdmLinkSourceEnum.AUTO;
242        }
243
244        public boolean isManual() {
245                return myLinkSource == MdmLinkSourceEnum.MANUAL;
246        }
247
248        public Date getCreated() {
249                return myCreated;
250        }
251
252        public MdmLink setCreated(Date theCreated) {
253                myCreated = theCreated;
254                return this;
255        }
256
257        public Date getUpdated() {
258                return myUpdated;
259        }
260
261        public MdmLink setUpdated(Date theUpdated) {
262                myUpdated = theUpdated;
263                return this;
264        }
265
266        public String getVersion() {
267                return myVersion;
268        }
269
270        public MdmLink setVersion(String theVersion) {
271                myVersion = theVersion;
272                return this;
273        }
274
275        public Long getVector() {
276                return myVector;
277        }
278
279        public MdmLink setVector(Long theVector) {
280                myVector = theVector;
281                return this;
282        }
283
284        public Double getScore() {
285                return myScore;
286        }
287
288        public MdmLink setScore(Double theScore) {
289                myScore = theScore;
290                return this;
291        }
292
293        public Boolean getEidMatch() {
294                return myEidMatch;
295        }
296
297        /**
298         * Note that this method can not be called <code>getEidMatch</code> or
299         * <code>isEidMatch</code> because Hibernate Search complains about having
300         * 2 accessors for this property
301         */
302        public boolean isEidMatchPresent() {
303                return myEidMatch != null && myEidMatch;
304        }
305
306        public MdmLink setEidMatch(Boolean theEidMatch) {
307                myEidMatch = theEidMatch;
308                return this;
309        }
310
311        public boolean getHadToCreateNewGoldenResource() {
312                return myHadToCreateNewGoldenResource != null && myHadToCreateNewGoldenResource;
313        }
314
315        public MdmLink setHadToCreateNewGoldenResource(Boolean theHadToCreateNewResource) {
316                myHadToCreateNewGoldenResource = theHadToCreateNewResource;
317                return this;
318        }
319
320        public MdmLink setMdmSourceType(String mdmSourceType) {
321                myMdmSourceType = mdmSourceType;
322                return this;
323        }
324
325        @Override
326        public String toString() {
327                return new ToStringBuilder(this)
328                        .append("myId", myId)
329                        .append("myGoldenResource", myGoldenResourcePid)
330                        .append("mySourcePid", mySourcePid)
331                        .append("myMdmSourceType", myMdmSourceType)
332                        .append("myMatchResult", myMatchResult)
333                        .append("myLinkSource", myLinkSource)
334                        .append("myEidMatch", myEidMatch)
335                        .append("myHadToCreateNewResource", myHadToCreateNewGoldenResource)
336                        .append("myScore", myScore)
337                        .append("myRuleCount", myRuleCount)
338                        .append("myPartitionId", getPartitionId())
339                        .toString();
340        }
341
342        public String getMdmSourceType() {
343                return myMdmSourceType;
344        }
345
346        public Long getRuleCount() {
347                return myRuleCount;
348        }
349
350        public void setRuleCount(Long theRuleCount) {
351                myRuleCount = theRuleCount;
352        }
353
354}