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