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.jpa.model.config.PartitionSettings; 024import ca.uhn.fhir.model.api.IQueryParameterType; 025import ca.uhn.fhir.rest.param.NumberParam; 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; 030import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ScaledNumberField; 031 032import javax.persistence.Column; 033import javax.persistence.Embeddable; 034import javax.persistence.Entity; 035import javax.persistence.GeneratedValue; 036import javax.persistence.GenerationType; 037import javax.persistence.Id; 038import javax.persistence.Index; 039import javax.persistence.SequenceGenerator; 040import javax.persistence.Table; 041import java.math.BigDecimal; 042import java.util.Objects; 043 044@Embeddable 045@Entity 046@Table(name = "HFJ_SPIDX_NUMBER", indexes = { 047// We used to have an index with name IDX_SP_NUMBER - Dont reuse 048 @Index(name = "IDX_SP_NUMBER_HASH_VAL", columnList = "HASH_IDENTITY,SP_VALUE"), 049 @Index(name = "IDX_SP_NUMBER_UPDATED", columnList = "SP_UPDATED"), 050 @Index(name = "IDX_SP_NUMBER_RESID", columnList = "RES_ID") 051}) 052public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchParam { 053 054 private static final long serialVersionUID = 1L; 055 @Column(name = "SP_VALUE", nullable = true) 056 @ScaledNumberField 057 public BigDecimal myValue; 058 059 @Id 060 @SequenceGenerator(name = "SEQ_SPIDX_NUMBER", sequenceName = "SEQ_SPIDX_NUMBER") 061 @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_NUMBER") 062 @Column(name = "SP_ID") 063 private Long myId; 064 /** 065 * @since 3.5.0 - At some point this should be made not-null 066 */ 067 @Column(name = "HASH_IDENTITY", nullable = true) 068 private Long myHashIdentity; 069 070 public ResourceIndexedSearchParamNumber() { 071 } 072 073 public ResourceIndexedSearchParamNumber(PartitionSettings thePartitionSettings, String theResourceType, String theParamName, BigDecimal theValue) { 074 setPartitionSettings(thePartitionSettings); 075 setResourceType(theResourceType); 076 setParamName(theParamName); 077 setValue(theValue); 078 calculateHashes(); 079 } 080 081 @Override 082 public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) { 083 super.copyMutableValuesFrom(theSource); 084 ResourceIndexedSearchParamNumber source = (ResourceIndexedSearchParamNumber) theSource; 085 myValue = source.myValue; 086 myHashIdentity = source.myHashIdentity; 087 } 088 089 @Override 090 public void clearHashes() { 091 myHashIdentity = null; 092 } 093 094 @Override 095 public void calculateHashes() { 096 if (myHashIdentity != null) { 097 return; 098 } 099 String resourceType = getResourceType(); 100 String paramName = getParamName(); 101 setHashIdentity(calculateHashIdentity(getPartitionSettings(), getPartitionId(), resourceType, paramName)); 102 } 103 104 public Long getHashIdentity() { 105 return myHashIdentity; 106 } 107 108 @Override 109 public boolean equals(Object theObj) { 110 if (this == theObj) { 111 return true; 112 } 113 if (theObj == null) { 114 return false; 115 } 116 if (!(theObj instanceof ResourceIndexedSearchParamNumber)) { 117 return false; 118 } 119 ResourceIndexedSearchParamNumber obj = (ResourceIndexedSearchParamNumber) theObj; 120 EqualsBuilder b = new EqualsBuilder(); 121 b.append(getResourceType(), obj.getResourceType()); 122 b.append(getParamName(), obj.getParamName()); 123 b.append(getHashIdentity(), obj.getHashIdentity()); 124 b.append(isMissing(), obj.isMissing()); 125 return b.isEquals(); 126 } 127 128 public void setHashIdentity(Long theHashIdentity) { 129 myHashIdentity = theHashIdentity; 130 } 131 132 @Override 133 public Long getId() { 134 return myId; 135 } 136 137 @Override 138 public void setId(Long theId) { 139 myId = theId; 140 } 141 142 public BigDecimal getValue() { 143 return myValue; 144 } 145 146 public void setValue(BigDecimal theValue) { 147 myValue = theValue; 148 } 149 150 @Override 151 public int hashCode() { 152 HashCodeBuilder b = new HashCodeBuilder(); 153 b.append(getResourceType()); 154 b.append(getParamName()); 155 b.append(getValue()); 156 b.append(isMissing()); 157 return b.toHashCode(); 158 } 159 160 @Override 161 public IQueryParameterType toQueryParameterType() { 162 return new NumberParam(myValue.toPlainString()); 163 } 164 165 @Override 166 public String toString() { 167 ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); 168 b.append("paramName", getParamName()); 169 b.append("resourceId", getResource().getId()); // TODO: add a field so we don't need to resolve this 170 b.append("value", getValue()); 171 return b.build(); 172 } 173 174 @Override 175 public boolean matches(IQueryParameterType theParam) { 176 if (!(theParam instanceof NumberParam)) { 177 return false; 178 } 179 NumberParam number = (NumberParam) theParam; 180 return Objects.equals(getValue(), number.getValue()); 181 } 182 183}