package org.openinfobutton.responder.dao.impl;
/*
* #%L
* Project: oib-rest-responder
* Director: Guilherme Del Fiol, MD, PhD
* University of Utah
* Biomedical Informatics
* 421 Wakara Way, Suite 140
* Salt Lake City, UT 84108-3514
* Phone: 801-581-4080
* %%
* Copyright (C) 2010 - 2014 University of Utah
* %%
* 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.
* #L%
*/
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Query;
import org.openinfobutton.app.dao.DaoBase;
import org.openinfobutton.app.helper.AgeToAgeGroupConversionHelper;
import org.openinfobutton.app.model.Asset;
import org.openinfobutton.app.model.Code;
import org.openinfobutton.responder.dao.ResponderAssetDao;
import org.openinfobutton.service.dao.CodeExpanderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
/**
*
* @author Rick Bradshaw
*/
@Repository
public class ResponderAssetDaoImpl extends DaoBase<Asset> implements ResponderAssetDao {
private int maxSupportedQueryCriteria = 950;
@Autowired
private CodeExpanderDao codeExpanderDao;
/**
*
* @param requestParameters
* @return
*/
@Override
public Collection<Asset> findByInfobuttonRequest(Map<String, String> requestParameters) {
Query hqlQuery = getHqlQueryFromOpenInfobuttonButtonRequest(requestParameters);
return hqlQuery.list();
}
/**
*
* @param maxSupportedQueryCriteria
*/
public void setMaxSupportedQueryCriteria(int maxSupportedQueryCriteria) {
this.maxSupportedQueryCriteria = maxSupportedQueryCriteria;
}
/**
* Builds the HQL search query. Assumes valid request parameters - no direct
* error handling/checking.
*
* @param requestParameters the infobutton standard parameters and values
* @return the Hibernate Query to the caller
*/
private Query getHqlQueryFromOpenInfobuttonButtonRequest(Map<String, String> requestParameters) {
StringBuilder mainSearchAdditionalPhrases = new StringBuilder();
Map<String, String> hqlParameters = new HashMap<String, String>();
Map<String, Set<String>> hqlParamatersForInPhrases = new HashMap<String, Set<String>>();
int aliasIndex = 5; // for alias count to ensure they are unique in the subqueries
StringBuilder subTopicPhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"subTopic.v.c",
"subTopic.v",
"subTopicCode", aliasIndex++);
StringBuilder agePhrase = getHqlCriterionForAge(
requestParameters,
hqlParamatersForInPhrases,
"age.v.v",
"age.v.u",
"ageGroup.v",
"convertedAgeGroups",
aliasIndex++);
StringBuilder ageGroupPhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"ageGroup.v.c",
"ageGroup.v",
"ageGroupCode", aliasIndex++);
StringBuilder administrativeGenderCodePhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"patientPerson.administrativeGenderCode.c",
"patientPerson.administrativeGenderCode",
"genderCode", aliasIndex++);
StringBuilder informationRecipientPhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"informationRecipient",
"informationRecipient",
"informationRecipientCode", aliasIndex++);
StringBuilder performerPhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"performer",
"performer",
"performerCode", aliasIndex++);
StringBuilder encounterPhrase = getHqlCriterionForParameterWithOptionalIndex(
requestParameters,
hqlParameters,
"encounter.c.c",
"encounter.c",
"encounterCode", aliasIndex++);
StringBuilder mainSearchCriterion
= getHqlMainSerchCriteria(requestParameters, hqlParameters, hqlParamatersForInPhrases, aliasIndex++);
String taskContext = requestParameters.get("taskContext.c.c");
StringBuilder hsql = new StringBuilder();
hsql.append("select a from Asset a \n");
hsql.append("where 1 = 1 \n");
hsql.append(mainSearchCriterion.toString());
hsql.append(mainSearchAdditionalPhrases.toString());
hsql.append("and a in (select p1.asset from AssetProperty p1 where p1.propertyName = 'taskContext.c' and p1.code = :taskContext ) \n");
hsql.append(subTopicPhrase.toString());
hsql.append(administrativeGenderCodePhrase.toString());
hsql.append(agePhrase.toString());
hsql.append(ageGroupPhrase.toString());
hsql.append(informationRecipientPhrase.toString());
hsql.append(performerPhrase.toString());
hsql.append(encounterPhrase.toString());
System.out.println(hsql.toString());
Query query = getSessionFactory().getCurrentSession().createQuery(hsql.toString());
query.setParameter("taskContext", taskContext);
for (String parameterName : hqlParameters.keySet()) {
query.setParameter(parameterName, hqlParameters.get(parameterName));
}
for (String parameterName : hqlParamatersForInPhrases.keySet()) {
query.setParameterList(parameterName, hqlParamatersForInPhrases.get(parameterName));
}
return query;
}
private StringBuilder getHqlCriterionForParameterWithOptionalIndex(
Map<String, String> requestParameters,
Map<String, String> hqlParameters,
String codeParameterName,
String dbPropertyName,
String hqlParameterName,
int aliasIndex) {
StringBuilder queryPhrase = new StringBuilder();
String aliasIndex2 = aliasIndex + "" + aliasIndex;
if (requestParameters.get(codeParameterName) != null) {
queryPhrase
.append(" and ( a in ( \n")
.append(" select p").append(aliasIndex).append(".asset from AssetProperty p").append(aliasIndex).append(" \n")
.append(" where p").append(aliasIndex).append(".propertyName = '").append(dbPropertyName).append("' \n")
.append(" and p").append(aliasIndex).append(".code = :").append(hqlParameterName).append(") \n")
.append(" or a not in ( \n")
.append(" select p").append(aliasIndex2).append(".asset from AssetProperty p").append(aliasIndex2).append(" \n")
.append(" where p").append(aliasIndex2).append(".propertyName = '").append(dbPropertyName).append("') \n")
.append(" ) \n");
hqlParameters.put(hqlParameterName, requestParameters.get(codeParameterName));
}
return queryPhrase;
}
private StringBuilder getHqlMainSerchCriteria(
Map<String, String> requestParameters,
Map<String, String> hqlParameters,
Map<String, Set<String>> hqlInPhraseParameters,
int aliasIndex) {
StringBuilder queryPhrase = new StringBuilder();
String mainSearchCriteriaCode = null;
String mainSearchCriteriaCodeSystem = null;
int criteriaIndex = 0;
boolean moreCriteria = true;
// and ((m) or (m1) or (m2) ... )
while (moreCriteria && criteriaIndex <= maxSupportedQueryCriteria) {
if (criteriaIndex == 0) {
queryPhrase.append(" and ( \n");
mainSearchCriteriaCode = requestParameters.get("mainSearchCriteria.v.c");
mainSearchCriteriaCodeSystem = requestParameters.get("mainSearchCriteria.v.cs");
} else {
mainSearchCriteriaCode = requestParameters.get("mainSearchCriteria.v.c" + criteriaIndex);
mainSearchCriteriaCodeSystem = requestParameters.get("mainSearchCriteria.v.cs" + criteriaIndex);
}
if (mainSearchCriteriaCode != null) {
if (criteriaIndex > 0) {
queryPhrase.append(" or \n");
}
queryPhrase
.append("(a.assetId in \n")
.append("(select p").append(aliasIndex).append(".asset from AssetProperty p").append(aliasIndex).append(" \n")
.append(" where (p").append(aliasIndex).append(".propertyName = 'mainSearchCriteria.v' \n")
.append(" and p").append(aliasIndex).append(".codeSystem = :mainSearchCriteriaCodeSystem \n");
hqlParameters.put("mainSearchCriteriaCodeSystem", mainSearchCriteriaCodeSystem);
if (CodeExpanderDao.RXNORM_CODE_SYSTEM_OID.equals(mainSearchCriteriaCodeSystem)) {
String hqlParameterName = "mainSearchCriteriaCodeList" + criteriaIndex;
queryPhrase.append(" and p").append(aliasIndex).append(".code in (:").append(hqlParameterName).append("))) \n ) \n");
Set<Code> expansionCodes = codeExpanderDao.getExpansionCodes(CodeExpanderDao.RXNORM_CODE_SYSTEM_OID, mainSearchCriteriaCode);
Set<String> codes = getCodesOnly(expansionCodes);
hqlInPhraseParameters.put(hqlParameterName, codes);
} else {
String hqlParameterName = "mainSearchCriteriaCode" + criteriaIndex;
queryPhrase.append(" and p").append(aliasIndex).append(".code = :").append(hqlParameterName).append(")) \n ) \n");
hqlParameters.put(hqlParameterName, mainSearchCriteriaCode);
}
} else {
moreCriteria = false;
}
criteriaIndex++;
}
queryPhrase.append(" ) \n");
return queryPhrase;
}
private StringBuilder getHqlCriterionForAge(
Map<String, String> requestParameters,
Map<String, Set<String>> hqlInPhraseParameters,
String ageParameterName,
String ageUnitsParameterName,
String dbPropertyName,
String hqlParameterName,
int aliasIndex) {
StringBuilder queryPhrase = new StringBuilder();
String aliasIndex2 = aliasIndex + "" + aliasIndex;
final String ageValue = requestParameters.get(ageParameterName);
final String ageUnitsCode = requestParameters.get(ageUnitsParameterName);
if (ageValue != null && ageUnitsCode != null) {
List<Code> hqlAgeGroupCodes = AgeToAgeGroupConversionHelper.ageToAgeGroup(Integer.parseInt(ageValue), ageUnitsCode);
Set<String> hqlAgeGroupCodesSet = new HashSet<String>();
for (Code ageGroupCode : hqlAgeGroupCodes) {
hqlAgeGroupCodesSet.add(ageGroupCode.getCode());
}
queryPhrase
.append(" and ( a in ( \n")
.append(" select p").append(aliasIndex).append(".asset from AssetProperty p").append(aliasIndex).append(" \n")
.append(" where p").append(aliasIndex).append(".propertyName = '").append(dbPropertyName).append("' \n")
.append(" and p").append(aliasIndex).append(".code in (:").append(hqlParameterName).append(")) \n")
.append(" or a not in ( \n")
.append(" select p").append(aliasIndex2).append(".asset from AssetProperty p").append(aliasIndex2).append(" \n")
.append(" where p").append(aliasIndex2).append(".propertyName = '").append(dbPropertyName).append("') \n")
.append(" ) \n");
hqlInPhraseParameters.put(hqlParameterName, hqlAgeGroupCodesSet);
}
return queryPhrase;
}
private Set<String> getCodesOnly(Set<Code> codes) {
Set<String> codesOnly = new HashSet<String>();
for (Code code_ : codes) {
codesOnly.add(code_.getCode());
}
return codesOnly;
}
}