/* * JBoss, Home of Professional Open Source * Copyright ${year}, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.richfaces.renderkit; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import javax.el.ELContext; import javax.el.ELException; import javax.el.ValueExpression; import javax.faces.FacesException; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import org.richfaces.component.AbstractColumn; import org.richfaces.component.SortOrder; import org.richfaces.component.UIDataTableBase; import org.richfaces.model.SortMode; import org.richfaces.validator.MessageFactory; /** * @author Anton Belevich * */ public abstract class SortingFilteringRowsRenderer extends AbstractRowsRenderer { private static final String FILTERING_STRING = "rich:filtering"; private static final String SORTING_STRING = "rich:sorting"; private static final String FILTER_VALUE_STRING = "filterValue"; private static final String SORT_ORDER_STRING = "sortOrder"; private static final String SORT_PRIORITY_STRING = "sortPriority"; private static final String SEPARATOR = ":"; protected void decodeSortingFiltering(FacesContext context, UIComponent component) { if (component instanceof UIDataTableBase) { UIDataTableBase dataTableBase = (UIDataTableBase) component; Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap(); String clientId = dataTableBase.getClientId(context); String filtering = requestMap.get(clientId + FILTERING_STRING); if (filtering != null && filtering.trim().length() > 0) { decodeFiltering(context, dataTableBase, filtering); } String sorting = requestMap.get(clientId + SORTING_STRING); if (sorting != null && sorting.trim().length() > 0) { decodeSorting(context, dataTableBase, sorting); } } } protected void decodeFiltering(FacesContext context, UIDataTableBase dataTableBase, String value) { String[] values = value.split(SEPARATOR); if (Boolean.parseBoolean(values[2])) { for (Iterator<UIComponent> iterator = dataTableBase.columns(); iterator.hasNext();) { UIComponent column = iterator.next(); if (values[0].equals(column.getId())) { updateAttribute(context, column, FILTER_VALUE_STRING, values[1]); } else { updateAttribute(context, column, FILTER_VALUE_STRING, null); } } } else { UIComponent child = dataTableBase.findComponent(values[0]); try { updateAttribute(context, child, FILTER_VALUE_STRING, values[1]); } catch (FacesException e) { if (child instanceof AbstractColumn && ((AbstractColumn)child).isBuiltInFilterControlsEnabled() && e.getCause() instanceof ELException) { addFilterConverterErrorMessage(context, (AbstractColumn) child, values[1], e); } else { throw e; } } } context.getPartialViewContext().getRenderIds().add(dataTableBase.getClientId(context)); // TODO Use partial re-rendering // here. } private void addFilterConverterErrorMessage(FacesContext context, AbstractColumn column, String submittedValue, Exception exception) { column.getAttributes().put("submittedFilterValue", submittedValue); FacesMessage message; String converterMessageString = column.getFilterConverterMessage(); if (null != converterMessageString) { message = new FacesMessage(FacesMessage.SEVERITY_ERROR, converterMessageString, converterMessageString); } else { message = MessageFactory.createMessage(context, "org.richfaces.BUILT_IN_FILTER_VALUE_CONVERSION_ERROR"); message.setSeverity(FacesMessage.SEVERITY_ERROR); message.setDetail(exception.getCause().getLocalizedMessage()); } context.addMessage(column.getClientId(), message); } protected void decodeSorting(FacesContext context, UIDataTableBase dataTableBase, String value) { Set<Object> sortPriority = new LinkedHashSet<Object>(); String[] values = value.split(SEPARATOR); String columnId = values[0]; String sortOrder = values[1]; boolean isClear = Boolean.parseBoolean(values[2]); if (isClear || SortMode.single.equals(dataTableBase.getSortMode())) { for (Iterator<UIComponent> iterator = dataTableBase.columns(); iterator.hasNext();) { UIComponent column = iterator.next(); if (columnId.equals(column.getId())) { updateSortOrder(context, column, sortOrder); sortPriority.add(columnId); } else { updateAttribute(context, column, SORT_ORDER_STRING, SortOrder.unsorted); } } } else { updateSortOrder(context, dataTableBase.findComponent(columnId), sortOrder); Collection<?> priority = dataTableBase.getSortPriority(); if (priority != null) { priority.remove(columnId); sortPriority.addAll(priority); } sortPriority.add(columnId); } updateAttribute(context, dataTableBase, SORT_PRIORITY_STRING, sortPriority); context.getPartialViewContext().getRenderIds().add(dataTableBase.getClientId(context)); } private void updateSortOrder(FacesContext context, UIComponent component, String value) { SortOrder sortOrder = SortOrder.ascending; try { sortOrder = SortOrder.valueOf(value); } catch (IllegalArgumentException e) { // If value isn't name of enum constant of SortOrder, toggle sortOrder of column. if (SortOrder.ascending.equals(component.getAttributes().get(SORT_ORDER_STRING))) { sortOrder = SortOrder.descending; } } updateAttribute(context, component, SORT_ORDER_STRING, sortOrder); } protected void updateAttribute(FacesContext context, UIComponent component, String attribute, Object value) { Object oldValue = component.getAttributes().get(attribute); if ((oldValue != null && !oldValue.equals(value)) || (oldValue == null && value != null)) { ELContext elContext = context.getELContext(); ValueExpression ve = component.getValueExpression(attribute); if (ve != null && !ve.isReadOnly(elContext)) { component.getAttributes().put(attribute, null); try { ve.setValue(elContext, value); } catch (ELException e) { throw new FacesException(e); } } else { component.getAttributes().put(attribute, value); } } } }