001/*-
002 * #%L
003 * HAPI FHIR JPA Model
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.model.entity;
021
022import ca.uhn.fhir.interceptor.model.RequestPartitionId;
023import ca.uhn.fhir.jpa.model.config.PartitionSettings;
024import jakarta.persistence.Column;
025import jakarta.persistence.Entity;
026import jakarta.persistence.ForeignKey;
027import jakarta.persistence.GeneratedValue;
028import jakarta.persistence.GenerationType;
029import jakarta.persistence.Id;
030import jakarta.persistence.Index;
031import jakarta.persistence.JoinColumn;
032import jakarta.persistence.ManyToOne;
033import jakarta.persistence.PrePersist;
034import jakarta.persistence.Table;
035import jakarta.persistence.Transient;
036import org.apache.commons.lang3.Validate;
037import org.apache.commons.lang3.builder.EqualsBuilder;
038import org.apache.commons.lang3.builder.HashCodeBuilder;
039import org.apache.commons.lang3.builder.ToStringBuilder;
040import org.apache.commons.lang3.builder.ToStringStyle;
041import org.hibernate.annotations.GenericGenerator;
042
043import java.io.Serializable;
044
045import static ca.uhn.fhir.jpa.model.util.SearchParamHash.hashSearchParam;
046
047@Entity
048@Table(
049                name = "HFJ_RES_PARAM_PRESENT",
050                indexes = {
051                        // We used to have a constraint named IDX_RESPARMPRESENT_SPID_RESID - Don't reuse
052                        @Index(name = "IDX_RESPARMPRESENT_RESID", columnList = "RES_ID"),
053                        @Index(name = "IDX_RESPARMPRESENT_HASHPRES", columnList = "HASH_PRESENCE")
054                })
055public class SearchParamPresentEntity extends BasePartitionable implements Serializable {
056
057        private static final long serialVersionUID = 1L;
058
059        @Id
060        @GenericGenerator(
061                        name = "SEQ_RESPARMPRESENT_ID",
062                        type = ca.uhn.fhir.jpa.model.dialect.HapiSequenceStyleGenerator.class)
063        @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_RESPARMPRESENT_ID")
064        @Column(name = "PID")
065        private Long myId;
066
067        @Column(name = "SP_PRESENT", nullable = false)
068        private boolean myPresent;
069
070        @ManyToOne()
071        @JoinColumn(
072                        name = "RES_ID",
073                        referencedColumnName = "RES_ID",
074                        nullable = false,
075                        foreignKey = @ForeignKey(name = "FK_RESPARMPRES_RESID"))
076        private ResourceTable myResource;
077
078        @Column(name = "RES_ID", nullable = false, insertable = false, updatable = false)
079        private Long myResourcePid;
080
081        @Transient
082        private transient String myParamName;
083
084        @Column(name = "HASH_PRESENCE")
085        private Long myHashPresence;
086
087        @Transient
088        private transient PartitionSettings myPartitionSettings;
089
090        /**
091         * Constructor
092         */
093        public SearchParamPresentEntity() {
094                super();
095        }
096
097        /**
098         * Constructor
099         */
100        public SearchParamPresentEntity(String theParamName, boolean thePresent) {
101                myParamName = theParamName;
102                myPresent = thePresent;
103        }
104
105        @SuppressWarnings("unused")
106        @PrePersist
107        public void calculateHashes() {
108                if (myHashPresence == null && getParamName() != null) {
109                        String resourceType = getResource().getResourceType();
110                        String paramName = getParamName();
111                        boolean present = myPresent;
112                        setHashPresence(
113                                        calculateHashPresence(getPartitionSettings(), getPartitionId(), resourceType, paramName, present));
114                }
115        }
116
117        public Long getHashPresence() {
118                Validate.notNull(myHashPresence);
119                return myHashPresence;
120        }
121
122        public void setHashPresence(Long theHashPresence) {
123                myHashPresence = theHashPresence;
124        }
125
126        public String getParamName() {
127                return myParamName;
128        }
129
130        public void setParamName(String theParamName) {
131                myParamName = theParamName;
132        }
133
134        public ResourceTable getResource() {
135                return myResource;
136        }
137
138        public void setResource(ResourceTable theResourceTable) {
139                myResource = theResourceTable;
140        }
141
142        public boolean isPresent() {
143                return myPresent;
144        }
145
146        public void setPresent(boolean thePresent) {
147                myPresent = thePresent;
148        }
149
150        @Override
151        public boolean equals(Object theO) {
152                if (this == theO) return true;
153
154                if (theO == null || getClass() != theO.getClass()) return false;
155
156                SearchParamPresentEntity that = (SearchParamPresentEntity) theO;
157
158                EqualsBuilder b = new EqualsBuilder();
159                b.append(getHashPresence(), that.getHashPresence());
160                return b.isEquals();
161        }
162
163        @Override
164        public int hashCode() {
165                HashCodeBuilder b = new HashCodeBuilder(17, 37);
166                b.append(getHashPresence());
167                return b.toHashCode();
168        }
169
170        @Override
171        public String toString() {
172                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
173
174                b.append("resPid", myResource.getIdDt().toUnqualifiedVersionless().getValue());
175                b.append("paramName", myParamName);
176                b.append("present", myPresent);
177                b.append("partition", getPartitionId());
178                return b.build();
179        }
180
181        public PartitionSettings getPartitionSettings() {
182                return myPartitionSettings;
183        }
184
185        public void setPartitionSettings(PartitionSettings thePartitionSettings) {
186                myPartitionSettings = thePartitionSettings;
187        }
188
189        /**
190         * Copy all mutable values from the given source
191         */
192        public void updateValues(SearchParamPresentEntity theSource) {
193                super.setPartitionId(theSource.getPartitionId());
194                setResource(theSource.getResource());
195                setPartitionSettings(theSource.getPartitionSettings());
196                setHashPresence(theSource.getHashPresence());
197                setParamName(theSource.getParamName());
198                setPresent(theSource.isPresent());
199        }
200
201        public static long calculateHashPresence(
202                        PartitionSettings thePartitionSettings,
203                        PartitionablePartitionId theRequestPartitionId,
204                        String theResourceType,
205                        String theParamName,
206                        Boolean thePresent) {
207                RequestPartitionId requestPartitionId = PartitionablePartitionId.toRequestPartitionId(theRequestPartitionId);
208                return calculateHashPresence(
209                                thePartitionSettings, requestPartitionId, theResourceType, theParamName, thePresent);
210        }
211
212        public static long calculateHashPresence(
213                        PartitionSettings thePartitionSettings,
214                        RequestPartitionId theRequestPartitionId,
215                        String theResourceType,
216                        String theParamName,
217                        Boolean thePresent) {
218                String string = thePresent != null ? Boolean.toString(thePresent) : Boolean.toString(false);
219                return hashSearchParam(thePartitionSettings, theRequestPartitionId, theResourceType, theParamName, string);
220        }
221}