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 ca.uhn.fhir.jpa.model.util.SearchParamHash; 025import jakarta.persistence.Column; 026import jakarta.persistence.Entity; 027import jakarta.persistence.ForeignKey; 028import jakarta.persistence.GeneratedValue; 029import jakarta.persistence.GenerationType; 030import jakarta.persistence.Id; 031import jakarta.persistence.Index; 032import jakarta.persistence.JoinColumn; 033import jakarta.persistence.ManyToOne; 034import jakarta.persistence.Table; 035import jakarta.persistence.Transient; 036import org.apache.commons.lang3.builder.CompareToBuilder; 037import org.apache.commons.lang3.builder.EqualsBuilder; 038import org.apache.commons.lang3.builder.HashCodeBuilder; 039import org.apache.commons.lang3.builder.ToStringBuilder; 040import org.hibernate.annotations.GenericGenerator; 041 042@Entity 043@Table( 044 name = ResourceIndexedComboTokenNonUnique.HFJ_IDX_CMB_TOK_NU, 045 indexes = { 046 // TODO: The hash index was added in 7.4.0 - In 7.6.0 we should drop the string index 047 @Index(name = "IDX_IDXCMBTOKNU_STR", columnList = "IDX_STRING", unique = false), 048 @Index(name = "IDX_IDXCMBTOKNU_HASHC", columnList = "HASH_COMPLETE,RES_ID,PARTITION_ID", unique = false), 049 @Index(name = "IDX_IDXCMBTOKNU_RES", columnList = "RES_ID", unique = false) 050 }) 051public class ResourceIndexedComboTokenNonUnique extends BaseResourceIndexedCombo 052 implements Comparable<ResourceIndexedComboTokenNonUnique>, IResourceIndexComboSearchParameter { 053 054 public static final String HFJ_IDX_CMB_TOK_NU = "HFJ_IDX_CMB_TOK_NU"; 055 056 @GenericGenerator( 057 name = "SEQ_IDXCMBTOKNU_ID", 058 type = ca.uhn.fhir.jpa.model.dialect.HapiSequenceStyleGenerator.class) 059 @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_IDXCMBTOKNU_ID") 060 @Id 061 @Column(name = "PID") 062 private Long myId; 063 064 @ManyToOne 065 @JoinColumn( 066 name = "RES_ID", 067 referencedColumnName = "RES_ID", 068 foreignKey = @ForeignKey(name = "FK_IDXCMBTOKNU_RES_ID")) 069 private ResourceTable myResource; 070 071 @Column(name = "RES_ID", insertable = false, updatable = false) 072 private Long myResourceId; 073 074 @Column(name = "HASH_COMPLETE", nullable = false) 075 private Long myHashComplete; 076 077 @Column(name = "IDX_STRING", nullable = false, length = ResourceIndexedComboStringUnique.MAX_STRING_LENGTH) 078 private String myIndexString; 079 080 @Transient 081 private transient PartitionSettings myPartitionSettings; 082 083 /** 084 * Constructor 085 */ 086 public ResourceIndexedComboTokenNonUnique() { 087 super(); 088 } 089 090 public ResourceIndexedComboTokenNonUnique( 091 PartitionSettings thePartitionSettings, ResourceTable theEntity, String theQueryString) { 092 myPartitionSettings = thePartitionSettings; 093 myResource = theEntity; 094 myIndexString = theQueryString; 095 calculateHashes(); 096 } 097 098 @Override 099 public String getIndexString() { 100 return myIndexString; 101 } 102 103 public void setIndexString(String theIndexString) { 104 myIndexString = theIndexString; 105 } 106 107 @Override 108 public boolean equals(Object theO) { 109 calculateHashes(); 110 111 if (this == theO) { 112 return true; 113 } 114 115 if (theO == null || getClass() != theO.getClass()) { 116 return false; 117 } 118 119 ResourceIndexedComboTokenNonUnique that = (ResourceIndexedComboTokenNonUnique) theO; 120 121 EqualsBuilder b = new EqualsBuilder(); 122 b.append(getHashComplete(), that.getHashComplete()); 123 return b.isEquals(); 124 } 125 126 @Override 127 public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) { 128 ResourceIndexedComboTokenNonUnique source = (ResourceIndexedComboTokenNonUnique) theSource; 129 myPartitionSettings = source.myPartitionSettings; 130 myHashComplete = source.myHashComplete; 131 myIndexString = source.myIndexString; 132 } 133 134 @Override 135 public Long getId() { 136 return myId; 137 } 138 139 @Override 140 public void setId(Long theId) { 141 myId = theId; 142 } 143 144 @Override 145 public void clearHashes() { 146 myHashComplete = null; 147 } 148 149 @Override 150 public void calculateHashes() { 151 if (myHashComplete != null) { 152 return; 153 } 154 155 PartitionSettings partitionSettings = getPartitionSettings(); 156 PartitionablePartitionId partitionId = getPartitionId(); 157 String queryString = myIndexString; 158 setHashComplete(calculateHashComplete(partitionSettings, partitionId, queryString)); 159 } 160 161 @Override 162 public int hashCode() { 163 calculateHashes(); 164 165 HashCodeBuilder builder = new HashCodeBuilder(17, 37); 166 builder.append(getHashComplete()); 167 return builder.toHashCode(); 168 } 169 170 public PartitionSettings getPartitionSettings() { 171 return myPartitionSettings; 172 } 173 174 public void setPartitionSettings(PartitionSettings thePartitionSettings) { 175 myPartitionSettings = thePartitionSettings; 176 } 177 178 @Override 179 public ResourceTable getResource() { 180 return myResource; 181 } 182 183 @Override 184 public void setResource(ResourceTable theResource) { 185 myResource = theResource; 186 } 187 188 public Long getHashComplete() { 189 return myHashComplete; 190 } 191 192 public void setHashComplete(Long theHashComplete) { 193 myHashComplete = theHashComplete; 194 } 195 196 @Override 197 public int compareTo(ResourceIndexedComboTokenNonUnique theO) { 198 CompareToBuilder b = new CompareToBuilder(); 199 b.append(myHashComplete, theO.getHashComplete()); 200 return b.toComparison(); 201 } 202 203 @Override 204 public String toString() { 205 return new ToStringBuilder(this) 206 .append("id", myId) 207 .append("resourceId", myResourceId) 208 .append("hashComplete", myHashComplete) 209 .append("indexString", myIndexString) 210 .toString(); 211 } 212 213 public static long calculateHashComplete( 214 PartitionSettings partitionSettings, PartitionablePartitionId thePartitionId, String queryString) { 215 RequestPartitionId requestPartitionId = PartitionablePartitionId.toRequestPartitionId(thePartitionId); 216 return SearchParamHash.hashSearchParam(partitionSettings, requestPartitionId, queryString); 217 } 218}