/*
* Copyright 2011 E.J.I.E., S.A.
*
* Licencia con arreglo a la EUPL, Versión 1.1 exclusivamente (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en
*
* http://ec.europa.eu/idabc/eupl.html
*
* Salvo cuando lo exija la legislación aplicable o se acuerde por escrito,
* el programa distribuido con arreglo a la Licencia se distribuye «TAL CUAL»,
* SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ni expresas ni implícitas.
* Véase la Licencia en el idioma concreto que rige los permisos y limitaciones
* que establece la Licencia.
*/
package com.ejie.x38.dto;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.util.StringUtils;
/**
*
* @author UDA
*
*/
@SuppressWarnings("rawtypes")
public class PaginationManagerJerarquia implements java.io.Serializable{
private static final long serialVersionUID = 2127819481595995328L;
/**
* NORMAL
*/
public static StringBuilder getQuery(
Pagination pagination,
StringBuilder query, Map<String, ?> mapaWhere,
String columna, String columnaPadre, String columnaParentNodes,
List<String> tabla, List<String> aliasTabla
){
return getQuery(pagination, query, mapaWhere, columna, columnaPadre, columnaParentNodes, tabla, aliasTabla, new StringBuilder(""), null, null);
}
public static StringBuilder getQuery(
Pagination pagination,
StringBuilder query, Map<String, ?> mapaWhere,
String columna, String columnaPadre, String columnaParentNodes,
List<String> tabla, List<String> aliasTabla, StringBuilder joins
){
return getQuery(pagination, query, mapaWhere, columna, columnaPadre, columnaParentNodes, tabla, aliasTabla, joins, null, null);
}
public static StringBuilder getQuery(
Pagination pagination,
StringBuilder query, Map<String, ?> mapaWhere,
String columna, String columnaPadre, String columnaParentNodes,
List<String> tabla, List<String> aliasTabla, StringBuilder joins,
StringBuilder businessFilters, List<?> businessParams
){
List<Object> queryParams = new ArrayList<Object>();
//Campos específicos de Jerarquía
query.append("\n\t").append("-- Campos JERARQUIA");
query.append("\n\t").append(", LEVEL");
query.append("\n\t").append(", sys_connect_by_path(").append(columnaParentNodes).append(", '").append(pagination.getJerarquia().getToken()).append("') as PARENTNODES ");
query.append("\n\t").append(", decode(connect_by_isleaf, 0, 'false', 'true') as ISLEAF ");
//Decodes para destacar filtrados
StringBuffer whereConditions = (StringBuffer) mapaWhere.get("query");
if (whereConditions.length()==0){
query.append("\n\t").append(", case when (1=0) then 'true' end as FILTER ");
} else{
whereConditions = new StringBuffer(whereConditions.substring(whereConditions.indexOf("AND")+4, whereConditions.length()));
query.append("\n\t").append(", case when (").append(whereConditions).append(") then 'true' end as FILTER ");
//Añadir los parametros al decode
@SuppressWarnings("unchecked")
List<Object> params = (List<Object>) mapaWhere.get("params");
queryParams.addAll(params);
}
return getJerarquiaQuery(pagination, query, mapaWhere, queryParams, columna, columnaPadre, tabla, aliasTabla, joins, businessFilters, businessParams);
}
/**
* PAGINACIÓN
*/
public static StringBuilder getPaginationQuery(Pagination pagination, StringBuilder query){
return PaginationManager.getQueryForPagination(pagination, query, true);
}
/**
* COUNT
*/
public static StringBuilder getQueryCount(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre,
List<String> tabla, List<String> aliasTabla
){
return getJerarquiaQuery(pagination, new StringBuilder("SELECT COUNT(1) "), mapaWhere, new ArrayList<Object>(), columna, columnaPadre, tabla, aliasTabla, new StringBuilder(""), null, null);
}
public static StringBuilder getQueryCount(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre, String columnaParentNodes,
List<String> tabla, List<String> aliasTabla, StringBuilder joins
){
return getJerarquiaQuery(pagination, new StringBuilder("SELECT COUNT(1) "), mapaWhere, new ArrayList<Object>(), columna, columnaPadre, tabla, aliasTabla, joins, null, null);
}
public static StringBuilder getQueryCount(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre, String columnaParentNodes,
List<String> tabla, List<String> aliasTabla, StringBuilder joins,
StringBuilder businessFilters, List<?> businessParams
){
return getJerarquiaQuery(pagination, new StringBuilder("SELECT COUNT(1) "), mapaWhere, new ArrayList<Object>(), columna, columnaPadre, tabla, aliasTabla, joins, businessFilters, businessParams);
}
/**
* GENERAL (interna)
*/
protected static StringBuilder getJerarquiaQuery(
Pagination pagination,
StringBuilder query, Map<String, ?> mapaWhere, List<Object> queryParams,
String columna, String columnaPadre,
List<String> tabla, List<String> aliasTabla, StringBuilder joins,
StringBuilder businessFilters, List<?> businessParams
){
query.insert(0,"\n\t");
//FROM (tabla + aliasTabla)
query.append("\n\t").append("from ");
StringBuilder from = new StringBuilder("");
int size = tabla.size();
for (int i = 0; i < size; i++) {
from.append(tabla.get(i).trim()).append(" ").append(aliasTabla.get(i).trim()).append(", ");
}
query.append(StringUtils.trimTrailingCharacter(from.toString().trim(), ','));
//Si tiene criterios aplicar _subqueries_ PADRE/HIJOS
if (!((List<?>) mapaWhere.get("params")).isEmpty()){
query.append(", (");
//Subqueries
//PADRES
query.append("\n\t\t").append("-- PADRES");
query = querySubquery(pagination, query, mapaWhere, queryParams, columna, tabla, aliasTabla, joins, businessFilters, businessParams);
query.append("\n\t\t").append("connect by prior ").append(columnaPadre).append(" = ").append(columna);
query.append("\n\t\t").append("union");
//HIJOS
query.append("\n\t\t").append("-- HIJOS");
query = querySubquery(pagination, query, mapaWhere, queryParams, columna, tabla, aliasTabla, joins, businessFilters, businessParams);
query.append("\n\t\t").append("connect by prior ").append(columna).append(" = ").append(columnaPadre);
query.append("\n\t").append(") jerarquia");
}
//CONDICIONES
query.append("\n\t").append("where 1=1 ");
//Si tiene criterios aplicar _join_ PADRE/HIJOS
if (!((List<?>) mapaWhere.get("params")).isEmpty()){
query.append("\n\t").append("-- JOIN JERARQUIA");
query.append("\n\t").append("and ").append(aliasTabla.get(0)).append(".").append(columna).append("=jerarquia.PK_JERARQUIA");
}
if (!"".equals(joins.toString())){
query.append("\n\t").append("-- JOINS");
query.append("\n\t").append(joins);
}
if (businessFilters!=null){
query.append("\n\t").append("-- Condiciones NEGOCIO");
query.append("\n\t").append(businessFilters.toString().trim());
queryParams.addAll(businessParams);
}
//Gestionar selección múltiple
query.append("\n\t").append("-- Relacion JERARQUIA");
if (pagination.getJerarquia().getParentId()==null || pagination.getJerarquia().getParentId().equals("")){
query.append("\n\t").append("start with ").append(columnaPadre).append(" is null");
} else {
query.append("\n\t").append("start with ").append(columnaPadre).append(" = ").append(pagination.getJerarquia().getParentId());
}
query.append("\n\t").append("connect by prior ").append(columna).append(" = ").append(columnaPadre);
//Nodos contraídos
query = filterUnexpanded(pagination, query, queryParams, columnaPadre);
//Modificar parámetros
@SuppressWarnings("unchecked")
List<Object> whereParams = (List<Object>) mapaWhere.get("params");
whereParams.clear();
whereParams.addAll(queryParams);
return query;
}
/**
* Subquery PADRES o HIJOS (interna)
*/
protected static StringBuilder querySubquery(
Pagination pagination,
StringBuilder query, Map<String, ?> mapaWhere, List<Object> queryParams,
String columna,
List<String> tabla, List<String> aliasTabla, StringBuilder joins,
StringBuilder businessFilters, List<?> businessParams){
@SuppressWarnings("unchecked")
List<Object> whereParams = (List<Object>) mapaWhere.get("params");
StringBuffer whereConditions = (StringBuffer) mapaWhere.get("query");
//Condiciones
String filterSubquery = whereConditions.toString();
String businessSubquery = (businessFilters!=null) ? businessFilters.toString() : "";
String joinsSubquery = joins.toString();
for (String aliasTablaStr : aliasTabla) {
filterSubquery = filterSubquery.replaceAll("(?i)"+aliasTablaStr+"\\.", "").trim();
businessSubquery = businessSubquery.replaceAll("(?i)"+aliasTablaStr+"\\.", "").trim();
joinsSubquery = joinsSubquery.toString().replaceAll("(?i)"+aliasTablaStr+"\\.", "").trim();
}
String token = pagination.getJerarquia().getToken();
query.append("\n\t\t").append("select distinct substr(sys_connect_by_path(").append(columna).append(", '").append(token).append("'),");
query.append("\n\t\t").append("instr(sys_connect_by_path(").append(columna).append(", '").append(token).append("'), '").append(token).append("', -1)+").append(token.length()).append(") PK_JERARQUIA");
query.append("\n\t\t").append("from ").append(StringUtils.collectionToCommaDelimitedString(tabla));
query.append("\n\t\t").append("where 1=1 ");
if (!"".equals(joinsSubquery)){
query.append("\n\t\t").append("-- JOINS");
query.append("\n\t\t").append(joinsSubquery);
}
if (!"".equals(businessSubquery)){
query.append("\n\t\t").append("-- Condiciones NEGOCIO");
query.append("\n\t\t").append(businessSubquery);
queryParams.addAll(businessParams);
}
//Jerarquia
query.append("\n\t\t").append("start with ").append(columna).append(" in ( ");
query.append("\n\t\t\t").append("select ").append(columna);
query.append("\n\t\t\t").append("from ").append(StringUtils.collectionToCommaDelimitedString(tabla));
query.append("\n\t\t\t").append("where 1=1 ");
if (!"".equals(joinsSubquery)){
query.append("\n\t\t\t").append("-- JOINS");
query.append("\n\t\t\t").append(joinsSubquery);
}
if (!"".equals(businessSubquery)){
query.append("\n\t\t\t").append("-- Condiciones NEGOCIO");
query.append("\n\t\t\t").append(businessSubquery);
queryParams.addAll(businessParams);
}
if (!"".equals(filterSubquery)){
query.append("\n\t\t\t").append("-- Condiciones FILTRO");
query.append("\n\t\t\t").append(filterSubquery);
queryParams.addAll(whereParams);
}
query.append("\n\t\t").append(")");
return query;
}
/**
* Filtrar elementos contraidos en la query (interna
*/
protected static StringBuilder filterUnexpanded(Pagination pagination, StringBuilder query, List<Object> params, String columnaPadre){
if (pagination.getJerarquia().getTree()!=null && !pagination.getJerarquia().getTree().equals("")) {
StringBuilder elems = new StringBuilder();
String[] arrTree = pagination.getJerarquia().getTree().split(",");
for (int i = 0; i < arrTree.length; i++) {
elems.append("?,");
}
elems = new StringBuilder(elems.substring(0, elems.length()-1));
query.append("\n\t").append("-- Registros CONTRAIDOS");
query.append("\n\t").append("and ").append("").append(columnaPadre).append("").append(" not in (").append(elems).append(")");
params.addAll(Arrays.asList(pagination.getJerarquia().getTree().split(",")));
}
return query;
}
/**
* HIJOS
*/
public static StringBuilder getQueryChildren(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre,
List<String> tabla, List<String> aliasTabla
){
return getQueryChildren(pagination, mapaWhere, columna, columnaPadre, tabla, aliasTabla, new StringBuilder(""), null, null);
}
public static StringBuilder getQueryChildren(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre,
List<String> tabla, List<String> aliasTabla, StringBuilder joins
){
return getQueryChildren(pagination, mapaWhere, columna, columnaPadre, tabla, aliasTabla, joins, null, null);
}
public static StringBuilder getQueryChildren(
Pagination pagination,
Map<String, ?> mapaWhere,
String columna, String columnaPadre,
List<String> tabla, List<String> aliasTabla, StringBuilder joins,
StringBuilder businessFilters, List<?> businessParams
){
//Jerarquia (filtro -> hijos del padre)
//Quitar buscar hijos/descendientes
Map<String,Object> mapaWhereTMP = new HashMap<String, Object>();
mapaWhereTMP.put("params", new ArrayList<Object>());
StringBuilder sqlJerarquiaHijos = getJerarquiaQuery(pagination, new StringBuilder(), mapaWhereTMP, new ArrayList<Object>(), columna, columnaPadre, tabla, aliasTabla, joins, businessFilters, businessParams);
//No requiere ordenación ya que es para obetner las PKs de los descendientes
//Quitar filtrado del padre (obtener todos los elementos para saber su página, línea en página y línea en tabla)
pagination.getJerarquia().setParentId(null);
//Jerarquia (all -> metadatos de todos)
StringBuilder sqlJerarquia = getJerarquiaQuery(pagination, new StringBuilder(), mapaWhere, new ArrayList<Object>(), columna, columnaPadre, tabla, aliasTabla, joins, businessFilters, businessParams);
//Ordenar según tabla
sqlJerarquia.append(PaginationManager.getOrderBy(pagination, true));
//Query propia
StringBuilder sbSQL = new StringBuilder();
sbSQL.append("\n").append("select ").append(columna).append(PaginationManager.getMultiselectionSelectOutter(pagination));
sbSQL.append("\n").append("from ( ");
sbSQL.append("\n\t").append("-- Query Jerarquia");
sbSQL.append("\n\t").append("select ").append(columna).append(PaginationManager.getMultiselectionSelectInner(pagination));
sbSQL.append("\n\t").append(sqlJerarquia.substring(sqlJerarquia.indexOf("from")));
sbSQL.append(") ");
sbSQL.append("\n").append("where ").append(columna).append(" in ( ");
sbSQL.append("\n\t").append("-- Query JerarquiaFiltro");
sbSQL.append("\n\t").append("select ").append(columna).append(" ");
if (pagination.getJerarquia().isChild()){
//Solo hijos directos
sbSQL.append("\n\t").append(sqlJerarquiaHijos.substring(sqlJerarquiaHijos.indexOf("from")).replaceAll("1=1", "LEVEL=1"));
} else {
//Todos los descendientes
sbSQL.append("\n\t").append(sqlJerarquiaHijos.substring(sqlJerarquiaHijos.indexOf("from")));
}
sbSQL.append("\n").append(") ");
return sbSQL;
}
}