/* * Smart GWT (GWT for SmartClient) * Copyright 2008 and beyond, Isomorphic Software, Inc. * * Smart GWT is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. Smart GWT is also * available under typical commercial license terms - see * http://smartclient.com/license * * This software 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 * Lesser General Public License for more details. */ package com.smartgwt.client.data; import com.smartgwt.client.event.*; import com.smartgwt.client.core.*; import com.smartgwt.client.types.*; import com.smartgwt.client.data.*; import com.smartgwt.client.data.events.*; import com.smartgwt.client.rpc.*; import com.smartgwt.client.widgets.*; import com.smartgwt.client.widgets.events.*; import com.smartgwt.client.widgets.form.*; import com.smartgwt.client.widgets.form.validator.*; import com.smartgwt.client.widgets.form.fields.*; import com.smartgwt.client.widgets.tile.*; import com.smartgwt.client.widgets.tile.events.*; import com.smartgwt.client.widgets.grid.*; import com.smartgwt.client.widgets.grid.events.*; import com.smartgwt.client.widgets.chart.*; import com.smartgwt.client.widgets.layout.*; import com.smartgwt.client.widgets.layout.events.*; import com.smartgwt.client.widgets.menu.*; import com.smartgwt.client.widgets.tab.*; import com.smartgwt.client.widgets.toolbar.*; import com.smartgwt.client.widgets.tree.*; import com.smartgwt.client.widgets.tree.events.*; import com.smartgwt.client.widgets.viewer.*; import com.smartgwt.client.widgets.calendar.*; import com.smartgwt.client.widgets.calendar.events.*; import com.smartgwt.client.widgets.cube.*; import java.util.Date; import java.util.List; import java.util.Map; import java.util.HashMap; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.user.client.Element; import com.smartgwt.client.util.*; import com.google.gwt.event.shared.*; import com.google.gwt.event.shared.HasHandlers; /** * An object representing a criterion to apply to a record. <P> A criterion is part of the definition of an {@link * com.smartgwt.client.data.AdvancedCriteria} object, which is used to filter records according to search criteria. <P> A * criterion consists of an {@link com.smartgwt.client.data.Criterion#getOperator operator} and typically a {@link * com.smartgwt.client.data.DataSourceField#getName fieldName} from a {@link com.smartgwt.client.data.Record} and a {@link * com.smartgwt.client.data.Criterion#getValue value} to compare to. However some operators either don't require a value * (eg, isNull) or act on other criteria rather than directly on a {@link com.smartgwt.client.data.Record}'s fields (eg, * the "and" and "or" logical operators). */ public class Criterion extends Criteria { public static Criterion getOrCreateRef(JavaScriptObject jsObj) { if(jsObj == null) return null; return new Criterion(jsObj); } public Criterion(){ } public Criterion(JavaScriptObject jsObj){ super(jsObj); } // ********************* Properties / Attributes *********************** /** * Name of the field in each {@link com.smartgwt.client.data.Record} that this criterion applies to. Not applicable for a * criterion with {@link com.smartgwt.client.data.Criterion#getCriteria sub-criteria}. * * @param fieldName fieldName Default value is null */ public void setFieldName(String fieldName) { setAttribute("fieldName", fieldName); } /** * Name of the field in each {@link com.smartgwt.client.data.Record} that this criterion applies to. Not applicable for a * criterion with {@link com.smartgwt.client.data.Criterion#getCriteria sub-criteria}. * * * @return String */ public String getFieldName() { return getAttributeAsString("fieldName"); } /** * Operator this criterion applies. * * @param operator operator Default value is null */ public void setOperator(OperatorId operator) { setAttribute("operator", operator == null ? null : operator.getValue()); } /** * Operator this criterion applies. * * * @return OperatorId */ public OperatorId getOperator() { return EnumUtil.getEnum(OperatorId.values(), getAttribute("operator")); } // ********************* Methods *********************** // ********************* Static Methods *********************** // *********************************************************** public Criterion(Criterion c) { Object o; o = c.getAttributeAsObject("operator"); if (o != null) setAttribute("operator", o); o = c.getAttributeAsObject("fieldName"); if (o != null) setAttribute("fieldName", o); o = c.getAttributeAsObject("criteria"); if (o != null) setAttribute("criteria", o); o = c.getAttributeAsObject("value"); if (o != null) setAttribute("value", o); } public Criterion(OperatorId operator, Criterion[] criterias) { buildCriterionFromList(operator, criterias); } public Criterion(OperatorId operator) { setAttribute("operator", operator.getValue()); } public Criterion(String fieldName, OperatorId operator) { setAttribute("fieldName", fieldName); setAttribute("operator", operator.getValue()); } /** * Constructor for Criterion with fieldName, operator and value. * * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, Integer value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator, start and end values. This constructor is only valid when * the operator is {@link OperatorId#BETWEEN} or {@link OperatorId#BETWEEN_INCLUSIVE} * * @param fieldName the field name * @param operator the operator * @param start the start value * @param end the end value */ public Criterion(String fieldName, OperatorId operator, Integer start, Integer end) { this(fieldName, operator); assert operator == OperatorId.BETWEEN || operator == OperatorId.BETWEEN_INCLUSIVE : "The operator type must be OperatorId.BETWEEN or OperatorId.BETWEEN_INCLUSIVE"; setAttribute("start", start); setAttribute("end", end); } /** * Constructor for Criterion with fieldName, operator and value. * * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, String value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator, start and end values. This constructor is only valid when * the operator is {@link OperatorId#BETWEEN} or {@link OperatorId#BETWEEN_INCLUSIVE} * * @param fieldName the field name * @param operator the operator * @param start the start value * @param end the end value */ public Criterion(String fieldName, OperatorId operator, String start, String end) { this(fieldName, operator); assert operator == OperatorId.BETWEEN || operator == OperatorId.BETWEEN_INCLUSIVE : "The operator type must be OperatorId.BETWEEN or OperatorId.BETWEEN_INCLUSIVE"; setAttribute("start", start); setAttribute("end", end); } /** * Constructor for Criterion with fieldName, operator and value. * * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, Float value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator, start and end values. This constructor is only valid when * the operator is {@link OperatorId#BETWEEN} or {@link OperatorId#BETWEEN_INCLUSIVE} * * @param fieldName the field name * @param operator the operator * @param start the start value * @param end the end value */ public Criterion(String fieldName, OperatorId operator, Float start, Float end) { this(fieldName, operator); assert operator == OperatorId.BETWEEN || operator == OperatorId.BETWEEN_INCLUSIVE : "The operator type must be OperatorId.BETWEEN or OperatorId.BETWEEN_INCLUSIVE"; setAttribute("start", start); setAttribute("end", end); } /** * Constructor for Criterion with fieldName, operator and value. * * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, Date value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator, start and end values. This constructor is only valid when * the operator is {@link OperatorId#BETWEEN} or {@link OperatorId#BETWEEN_INCLUSIVE} * * @param fieldName the field name * @param operator the operator * @param start the start value * @param end the end value */ public Criterion(String fieldName, OperatorId operator, Date start, Date end) { this(fieldName, operator); assert operator == OperatorId.BETWEEN || operator == OperatorId.BETWEEN_INCLUSIVE : "The operator type must be OperatorId.BETWEEN or OperatorId.BETWEEN_INCLUSIVE"; setAttribute("start", start); setAttribute("end", end); } /** * Constructor for Criterion with fieldName, operator and value. * * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, Boolean value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator and value. * Note that JavaScript does not natively have an equivalent format to * Java long (fixed point 64 bit). As such the value passed in will be * converted to a double value for storage. * @param fieldName the field name * @param operator the operator * @param value the value */ public Criterion(String fieldName, OperatorId operator, Long value) { this(fieldName, operator); setAttribute("value", value); } /** * Constructor for Criterion with fieldName, operator, start and end values. This constructor is only valid when * the operator is {@link OperatorId#BETWEEN} or {@link OperatorId#BETWEEN_INCLUSIVE} * * @param fieldName the field name * @param operator the operator * @param start the start value * @param end the end value */ public Criterion(String fieldName, OperatorId operator, Long start, Long end) { this(fieldName, operator); assert operator == OperatorId.BETWEEN || operator == OperatorId.BETWEEN_INCLUSIVE : "The operator type must be OperatorId.BETWEEN or OperatorId.BETWEEN_INCLUSIVE"; setAttribute("start", start); setAttribute("end", end); } public Criterion(String fieldName, OperatorId operator, Integer[] value) { this(fieldName, operator); setAttribute("value", value); } public Criterion(String fieldName, OperatorId operator, String[] value) { this(fieldName, operator); setAttribute("value", value); } public Criterion(String fieldName, OperatorId operator, Float[] value) { this(fieldName, operator); setAttribute("value", value); } public Criterion(String fieldName, OperatorId operator, Long[] value) { this(fieldName, operator); setAttribute("value", value); } public Criterion(String fieldName, OperatorId operator, Date[] value) { this(fieldName, operator); setAttribute("value", value); } public Criterion(String fieldName, OperatorId operator, Boolean[] value) { this(fieldName, operator); setAttribute("value", value); } /** * Adds a new criteria. * <p>If the present criteria operation is "and", * the new criteria is appended to the criteria list. * <p>Otherwise, the present criteria is replaced with an "and" * criteria, with two sub-criteria: the present criteria, and the passed criteria. * * @param c the passed criteria object */ public void addCriteria(Criterion c) { String opString = this.getAttributeAsString("operator"); if (opString != null && opString.equals(OperatorId.AND.getValue())) { appendToCriterionList(c); } else { Criterion thisCopy = new Criterion(this); JSOHelper.deleteAttributeIfExists(jsObj, "fieldName"); JSOHelper.deleteAttributeIfExists(jsObj, "value"); Criterion[] criteriaList = { thisCopy, c }; buildCriterionFromList(OperatorId.AND, criteriaList); } } /** * @see #addCriteria(Criterion) */ public void addCriteria(String field, String value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Integer value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Float value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Date value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Boolean value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, String[] value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Integer[] value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Float[] value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Date[] value) { addCriteria(field, OperatorId.EQUALS, value); } public void addCriteria(String field, Boolean[] value) { addCriteria(field, OperatorId.EQUALS, value); } /** * @see #addCriteria(Criterion) */ public void addCriteria(String field, OperatorId op, String value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Integer value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Float value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Date value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Boolean value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, String[] value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Integer[] value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Float[] value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Date[] value) { addCriteria(new Criterion(field, op, value)); } public void addCriteria(String field, OperatorId op, Boolean[] value) { addCriteria(new Criterion(field, op, value)); } public void buildCriterionFromList(OperatorId operator, Criterion[] criterias) { setAttribute("operator", operator.getValue()); setAttribute("criteria", JSOHelper.createJavaScriptArray()); for (int i = 0; i < criterias.length; i++) appendToCriterionList(criterias[i]); } public void appendToCriterionList(Criterion c) { c.unmarkAdvancedCriteria(); JavaScriptObject listJS = getAttributeAsJavaScriptObject("criteria"); if (!JSOHelper.isArray(listJS)) { SC.logWarn("appendToCriterionList called when no criterion list exists"); return; } JSOHelper.setArrayValue(listJS, JSOHelper.getArrayLength(listJS), c.getJsObj()); } public void markAdvancedCriteria() { setAttribute("_constructor", "AdvancedCriteria"); } public void unmarkAdvancedCriteria() { JSOHelper.deleteAttributeIfExists(jsObj, "_constructor"); } /** * Returns an array of sub-criteria for this criterion. Will return null if there are no sub criterion. * Only applicable for criterion with operator type set to <code>AND</code> or <code>OR</code>. * * * @return String */ public Criterion[] getCriteria() { JavaScriptObject[] jsCriteria = JSOHelper.getAttributeAsJavaScriptObjectArray(getJsObj(), "criteria"); if (jsCriteria == null) return null; Criterion[] criteria = new Criterion[jsCriteria.length]; for (int i = 0; i < jsCriteria.length; i++) { criteria[i] = Criterion.getOrCreateRef(jsCriteria[i]); } return criteria; } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public String getValueAsString() { return JSOHelper.getAttribute(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public Integer getValueAsInteger() { return JSOHelper.getAttributeAsInt(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public Float getValueAsFloat() { return JSOHelper.getAttributeAsFloat(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public Date getValueAsDate() { return JSOHelper.getAttributeAsDate(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public Boolean getValueAsBoolean() { return JSOHelper.getAttributeAsBoolean(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public String[] getValueAsStringArray() { return JSOHelper.getAttributeAsStringArray(getJsObj(), "value"); } /** * Retrieves the specified value for this criterion. Only applies to criterion where operator and value have * been specified - will not apply to criterion containing {@link #getCriteria(),sub criteria}. * @return */ public int[] getValueAsIntArray() { return JSOHelper.getAttributeAsIntArray(getJsObj(), "value"); } }