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