Package org.apache.myfaces.view.facelets.component

Source Code of org.apache.myfaces.view.facelets.component.UIRepeat$IndexedEvent

/*
* 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.myfaces.view.facelets.component;

import java.io.IOException;
import java.io.Serializable;
import java.sql.ResultSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.component.ContextCallback;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIData;
import javax.faces.component.UINamingContainer;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;
import javax.faces.event.PhaseId;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.ResultSetDataModel;
import javax.faces.model.ScalarDataModel;
import javax.faces.render.Renderer;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;

/**
* TODO: PartialStateSaving and pluginize this component!
*/
@JSFComponent(name="ui:repeat", defaultRendererType="facelets.ui.Repeat")
public class UIRepeat extends UIComponentBase implements NamingContainer
{
    public static final String COMPONENT_TYPE = "facelets.ui.Repeat";

    public static final String COMPONENT_FAMILY = "facelets";
   
    private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";

    private final static DataModel<?> EMPTY_MODEL = new ListDataModel<Object>(Collections.emptyList());

    private final static SavedState NULL_STATE = new SavedState();

    private Map<String, SavedState> _childState;

    // our data
    private Object _value;

    // variables
    private String _var;
   
    private int _end = -1;
   
    private int _count;
   
    private int _index = -1;

    // scoping
    private int _offset = -1;

    private int _size = -1;
   
    private int _step = -1;
   
    private String _varStatus;
   
    private transient StringBuffer _buffer;
    private transient DataModel<?> _model;
    private transient Object _origValue;
    private transient Object _origVarStatus;

    private transient FacesContext _facesContext;
   
    public UIRepeat()
    {
        setRendererType("facelets.ui.Repeat");
    }

    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }
   
    @JSFProperty
    public int getOffset()
    {
        if (_offset != -1)
        {
            return _offset;
        }
       
        ValueExpression ve = getValueExpression("offset");
        if (ve != null)
        {
            return ((Integer)ve.getValue(getFacesContext().getELContext())).intValue();
        }
       
        return 0;
    }

    public void setOffset(int offset)
    {
        _offset = offset;
    }
   
    @JSFProperty
    public int getSize()
    {
        if (_size != -1)
        {
            return _size;
        }
       
        ValueExpression ve = getValueExpression("size");
        if (ve != null)
        {
            return ((Integer)ve.getValue(getFacesContext().getELContext())).intValue();
        }
       
        return -1;
    }

    public void setSize(int size)
    {
        _size = size;
    }
   
    @JSFProperty
    public int getStep()
    {
        if (_step != -1)
        {
            return _step;
        }
       
        ValueExpression ve = getValueExpression("step");
        if (ve != null)
        {
            return ((Integer)ve.getValue(getFacesContext().getELContext())).intValue();
        }
       
        return 1;
    }

    public void setStep(int step)
    {
        _step = step;
    }
   
    @JSFProperty
    public String getVar()
    {
        return _var;
    }

    public void setVar(String var)
    {
        _var = var;
    }
   
    @JSFProperty
    public String getVarStatus ()
    {
        return _varStatus;
    }
   
    public void setVarStatus (String varStatus)
    {
        _varStatus = varStatus;
    }
   
    private synchronized void setDataModel(DataModel<?> model)
    {
        _model = model;
    }

    @SuppressWarnings("unchecked")
    private synchronized DataModel<?> getDataModel()
    {
        if (_model == null)
        {
            Object val = getValue();
            if (val == null)
            {
                _model = EMPTY_MODEL;
            }
            else if (val instanceof DataModel)
            {
                _model = (DataModel<?>) val;
            }
            else if (val instanceof List)
            {
                _model = new ListDataModel<Object>((List<Object>) val);
            }
            else if (Object[].class.isAssignableFrom(val.getClass()))
            {
                _model = new ArrayDataModel<Object>((Object[]) val);
            }
            else if (val instanceof ResultSet)
            {
                _model = new ResultSetDataModel((ResultSet) val);
            }
            else
            {
                _model = new ScalarDataModel(val);
            }
        }
        return _model;
    }
   
    @JSFProperty
    public Object getValue()
    {
        if (_value == null)
        {
            ValueExpression ve = getValueExpression("value");
            if (ve != null)
            {
                return ve.getValue(getFacesContext().getELContext());
            }
        }
       
        return _value;
    }

    public void setValue(Object value)
    {
        _value = value;
    }

    /*
    @Override
    public String getClientId(FacesContext faces)
    {
        String id = super.getClientId(faces);
        if (_index >= 0)
        {
            id = _getBuffer().append(id).append(UINamingContainer.getSeparatorChar(faces)).append(_index).toString();
        }
        return id;
    }*/
   
    @Override
    public String getContainerClientId(FacesContext faces)
    {
        String id = super.getContainerClientId(faces);
        if (_index >= 0)
        {
            id = _getBuffer().append(id).append(UINamingContainer.getSeparatorChar(faces)).append(_index).toString();
        }
        return id;
    }
   
    private RepeatStatus _getRepeatStatus()
    {
        return new RepeatStatus(_count == 0, _index + getStep() >= getDataModel().getRowCount(),
            _count, _index, getOffset(), _end, getStep());
    }

    private void _captureScopeValues()
    {
        if (_var != null)
        {
            _origValue = getFacesContext().getExternalContext().getRequestMap().get(_var);
        }
        if (_varStatus != null)
        {
            _origVarStatus = getFacesContext().getExternalContext().getRequestMap().get(_varStatus);
        }
    }
   
    private StringBuffer _getBuffer()
    {
        if (_buffer == null)
        {
            _buffer = new StringBuffer();
        }
       
        _buffer.setLength(0);
       
        return _buffer;
    }

    private Map<String, SavedState> _getChildState()
    {
        if (_childState == null)
        {
            _childState = new HashMap<String, SavedState>();
        }
       
        return _childState;
    }

    private boolean _isIndexAvailable()
    {
        return getDataModel().isRowAvailable();
    }

    private boolean _isNestedInIterator()
    {
        UIComponent parent = getParent();
        while (parent != null)
        {
            if (parent instanceof UIData || parent instanceof UIRepeat)
            {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }

    private boolean _keepSaved(FacesContext context)
    {
        for (String clientId : _getChildState().keySet())
        {
            // Perf: messages are instances of arrayList (or Collections.emptyList): see Method org.apache.myfaces.context.servlet.FacesContextImpl.addMessage(String, FacesMessage)
            List<FacesMessage> messageList = context.getMessageList(clientId);
            for (int i = 0, size = messageList.size(); i < size; i++)
            {
                FacesMessage message = messageList.get(i);
                if (message.getSeverity().compareTo(FacesMessage.SEVERITY_ERROR) >= 0)
                {
                    return true;
                }
            }
        }
       
        return _isNestedInIterator();
    }

    private void _resetDataModel()
    {
        if (_isNestedInIterator())
        {
            setDataModel(null);
        }
    }

    private void _restoreScopeValues()
    {
        if (_var != null)
        {
            Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
            if (_origValue != null)
            {
                attrs.put(_var, _origValue);
                _origValue = null;
            }
            else
            {
                attrs.remove(_var);
            }
        }
        if (_varStatus != null)
        {
            Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
            if (_origVarStatus != null)
            {
                attrs.put(_varStatus, _origVarStatus);
                _origVarStatus = null;
            }
            else
            {
                attrs.remove(_varStatus);
            }
        }
    }
   
    private void _restoreChildState()
    {
        if (getChildCount() > 0)
        {
            FacesContext context = getFacesContext();
            for (int i = 0, childCount = getChildCount(); i < childCount; i++)
            {
                UIComponent child = getChildren().get(i);
                _restoreChildState(context, child);
            }
        }
    }

    private void _restoreChildState(FacesContext faces, UIComponent c)
    {
        // reset id
        String id = c.getId();
        c.setId(id);

        // hack
        if (c instanceof EditableValueHolder)
        {
            EditableValueHolder evh = (EditableValueHolder) c;
            String clientId = c.getClientId(faces);
            SavedState ss = _getChildState().get(clientId);
            if (ss != null)
            {
                ss.apply(evh);
            }
            else
            {
                NULL_STATE.apply(evh);
            }
        }

        // continue hack
        if (c.getFacetCount() > 0)
        {
            for (UIComponent facet : c.getFacets().values())
            {
                _restoreChildState(faces, facet);
            }
        }
        int childCount = c.getChildCount();
        if (childCount > 0)
        {
            for (int i = 0; i < childCount; i++)
            {
                UIComponent child = c.getChildren().get(i);
                _restoreChildState(faces, child);
            }
        }
    }

    private void _saveChildState()
    {
        if (getChildCount() > 0)
        {
            FacesContext context = getFacesContext();
            for (int i = 0, childCount = getChildCount(); i < childCount; i++)
            {
                UIComponent child = getChildren().get(i);
                _saveChildState(context, child);
            }
        }
    }

    private void _saveChildState(FacesContext faces, UIComponent c)
    {
        if (c instanceof EditableValueHolder && !c.isTransient())
        {
            String clientId = c.getClientId(faces);
            SavedState ss = (SavedState) _getChildState().get(clientId);
            if (ss == null)
            {
                ss = new SavedState();
                _getChildState().put(clientId, ss);
            }
           
            ss.populate((EditableValueHolder) c);
        }

        // continue hack
        if (c.getFacetCount() > 0)
        {
            for (UIComponent facet : c.getFacets().values())
            {
                _saveChildState(faces, facet);
            }
        }
        int childCount = c.getChildCount();
        if (childCount > 0)
        {
            for (int i = 0; i < childCount; i++)
            {
                UIComponent child = c.getChildren().get(i);
                _saveChildState(faces, child);
            }
        }
    }
   
    /**
     * Returns the rowCount of the underlying DataModel.
     * @return
     */
    public int getRowCount()
    {
        return getDataModel().getRowCount();
    }
   
    /**
     * Returns the current index.
     */
    public int getIndex()
    {
        return _index;
    }
   
    private void _setIndex(int index)
    {
        // save child state
        _saveChildState();

        _index = index;
       
        DataModel<?> localModel = getDataModel();
        localModel.setRowIndex(index);

        if (_index != -1)
        {
            if (_var != null && localModel.isRowAvailable())
            {
                getFacesContext().getExternalContext().getRequestMap()
                        .put(_var, localModel.getRowData());
            }
            if (_varStatus != null)
            {
                getFacesContext().getExternalContext().getRequestMap()
                        .put(_varStatus, _getRepeatStatus());
            }
        }

        // restore child state
        _restoreChildState();
    }
   
    /**
     * Calculates the count value for the given index.
     * @param index
     * @return
     */
    private int _calculateCountForIndex(int index)
    {
        return (index - getOffset()) / getStep();
    }

    private void _validateAttributes() throws FacesException
    {
        int begin = getOffset();
        int end = getDataModel().getRowCount();
        int size = getSize();
        int step = getStep();
        boolean sizeIsEnd = false;

        if (size == -1)
        {
            size = end;
            sizeIsEnd = true;
        }

        if (end >= 0)
        {
            if (size < 0)
            {
                throw new FacesException("iteration size cannot be less " +
                        "than zero");
            }

            else if (!sizeIsEnd && (begin + size) > end)
            {
                throw new FacesException("iteration size cannot be greater " +
                        "than collection size");
            }
        }

        if ((size > -1) && (begin > end))
        {
            throw new FacesException("iteration offset cannot be greater " +
                    "than collection size");
        }

        if (step == -1)
        {
            step = 1;
        }

        if (step < 0)
        {
            throw new FacesException("iteration step size cannot be less " +
                    "than zero");
        }

        else if (step == 0)
        {
            throw new FacesException("iteration step size cannot be equal " +
                    "to zero");
        }

        _end = size;
        _step = step;
    }

    public void process(FacesContext faces, PhaseId phase)
    {
        // stop if not rendered
        if (!isRendered())
        {
            return;
        }
       
        // validate attributes
        _validateAttributes();
       
        // clear datamodel
        _resetDataModel();

        // reset index
        _captureScopeValues();
        _setIndex(-1);

        try
        {
            // has children
            if (getChildCount() > 0)
            {
                int i = getOffset();
                int end = getSize();
                int step = getStep();
                end = (end >= 0) ? i + end : Integer.MAX_VALUE - 1;
               
                // grab renderer
                String rendererType = getRendererType();
                Renderer renderer = null;
                if (rendererType != null)
                {
                    renderer = getRenderer(faces);
                }
               
                _count = 0;
               
                _setIndex(i);
                while (i <= end && _isIndexAvailable())
                {

                    if (PhaseId.RENDER_RESPONSE.equals(phase) && renderer != null)
                    {
                        renderer.encodeChildren(faces, this);
                    }
                    else
                    {
                        for (int j = 0, childCount = getChildCount(); j < childCount; j++)
                        {
                            UIComponent child = getChildren().get(j);
                            if (PhaseId.APPLY_REQUEST_VALUES.equals(phase))
                            {
                                child.processDecodes(faces);
                            }
                            else if (PhaseId.PROCESS_VALIDATIONS.equals(phase))
                            {
                                child.processValidators(faces);
                            }
                            else if (PhaseId.UPDATE_MODEL_VALUES.equals(phase))
                            {
                                child.processUpdates(faces);
                            }
                            else if (PhaseId.RENDER_RESPONSE.equals(phase))
                            {
                                child.encodeAll(faces);
                            }
                        }
                    }
                   
                    ++_count;
                   
                    i += step;
                   
                    _setIndex(i);
                }
            }
        }
        catch (IOException e)
        {
            throw new FacesException(e);
        }
        finally
        {
            _setIndex(-1);
            _restoreScopeValues();
        }
    }

    @Override
    public boolean invokeOnComponent(FacesContext context, String clientId,
            ContextCallback callback) throws FacesException
    {
        if (context == null || clientId == null || callback == null)
        {
            throw new NullPointerException();
        }
       
        final String baseClientId = getClientId(context);

        // searching for this component?
        boolean returnValue = baseClientId.equals(clientId);

        boolean isCachedFacesContext = isTemporalFacesContext();
        if (!isCachedFacesContext)
        {
            setTemporalFacesContext(context);
        }

        pushComponentToEL(context, this);
        try
        {
            if (returnValue)
            {
                try
                {
                    callback.invokeContextCallback(context, this);
                    return true;
                }
                catch (Exception e)
                {
                    throw new FacesException(e);
                }
            }
   
            // Now Look throught facets on this UIComponent
            if (this.getFacetCount() > 0)
            {
                for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
                {
                    returnValue = it.next().invokeOnComponent(context, clientId, callback);
                }
            }
   
            if (returnValue)
            {
                return returnValue;
            }
           
            // is the component an inner component?
            if (clientId.startsWith(baseClientId))
            {
                // Check if the clientId for the component, which we
                // are looking for, has a rowIndex attached
                char separator = UINamingContainer.getSeparatorChar(context);
                String subId = clientId.substring(baseClientId.length() + 1);
                //If the char next to baseClientId is the separator one and
                //the subId matches the regular expression
                if (clientId.charAt(baseClientId.length()) == separator &&
                        subId.matches("[0-9]+"+separator+".*"))
                {
                    String clientRow = subId.substring(0, subId.indexOf(separator));
       
                    // safe the current index, count aside
                    final int prevIndex = _index;
                    final int prevCount = _count;
                   
                    try
                    {
                        int invokeIndex = Integer.parseInt(clientRow);
                        // save the current scope values and set the right index
                        _captureScopeValues();
                        if (invokeIndex != -1)
                        {
                            // calculate count for RepeatStatus
                            _count = _calculateCountForIndex(invokeIndex);
                        }
                        _setIndex(invokeIndex);
                       
                        if (!_isIndexAvailable())
                        {
                            return false;
                        }
                       
                        for (Iterator<UIComponent> it1 = getChildren().iterator();
                            !returnValue && it1.hasNext();)
                        {
                            //recursive call to find the component
                            returnValue = it1.next().invokeOnComponent(context, clientId, callback);
                        }
                    }
                    finally
                    {
                        // restore the previous count, index and scope values
                        _count = prevCount;
                        _setIndex(prevIndex);
                        _restoreScopeValues();
                    }
                }
                else
                {
                    // Searching for this component's children
                    if (this.getChildCount() > 0)
                    {
                        // Searching for this component's children/facets
                        for (Iterator<UIComponent> it = this.getChildren().iterator(); !returnValue && it.hasNext();)
                        {
                            returnValue = it.next().invokeOnComponent(context, clientId, callback);
                        }
                    }
                }
            }
        }
        finally
        {
            //all components must call popComponentFromEl after visiting is finished
            popComponentFromEL(context);
            if (!isCachedFacesContext)
            {
                setTemporalFacesContext(null);
            }
        }

        return returnValue;
    }
   
    @Override
    protected FacesContext getFacesContext()
    {
        if (_facesContext == null)
        {
            return super.getFacesContext();
        }
        else
        {
            return _facesContext;
        }
    }
   
    private boolean isTemporalFacesContext()
    {
        return _facesContext != null;
    }
   
    private void setTemporalFacesContext(FacesContext facesContext)
    {
        _facesContext = facesContext;
    }

    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback)
    {
        // override the behavior from UIComponent to visit
        // all children once per "row"
       
        Boolean skipIterationHint = (Boolean) context.getFacesContext().getAttributes().get(SKIP_ITERATION_HINT);
        if (skipIterationHint != null && skipIterationHint.booleanValue())
        {
            return super.visitTree(context, callback);
        }
       
        if (!isVisitable(context))
        {
            return false;
        }
       
        // save the current index, count aside
        final int prevIndex = _index;
        final int prevCount = _count;
       
        // validate attributes
        _validateAttributes();
       
        // clear datamodel
        _resetDataModel();

        // reset index and save scope values
        _captureScopeValues();
        _setIndex(-1);
       
        // push the Component to EL
        pushComponentToEL(context.getFacesContext(), this);
        try
        {
            VisitResult res = context.invokeVisitCallback(this, callback);
            switch (res)
            {
            // we are done, nothing has to be processed anymore
            case COMPLETE:
                return true;

            case REJECT:
                return false;

            //accept
            default:
                // determine if we need to visit our children
                // Note that we need to do this check because we are a NamingContainer
                Collection<String> subtreeIdsToVisit = context
                        .getSubtreeIdsToVisit(this);
                boolean doVisitChildren = subtreeIdsToVisit != null
                        && !subtreeIdsToVisit.isEmpty();
                if (doVisitChildren)
                {
                    // visit the facets of the component
                    if (getFacetCount() > 0)
                    {
                        for (UIComponent facet : getFacets().values())
                        {
                            if (facet.visitTree(context, callback))
                            {
                                return true;
                            }
                        }
                    }
                   
                    // visit the children once per "row"
                    if (getChildCount() > 0)
                    {
                        int i = getOffset();
                        int end = getSize();
                        int step = getStep();
                        end = (end >= 0) ? i + end : Integer.MAX_VALUE - 1;
                        _count = 0;
                       
                        _setIndex(i);
                        while (i <= end && _isIndexAvailable())
                        {
                            for (int j = 0, childCount = getChildCount(); j < childCount; j++)
                            {
                                UIComponent child = getChildren().get(j);
                                if (child.visitTree(context, callback))
                                {
                                    return true;
                                }
                            }
                           
                            _count++;
                            i += step;
                           
                            _setIndex(i);
                        }
                    }
                }
                return false;
            }
        }
        finally
        {
            // pop the component from EL
            popComponentFromEL(context.getFacesContext());
           
            // restore the previous count, index and scope values
            _count = prevCount;
            _setIndex(prevIndex);
            _restoreScopeValues();
        }
    }

    @Override
    public void processDecodes(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
       
        setDataModel(null);
        if (!_keepSaved(faces))
        {
            _childState = null;
        }
       
        process(faces, PhaseId.APPLY_REQUEST_VALUES);
        decode(faces);
    }

    @Override
    public void processUpdates(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
       
        _resetDataModel();
        process(faces, PhaseId.UPDATE_MODEL_VALUES);
    }

    @Override
    public void processValidators(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
       
        _resetDataModel();
        process(faces, PhaseId.PROCESS_VALIDATIONS);
    }

    // from RI
    private final static class SavedState implements Serializable
    {
        private boolean _localValueSet;
        private Object _submittedValue;
        private boolean _valid = true;
        private Object _value;

        private static final long serialVersionUID = 2920252657338389849L;

        Object getSubmittedValue()
        {
            return (_submittedValue);
        }

        void setSubmittedValue(Object submittedValue)
        {
            _submittedValue = submittedValue;
        }

        boolean isValid()
        {
            return (_valid);
        }

        void setValid(boolean valid)
        {
            _valid = valid;
        }

        Object getValue()
        {
            return _value;
        }

        public void setValue(Object value)
        {
            _value = value;
        }

        boolean isLocalValueSet()
        {
            return _localValueSet;
        }

        public void setLocalValueSet(boolean localValueSet)
        {
            _localValueSet = localValueSet;
        }

        @Override
        public String toString()
        {
            return ("submittedValue: " + _submittedValue + " value: " + _value + " localValueSet: " + _localValueSet);
        }

        public void populate(EditableValueHolder evh)
        {
            _value = evh.getLocalValue();
            _valid = evh.isValid();
            _submittedValue = evh.getSubmittedValue();
            _localValueSet = evh.isLocalValueSet();
        }

        public void apply(EditableValueHolder evh)
        {
            evh.setValue(_value);
            evh.setValid(_valid);
            evh.setSubmittedValue(_submittedValue);
            evh.setLocalValueSet(_localValueSet);
        }
    }

    private final class IndexedEvent extends FacesEvent
    {
        private final FacesEvent _target;

        private final int _index;

        public IndexedEvent(UIRepeat owner, FacesEvent target, int index)
        {
            super(owner);
            _target = target;
            _index = index;
        }

        @Override
        public PhaseId getPhaseId()
        {
            return _target.getPhaseId();
        }

        @Override
        public void setPhaseId(PhaseId phaseId)
        {
            _target.setPhaseId(phaseId);
        }

        public boolean isAppropriateListener(FacesListener listener)
        {
            return _target.isAppropriateListener(listener);
        }

        public void processListener(FacesListener listener)
        {
            UIRepeat owner = (UIRepeat) getComponent();
           
            // safe the current index, count aside
            final int prevIndex = owner._index;
            final int prevCount = owner._count;
           
            try
            {
                owner._captureScopeValues();
                if (this._index != -1)
                {
                    // calculate count for RepeatStatus
                    _count = _calculateCountForIndex(this._index);
                }
                owner._setIndex(this._index);
                if (owner._isIndexAvailable())
                {
                    _target.processListener(listener);
                }
            }
            finally
            {
                // restore the previous count, index and scope values
                owner._count = prevCount;
                owner._setIndex(prevIndex);
                owner._restoreScopeValues();
            }
        }

        public int getIndex()
        {
            return _index;
        }

        public FacesEvent getTarget()
        {
            return _target;
        }

    }

    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException
    {
        if (event instanceof IndexedEvent)
        {
            IndexedEvent idxEvent = (IndexedEvent) event;
            _resetDataModel();
           
            // safe the current index, count aside
            final int prevIndex = _index;
            final int prevCount = _count;
           
            try
            {
                _captureScopeValues();
                if (idxEvent.getIndex() != -1)
                {
                    // calculate count for RepeatStatus
                    _count = _calculateCountForIndex(idxEvent.getIndex());
                }
                _setIndex(idxEvent.getIndex());
                if (_isIndexAvailable())
                {
                    // get the target FacesEvent
                    FacesEvent target = idxEvent.getTarget();
                    FacesContext facesContext = getFacesContext();
                   
                    // get the component associated with the target event and push
                    // it and its composite component parent, if available, to the
                    // component stack to have them available while processing the
                    // event (see also UIViewRoot._broadcastAll()).
                    UIComponent targetComponent = target.getComponent();
                    UIComponent compositeParent = UIComponent
                            .getCompositeComponentParent(targetComponent);
                    if (compositeParent != null)
                    {
                        pushComponentToEL(facesContext, compositeParent);
                    }
                    pushComponentToEL(facesContext, targetComponent);
                   
                    try
                    {
                        // actual event broadcasting
                        targetComponent.broadcast(target);
                    }
                    finally
                    {
                        // remove the components from the stack again
                        popComponentFromEL(facesContext);
                        if (compositeParent != null)
                        {
                            popComponentFromEL(facesContext);
                        }
                    }
                }
            }
            finally
            {
                // restore the previous count, index and scope values
                _count = prevCount;
                _setIndex(prevIndex);
                _restoreScopeValues();
            }
        }
        else
        {
            super.broadcast(event);
        }
    }

    @Override
    public void queueEvent(FacesEvent event)
    {
        super.queueEvent(new IndexedEvent(this, event, _index));
    }

    @SuppressWarnings("unchecked")
    @Override
    public void restoreState(FacesContext faces, Object object)
    {
        Object[] state = (Object[]) object;
        super.restoreState(faces, state[0]);
        _childState = (Map<String, SavedState>) state[1];
        _offset = ((Integer) state[2]).intValue();
        _size = ((Integer) state[3]).intValue();
        _var = (String) state[4];
        _value = state[5];
        _varStatus = (String) state[6];
    }

    @Override
    public Object saveState(FacesContext faces)
    {
        Object[] state = new Object[7];
        state[0] = super.saveState(faces);
        state[1] = _childState;
        state[2] = Integer.valueOf(_offset);
        state[3] = Integer.valueOf(_size);
        state[4] = _var;
        state[5] = _value;
        state[6] = _varStatus;
        return state;
    }

    @Override
    public void encodeChildren(FacesContext faces) throws IOException
    {
        if (!isRendered())
        {
            return;
        }
       
        setDataModel(null);
       
        if (!_keepSaved(faces))
        {
            _childState = null;
        }
       
        process(faces, PhaseId.RENDER_RESPONSE);
    }

    @Override
    public boolean getRendersChildren()
    {
        if (getRendererType() != null)
        {
            Renderer renderer = getRenderer(getFacesContext());
            if (renderer != null)
            {
                return renderer.getRendersChildren();
            }
        }
       
        return true;
    }
}
TOP

Related Classes of org.apache.myfaces.view.facelets.component.UIRepeat$IndexedEvent

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.