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.context.FhirVersionEnum;
023import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
024import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
025import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
026import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
027import ca.uhn.fhir.jpa.model.entity.ResourceTable;
028import ca.uhn.fhir.model.primitive.IdDt;
029import ca.uhn.fhir.model.primitive.InstantDt;
030import ca.uhn.fhir.rest.api.Constants;
031import jakarta.annotation.Nullable;
032import jakarta.persistence.Column;
033import jakarta.persistence.Entity;
034import jakarta.persistence.EnumType;
035import jakarta.persistence.Enumerated;
036import jakarta.persistence.Id;
037import jakarta.persistence.Lob;
038import jakarta.persistence.Temporal;
039import jakarta.persistence.TemporalType;
040import org.hibernate.annotations.Immutable;
041import org.hibernate.annotations.Subselect;
042
043import java.io.Serializable;
044import java.util.Date;
045
046@SuppressWarnings("SqlDialectInspection")
047@Entity
048@Immutable
049// Ideally, all tables and columns should be in UPPERCASE if we ever choose to use a case-sensitive collation for MSSQL
050// and there's a risk that queries on lowercase database objects fail.
051@Subselect("SELECT h.PID               as PID,            "
052                + "               r.RES_ID            as RES_ID,         "
053                + "               h.RES_TYPE          as RES_TYPE,       "
054                + "               h.RES_VERSION       as RES_VERSION,    "
055                // FHIR version
056                + "               h.RES_VER           as RES_VER,        "
057                // resource version
058                + "               h.HAS_TAGS          as HAS_TAGS,       "
059                + "               h.RES_DELETED_AT    as RES_DELETED_AT, "
060                + "               h.RES_PUBLISHED     as RES_PUBLISHED,  "
061                + "               h.RES_UPDATED       as RES_UPDATED,    "
062                + "               h.RES_TEXT          as RES_TEXT,       "
063                + "               h.RES_TEXT_VC       as RES_TEXT_VC,    "
064                + "               h.RES_ENCODING      as RES_ENCODING,   "
065                + "               h.PARTITION_ID      as PARTITION_ID,   "
066                + "               p.SOURCE_URI        as PROV_SOURCE_URI,"
067                + "               p.REQUEST_ID        as PROV_REQUEST_ID,"
068                + "               r.FHIR_ID         as FHIR_ID      "
069                + "FROM HFJ_RESOURCE r "
070                + "    INNER JOIN HFJ_RES_VER h ON r.RES_ID = h.RES_ID and r.RES_VER = h.RES_VER"
071                + "    LEFT OUTER JOIN HFJ_RES_VER_PROV p ON p.RES_VER_PID = h.PID ")
072public class ResourceSearchView implements IBaseResourceEntity, Serializable {
073
074        private static final long serialVersionUID = 1L;
075
076        @Id
077        @Column(name = "PID")
078        private Long myId;
079
080        @Column(name = "RES_ID")
081        private Long myResourceId;
082
083        @Column(name = "RES_TYPE", length = Constants.MAX_RESOURCE_NAME_LENGTH)
084        private String myResourceType;
085
086        @Column(name = "RES_VERSION")
087        @Enumerated(EnumType.STRING)
088        private FhirVersionEnum myFhirVersion;
089
090        @Column(name = "RES_VER")
091        private Long myResourceVersion;
092
093        @Column(name = "PROV_REQUEST_ID", length = Constants.REQUEST_ID_LENGTH)
094        private String myProvenanceRequestId;
095
096        @Column(name = "PROV_SOURCE_URI", length = ResourceHistoryTable.SOURCE_URI_LENGTH)
097        private String myProvenanceSourceUri;
098
099        @Column(name = "HAS_TAGS")
100        private boolean myHasTags;
101
102        @Column(name = "RES_DELETED_AT")
103        @Temporal(TemporalType.TIMESTAMP)
104        private Date myDeleted;
105
106        @Temporal(TemporalType.TIMESTAMP)
107        @Column(name = "RES_PUBLISHED")
108        private Date myPublished;
109
110        @Temporal(TemporalType.TIMESTAMP)
111        @Column(name = "RES_UPDATED")
112        private Date myUpdated;
113
114        @Column(name = "RES_TEXT")
115        @Lob()
116        private byte[] myResource;
117
118        @Column(name = "RES_TEXT_VC")
119        private String myResourceTextVc;
120
121        @Column(name = "RES_ENCODING")
122        @Enumerated(EnumType.STRING)
123        private ResourceEncodingEnum myEncoding;
124
125        @Column(name = "FHIR_ID", length = ResourceTable.MAX_FORCED_ID_LENGTH)
126        private String myFhirId;
127
128        @Column(name = "PARTITION_ID")
129        private Integer myPartitionId;
130
131        public ResourceSearchView() {
132                // public constructor for Hibernate
133        }
134
135        public String getResourceTextVc() {
136                return myResourceTextVc;
137        }
138
139        public String getProvenanceRequestId() {
140                return myProvenanceRequestId;
141        }
142
143        public String getProvenanceSourceUri() {
144                return myProvenanceSourceUri;
145        }
146
147        @Override
148        public Date getDeleted() {
149                return myDeleted;
150        }
151
152        public void setDeleted(Date theDate) {
153                myDeleted = theDate;
154        }
155
156        @Override
157        public FhirVersionEnum getFhirVersion() {
158                return myFhirVersion;
159        }
160
161        public void setFhirVersion(FhirVersionEnum theFhirVersion) {
162                myFhirVersion = theFhirVersion;
163        }
164
165        public String getFhirId() {
166                return myFhirId;
167        }
168
169        @Override
170        public Long getId() {
171                return myResourceId;
172        }
173
174        @Override
175        public IdDt getIdDt() {
176                if (myFhirId == null) {
177                        Long id = myResourceId;
178                        return new IdDt(myResourceType + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
179                } else {
180                        return new IdDt(getResourceType() + '/' + getFhirId() + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
181                }
182        }
183
184        @Override
185        public InstantDt getPublished() {
186                if (myPublished != null) {
187                        return new InstantDt(myPublished);
188                } else {
189                        return null;
190                }
191        }
192
193        public void setPublished(Date thePublished) {
194                myPublished = thePublished;
195        }
196
197        @Override
198        public Long getResourceId() {
199                return myResourceId;
200        }
201
202        @Override
203        public String getResourceType() {
204                return myResourceType;
205        }
206
207        @Override
208        public InstantDt getUpdated() {
209                return new InstantDt(myUpdated);
210        }
211
212        @Override
213        public Date getUpdatedDate() {
214                return myUpdated;
215        }
216
217        @Override
218        public long getVersion() {
219                return myResourceVersion;
220        }
221
222        @Override
223        public boolean isHasTags() {
224                return myHasTags;
225        }
226
227        @Override
228        @Nullable
229        public PartitionablePartitionId getPartitionId() {
230                if (myPartitionId != null) {
231                        return new PartitionablePartitionId(myPartitionId, null);
232                } else {
233                        return null;
234                }
235        }
236
237        public byte[] getResource() {
238                return myResource;
239        }
240
241        public ResourceEncodingEnum getEncoding() {
242                return myEncoding;
243        }
244}