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