001package ca.uhn.fhir.jpa.model.entity;
002
003/*
004 * #%L
005 * HAPI FHIR JPA Model
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.context.FhirVersionEnum;
024import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
025import ca.uhn.fhir.model.primitive.InstantDt;
026import org.hibernate.annotations.OptimisticLock;
027
028import javax.persistence.Column;
029import javax.persistence.EnumType;
030import javax.persistence.Enumerated;
031import javax.persistence.MappedSuperclass;
032import javax.persistence.Temporal;
033import javax.persistence.TemporalType;
034import javax.persistence.Transient;
035import java.util.Collection;
036import java.util.Date;
037
038import static org.apache.commons.lang3.StringUtils.defaultString;
039
040@MappedSuperclass
041public abstract class BaseHasResource extends BasePartitionable implements IBaseResourceEntity, IBasePersistedResource {
042
043        @Column(name = "RES_DELETED_AT", nullable = true)
044        @Temporal(TemporalType.TIMESTAMP)
045        private Date myDeleted;
046
047        @Column(name = "RES_VERSION", nullable = true, length = 7)
048        @Enumerated(EnumType.STRING)
049        @OptimisticLock(excluded = true)
050        private FhirVersionEnum myFhirVersion;
051
052        @Column(name = "HAS_TAGS", nullable = false)
053        @OptimisticLock(excluded = true)
054        private boolean myHasTags;
055
056        @Temporal(TemporalType.TIMESTAMP)
057        @Column(name = "RES_PUBLISHED", nullable = false)
058        @OptimisticLock(excluded = true)
059        private Date myPublished;
060
061        @Temporal(TemporalType.TIMESTAMP)
062        @Column(name = "RES_UPDATED", nullable = false)
063        @OptimisticLock(excluded = true)
064        private Date myUpdated;
065
066        /**
067         * This is stored as an optimization to avoid needing to query for this
068         * after an update
069         */
070        @Transient
071        private transient String myTransientForcedId;
072
073        public String getTransientForcedId() {
074                return myTransientForcedId;
075        }
076
077        public void setTransientForcedId(String theTransientForcedId) {
078                assert !defaultString(theTransientForcedId).contains("/") : "Forced ID should not include type: " + theTransientForcedId;
079                myTransientForcedId = theTransientForcedId;
080        }
081
082
083        public abstract BaseTag addTag(TagDefinition theDef);
084
085        @Override
086        public Date getDeleted() {
087                return cloneDate(myDeleted);
088        }
089
090        @Override
091        public FhirVersionEnum getFhirVersion() {
092                return myFhirVersion;
093        }
094
095        public void setFhirVersion(FhirVersionEnum theFhirVersion) {
096                myFhirVersion = theFhirVersion;
097        }
098
099        abstract public ForcedId getForcedId();
100
101        abstract public void setForcedId(ForcedId theForcedId);
102
103        @Override
104        public abstract Long getId();
105
106
107
108        public void setDeleted(Date theDate) {
109                myDeleted = theDate;
110        }
111
112        @Override
113        public InstantDt getPublished() {
114                if (myPublished != null) {
115                        return new InstantDt(getPublishedDate());
116                } else {
117                        return null;
118                }
119        }
120
121        public Date getPublishedDate() {
122                return cloneDate(myPublished);
123        }
124
125        public void setPublished(Date thePublished) {
126                myPublished = thePublished;
127        }
128
129        public void setPublished(InstantDt thePublished) {
130                myPublished = thePublished.getValue();
131        }
132
133        @Override
134        public abstract Long getResourceId();
135
136        @Override
137        public abstract String getResourceType();
138
139        public abstract Collection<? extends BaseTag> getTags();
140
141        @Override
142        public InstantDt getUpdated() {
143                return new InstantDt(getUpdatedDate());
144        }
145
146        @Override
147        public Date getUpdatedDate() {
148                return cloneDate(myUpdated);
149        }
150
151        public void setUpdated(Date theUpdated) {
152                myUpdated = theUpdated;
153        }
154
155        public void setUpdated(InstantDt theUpdated) {
156                myUpdated = theUpdated.getValue();
157        }
158
159        @Override
160        public abstract long getVersion();
161
162        @Override
163        public boolean isHasTags() {
164                return myHasTags;
165        }
166
167        public void setHasTags(boolean theHasTags) {
168                myHasTags = theHasTags;
169        }
170
171        static Date cloneDate(Date theDate) {
172                Date retVal = theDate;
173                if (retVal != null) {
174                        retVal = new Date(retVal.getTime());
175                }
176                return retVal;
177        }
178
179}