org.richfaces.component.RenderPhaseDataScrollerVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.richfaces.component.RenderPhaseDataScrollerVisitor.java

Source

/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.richfaces.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.el.Expression;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;

import org.ajax4jsf.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.component.util.MessageUtil;
import org.richfaces.event.RenderPhaseComponentVisitor;

/**
 * Created 08.03.2008
 * @author Nick Belaevski
 * @since 3.2
 */

public class RenderPhaseDataScrollerVisitor implements RenderPhaseComponentVisitor {

    private class State {

        private ComponentConnections connections;
        private LinkedList<UIComponent> components;

        private State(LinkedList<UIComponent> components, ComponentConnections connections) {
            this.components = components;
            this.connections = connections;
        }
    }

    private static final class ComponentConnections {
        private final Map<UIData, List<UIDatascroller>> map = new HashMap<UIData, List<UIDatascroller>>();

        public void addConnection(UIData one, UIDatascroller multi) {
            List<UIDatascroller> list = map.get(one);
            if (list == null) {
                list = new ArrayList<UIDatascroller>(1);
                map.put(one, list);
            }

            list.add(multi);
        }

        public Iterator<Entry<UIData, List<UIDatascroller>>> iterator() {
            return map.entrySet().iterator();
        }

        @Override
        public String toString() {
            return this.getClass().getSimpleName() + ": " + map;
        }
    }

    private static final Log log = LogFactory.getLog(RenderPhaseDataScrollerVisitor.class);

    public Object beforeRoot(PhaseEvent event) {
        return new State(new LinkedList<UIComponent>(), new ComponentConnections());
    }

    public void beforeComponent(UIComponent component, PhaseEvent event, Object object) {
        State state = (State) object;
        state.components.addLast(component);

        if (component instanceof UIDatascroller && isRendered(state.components)) {
            UIDatascroller datascroller = (UIDatascroller) component;
            UIData dataTable = datascroller.getDataTable();

            state.connections.addConnection(dataTable, datascroller);
        }
    }

    public void afterComponent(UIComponent component, PhaseEvent event, Object object) {
        State state = (State) object;
        state.components.removeLast();
    }

    public void afterRoot(PhaseEvent event, Object object) {
        State state = (State) object;
        FacesContext facesContext = event.getFacesContext();
        Iterator<Entry<UIData, List<UIDatascroller>>> entries = state.connections.iterator();

        while (entries.hasNext()) {
            Entry<UIData, List<UIDatascroller>> entry = entries.next();
            List<UIDatascroller> scrollers = entry.getValue();
            if (!scrollers.isEmpty()) {
                List<Object> values = new ArrayList<Object>(scrollers.size());

                UIData data = entry.getKey();
                UIDatascroller activeComponent = null;

                Map<String, Object> attributes = data.getAttributes();
                Object pageValue = attributes.get(UIDatascroller.SCROLLER_STATE_ATTRIBUTE);

                if (pageValue == null) {
                    boolean valid = true;

                    for (UIDatascroller datascroller : scrollers) {
                        Object nextPageValue = null;

                        if (datascroller.isLocalPageSet()) {
                            nextPageValue = datascroller.getPage();
                            attributes.put(UIDatascroller.SCROLLER_STATE_ATTRIBUTE, nextPageValue);
                            datascroller.resetLocalPage();
                        } else {
                            nextPageValue = datascroller.getValueExpression("page");
                        }

                        if (!values.isEmpty() && !same(values.get(values.size() - 1), nextPageValue)) {
                            valid = false;
                        }

                        values.add(nextPageValue);

                        if (nextPageValue != null) {
                            activeComponent = datascroller;
                            pageValue = nextPageValue;
                        }
                    }

                    if (!valid) {
                        StringBuilder builder = new StringBuilder("\n[");
                        Iterator<UIDatascroller> scrollerItr = scrollers.iterator();
                        Iterator<Object> valueItr = values.iterator();

                        while (scrollerItr.hasNext()) {
                            UIDatascroller next = scrollerItr.next();
                            builder.append(MessageUtil.getLabel(facesContext, next));
                            builder.append(": ");

                            Object value = valueItr.next();
                            if (value instanceof Expression) {
                                builder.append(((Expression) value).getExpressionString());
                            } else {
                                builder.append(value);
                            }

                            builder.append(scrollerItr.hasNext() ? ",\n" : "]");
                        }

                        String formattedMessage = Messages.getMessage(Messages.DATASCROLLER_PAGES_DIFFERENT,
                                new Object[] { MessageUtil.getLabel(facesContext, data), builder });

                        log.error(formattedMessage);
                    }

                }

                if (activeComponent == null) {
                    activeComponent = scrollers.get(scrollers.size() - 1);
                }

                if (pageValue != null) {
                    activeComponent.setupFirstRowValue();
                }
            }
        }
    }

    private static boolean isRendered(List<UIComponent> components) {
        boolean rendered;

        for (UIComponent component : components) {
            rendered = false;

            try {
                rendered = component.isRendered();
            } catch (Exception e) {
                //ignore that
                if (log.isDebugEnabled()) {
                    log.debug(e.getLocalizedMessage(), e);
                }
            }

            if (!rendered) {
                return false;
            }
        }

        return true;
    }

    private static boolean same(Object o1, Object o2) {
        if (o1 instanceof ValueExpression && o2 instanceof ValueExpression) {
            ValueExpression ve1 = (ValueExpression) o1;
            ValueExpression ve2 = (ValueExpression) o2;

            if (same(ve1.getExpressionString(), ve2.getExpressionString())
                    && same(ve1.getExpectedType(), ve2.getExpectedType())) {
                return true;
            }
        }

        return (o1 != null && o1.equals(o2)) || (o1 == null && o2 == null);
    }
}