001/* 002 * #%L 003 * HAPI FHIR JPA Server 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.search.builder.predicate; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser; 025import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam; 026import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParamQuantity; 027import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder; 028import ca.uhn.fhir.jpa.util.QueryParameterUtils; 029import ca.uhn.fhir.rest.param.ParamPrefixEnum; 030import ca.uhn.fhir.rest.param.QuantityParam; 031import com.healthmarketscience.sqlbuilder.BinaryCondition; 032import com.healthmarketscience.sqlbuilder.ComboCondition; 033import com.healthmarketscience.sqlbuilder.Condition; 034import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn; 035import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable; 036import jakarta.persistence.criteria.CriteriaBuilder; 037import org.springframework.beans.factory.annotation.Autowired; 038 039import java.math.BigDecimal; 040 041import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; 042import static org.apache.commons.lang3.StringUtils.isBlank; 043 044public abstract class BaseQuantityPredicateBuilder extends BaseSearchParamPredicateBuilder { 045 046 protected DbColumn myColumnHashIdentitySystemUnits; 047 protected DbColumn myColumnHashIdentityUnits; 048 protected DbColumn myColumnValue; 049 050 @Autowired 051 private FhirContext myFhirContext; 052 053 /** 054 * Constructor 055 */ 056 public BaseQuantityPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder, DbTable theTable) { 057 super(theSearchSqlBuilder, theTable); 058 } 059 060 public Condition createPredicateQuantity( 061 QuantityParam theParam, 062 String theResourceName, 063 String theParamName, 064 CriteriaBuilder theBuilder, 065 BaseQuantityPredicateBuilder theFrom, 066 SearchFilterParser.CompareOperation theOperation, 067 RequestPartitionId theRequestPartitionId) { 068 069 String systemValue = theParam.getSystem(); 070 String unitsValue = theParam.getUnits(); 071 ParamPrefixEnum cmpValue = theParam.getPrefix(); 072 BigDecimal valueValue = theParam.getValue(); 073 074 Condition hashPredicate; 075 if (!isBlank(systemValue) && !isBlank(unitsValue)) { 076 long hash = BaseResourceIndexedSearchParamQuantity.calculateHashSystemAndUnits( 077 getPartitionSettings(), 078 theRequestPartitionId, 079 theResourceName, 080 theParamName, 081 systemValue, 082 unitsValue); 083 hashPredicate = BinaryCondition.equalTo(myColumnHashIdentitySystemUnits, generatePlaceholder(hash)); 084 } else if (!isBlank(unitsValue)) { 085 long hash = BaseResourceIndexedSearchParamQuantity.calculateHashUnits( 086 getPartitionSettings(), theRequestPartitionId, theResourceName, theParamName, unitsValue); 087 hashPredicate = BinaryCondition.equalTo(myColumnHashIdentityUnits, generatePlaceholder(hash)); 088 } else { 089 long hash = BaseResourceIndexedSearchParam.calculateHashIdentity( 090 getPartitionSettings(), theRequestPartitionId, theResourceName, theParamName); 091 hashPredicate = BinaryCondition.equalTo(getColumnHashIdentity(), generatePlaceholder(hash)); 092 } 093 094 SearchFilterParser.CompareOperation operation = theOperation; 095 if (operation == null && cmpValue != null) { 096 operation = QueryParameterUtils.toOperation(cmpValue); 097 } 098 operation = defaultIfNull(operation, SearchFilterParser.CompareOperation.eq); 099 Condition numericPredicate = NumberPredicateBuilder.createPredicateNumeric( 100 this, operation, valueValue, myColumnValue, "invalidQuantityPrefix", myFhirContext, theParam); 101 102 return ComboCondition.and(hashPredicate, numericPredicate); 103 } 104 105 public DbColumn getColumnValue() { 106 return myColumnValue; 107 } 108}