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}