package io.robe.hibernate.criteria.hql; import io.robe.common.dto.BooleanHolder; import io.robe.common.dto.Increment; import io.robe.common.dto.Pair; import io.robe.common.utils.Validations; import io.robe.hibernate.criteria.api.Criteria; import io.robe.hibernate.criteria.api.CriteriaJoin; import io.robe.hibernate.criteria.api.CriteriaParent; import io.robe.hibernate.criteria.api.Order; import io.robe.hibernate.criteria.api.cache.FieldMeta; import java.util.*; /** * Created by kamilbukum on 30/01/2017. */ public class TransformerUtil { public static class Elements { Map<String, String> elementsMap = null; String elementsQuery = null; } /** * * @param criteria * @param <T> * @return */ public static <T> Pair<String, Map<String, Object>> query(Criteria<T> criteria, Elements elements) { StringBuilder listBuilder = new StringBuilder(); // configure select StringJoiner selectJoiner = new StringJoiner(", "); BooleanHolder groupBy = new BooleanHolder(false); Pair<String, Map<String, Object>> commonPair = criteriaToQuery(criteria, selectJoiner, elements, groupBy); listBuilder .append("SELECT ") .append(selectJoiner.length() > 0 ? selectJoiner.toString(): criteria.getAlias()) .append(" ") .append(commonPair.getLeft()) .append("\n") .append(orderBy(criteria)); String query = listBuilder.toString(); Pair<String, Map<String, Object>> pair = new Pair<>(listBuilder.toString(), commonPair.getRight()); return pair; } /** * * @param criteria * @param groupBy * @param <T> * @return */ public static <T> Pair<String, Map<String, Object>> count(Criteria<T> criteria, BooleanHolder groupBy) { StringBuilder countBuilder = new StringBuilder(); Pair<String, Map<String, Object>> commonPair = criteriaToQuery(criteria, null, null, groupBy); countBuilder .append("SELECT ") .append("count(1)") .append(" ") .append(commonPair.getLeft()); return new Pair<>(countBuilder.toString(), commonPair.getRight()); } /** * * @param criteria * @param groupBy * @param <T> * @return */ public static <T> Pair<String, Pair<String, Map<String, Object>>> pairList(Criteria<T> criteria, Elements elements, BooleanHolder groupBy) { StringBuilder countBuilder = new StringBuilder(); // configure select StringJoiner selectJoiner = new StringJoiner(", "); Pair<String, Map<String, Object>> commonPair = criteriaToQuery(criteria, selectJoiner, elements, groupBy); String listQuery = "SELECT " + (selectJoiner.length() > 0 ? selectJoiner.toString(): criteria.getAlias()); String commonQueryForList = " " + commonPair.getLeft() + "\n" + orderBy(criteria); if(elements != null && elements.elementsMap != null && elements.elementsMap.size() > 0) { elements.elementsQuery = "SELECT " + criteria.getAlias() + commonQueryForList; } listQuery = listQuery + commonQueryForList; countBuilder .append("SELECT ") .append("count(1)") .append(" ") .append(commonPair.getLeft()); return new Pair<>(listQuery, new Pair<>(countBuilder.toString(), commonPair.getRight())); } /** * * @param criteria * @param selectJoiner * @param groupBy * @param <E> * @return */ public static <E> Pair<String, Map<String, Object>> criteriaToQuery(Criteria<E> criteria, StringJoiner selectJoiner, Elements elements, BooleanHolder groupBy) { Map<String, Object> variableMap = new LinkedHashMap<>(); String from = from(criteria); StringJoiner joinJoiner = new StringJoiner("\n"); StringJoiner restrictionJoiner = new StringJoiner(" AND "); StringJoiner qJoiner = new StringJoiner(" OR "); StringJoiner groupByJoiner = new StringJoiner(", "); criteriaToQuery(criteria, selectJoiner, elements, joinJoiner, restrictionJoiner, qJoiner, groupByJoiner, variableMap); StringBuilder builder = new StringBuilder(); if(joinJoiner.length() > 0) { builder.append("\n").append(joinJoiner.toString()); } if(restrictionJoiner.length() > 0 ) { builder.append("\nWHERE "); builder.append(restrictionJoiner.toString()); if(qJoiner.length() > 0) { if(qJoiner.length() > 1) { builder.append(" AND ( ").append(qJoiner.toString()).append(" ) "); } else { builder.append(" AND ").append(qJoiner.toString()); } } } else if(qJoiner.length() > 0) { builder.append("\nWHERE "); builder.append(qJoiner.toString()); } if(groupByJoiner.length() > 0) { groupBy.set(true); builder.append("\nGROUP BY ").append(groupByJoiner.toString()); } return new Pair<>(from + builder.toString(), variableMap); } /** * * @param criteria * @param selectJoiner * @param elements * @param joinJoiner * @param restrictionJoiner * @param qJoiner * @param groupJoiner * @param variableMap * @param <E> */ public static <E> void criteriaToQuery( CriteriaParent<E> criteria, StringJoiner selectJoiner, Elements elements, StringJoiner joinJoiner, StringJoiner restrictionJoiner, StringJoiner qJoiner, StringJoiner groupJoiner, Map<String, Object> variableMap ){ if(selectJoiner != null) { if(criteria.getProjection() != null) { String select = HqlUtil.selectForListByProjection(criteria, criteria.getProjection(), null, elements, groupJoiner); if(!Validations.isEmptyOrNull(select)) { selectJoiner.add(select); } } } if(criteria.getRestrictions() != null && criteria.getRestrictions().size() > 0) { HqlUtil.generateRestrictions( criteria, criteria.getRestrictions(), restrictionJoiner, qJoiner, variableMap, new Increment(0) ); } if(criteria.getJoins() != null && criteria.getJoins().size() > 0) { for(Map.Entry<String, CriteriaJoin<E>> joinEntry: criteria.getJoins().entrySet()) { String joinToString = HqlUtil.joinToString(joinEntry.getValue()); if(!Validations.isEmptyOrNull(joinToString)) { joinJoiner.add(joinToString); } criteriaToQuery(joinEntry.getValue(), selectJoiner, elements, joinJoiner, restrictionJoiner, qJoiner, groupJoiner, variableMap); } } } /** * * @param criteria * @param <E> * @return */ public static <E> String orderBy(Criteria<E> criteria) { if(criteria.getOrders() != null && criteria.getOrders().size() > 0) { StringJoiner joiner = new StringJoiner(", "); for(Order order :criteria.getOrders() ) { String name; if(order.isAlias()) { name = order.getName(); } else { if(Validations.isEmptyOrNull(order.getCriteriaAlias())) { name = order.getName(); } else { name = order.getCriteriaAlias() + "." + order.getName(); } } joiner.add(name + " " + order.getType().name()); } return "ORDER BY " + joiner.toString(); } return ""; } /** * * @param criteria * @return */ public static String from(Criteria criteria){ return "\nFROM " + criteria.getEntityClass().getName() + " " + criteria.getAlias(); } }