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);
}
}