/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ohdsi.webapi.vocabulary; import java.util.ArrayList; import org.apache.commons.lang3.StringUtils; import org.ohdsi.webapi.helper.ResourceHelper; /** * * Unit tests for CocneptSetExpressionQueryBuilder. */ public class ConceptSetExpressionQueryBuilder { private final static String CONCEPT_SET_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/vocabulary/sql/conceptSetQuery.sql"); private final static String CONCEPT_SET_DESCENDANTS_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/vocabulary/sql/conceptSetDescendants.sql"); private final static String CONCEPT_SET_MAPPED_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/vocabulary/sql/conceptSetMapped.sql"); private final static String CONCEPT_SET_INCLUDE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/vocabulary/sql/conceptSetInclude.sql"); private final static String CONCEPT_SET_EXCLUDE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/vocabulary/sql/conceptSetExclude.sql"); private ArrayList<Long> getConceptIds(ArrayList<Concept> concepts) { ArrayList<Long> conceptIdList = new ArrayList<>(); for (Concept concept : concepts) { conceptIdList.add(concept.conceptId); } return conceptIdList; } private String buildConceptSetSubQuery ( ArrayList<Concept> concepts, ArrayList<Concept> descendantConcepts ) { ArrayList<String> queries = new ArrayList<>(); if (concepts.size() > 0) { queries.add(StringUtils.replace(CONCEPT_SET_QUERY_TEMPLATE, "@conceptIds", StringUtils.join(getConceptIds(concepts), ","))); } if (descendantConcepts.size() > 0) { queries.add(StringUtils.replace(CONCEPT_SET_DESCENDANTS_TEMPLATE, "@conceptIds", StringUtils.join(getConceptIds(descendantConcepts), ","))); } return StringUtils.join(queries, "UNION"); } private String buildConceptSetMappedQuery ( ArrayList<Concept> mappedConcepts, ArrayList<Concept> mappedDescendantConcepts ) { String conceptSetQuery = buildConceptSetSubQuery(mappedConcepts, mappedDescendantConcepts); return StringUtils.replace(CONCEPT_SET_MAPPED_TEMPLATE, "@conceptsetQuery", conceptSetQuery); } private String buildConceptSetQuery( ArrayList<Concept> concepts, ArrayList<Concept> descendantConcepts, ArrayList<Concept> mappedConcepts, ArrayList<Concept> mappedDesandantConcepts) { if (concepts.size() == 0) { return "select concept_id from @cdm_database_schema.CONCEPT where 0=1"; } String conceptSetQuery = buildConceptSetSubQuery(concepts, descendantConcepts); if (mappedConcepts.size() > 0 || mappedDesandantConcepts.size() > 0) { buildConceptSetMappedQuery(mappedConcepts,mappedDesandantConcepts); conceptSetQuery += "UNION\n" + buildConceptSetMappedQuery(mappedConcepts,mappedDesandantConcepts); } return conceptSetQuery; } public String buildExpressionQuery(ConceptSetExpression expression) { // handle included concepts. ArrayList<Concept> includeConcepts = new ArrayList<>(); ArrayList<Concept> includeDescendantConcepts = new ArrayList<>(); ArrayList<Concept> includeMappedConcepts = new ArrayList<>(); ArrayList<Concept> includeMappedDescendantConcepts = new ArrayList<>(); ArrayList<Concept> excludeConcepts = new ArrayList<>(); ArrayList<Concept> excludeDescendantConcepts = new ArrayList<>(); ArrayList<Concept> excludeMappedConcepts = new ArrayList<>(); ArrayList<Concept> excludeMappedDescendantConcepts = new ArrayList<>(); // populate each sub-set of cocnepts from the flags set in each concept set item for (ConceptSetExpression.ConceptSetItem item : expression.items) { if (!item.isExcluded) { includeConcepts.add(item.concept); if (item.includeDescendants) includeDescendantConcepts.add(item.concept); if (item.includeMapped) { includeMappedConcepts.add(item.concept); if (item.includeDescendants) includeMappedDescendantConcepts.add(item.concept); } } else { excludeConcepts.add(item.concept); if (item.includeDescendants) excludeDescendantConcepts.add(item.concept); if (item.includeMapped) { excludeMappedConcepts.add(item.concept); if (item.includeDescendants) excludeMappedDescendantConcepts.add(item.concept); } } } // each ArrayList contains the concepts that are used in the sub-query of the codeset expression query String conceptSetQuery = StringUtils.replace(CONCEPT_SET_INCLUDE_TEMPLATE,"@includeQuery", buildConceptSetQuery(includeConcepts, includeDescendantConcepts, includeMappedConcepts, includeMappedDescendantConcepts)); if (excludeConcepts.size() > 0){ String excludeConceptsQuery = StringUtils.replace(CONCEPT_SET_EXCLUDE_TEMPLATE, "@excludeQuery", buildConceptSetQuery(excludeConcepts, excludeDescendantConcepts, excludeMappedConcepts, excludeMappedDescendantConcepts)); conceptSetQuery += excludeConceptsQuery; } return conceptSetQuery; } }