package org.openswing.swing.util.server; import java.util.*; import org.apache.cayenne.access.DataContext; import org.apache.cayenne.exp.Expression; import org.apache.cayenne.exp.ExpressionFactory; import org.apache.cayenne.query.SelectQuery; import org.apache.cayenne.Persistent; import org.apache.cayenne.DataObject; import org.openswing.swing.message.receive.java.*; import org.openswing.swing.message.send.java.*; import org.openswing.swing.server.*; import org.apache.cayenne.query.Query; import org.openswing.swing.util.java.Consts; /** * <p>Title: OpenSwing Framework</p> * <p>Description: Helper class containing some utility methods useful when retrieving data for a grid.</p> * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p> * * <p> This file is part of OpenSwing Framework. * This library is free software; you can redistribute it and/or * modify it under the terms of the (LGPL) Lesser General Public * License as published by the Free Software Foundation; * * GNU LESSER GENERAL PUBLIC LICENSE * Version 2.1, February 1999 * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author may be contacted at: * maurocarniel@tin.it</p> * * @author Mauro Carniel * @version 1.0 */ public class CayenneUtils { /** * Apply filtering and sorting conditions to the specified base select query and return * a new query that contains those conditions too. * @param filteredColumns filtering conditions * @param currentSortedColumns sorting conditions (attribute names) * @param currentSortedVersusColumns sorting conditions (order versus) * @param query Cayenne SelectQuery object * @param additionalConditions conditions expressed as <attribute name,value> * @param context Cayenne data context */ public static SelectQuery applyFiltersAndSorter( Map filteredColumns, ArrayList currentSortedColumns, ArrayList currentSortedVersusColumns, SelectQuery query, Map additionalConditions, DataContext context ) throws Exception { // append filtering conditions... query = query.queryWithParameters(additionalConditions); HashMap values = new HashMap(); String baseSQL = ""; Iterator keys = filteredColumns.keySet().iterator(); String attributeName = null; FilterWhereClause[] filterClauses = null; int num = 1; while (keys.hasNext()) { attributeName = keys.next().toString(); filterClauses = (FilterWhereClause[]) filteredColumns.get(attributeName); if ( filterClauses[0].getValue()!=null && !(filterClauses[0].getOperator().equals(Consts.IS_NOT_NULL) || filterClauses[0].getOperator().equals(Consts.IS_NULL))) { if (filterClauses[0].getValue() instanceof ArrayList) { // name IN (...) // name NOT IN (...) // (name op value1 OR name op value2 OR ...) if (filterClauses[0].getOperator().equals(Consts.IN) || filterClauses[0].getOperator().equals(Consts.NOT_IN)) { // name IN (...) // name NOT IN (...) baseSQL += attributeName + " " + filterClauses[0].getOperator() + " ("; ArrayList inValues = (ArrayList)filterClauses[0].getValue(); for(int j=0;j<inValues.size();j++) { baseSQL += " $n"+num+","; values.put("n"+num,inValues.get(j)); num++; } baseSQL = baseSQL.substring(0,baseSQL.length()-1); baseSQL += ") and "; } else { // (name op value1 OR name op value2 OR ...) baseSQL += "("; ArrayList inValues = (ArrayList)filterClauses[0].getValue(); for(int j=0;j<inValues.size();j++) { baseSQL += attributeName + " " + filterClauses[0].getOperator() + " $n"+num+" or "; values.put("n"+num,inValues.get(j)); num++; } baseSQL = baseSQL.substring(0,baseSQL.length()-3); baseSQL += ") and "; } } else { // name op value baseSQL += attributeName + " " + filterClauses[0].getOperator() + " $n"+num+" and "; values.put("n"+num,filterClauses[0].getValue()); num++; } } else { // name IS NULL // name IS NOT NULL baseSQL += attributeName + " " + filterClauses[0].getOperator() + " " + "and "; } if (filterClauses[1] != null) { if ( filterClauses[1].getValue()!=null && !(filterClauses[1].getOperator().equals(Consts.IS_NOT_NULL) || filterClauses[1].getOperator().equals(Consts.IS_NULL))) { if (filterClauses[1].getValue() instanceof ArrayList) { // name IN (...) // name NOT IN (...) // (name op value1 OR name op value2 OR ...) if (filterClauses[1].getOperator().equals(Consts.IN) || filterClauses[1].getOperator().equals(Consts.NOT_IN)) { // name IN (...) // name NOT IN (...) baseSQL += attributeName + " " + filterClauses[1].getOperator() + " ("; ArrayList inValues = (ArrayList)filterClauses[1].getValue(); for(int j=0;j<inValues.size();j++) { baseSQL += " $n"+num+","; values.put("n"+num,inValues.get(j)); num++; } baseSQL = baseSQL.substring(0,baseSQL.length()-1); baseSQL += ") and "; } else { // (name op value1 OR name op value2 OR ...) baseSQL += "("; ArrayList inValues = (ArrayList)filterClauses[1].getValue(); for(int j=0;j<inValues.size();j++) { baseSQL += attributeName + " " + filterClauses[1].getOperator() + " $n"+num+" or "; values.put("n"+num,inValues.get(j)); num++; } baseSQL = baseSQL.substring(0,baseSQL.length()-3); baseSQL += ") and "; } } else { // name op value baseSQL += attributeName + " " + filterClauses[1].getOperator() + " $n"+num+" and "; values.put("n"+num,filterClauses[1].getValue()); num++; } } else { // name IS NULL // name IS NOT NULL baseSQL += attributeName + " " + filterClauses[1].getOperator() + " " + "and "; } } } if (baseSQL.length()>4) { baseSQL = baseSQL.substring(0, baseSQL.length() - 4); query.andQualifier(Expression.fromString(baseSQL).expWithParameters(values)); } for(int i=0;i<currentSortedColumns.size();i++) query.addOrdering(currentSortedColumns.get(i).toString(),currentSortedVersusColumns.get(i).toString().equalsIgnoreCase("ASC")); return query; } /** * Read the whole result set, by applying filtering and sorting conditions + query parameters. * @param filteredColumns filtering conditions * @param currentSortedColumns sorting conditions (attribute names) * @param currentSortedVersusColumns sorting conditions (order versus) * @param valueObjectType value object type * @param query Cayenne SelectQuery object * @param additionalConditions conditions expressed as <attribute name,value> * @param context Cayenne data context */ public static Response getAllFromQuery( Map filteredColumns, ArrayList currentSortedColumns, ArrayList currentSortedVersusColumns, Class valueObjectType, SelectQuery query, Map additionalConditions, DataContext context ) throws Exception { query = applyFiltersAndSorter( filteredColumns, currentSortedColumns, currentSortedVersusColumns, query, additionalConditions, context ); ArrayList gridList = new ArrayList(); boolean moreRows = false; int resultSetLength = -1; // read the whole result set... List list = context.performQuery(query); gridList.addAll(list); resultSetLength = gridList.size(); return new VOListResponse(gridList,moreRows,resultSetLength); } /** * Read a block of records from the result set, by applying filtering and sorting conditions + query parameters. * @param action fetching versus: PREVIOUS_BLOCK_ACTION, NEXT_BLOCK_ACTION or LAST_BLOCK_ACTION * @param startPos start position of data fetching in result set * @param blockSize number of records to read * @param filteredColumns filtering conditions * @param currentSortedColumns sorting conditions (attribute names) * @param currentSortedVersusColumns sorting conditions (order versus) * @param query Cayenne SelectQuery object * @param additionalConditions conditions expressed as <attribute name,value> * @param tableName table name related to baseSQL and v.o. * @param context Cayenne data context */ public static Response getBlockFromQuery( int action, int startIndex, int blockSize, Map filteredColumns, ArrayList currentSortedColumns, ArrayList currentSortedVersusColumns, SelectQuery query, Map additionalConditions, DataContext context ) throws Exception { query = applyFiltersAndSorter( filteredColumns, currentSortedColumns, currentSortedVersusColumns, query, additionalConditions, context ); return getBlockFromQuery( action, startIndex, blockSize, query, context ); } /** * Read a block of records from the result set, starting from a Query object. * @param action fetching versus: PREVIOUS_BLOCK_ACTION, NEXT_BLOCK_ACTION or LAST_BLOCK_ACTION * @param startPos start position of data fetching in result set * @param blockSize number of records to read * @param query Query object * @param context Cayenne data context */ public static Response getBlockFromQuery( int action, int startIndex, int blockSize, SelectQuery query, DataContext context ) throws Exception { // read a block of records... ArrayList gridList = new ArrayList(); boolean moreRows = false; int resultSetLength = -1; int rowCount = 0; List list = null; if (action==GridParams.LAST_BLOCK_ACTION) { // last block requested: the whole result set will be loaded, to determine the result set length list = context.performQuery(query); resultSetLength = list.size(); startIndex = Math.max(rowCount-blockSize,0); for(int i=startIndex;i<resultSetLength;i++) gridList.add(list.get(i)); return new VOListResponse(gridList,false,resultSetLength); } else { if (action==GridParams.PREVIOUS_BLOCK_ACTION) { action = GridParams.NEXT_BLOCK_ACTION; startIndex = Math.max(startIndex-blockSize,0); } } // read a block of data... query.setFetchLimit(startIndex+blockSize+1); list = context.performQuery(query); for(int i=startIndex;i<list.size();i++) { if (gridList.size()==blockSize) { moreRows = true; break; } gridList.add(list.get(i)); } if (resultSetLength==-1) resultSetLength = gridList.size(); return new VOListResponse(gridList,moreRows,resultSetLength); } }