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.interceptor.model.RequestPartitionId; 023import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; 024import ca.uhn.fhir.jpa.model.entity.TagTypeEnum; 025import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder; 026import ca.uhn.fhir.rest.param.UriParamQualifierEnum; 027import com.google.common.collect.Lists; 028import com.healthmarketscience.sqlbuilder.BinaryCondition; 029import com.healthmarketscience.sqlbuilder.ComboCondition; 030import com.healthmarketscience.sqlbuilder.Condition; 031import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn; 032import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable; 033import org.apache.commons.lang3.tuple.Triple; 034 035import java.util.List; 036import java.util.Objects; 037 038import static ca.uhn.fhir.jpa.search.builder.predicate.StringPredicateBuilder.createLeftMatchLikeExpression; 039import static org.apache.commons.lang3.StringUtils.isNotBlank; 040 041public class TagPredicateBuilder extends BaseJoiningPredicateBuilder { 042 043 private final DbColumn myColumnResId; 044 private final DbTable myTagDefinitionTable; 045 private final DbColumn myTagDefinitionColumnTagId; 046 private final DbColumn myTagDefinitionColumnTagSystem; 047 private final DbColumn myTagDefinitionColumnTagCode; 048 private final DbColumn myColumnTagId; 049 private final DbColumn myTagDefinitionColumnTagType; 050 051 public TagPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) { 052 super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_RES_TAG")); 053 054 myColumnResId = getTable().addColumn("RES_ID"); 055 myColumnTagId = getTable().addColumn("TAG_ID"); 056 057 myTagDefinitionTable = theSearchSqlBuilder.addTable("HFJ_TAG_DEF"); 058 myTagDefinitionColumnTagId = myTagDefinitionTable.addColumn("TAG_ID"); 059 myTagDefinitionColumnTagSystem = myTagDefinitionTable.addColumn("TAG_SYSTEM"); 060 myTagDefinitionColumnTagCode = myTagDefinitionTable.addColumn("TAG_CODE"); 061 myTagDefinitionColumnTagType = myTagDefinitionTable.addColumn("TAG_TYPE"); 062 } 063 064 public Condition createPredicateTag( 065 TagTypeEnum theTagType, 066 List<Triple<String, String, String>> theTokens, 067 String theParamName, 068 RequestPartitionId theRequestPartitionId) { 069 addJoin(getTable(), myTagDefinitionTable, myColumnTagId, myTagDefinitionColumnTagId); 070 return createPredicateTagList(theTagType, theTokens); 071 } 072 073 private Condition createPredicateTagList(TagTypeEnum theTagType, List<Triple<String, String, String>> theTokens) { 074 Condition typePredicate = 075 BinaryCondition.equalTo(myTagDefinitionColumnTagType, generatePlaceholder(theTagType.ordinal())); 076 077 List<Condition> orPredicates = Lists.newArrayList(); 078 for (Triple<String, String, String> next : theTokens) { 079 String system = next.getLeft(); 080 String code = next.getRight(); 081 String qualifier = next.getMiddle(); 082 083 if (theTagType == TagTypeEnum.PROFILE) { 084 system = BaseHapiFhirDao.NS_JPA_PROFILE; 085 } 086 087 Condition codePredicate = Objects.equals(qualifier, UriParamQualifierEnum.BELOW.getValue()) 088 ? BinaryCondition.like( 089 myTagDefinitionColumnTagCode, generatePlaceholder(createLeftMatchLikeExpression(code))) 090 : BinaryCondition.equalTo(myTagDefinitionColumnTagCode, generatePlaceholder(code)); 091 092 if (isNotBlank(system)) { 093 Condition systemPredicate = 094 BinaryCondition.equalTo(myTagDefinitionColumnTagSystem, generatePlaceholder(system)); 095 orPredicates.add(ComboCondition.and(typePredicate, systemPredicate, codePredicate)); 096 } else { 097 // Note: We don't have an index for this combo, which means that this may not perform 098 // well on MySQL (and maybe others) without an added index 099 orPredicates.add(ComboCondition.and(typePredicate, codePredicate)); 100 } 101 } 102 103 return ComboCondition.or(orPredicates.toArray(new Condition[0])); 104 } 105 106 @Override 107 public DbColumn getResourceIdColumn() { 108 return myColumnResId; 109 } 110}