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