Package org.openfaces.component.filter

Source Code of org.openfaces.component.filter.ExpressionFilter

/*
* OpenFaces - JSF Component Library 2.0
* Copyright (C) 2007-2012, TeamDev Ltd.
* licensing@openfaces.org
* Unless agreed in writing the contents of this file are subject to
* the GNU Lesser General Public License Version 2.1 (the "LGPL" License).
* 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.
* Please visit http://openfaces.org/licensing/ for more details.
*/
package org.openfaces.component.filter;

import org.openfaces.component.CompoundComponent;
import org.openfaces.component.FilterableComponent;
import org.openfaces.component.table.BaseColumn;
import org.openfaces.util.ValueBindings;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
* @author Dmitry Pikhulya
*/
public abstract class ExpressionFilter extends Filter implements CompoundComponent, ValueHolder {
    private static final String DEFAULT_ALL_RECORDS_CRITERION_NAME = "<All>";
    private static final String DEFAULT_EMPTY_RECORDS_CRITERION_NAME = "<Empty>";
    private static final String DEFAULT_NON_EMPTY_RECORDS_CRITERION_NAME = "<Non-empty>";

    private ExpressionFilterCriterion value;
    private ExpressionFilterCriterion condition;
    private Object expression;
    private boolean explicitExpression;
    private Converter converter;
    private boolean criterionModelUpdateRequired;
    private Boolean caseSensitive;
    private Integer autoFilterDelay;

    private String predefinedCriterionStyle;
    private String predefinedCriterionClass;

    protected String allRecordsText;
    protected String emptyRecordsText;
    protected String nonEmptyRecordsText;

    private String promptText;
    private String promptTextStyle;
    private String promptTextClass;
    private String accesskey;
    private String tabindex;
    private String title;

    @Override
    public Object saveState(FacesContext context) {
        Object superState = super.saveState(context);
        return new Object[]{superState, value, condition, saveAttachedState(context, converter), expression,
                explicitExpression, predefinedCriterionStyle, predefinedCriterionClass,
                allRecordsText, emptyRecordsText, nonEmptyRecordsText,
                promptText, promptTextStyle, promptTextClass, caseSensitive, accesskey, tabindex, title, autoFilterDelay
        };
    }

    @Override
    public void restoreState(FacesContext context, Object stateObj) {
        Object[] state = (Object[]) stateObj;
        int i = 0;
        super.restoreState(context, state[i++]);
        value = (ExpressionFilterCriterion) state[i++];
        condition = (ExpressionFilterCriterion) state[i++];
        converter = (Converter) restoreAttachedState(context, state[i++]);
        expression = state[i++];
        explicitExpression = (Boolean) state[i++];
        predefinedCriterionStyle = (String) state[i++];
        predefinedCriterionClass = (String) state[i++];
        allRecordsText = (String) state[i++];
        emptyRecordsText = (String) state[i++];
        nonEmptyRecordsText = (String) state[i++];

        promptText = (String) state[i++];
        promptTextStyle = (String) state[i++];
        promptTextClass = (String) state[i++];
        caseSensitive = (Boolean) state[i++];
        accesskey = (String) state[i++];
        tabindex = (String) state[i++];
        title = (String) state[i++];
        autoFilterDelay = (Integer) state[i++];
    }

    public boolean isCaseSensitive() {
        return ValueBindings.get(this, "caseSensitive", caseSensitive, false);
    }

    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public Converter getConverter() {
        if (converter != null) return converter;
        ValueExpression ve = getValueExpression("converter");
        if (ve != null)
            return (Converter) ve.getValue(getFacesContext().getELContext());
        if (explicitExpression) {
            // don't derive converter from a column if an expression is specified explicitly for the filter;
            // explicitly specified expression requires an explicitly specified converter (for the appropriate
            // expression's type) so the absence of explicit converter specification should be interpreted as intentional.
            return null;
        }
        BaseColumn column = getColumn();
        if (column != null) {
            converter = column.getColumnValueConverter();
            return converter;
        }
        return null;
    }

    public void setConverter(Converter converter) {
        this.converter = converter;
    }


    public String getPredefinedCriterionStyle() {
        return ValueBindings.get(this, "predefinedCriterionStyle", predefinedCriterionStyle);
    }

    public void setPredefinedCriterionStyle(String style) {
        predefinedCriterionStyle = style;
    }

    public String getPredefinedCriterionClass() {
        return ValueBindings.get(this, "predefinedCriterionClass", predefinedCriterionClass);
    }

    public void setPredefinedCriterionClass(String styleClass) {
        predefinedCriterionClass = styleClass;
    }

    public String getPromptText() {
        return ValueBindings.get(this, "promptText", promptText);
    }

    public void setPromptText(String promptText) {
        this.promptText = promptText;
    }

    public String getPromptTextStyle() {
        return ValueBindings.get(this, "promptTextStyle", promptTextStyle);
    }

    public void setPromptTextStyle(String promptTextStyle) {
        this.promptTextStyle = promptTextStyle;
    }

    public String getPromptTextClass() {
        return ValueBindings.get(this, "promptTextClass", promptTextClass);
    }

    public void setPromptTextClass(String promptTextClass) {
        this.promptTextClass = promptTextClass;
    }

    private BaseColumn getColumn() {
        UIComponent component = getParent();
        if (component instanceof BaseColumn)
            return (BaseColumn) component;
        else
            return null;
    }

    public Object getExpression() {
        if (expression == null) {
            BaseColumn column = getColumn();
            if (column != null)
                expression = column.getColumnValueExpression();
        }
        return expression;
    }

    /**
     * Expression should usually be a ValueExpression instance, though it is possible to specify a string value in
     * case of using the custom data providing mode, where expression identifies the filter for the user's custom data
     * providing code.
     */
    public void setExpression(Object expression) {
        this.expression = expression;
        this.explicitExpression = true;
    }

    public String getAllRecordsText() {
        String result = ValueBindings.get(this, "allRecordsCriterionName", allRecordsText);
        if (result == null) {
            FilterableComponent filteredComponent = getFilteredComponent();
            if (filteredComponent != null)
                result = filteredComponent.getAllRecordsFilterText();
        }
        if (result == null)
            result = DEFAULT_ALL_RECORDS_CRITERION_NAME;
        return result;
    }

    public void setAllRecordsText(String allRecordsText) {
        this.allRecordsText = allRecordsText;
    }

    public String getEmptyRecordsText() {
        String result = ValueBindings.get(this, "emptyRecordsCriterionName", emptyRecordsText);
        if (result == null) {
            FilterableComponent filteredComponent = getFilteredComponent();
            if (filteredComponent != null)
                result = filteredComponent.getEmptyRecordsFilterText();
        }
        if (result == null)
            result = DEFAULT_EMPTY_RECORDS_CRITERION_NAME;
        return result;
    }

    public void setEmptyRecordsText(String value) {
        emptyRecordsText = value;
    }

    public String getNonEmptyRecordsText() {
        String result = ValueBindings.get(this, "nonEmptyRecordsCriterionName", nonEmptyRecordsText);
        if (result == null) {
            FilterableComponent filteredComponent = getFilteredComponent();
            if (filteredComponent != null)
                result = filteredComponent.getNonEmptyRecordsFilterText();
        }
        if (result == null)
            result = DEFAULT_NON_EMPTY_RECORDS_CRITERION_NAME;
        return result;
    }

    public void setNonEmptyRecordsText(String value) {
        nonEmptyRecordsText = value;
    }

    public ValueExpression getOptionsExpression() {
        return getValueExpression("options");
    }

    public void setOptionsExpression(ValueExpression optionsExpression) {
        setValueExpression("options", optionsExpression);
    }

    public boolean getWantsRowList() {
        if (!isShowingPredefinedCriterionNames())
            return false;
        ValueExpression filterValuesExpression = getOptionsExpression();
        return filterValuesExpression == null;
    }

    protected boolean isShowingPredefinedCriterionNames() {
        return false;
    }

    public Collection<Object> calculateAllCriterionNames(FacesContext context) {
        ValueExpression valuesExpression = getOptionsExpression();
        if (valuesExpression != null) {
            Iterable values = (Iterable) valuesExpression.getValue(context.getELContext());
            List<Object> result = new ArrayList<Object>();
            if (values != null) {
                for (Object value : values) {
                    result.add(value);
                }
            }
            return result;
        }
        Object expression = getExpression();

        Set<Object> criterionNamesSet = new TreeSet<Object>();
        FilterableComponent filteredComponent = getFilteredComponent();
        List originalRowList = filteredComponent.getRowListForFiltering(this);
        boolean thereAreNullValues = false;
        for (Object data : originalRowList) {
            Object value = filteredComponent.getFilteredValueByData(context, data, expression);
            if (value == null)
                thereAreNullValues = true;
            else
                criterionNamesSet.add(value);
        }
        List<Object> list = new ArrayList<Object>();
        if (thereAreNullValues)
            list.add(null);
        list.addAll(criterionNamesSet);
        return list;
    }

    public void updateValueFromBinding(FacesContext context) {
        ValueExpression valueExpression = getValueExpression("value");
        if (valueExpression != null) {
            value = (ExpressionFilterCriterion) valueExpression.getValue(context.getELContext());
            if (value != null) {
                value.process(new FilterCriterionProcessor() {
                    public Object process(ExpressionFilterCriterion criterion) {
                        validateCriterion(criterion);
                        return null;
                    }

                    public Object process(AndFilterCriterion criterion) {
                        List<FilterCriterion> criteria = criterion.getCriteria();
                        for (FilterCriterion c : criteria) {
                            c.process(this);
                        }
                        return null;
                    }

                    public Object process(OrFilterCriterion criterion) {
                        List<FilterCriterion> criteria = criterion.getCriteria();
                        for (FilterCriterion c : criteria) {
                            c.process(this);
                        }
                        return null;
                    }
                });
            }
        } else {
            if (value != null)
                validateCriterion(value);
        }
    }

    private void validateCriterion(ExpressionFilterCriterion criterion) {
        boolean caseSensitive = isCaseSensitive();
        if (criterion.getPropertyLocator() == null)
            criterion.setPropertyLocator(getPropertyLocator());
        criterion.setCaseSensitive(caseSensitive);
    }

    public PropertyLocator getPropertyLocator() {
        FilterableComponent component = getFilteredComponent();
        Object expression = getExpression();
        if (expression == null)
            throw new FacesException("Filter expression cannot be detected automatically and is not specified " +
                    "explicitly. Filter id: " + getClientId(getFacesContext()));
        if (component != null) {
            final PropertyLocatorFactory factory = new FilterableComponentPropertyLocatorFactory(component);
            return factory.create(expression);
        } else {
            return PropertyLocator.getDefaultInstance(expression);
        }
    }

    public Object getLocalValue() {
        return value;
    }

    public int getAutoFilterDelay() {
        FilterableComponent component = getFilteredComponent();
        int defaultValue = component != null ? component.getAutoFilterDelay() : Integer.MIN_VALUE;
        return ValueBindings.get(this, "autoFilterDelay", autoFilterDelay, defaultValue);
    }

    public void setAutoFilterDelay(int autoFilterDelay) {
        this.autoFilterDelay = autoFilterDelay;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = (ExpressionFilterCriterion) value;
    }

    public ExpressionFilterCriterion getCondition() {
        return condition;
    }

    /**
     *
     * @param condition
     */
    public void setCondition(ExpressionFilterCriterion condition) {
        if (condition.getPropertyLocator() != null) throw new IllegalArgumentException("The condition attribute should " +
                "receive ExpressionFilterCriterion with just \"condition\" and \"inverse\" attributes specified, but " +
                "propertyLocator was specified.");
        if (condition.getArg1() != null) throw new IllegalArgumentException("The condition attribute should " +
                "receive ExpressionFilterCriterion with just \"condition\" and \"inverse\" attributes specified, but " +
                "arg1 was specified.");
        FilterCondition filterCondition = condition.getCondition();
        if (filterCondition == null || filterCondition == FilterCondition.EMPTY || filterCondition == FilterCondition.BETWEEN) {
            String possibleConditionsStr = "";
            for (FilterCondition c : FilterCondition.values()) {
                if (c == FilterCondition.EMPTY || c == FilterCondition.BETWEEN)
                    continue;
                if (possibleConditionsStr.length() > 0)
                    possibleConditionsStr += ", ";
                String n = c.getName();
                possibleConditionsStr += n;
            }
            throw new FacesException("\"condition\" property value (\"" + value + "\") cannot be \"empty\" or \"between\" here. It should be one of: " + possibleConditionsStr);
        }
        this.condition = condition;
        setValue(new ExpressionFilterCriterion(condition.getCondition(), condition.isInverse()));
    }

    /**
     * @param newCriterion new search criterion
     * @return true if the new criterion results in the different filtering behavior as opposed to this filter's previous
     *         criterion
     */
    public boolean changeCriterion(ExpressionFilterCriterion newCriterion) {
        FilterCriterion oldCriterion = (FilterCriterion) getValue();
        criterionModelUpdateRequired = true;

        if (isAllRecordsCriterion(newCriterion)) {
            if (isAllRecordsCriterion(oldCriterion))
                return false;
        } else if (newCriterion.equals(oldCriterion))
            return false;
        setValue(newCriterion);
        return true;
    }

    private boolean isAllRecordsCriterion(FilterCriterion criterion) {
        return criterion == null || criterion.acceptsAll();
    }

    @Override
    public void processUpdates(FacesContext context) {
        super.processUpdates(context);
        if (!criterionModelUpdateRequired)
            return;

        ValueExpression criterionExpression = getValueExpression("value");
        if (criterionExpression != null) {
            criterionExpression.setValue(context.getELContext(), value);
            criterionModelUpdateRequired = false;
        }
    }

    public void createSubComponents(FacesContext context) {
    }

}
TOP

Related Classes of org.openfaces.component.filter.ExpressionFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.