blob: 8370d2dcc6939d22ab10561f5b15ba6c9fc70708 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*******************************************************************************/
package org.apache.ofbiz.common;
import static org.apache.ofbiz.base.util.UtilGenerics.checkList;
import static org.apache.ofbiz.base.util.UtilGenerics.checkMap;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.ObjectType;
import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntity;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityComparisonOperator;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityConditionList;
import org.apache.ofbiz.entity.condition.EntityFunction;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.model.ModelEntity;
import org.apache.ofbiz.entity.model.ModelField;
import org.apache.ofbiz.entity.util.EntityListIterator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceUtil;
/**
* FindServices Class
*/
public class FindServices {
public static final String module = FindServices.class.getName();
public static final String resource = "CommonUiLabels";
public static Map<String, EntityComparisonOperator<?, ?>> entityOperators;
static {
entityOperators = new LinkedHashMap<String, EntityComparisonOperator<?, ?>>();
entityOperators.put("between", EntityOperator.BETWEEN);
entityOperators.put("equals", EntityOperator.EQUALS);
entityOperators.put("greaterThan", EntityOperator.GREATER_THAN);
entityOperators.put("greaterThanEqualTo", EntityOperator.GREATER_THAN_EQUAL_TO);
entityOperators.put("in", EntityOperator.IN);
entityOperators.put("not-in", EntityOperator.NOT_IN);
entityOperators.put("lessThan", EntityOperator.LESS_THAN);
entityOperators.put("lessThanEqualTo", EntityOperator.LESS_THAN_EQUAL_TO);
entityOperators.put("like", EntityOperator.LIKE);
entityOperators.put("notLike", EntityOperator.NOT_LIKE);
entityOperators.put("not", EntityOperator.NOT);
entityOperators.put("notEqual", EntityOperator.NOT_EQUAL);
}
public FindServices() {}
/**
* prepareField, analyse inputFields to created normalizedFields a map with field name and operator.
*
* This is use to the generic method that expects entity data affixed with special suffixes
* to indicate their purpose in formulating an SQL query statement.
* @param inputFields Input parameters run thru UtilHttp.getParameterMap
* @return a map with field name and operator
*/
public static Map<String, Map<String, Map<String, Object>>> prepareField(Map<String, ?> inputFields, Map<String, Object> queryStringMap, Map<String, List<Object[]>> origValueMap) {
// Strip the "_suffix" off of the parameter name and
// build a three-level map of values keyed by fieldRoot name,
// fld0 or fld1, and, then, "op" or "value"
// ie. id
// - fld0
// - op:like
// - value:abc
// - fld1 (if there is a range)
// - op:lessThan
// - value:55 (note: these two "flds" wouldn't really go together)
// Also note that op/fld can be in any order. (eg. id_fld1_equals or id_equals_fld1)
// Note that "normalizedFields" will contain values other than those
// Contained in the associated entity.
// Those extra fields will be ignored in the second half of this method.
Map<String, Map<String, Map<String, Object>>> normalizedFields = new LinkedHashMap<String, Map<String, Map<String, Object>>>();
for (String fieldNameRaw: inputFields.keySet()) { // The name as it appeas in the HTML form
String fieldNameRoot = null; // The entity field name. Everything to the left of the first "_" if
// it exists, or the whole word, if not.
String fieldPair = null; // "fld0" or "fld1" - begin/end of range or just fld0 if no range.
Object fieldValue = null; // If it is a "value" field, it will be the value to be used in the query.
// If it is an "op" field, it will be "equals", "greaterThan", etc.
int iPos = -1;
int iPos2 = -1;
Map<String, Map<String, Object>> subMap = null;
Map<String, Object> subMap2 = null;
String fieldMode = null;
fieldValue = inputFields.get(fieldNameRaw);
if (ObjectType.isEmpty(fieldValue)) {
continue;
}
queryStringMap.put(fieldNameRaw, fieldValue);
iPos = fieldNameRaw.indexOf("_"); // Look for suffix
// This is a hack to skip fields from "multi" forms
// These would have the form "fieldName_o_1"
if (iPos >= 0) {
String suffix = fieldNameRaw.substring(iPos + 1);
iPos2 = suffix.indexOf("_");
if (iPos2 == 1) {
continue;
}
}
// If no suffix, assume no range (default to fld0) and operations of equals
// If no field op is present, it will assume "equals".
if (iPos < 0) {
fieldNameRoot = fieldNameRaw;
fieldPair = "fld0";
fieldMode = "value";
} else { // Must have at least "fld0/1" or "equals, greaterThan, etc."
// Some bogus fields will slip in, like "ENTITY_NAME", but they will be ignored
fieldNameRoot = fieldNameRaw.substring(0, iPos);
String suffix = fieldNameRaw.substring(iPos + 1);
iPos2 = suffix.indexOf("_");
if (iPos2 < 0) {
if (suffix.startsWith("fld")) {
// If only one token and it starts with "fld"
// assume it is a value field, not an op
fieldPair = suffix;
fieldMode = "value";
} else {
// if it does not start with fld, assume it is an op or the 'ignore case' (ic) field
fieldPair = "fld0";
fieldMode = suffix;
}
} else {
String tkn0 = suffix.substring(0, iPos2);
String tkn1 = suffix.substring(iPos2 + 1);
// If suffix has two parts, let them be in any order
// One will be "fld0/1" and the other will be the op (eg. equals, greaterThan_
if (tkn0.startsWith("fld")) {
fieldPair = tkn0;
fieldMode = tkn1;
} else {
fieldPair = tkn1;
fieldMode = tkn0;
}
}
}
subMap = normalizedFields.get(fieldNameRoot);
if (subMap == null) {
subMap = new LinkedHashMap<String, Map<String, Object>>();
normalizedFields.put(fieldNameRoot, subMap);
}
subMap2 = subMap.get(fieldPair);
if (subMap2 == null) {
subMap2 = new LinkedHashMap<String, Object>();
subMap.put(fieldPair, subMap2);
}
subMap2.put(fieldMode, fieldValue);
List<Object[]> origList = origValueMap.get(fieldNameRoot);
if (origList == null) {
origList = new LinkedList<Object[]>();
origValueMap.put(fieldNameRoot, origList);
}
Object [] origValues = {fieldNameRaw, fieldValue};
origList.add(origValues);
}
return normalizedFields;
}
/**
* Parses input parameters and returns an <code>EntityCondition</code> list.
*
* @param parameters
* @param fieldList
* @param queryStringMap
* @param delegator
* @param context
* @return returns an EntityCondition list
*/
public static List<EntityCondition> createConditionList(Map<String, ? extends Object> parameters, List<ModelField> fieldList, Map<String, Object> queryStringMap, Delegator delegator, Map<String, ?> context) {
Set<String> processed = new LinkedHashSet<String>();
Set<String> keys = new LinkedHashSet<String>();
Map<String, ModelField> fieldMap = new LinkedHashMap<String, ModelField>();
for (ModelField modelField : fieldList) {
fieldMap.put(modelField.getName(), modelField);
}
List<EntityCondition> result = new LinkedList<EntityCondition>();
for (Map.Entry<String, ? extends Object> entry : parameters.entrySet()) {
String parameterName = entry.getKey();
if (processed.contains(parameterName)) {
continue;
}
keys.clear();
String fieldName = parameterName;
Object fieldValue = null;
String operation = null;
boolean ignoreCase = false;
if (parameterName.endsWith("_ic") || parameterName.endsWith("_op")) {
fieldName = parameterName.substring(0, parameterName.length() - 3);
} else if (parameterName.endsWith("_value")) {
fieldName = parameterName.substring(0, parameterName.length() - 6);
}
String key = fieldName.concat("_ic");
if (parameters.containsKey(key)) {
keys.add(key);
ignoreCase = "Y".equals(parameters.get(key));
}
key = fieldName.concat("_op");
if (parameters.containsKey(key)) {
keys.add(key);
operation = (String) parameters.get(key);
}
key = fieldName.concat("_value");
if (parameters.containsKey(key)) {
keys.add(key);
fieldValue = parameters.get(key);
}
if (fieldName.endsWith("_fld0") || fieldName.endsWith("_fld1")) {
if (parameters.containsKey(fieldName)) {
keys.add(fieldName);
}
fieldName = fieldName.substring(0, fieldName.length() - 5);
}
if (parameters.containsKey(fieldName)) {
keys.add(fieldName);
}
processed.addAll(keys);
ModelField modelField = fieldMap.get(fieldName);
if (modelField == null) {
continue;
}
if (fieldValue == null) {
fieldValue = parameters.get(fieldName);
}
if (ObjectType.isEmpty(fieldValue) && !"empty".equals(operation)) {
continue;
}
result.add(createSingleCondition(modelField, operation, fieldValue, ignoreCase, delegator, context));
for (String mapKey : keys) {
queryStringMap.put(mapKey, parameters.get(mapKey));
}
}
return result;
}
/**
* Creates a single <code>EntityCondition</code> based on a set of parameters.
*
* @param modelField
* @param operation
* @param fieldValue
* @param ignoreCase
* @param delegator
* @param context
* @return return an EntityCondition
*/
public static EntityCondition createSingleCondition(ModelField modelField, String operation, Object fieldValue, boolean ignoreCase, Delegator delegator, Map<String, ?> context) {
EntityCondition cond = null;
String fieldName = modelField.getName();
Locale locale = (Locale) context.get("locale");
TimeZone timeZone = (TimeZone) context.get("timeZone");
EntityComparisonOperator<?, ?> fieldOp = null;
if (operation != null) {
if (operation.equals("contains")) {
fieldOp = EntityOperator.LIKE;
fieldValue = "%" + fieldValue + "%";
} else if ("not-contains".equals(operation) || "notContains".equals(operation)) {
fieldOp = EntityOperator.NOT_LIKE;
fieldValue = "%" + fieldValue + "%";
} else if (operation.equals("empty")) {
return EntityCondition.makeCondition(fieldName, EntityOperator.EQUALS, null);
} else if (operation.equals("like")) {
fieldOp = EntityOperator.LIKE;
fieldValue = fieldValue + "%";
} else if ("not-like".equals(operation) || "notLike".equals(operation)) {
fieldOp = EntityOperator.NOT_LIKE;
fieldValue = fieldValue + "%";
} else if ("opLessThan".equals(operation)) {
fieldOp = EntityOperator.LESS_THAN;
} else if ("upToDay".equals(operation)) {
fieldOp = EntityOperator.LESS_THAN;
} else if ("upThruDay".equals(operation)) {
fieldOp = EntityOperator.LESS_THAN_EQUAL_TO;
} else if (operation.equals("greaterThanFromDayStart")) {
String timeStampString = (String) fieldValue;
Object startValue = modelField.getModelEntity().convertFieldValue(modelField, dayStart(timeStampString, 0, timeZone, locale), delegator, context);
return EntityCondition.makeCondition(fieldName, EntityOperator.GREATER_THAN_EQUAL_TO, startValue);
} else if (operation.equals("sameDay")) {
String timeStampString = (String) fieldValue;
Object startValue = modelField.getModelEntity().convertFieldValue(modelField, dayStart(timeStampString, 0, timeZone, locale), delegator, context);
EntityCondition startCond = EntityCondition.makeCondition(fieldName, EntityOperator.GREATER_THAN_EQUAL_TO, startValue);
Object endValue = modelField.getModelEntity().convertFieldValue(modelField, dayStart(timeStampString, 1, timeZone, locale), delegator, context);
EntityCondition endCond = EntityCondition.makeCondition(fieldName, EntityOperator.LESS_THAN, endValue);
return EntityCondition.makeCondition(startCond, endCond);
} else {
fieldOp = entityOperators.get(operation);
}
} else {
if (UtilValidate.isNotEmpty(UtilGenerics.toList(fieldValue))) {
fieldOp = EntityOperator.IN;
} else {
fieldOp = EntityOperator.EQUALS;
}
}
Object fieldObject = fieldValue;
if ((fieldOp != EntityOperator.IN && fieldOp != EntityOperator.NOT_IN ) || !(fieldValue instanceof Collection<?>)) {
fieldObject = modelField.getModelEntity().convertFieldValue(modelField, fieldValue, delegator, context);
}
if (ignoreCase && fieldObject instanceof String) {
cond = EntityCondition.makeCondition(EntityFunction.UPPER_FIELD(fieldName), fieldOp, EntityFunction.UPPER(((String)fieldValue).toUpperCase()));
} else {
if (fieldObject.equals(GenericEntity.NULL_FIELD.toString())) {
fieldObject = null;
}
cond = EntityCondition.makeCondition(fieldName, fieldOp, fieldObject);
}
if (EntityOperator.NOT_EQUAL.equals(fieldOp) && fieldObject != null) {
cond = EntityCondition.makeCondition(UtilMisc.toList(cond, EntityCondition.makeCondition(fieldName, null)), EntityOperator.OR);
}
return cond;
}
/**
* createCondition, comparing the normalizedFields with the list of keys, .
*
* This is use to the generic method that expects entity data affixed with special suffixes
* to indicate their purpose in formulating an SQL query statement.
* @param modelEntity the model entity object
* @param normalizedFields list of field the user have populated
* @return a arrayList usable to create an entityCondition
*/
public static List<EntityCondition> createCondition(ModelEntity modelEntity, Map<String, Map<String, Map<String, Object>>> normalizedFields, Map<String, Object> queryStringMap, Map<String, List<Object[]>> origValueMap, Delegator delegator, Map<String, ?> context) {
Map<String, Map<String, Object>> subMap = null;
Map<String, Object> subMap2 = null;
Object fieldValue = null; // If it is a "value" field, it will be the value to be used in the query.
// If it is an "op" field, it will be "equals", "greaterThan", etc.
EntityCondition cond = null;
List<EntityCondition> tmpList = new LinkedList<EntityCondition>();
String opString = null;
boolean ignoreCase = false;
List<ModelField> fields = modelEntity.getFieldsUnmodifiable();
for (ModelField modelField: fields) {
String fieldName = modelField.getName();
subMap = normalizedFields.get(fieldName);
if (subMap == null) {
continue;
}
subMap2 = subMap.get("fld0");
fieldValue = subMap2.get("value");
opString = (String) subMap2.get("op");
// null fieldValue is OK if operator is "empty"
if (fieldValue == null && !"empty".equals(opString)) {
continue;
}
ignoreCase = "Y".equals(subMap2.get("ic"));
cond = createSingleCondition(modelField, opString, fieldValue, ignoreCase, delegator, context);
tmpList.add(cond);
subMap2 = subMap.get("fld1");
if (subMap2 == null) {
continue;
}
fieldValue = subMap2.get("value");
opString = (String) subMap2.get("op");
if (fieldValue == null && !"empty".equals(opString)) {
continue;
}
ignoreCase = "Y".equals(subMap2.get("ic"));
cond = createSingleCondition(modelField, opString, fieldValue, ignoreCase, delegator, context);
tmpList.add(cond);
// add to queryStringMap
List<Object[]> origList = origValueMap.get(fieldName);
if (UtilValidate.isNotEmpty(origList)) {
for (Object[] arr: origList) {
queryStringMap.put((String) arr[0], arr[1]);
}
}
}
return tmpList;
}
/**
*
* same as performFind but now returning a list instead of an iterator
* Extra parameters viewIndex: startPage of the partial list (0 = first page)
* viewSize: the length of the page (number of records)
* Extra output parameter: listSize: size of the totallist
* list : the list itself.
*
* @param dctx
* @param context
* @return Map
*/
public static Map<String, Object> performFindList(DispatchContext dctx, Map<String, Object> context) {
Integer viewSize = (Integer) context.get("viewSize");
if (viewSize == null) viewSize = Integer.valueOf(20); // default
context.put("viewSize", viewSize);
Integer viewIndex = (Integer) context.get("viewIndex");
if (viewIndex == null) viewIndex = Integer.valueOf(0); // default
context.put("viewIndex", viewIndex);
Map<String, Object> result = performFind(dctx,context);
int start = viewIndex.intValue() * viewSize.intValue();
List<GenericValue> list = null;
Integer listSize = 0;
try {
EntityListIterator it = (EntityListIterator) result.get("listIt");
list = it.getPartialList(start+1, viewSize); // list starts at '1'
listSize = it.getResultsSizeAfterPartialList();
it.close();
} catch (Exception e) {
Debug.logInfo("Problem getting partial list" + e,module);
}
result.put("listSize", listSize);
result.put("list",list);
result.remove("listIt");
return result;
}
/**
* performFind
*
* This is a generic method that expects entity data affixed with special suffixes
* to indicate their purpose in formulating an SQL query statement.
*/
public static Map<String, Object> performFind(DispatchContext dctx, Map<String, ?> context) {
String entityName = (String) context.get("entityName");
String orderBy = (String) context.get("orderBy");
Map<String, ?> inputFields = checkMap(context.get("inputFields"), String.class, Object.class); // Input
String noConditionFind = (String) context.get("noConditionFind");
String distinct = (String) context.get("distinct");
List<String> fieldList = UtilGenerics.<String>checkList(context.get("fieldList"));
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
Delegator delegator = dctx.getDelegator();
if (UtilValidate.isEmpty(noConditionFind)) {
// try finding in inputFields Map
noConditionFind = (String) inputFields.get("noConditionFind");
}
if (UtilValidate.isEmpty(noConditionFind)) {
// Use configured default
noConditionFind = EntityUtilProperties.getPropertyValue("widget", "widget.defaultNoConditionFind", delegator);
}
String filterByDate = (String) context.get("filterByDate");
if (UtilValidate.isEmpty(filterByDate)) {
// try finding in inputFields Map
filterByDate = (String) inputFields.get("filterByDate");
}
Timestamp filterByDateValue = (Timestamp) context.get("filterByDateValue");
String fromDateName = (String) context.get("fromDateName");
if (UtilValidate.isEmpty(fromDateName)) {
// try finding in inputFields Map
fromDateName = (String) inputFields.get("fromDateName");
}
String thruDateName = (String) context.get("thruDateName");
if (UtilValidate.isEmpty(thruDateName)) {
// try finding in inputFields Map
thruDateName = (String) inputFields.get("thruDateName");
}
Integer viewSize = (Integer) context.get("viewSize");
Integer viewIndex = (Integer) context.get("viewIndex");
Integer maxRows = null;
if (viewSize != null && viewIndex != null) {
maxRows = viewSize * (viewIndex + 1);
}
LocalDispatcher dispatcher = dctx.getDispatcher();
Map<String, Object> prepareResult = null;
try {
prepareResult = dispatcher.runSync("prepareFind", UtilMisc.toMap("entityName", entityName, "orderBy", orderBy,
"inputFields", inputFields, "filterByDate", filterByDate, "noConditionFind", noConditionFind,
"filterByDateValue", filterByDateValue, "userLogin", userLogin, "fromDateName", fromDateName, "thruDateName", thruDateName,
"locale", context.get("locale"), "timeZone", context.get("timeZone")));
} catch (GenericServiceException gse) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonFindErrorPreparingConditions", UtilMisc.toMap("errorString", gse.getMessage()), locale));
}
EntityConditionList<EntityCondition> exprList = UtilGenerics.cast(prepareResult.get("entityConditionList"));
List<String> orderByList = checkList(prepareResult.get("orderByList"), String.class);
Map<String, Object> executeResult = null;
try {
executeResult = dispatcher.runSync("executeFind", UtilMisc.toMap("entityName", entityName, "orderByList", orderByList,
"fieldList", fieldList, "entityConditionList", exprList,
"noConditionFind", noConditionFind, "distinct", distinct,
"locale", context.get("locale"), "timeZone", context.get("timeZone"),
"maxRows", maxRows));
} catch (GenericServiceException gse) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonFindErrorRetrieveIterator", UtilMisc.toMap("errorString", gse.getMessage()), locale));
}
if (executeResult.get("listIt") == null) {
if (Debug.verboseOn()) Debug.logVerbose("No list iterator found for query string + [" + prepareResult.get("queryString") + "]", module);
}
Map<String, Object> results = ServiceUtil.returnSuccess();
results.put("listIt", executeResult.get("listIt"));
results.put("listSize", executeResult.get("listSize"));
results.put("queryString", prepareResult.get("queryString"));
results.put("queryStringMap", prepareResult.get("queryStringMap"));
return results;
}
/**
* prepareFind
*
* This is a generic method that expects entity data affixed with special suffixes
* to indicate their purpose in formulating an SQL query statement.
*/
public static Map<String, Object> prepareFind(DispatchContext dctx, Map<String, ?> context) {
String entityName = (String) context.get("entityName");
Delegator delegator = dctx.getDelegator();
String orderBy = (String) context.get("orderBy");
Map<String, ?> inputFields = checkMap(context.get("inputFields"), String.class, Object.class); // Input
String noConditionFind = (String) context.get("noConditionFind");
if (UtilValidate.isEmpty(noConditionFind)) {
// try finding in inputFields Map
noConditionFind = (String) inputFields.get("noConditionFind");
}
if (UtilValidate.isEmpty(noConditionFind)) {
// Use configured default
noConditionFind = EntityUtilProperties.getPropertyValue("widget", "widget.defaultNoConditionFind", delegator);
}
String filterByDate = (String) context.get("filterByDate");
if (UtilValidate.isEmpty(filterByDate)) {
// try finding in inputFields Map
filterByDate = (String) inputFields.get("filterByDate");
}
Timestamp filterByDateValue = (Timestamp) context.get("filterByDateValue");
String fromDateName = (String) context.get("fromDateName");
String thruDateName = (String) context.get("thruDateName");
Map<String, Object> queryStringMap = new LinkedHashMap<String, Object>();
ModelEntity modelEntity = delegator.getModelEntity(entityName);
List<EntityCondition> tmpList = createConditionList(inputFields, modelEntity.getFieldsUnmodifiable(), queryStringMap, delegator, context);
/* the filter by date condition should only be added when there are other conditions or when
* the user has specified a noConditionFind. Otherwise, specifying filterByDate will become
* its own condition.
*/
if (tmpList.size() > 0 || "Y".equals(noConditionFind)) {
if ("Y".equals(filterByDate)) {
queryStringMap.put("filterByDate", filterByDate);
if (UtilValidate.isEmpty(fromDateName)) fromDateName = "fromDate";
else queryStringMap.put("fromDateName", fromDateName);
if (UtilValidate.isEmpty(thruDateName)) thruDateName = "thruDate";
else queryStringMap.put("thruDateName", thruDateName);
if (UtilValidate.isEmpty(filterByDateValue)) {
EntityCondition filterByDateCondition = EntityUtil.getFilterByDateExpr(fromDateName, thruDateName);
tmpList.add(filterByDateCondition);
} else {
queryStringMap.put("filterByDateValue", filterByDateValue);
EntityCondition filterByDateCondition = EntityUtil.getFilterByDateExpr(filterByDateValue, fromDateName, thruDateName);
tmpList.add(filterByDateCondition);
}
}
}
EntityConditionList<EntityCondition> exprList = null;
if (tmpList.size() > 0) {
exprList = EntityCondition.makeCondition(tmpList);
}
List<String> orderByList = null;
if (UtilValidate.isNotEmpty(orderBy)) {
orderByList = StringUtil.split(orderBy,"|");
}
Map<String, Object> results = ServiceUtil.returnSuccess();
queryStringMap.put("noConditionFind", noConditionFind);
String queryString = UtilHttp.urlEncodeArgs(queryStringMap);
results.put("queryString", queryString);
results.put("queryStringMap", queryStringMap);
results.put("orderByList", orderByList);
results.put("entityConditionList", exprList);
return results;
}
/**
* executeFind
*
* This is a generic method that returns an EntityListIterator.
*/
public static Map<String, Object> executeFind(DispatchContext dctx, Map<String, ?> context) {
String entityName = (String) context.get("entityName");
EntityConditionList<EntityCondition> entityConditionList = UtilGenerics.cast(context.get("entityConditionList"));
List<String> orderByList = checkList(context.get("orderByList"), String.class);
boolean noConditionFind = "Y".equals(context.get("noConditionFind"));
boolean distinct = "Y".equals(context.get("distinct"));
List<String> fieldList = UtilGenerics.checkList(context.get("fieldList"));
Locale locale = (Locale) context.get("locale");
Set<String> fieldSet = null;
if (fieldList != null) {
fieldSet = UtilMisc.makeSetWritable(fieldList);
}
Integer maxRows = (Integer) context.get("maxRows");
maxRows = maxRows != null ? maxRows : -1;
Delegator delegator = dctx.getDelegator();
// Retrieve entities - an iterator over all the values
EntityListIterator listIt = null;
int listSize = 0;
try {
if (noConditionFind || (entityConditionList != null && entityConditionList.getConditionListSize() > 0)) {
listIt = EntityQuery.use(delegator)
.select(fieldSet)
.from(entityName)
.where(entityConditionList)
.orderBy(orderByList)
.cursorScrollInsensitive()
.maxRows(maxRows)
.distinct(distinct)
.queryIterator();
listSize = listIt.getResultsSizeAfterPartialList();
}
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonFindErrorRunning", UtilMisc.toMap("entityName", entityName, "errorString", e.getMessage()), locale));
}
Map<String, Object> results = ServiceUtil.returnSuccess();
results.put("listIt", listIt);
results.put("listSize", listSize);
return results;
}
private static String dayStart(String timeStampString, int daysLater, TimeZone timeZone, Locale locale) {
String retValue = null;
Timestamp ts = null;
Timestamp startTs = null;
try {
ts = Timestamp.valueOf(timeStampString);
} catch (IllegalArgumentException e) {
timeStampString += " 00:00:00.000";
try {
ts = Timestamp.valueOf(timeStampString);
} catch (IllegalArgumentException e2) {
return retValue;
}
}
startTs = UtilDateTime.getDayStart(ts, daysLater, timeZone, locale);
retValue = startTs.toString();
return retValue;
}
public static Map<String, Object> buildReducedQueryString(Map<String, ?> inputFields, String entityName, Delegator delegator) {
// Strip the "_suffix" off of the parameter name and
// build a three-level map of values keyed by fieldRoot name,
// fld0 or fld1, and, then, "op" or "value"
// ie. id
// - fld0
// - op:like
// - value:abc
// - fld1 (if there is a range)
// - op:lessThan
// - value:55 (note: these two "flds" wouldn't really go together)
// Also note that op/fld can be in any order. (eg. id_fld1_equals or id_equals_fld1)
// Note that "normalizedFields" will contain values other than those
// Contained in the associated entity.
// Those extra fields will be ignored in the second half of this method.
ModelEntity modelEntity = delegator.getModelEntity(entityName);
Map<String, Object> normalizedFields = new LinkedHashMap<String, Object>();
//StringBuffer queryStringBuf = new StringBuffer();
for (String fieldNameRaw: inputFields.keySet()) { // The name as it appeas in the HTML form
String fieldNameRoot = null; // The entity field name. Everything to the left of the first "_" if
// it exists, or the whole word, if not.
Object fieldValue = null; // If it is a "value" field, it will be the value to be used in the query.
// If it is an "op" field, it will be "equals", "greaterThan", etc.
int iPos = -1;
int iPos2 = -1;
fieldValue = inputFields.get(fieldNameRaw);
if (ObjectType.isEmpty(fieldValue)) {
continue;
}
//queryStringBuffer.append(fieldNameRaw + "=" + fieldValue);
iPos = fieldNameRaw.indexOf("_"); // Look for suffix
// This is a hack to skip fields from "multi" forms
// These would have the form "fieldName_o_1"
if (iPos >= 0) {
String suffix = fieldNameRaw.substring(iPos + 1);
iPos2 = suffix.indexOf("_");
if (iPos2 == 1) {
continue;
}
}
// If no suffix, assume no range (default to fld0) and operations of equals
// If no field op is present, it will assume "equals".
if (iPos < 0) {
fieldNameRoot = fieldNameRaw;
} else { // Must have at least "fld0/1" or "equals, greaterThan, etc."
// Some bogus fields will slip in, like "ENTITY_NAME", but they will be ignored
fieldNameRoot = fieldNameRaw.substring(0, iPos);
}
if (modelEntity.isField(fieldNameRoot)) {
normalizedFields.put(fieldNameRaw, fieldValue);
}
}
return normalizedFields;
}
/**
* Returns the first generic item of the service 'performFind'
* Same parameters as performFind service but returns a single GenericValue
*
* @param dctx
* @param context
* @return returns the first item
*/
public static Map<String, Object> performFindItem(DispatchContext dctx, Map<String, Object> context) {
context.put("viewSize", 1);
context.put("viewIndex", 0);
Map<String, Object> result = org.apache.ofbiz.common.FindServices.performFind(dctx,context);
List<GenericValue> list = null;
GenericValue item= null;
try {
EntityListIterator it = (EntityListIterator) result.get("listIt");
list = it.getPartialList(1, 1); // list starts at '1'
if (UtilValidate.isNotEmpty(list)) {
item = list.get(0);
}
it.close();
} catch (Exception e) {
Debug.logInfo("Problem getting list Item" + e,module);
}
if (UtilValidate.isNotEmpty(item)) {
result.put("item",item);
}
result.remove("listIt");
if (result.containsKey("listSize")) {
result.remove("listSize");
}
return result;
}
}