[richfaces-svn-commits] JBoss Rich Faces SVN: r1427 - in branches/refactor1: framework/impl/src/main/java/org/ajax4jsf/ajax/repeat and 1 other directories.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Fri Jun 29 20:03:04 EDT 2007


Author: alexsmirnov
Date: 2007-06-29 20:03:04 -0400 (Fri, 29 Jun 2007)
New Revision: 1427

Added:
   branches/refactor1/framework/impl/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java
Removed:
   branches/refactor1/framework/api/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java
Modified:
   branches/refactor1/ui/core/src/main/java/org/ajax4jsf/renderkit/html/RepeatRenderer.java
Log:
move UIDataAdaptor into implementation project

Deleted: branches/refactor1/framework/api/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java
===================================================================
--- branches/refactor1/framework/api/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java	2007-06-29 23:59:08 UTC (rev 1426)
+++ branches/refactor1/framework/api/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java	2007-06-30 00:03:04 UTC (rev 1427)
@@ -1,1322 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * 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.ajax4jsf.ajax.repeat;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.faces.FacesException;
-import javax.faces.application.FacesMessage;
-import javax.faces.component.EditableValueHolder;
-import javax.faces.component.NamingContainer;
-import javax.faces.component.StateHolder;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIData;
-import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
-import javax.faces.event.AbortProcessingException;
-import javax.faces.event.FacesEvent;
-import javax.faces.event.FacesListener;
-import javax.faces.event.PhaseId;
-import javax.faces.model.DataModel;
-import javax.faces.model.ListDataModel;
-import javax.faces.render.Renderer;
-
-import org.ajax4jsf.framework.renderer.AjaxRenderer;
-
-/**
- * Base class for iterable components, like dataTable, Tomahawk dataList,
- * Facelets repeat, tree etc., with support for partial rendering on AJAX
- * responces for one or more selected iterations.
- * 
- * @author shura
- * 
- */
-public abstract class UIDataAdaptor extends UIData implements AjaxDataEncoder {
-
-    /**
-         * 
-         */
-    public static final String COMPONENT_STATE_ATTRIBUTE = "componentState";
-
-    public final static DataModel EMPTY_MODEL = new ListDataModel(
-	    Collections.EMPTY_LIST);
-
-    /**
-         * Base class for visit data model at phases decode, validation and
-         * update model
-         * 
-         * @author shura
-         * 
-         */
-    protected abstract class ComponentVisitor implements DataVisitor {
-
-	public void process(FacesContext context, Object rowKey, Object argument)
-		throws IOException {
-	    setRowKey(context, rowKey);
-	    if (isRowAvailable()) {
-		Iterator childIterator = dataChildren();
-		while (childIterator.hasNext()) {
-		    UIComponent component = (UIComponent) childIterator.next();
-		    processComponent(context, component, argument);
-		}
-
-	    }
-	}
-
-	public abstract void processComponent(FacesContext context,
-		UIComponent c, Object argument) throws IOException;
-
-    }
-
-    /**
-         * Visitor for process decode on children components.
-         */
-    protected ComponentVisitor decodeVisitor = new ComponentVisitor() {
-
-	public void processComponent(FacesContext context, UIComponent c,
-		Object argument) {
-	    c.processDecodes(context);
-	}
-
-    };
-
-    /**
-         * Visitor for process validation phase
-         */
-    protected ComponentVisitor validateVisitor = new ComponentVisitor() {
-
-	public void processComponent(FacesContext context, UIComponent c,
-		Object argument) {
-	    c.processValidators(context);
-	}
-
-    };
-
-    /**
-         * Visitor for process update model phase.
-         */
-    protected ComponentVisitor updateVisitor = new ComponentVisitor() {
-
-	public void processComponent(FacesContext context, UIComponent c,
-		Object argument) {
-	    c.processUpdates(context);
-	}
-
-    };
-
-    /**
-         * Base client id's of this component, for wich invoked encode...
-         * methods. Component will save state and serialisable models for this
-         * keys only.
-         */
-    private Set _encoded;
-
-    /**
-         * Storage for data model instances with different client id's of this
-         * component. In case of child for UIData component, this map will keep
-         * data models for different iterations between phases.
-         */
-    private Map _modelsMap = new HashMap();
-
-    /**
-         * Reference for curent data model
-         */
-    private ExtendedDataModel _currentModel = null;
-
-    /**
-         * States of this component for diferent iterations, same as for models.
-         */
-    private Map _statesMap = new HashMap();
-
-    /**
-         * Reference for current component state.
-         */
-    private DataComponentState _currentState = null;
-
-    /**
-         * Name of EL variable for current component state.
-         */
-    private String _stateVar;
-
-    private String _rowKeyVar;
-
-    /**
-         * Key for current value in model.
-         */
-    private Object _rowKey = null;
-
-    /**
-         * Values of row keys, encoded on ajax response rendering.
-         */
-    private Set _ajaxKeys = null;
-
-    private Object _ajaxRowKey = null;
-
-    private Map _ajaxRowKeysMap = new HashMap();
-
-    /**
-         * Get name of EL variable for component state.
-         * 
-         * @return the varState
-         */
-    public String getStateVar() {
-	return _stateVar;
-    }
-
-    /**
-         * @param varStatus
-         *                the varStatus to set
-         */
-    public void setStateVar(String varStatus) {
-	this._stateVar = varStatus;
-    }
-
-    /**
-         * @return the rowKeyVar
-         */
-    public String getRowKeyVar() {
-	return this._rowKeyVar;
-    }
-
-    /**
-         * @param rowKeyVar
-         *                the rowKeyVar to set
-         */
-    public void setRowKeyVar(String rowKeyVar) {
-	this._rowKeyVar = rowKeyVar;
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#getRowCount()
-         */
-    public int getRowCount() {
-	return getExtendedDataModel().getRowCount();
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#getRowData()
-         */
-    public Object getRowData() {
-	return getExtendedDataModel().getRowData();
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#isRowAvailable()
-         */
-    public boolean isRowAvailable() {
-	return this.getExtendedDataModel().isRowAvailable();
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#setRowIndex(int)
-         */
-    public void setRowIndex(int index) {
-	FacesContext faces = FacesContext.getCurrentInstance();
-	ExtendedDataModel localModel = getExtendedDataModel();
-	// if(key == localModel.getRowIndex()){
-	// return;
-	// }
-	// save child state
-	this.saveChildState(faces);
-	// Set current model row by int, but immediately get value from model.
-	// for compability, complex models must provide values map between
-	// integer and key value.
-	localModel.setRowIndex(index);
-	this._rowKey = localModel.getRowKey();
-	this._clientId = null;
-	boolean rowSelected = this._rowKey != null;
-
-	setupVariable(faces, localModel, rowSelected);
-	// restore child state
-	this.restoreChildState(faces);
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#getRowIndex()
-         */
-    public int getRowIndex() {
-	return getExtendedDataModel().getRowIndex();
-    }
-
-    /**
-         * Same as for int index, but for complex model key.
-         * 
-         * @return
-         */
-    public Object getRowKey() {
-	return this._rowKey;
-    }
-
-    public void setRowKey(Object key) {
-	setRowKey(FacesContext.getCurrentInstance(), key);
-    }
-
-    /**
-         * Setup current roy by key. Perform same functionality as
-         * {@link UIData#setRowIndex(int)}, but for key object - it may be not
-         * only row number in sequence data, but, for example - path to current
-         * node in tree.
-         * 
-         * @param faces -
-         *                current FacesContext
-         * @param key
-         *                new key value.
-         */
-    public void setRowKey(FacesContext faces, Object key) {
-	ExtendedDataModel localModel = getExtendedDataModel();
-	// save child state
-	this.saveChildState(faces);
-	this._rowKey = key;
-	this._clientId = null;
-	localModel.setRowKey(key);
-
-	boolean rowSelected = key != null;
-
-	setupVariable(faces, localModel, rowSelected);
-	// restore child state
-	this.restoreChildState(faces);
-
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see org.ajax4jsf.ajax.repeat.AjaxDataEncoder#getAjaxKeys()
-         */
-    public Set getAjaxKeys() {
-	Set keys = null;
-	if (this._ajaxKeys != null) {
-	    keys = (this._ajaxKeys);
-	} else {
-		ValueBinding vb = getValueBinding("ajaxKeys");
-		if (vb != null) {
-		    keys = (Set) (vb.getValue(getFacesContext()));
-		} else if(null != _ajaxRowKey){
-		    // If none of above exist , use row with submitted AjaxComponent
-		    keys = new HashSet(1);
-		    keys.add(_ajaxRowKey);
-		}
-	}
-	return keys;
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see org.ajax4jsf.ajax.repeat.AjaxDataEncoder#setAjaxKeys(java.util.Set)
-         */
-    public void setAjaxKeys(Set ajaxKeys) {
-	this._ajaxKeys = ajaxKeys;
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see org.ajax4jsf.framework.ajax.AjaxChildrenEncoder#encodeAjaxChild(javax.faces.context.FacesContext,
-         *      java.lang.String, java.util.Set, java.util.Set)
-         */
-    public void encodeAjaxChild(FacesContext context, String path,
-	    final Set ids, final Set renderedAreas) throws IOException {
-	resetDataModel();
-
-	Renderer renderer = getRenderer(context);
-	if (null != renderer && renderer instanceof AjaxRenderer) {
-	    // If renderer support partial encoding - call them.
-	    AjaxRenderer childrenRenderer = (AjaxRenderer) renderer;
-	    childrenRenderer.encodeAjaxChildren(context, this, path, ids,
-		    renderedAreas);
-	}
-	/*else {
-	    // Use simple ajax children encoding for iterate other keys.
-	    final AjaxRenderer childrenRenderer = getChildrenRenderer();
-	    final String childrenPath = path + getId() + NamingContainer.SEPARATOR_CHAR;
-	    ComponentVisitor ajaxVisitor = new ComponentVisitor() {
-
-		public void processComponent(FacesContext context,
-			UIComponent c, Object argument) throws IOException {
-		    childrenRenderer.encodeAjaxComponent(context, c, childrenPath,
-			    ids, renderedAreas);
-		}
-
-	    };
-	    Set ajaxKeys = getAjaxKeys();
-	    if (null != ajaxKeys) {
-		captureOrigValue();
-		Object savedKey = getRowKey();
-		setRowKey(context, null);
-		Iterator fixedChildren = fixedChildren();
-		while (fixedChildren.hasNext()) {
-		    UIComponent component = (UIComponent) fixedChildren.next();
-		    ajaxVisitor.processComponent(context, component, null);
-		}
-		for (Iterator iter = ajaxKeys.iterator(); iter.hasNext();) {
-		    Object key = (Object) iter.next();
-		    ajaxVisitor.process(context, key, null);
-		}
-		setRowKey(savedKey);
-		restoreOrigValue();
-	    } else {
-		iterate(context, ajaxVisitor, null);
-	    }
-	}*/
-    }
-
-    /**
-         * Instance of default renderer in ajax responses.
-         */
-    private AjaxRenderer _childrenRenderer = null;
-
-    /**
-         * getter for simple {@link AjaxChildrenRenderer} instance in case of
-         * ajax responses. If default renderer not support search of children
-         * for encode in ajax response, component will use this instance by
-         * default.
-         * 
-         * @return
-         */
-//    protected AjaxRenderer getChildrenRenderer() {
-//	if (_childrenRenderer == null) {
-//	    _childrenRenderer = new AjaxChildrenRenderer() {
-//
-//		protected Class getComponentClass() {
-//		    return UIDataAdaptor.class;
-//		}
-//
-//	    };
-//
-//	}
-//
-//	return _childrenRenderer;
-//    }
-
-    /**
-         * @return Set of values for clientId's of this component, for wich was
-         *         invoked "encode" methods.
-         */
-    protected Set getEncodedIds() {
-	if (_encoded == null) {
-	    _encoded = new HashSet();
-	}
-
-	return _encoded;
-    }
-
-    /**
-         * Setup EL variable for different iteration. Value of row data and
-         * component state will be put into request scope attributes with names
-         * given by "var" and "varState" bean properties.
-         * 
-         * @param faces
-         *                current faces context
-         * @param localModel
-         * @param rowSelected
-         */
-    protected void setupVariable(FacesContext faces, DataModel localModel,
-	    boolean rowSelected) {
-	Map attrs = faces.getExternalContext().getRequestMap();
-	if (rowSelected && isRowAvailable()) {
-	    // Current row data.
-	    setupVariable(getVar(), attrs, localModel.getRowData());
-	    // Component state variable.
-	    setupVariable(getStateVar(), attrs, getComponentState());
-	    // Row key Data variable.
-	    setupVariable(getRowKeyVar(), attrs, getRowKey());
-
-	} else {
-	    removeVariable(getVar(), attrs);
-	    removeVariable(getStateVar(), attrs);
-	    removeVariable(getRowKeyVar(), attrs);
-	}
-    }
-
-    /**
-         * @param var
-         * @param attrs
-         * @param rowData
-         */
-    private void setupVariable(String var, Map attrs, Object rowData) {
-	if (var != null) {
-	    attrs.put(var, rowData);
-	}
-    }
-
-    /**
-         * @param var
-         * @param attrs
-         * @param rowData
-         */
-    private void removeVariable(String var, Map attrs) {
-	if (var != null) {
-	    attrs.remove(var);
-	}
-    }
-
-    /**
-         * Reset data model. this method must be called twice per request -
-         * before decode phase and before component encoding.
-         */
-    protected void resetDataModel() {
-	this.setExtendedDataModel(null);
-    }
-
-    /**
-         * Set data model. Model value will be stored in Map with key as current
-         * clientId for this component, to keep models between phases for same
-         * iteration in case if this component child for other UIData
-         * 
-         * @param model
-         */
-    protected void setExtendedDataModel(ExtendedDataModel model) {
-	this._currentModel = model;
-	this._modelsMap.put(getBaseClientId(getFacesContext()), model);
-    }
-
-    /**
-         * Get current data model, or create it by {@link #createDataModel()}
-         * method. For different iterations in ancestor UIData ( if present )
-         * will be returned different models.
-         * 
-         * @return current data model.
-         */
-    protected ExtendedDataModel getExtendedDataModel() {
-	if (this._currentModel == null) {
-	    String baseClientId = getBaseClientId(getFacesContext());
-	    ExtendedDataModel model = (ExtendedDataModel) this._modelsMap
-		    .get(baseClientId);
-	    if (null == model) {
-		model = createDataModel();
-		this._modelsMap.put(baseClientId, model);
-	    }
-	    this._currentModel = model;
-	}
-	return this._currentModel;
-    }
-
-    /**
-         * Hook mathod for create data model in concrete implementations.
-         * 
-         * @return
-         */
-    protected abstract ExtendedDataModel createDataModel();
-
-    /**
-         * Set current state ( at most cases, visual representation ) of this
-         * component. Same as for DataModel, component will keep states for
-         * different iterations.
-         * 
-         * @param state
-         */
-    public void setComponentState(DataComponentState state) {
-	this._currentState = state;
-	this._statesMap.put(getBaseClientId(getFacesContext()),
-		this._currentState);
-    }
-
-    /**
-         * @return current state of this component.
-         */
-    public DataComponentState getComponentState() {
-	DataComponentState state = null;
-	if (this._currentState == null) {
-	    // Check for binding state to user bean.
-	    ValueBinding valueBinding = getValueBinding(UIDataAdaptor.COMPONENT_STATE_ATTRIBUTE);
-	    FacesContext facesContext = getFacesContext();
-	    if (null != valueBinding) {
-		state = (DataComponentState) valueBinding
-			.getValue(facesContext);
-		if (null == state) {
-		    // Create default state
-		    state = createComponentState();
-		    if (!valueBinding.isReadOnly(facesContext)) {
-			// Store created state in user bean.
-			valueBinding.setValue(facesContext, state);
-		    }
-		}
-	    } else {
-		// Check for stored state in map for parent iterations
-		String baseClientId = getBaseClientId(facesContext);
-		state = (DataComponentState) this._statesMap.get(baseClientId);
-		if (null == state) {
-		    // Create default component state
-		    state = createComponentState();
-		    this._statesMap.put(baseClientId, state);
-		}
-		this._currentState = state;
-	    }
-	} else {
-	    state = this._currentState;
-	}
-	return state;
-    }
-
-    /**
-         * Hook method for create default state in concrete implementations.
-         * 
-         * @return
-         */
-    protected abstract DataComponentState createComponentState();
-
-    private String _clientId = null;
-
-    public String getClientId(FacesContext faces) {
-	if (null == _clientId) {
-	    StringBuffer id = new StringBuffer(getBaseClientId(faces));
-	    Object rowKey = getRowKey();
-	    if (rowKey != null) {
-		id.append(NamingContainer.SEPARATOR_CHAR).append(
-			rowKey.toString());
-	    }
-	    Renderer renderer;
-	    if (null != (renderer = getRenderer(faces))) {
-		_clientId = renderer.convertClientId(faces, id.toString());
-	    } else {
-		_clientId = id.toString();
-	    }
-
-	}
-	return _clientId;
-    }
-
-    private String _baseClientId = null;
-
-    /**
-         * Get base clietntId of this component ( withowt iteration part )
-         * 
-         * @param faces
-         * @return
-         */
-    public String getBaseClientId(FacesContext faces) {
-	// Return any previously cached client identifier
-	if (_baseClientId == null) {
-
-	    // Search for an ancestor that is a naming container
-	    UIComponent ancestorContainer = this;
-	    StringBuffer parentIds = new StringBuffer();
-	    while (null != (ancestorContainer = ancestorContainer.getParent())) {
-		if (ancestorContainer instanceof NamingContainer) {
-		    parentIds.append(ancestorContainer.getClientId(faces))
-			    .append(NamingContainer.SEPARATOR_CHAR);
-		    break;
-		}
-	    }
-	    String id = getId();
-	    if (null != id) {
-		_baseClientId = parentIds.append(id).toString();
-	    } else {
-		_baseClientId = parentIds.append(
-			faces.getViewRoot().createUniqueId()).toString();
-	    }
-	}
-	return (_baseClientId);
-
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIComponentBase#setId(java.lang.String)
-         */
-    public void setId(String id) {
-	// If component created by restoring tree or JSP, initial Id is null.
-	boolean haveId = null != super.getId();
-	super.setId(id);
-	_baseClientId = null;
-	_clientId = null;
-	if (haveId) {
-	    // parent UIData ( if present ) will be set same Id at iteration
-	    // -
-	    // we use it for
-	    // switch to different model and state.
-	    String baseClientId = getBaseClientId(getFacesContext());
-	    this._currentState = (DataComponentState) this._statesMap
-		    .get(baseClientId);
-	    this._currentModel = (ExtendedDataModel) this._modelsMap
-		    .get(baseClientId);
-	    if (null != this._currentModel) {
-		this._rowKey = this._currentModel.getRowKey();
-		// restoreChildState();
-	    }
-	    // Restore value for row with submitted AjaxComponent.
-	    this._ajaxRowKey = _ajaxRowKeysMap.get(baseClientId);
-	}
-    }
-
-    private Object origValue;
-
-    /**
-         * Save current state of data variable.
-         */
-    public void captureOrigValue() {
-	captureOrigValue(FacesContext.getCurrentInstance());
-    }
-
-    /**
-         * Save current state of data variable.
-         * 
-         * @param faces
-         *                current faces context
-         */
-    public void captureOrigValue(FacesContext faces) {
-	String var = getVar();
-	if (var != null) {
-	    Map attrs = faces.getExternalContext().getRequestMap();
-	    this.origValue = attrs.get(var);
-	}
-    }
-
-    /**
-         * Restore value of data variable after processing phase.
-         */
-    public void restoreOrigValue() {
-	restoreOrigValue(FacesContext.getCurrentInstance());
-    }
-
-    /**
-         * Restore value of data variable after processing phase.
-         * 
-         * @param faces
-         *                current faces context
-         */
-    public void restoreOrigValue(FacesContext faces) {
-	String var = getVar();
-	if (var != null) {
-	    Map attrs = faces.getExternalContext().getRequestMap();
-	    if (this.origValue != null) {
-		attrs.put(var, this.origValue);
-	    } else {
-		attrs.remove(var);
-	    }
-	}
-    }
-
-    /**
-         * Saved values of {@link EditableValueHolder} fields per iterations.
-         */
-    private Map childState;
-
-    /**
-         * @param faces
-         * @return Saved values of {@link EditableValueHolder} fields per
-         *         iterations.
-         */
-    protected Map getChildState(FacesContext faces) {
-	if (this.childState == null) {
-	    this.childState = new HashMap();
-	}
-	String baseClientId = getBaseClientId(faces);
-	Map currentChildState = (Map) childState.get(baseClientId);
-	if (null == currentChildState) {
-	    currentChildState = new HashMap();
-	    childState.put(baseClientId, currentChildState);
-	}
-	return currentChildState;
-    }
-
-    /**
-         * Save values of {@link EditableValueHolder} fields before change
-         * current row.
-         * 
-         * @param faces
-         */
-    protected void saveChildState(FacesContext faces) {
-
-	Iterator itr = dataChildren();
-	while (itr.hasNext()) {
-	    Map childState = this.getChildState(faces);
-	    this.saveChildState(faces, (UIComponent) itr.next(), childState);
-	}
-    }
-
-    /**
-         * Recursive method for Iterate on children for save
-         * {@link EditableValueHolder} fields states.
-         * 
-         * @param faces
-         * @param c
-         * @param childState
-         */
-    private void saveChildState(FacesContext faces, UIComponent c,
-	    Map childState) {
-
-	if (c instanceof EditableValueHolder && !c.isTransient()) {
-	    String clientId = c.getClientId(faces);
-	    SavedState ss = (SavedState) childState.get(clientId);
-	    if (ss == null) {
-		ss = new SavedState();
-		childState.put(clientId, ss);
-	    }
-	    ss.populate((EditableValueHolder) c);
-	}
-
-	// continue hack
-	Iterator itr = c.getChildren().iterator();
-	while (itr.hasNext()) {
-	    saveChildState(faces, (UIComponent) itr.next(), childState);
-	}
-	itr = c.getFacets().values().iterator();
-	while (itr.hasNext()) {
-	    saveChildState(faces, (UIComponent) itr.next(), childState);
-	}
-    }
-
-    /**
-         * Restore values of {@link EditableValueHolder} fields after change
-         * current row.
-         * 
-         * @param faces
-         */
-    protected void restoreChildState(FacesContext faces) {
-
-	Iterator itr = dataChildren();
-	while (itr.hasNext()) {
-	    Map childState = this.getChildState(faces);
-	    this.restoreChildState(faces, (UIComponent) itr.next(), childState);
-	}
-    }
-
-    /**
-         * Recursive part of
-         * {@link #restoreChildState(FacesContext, UIComponent, Map)}
-         * 
-         * @param faces
-         * @param c
-         * @param childState
-         * 
-         */
-    private void restoreChildState(FacesContext faces, UIComponent c,
-	    Map childState) {
-	// 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 = (SavedState) childState.get(clientId);
-	    if (ss != null) {
-		ss.apply(evh);
-	    } else {
-		NullState.apply(evh);
-	    }
-	}
-
-	// continue hack
-	Iterator itr = c.getChildren().iterator();
-	while (itr.hasNext()) {
-	    restoreChildState(faces, (UIComponent) itr.next(), childState);
-	}
-	itr = c.getFacets().values().iterator();
-	while (itr.hasNext()) {
-	    restoreChildState(faces, (UIComponent) itr.next(), childState);
-	}
-    }
-
-    /**
-         * Check for validation errors on children components. If true, saved
-         * values must be keep on render phase
-         * 
-         * @param context
-         * @return
-         */
-    private boolean keepSaved(FacesContext context) {
-
-	Iterator clientIds = this.getChildState(context).keySet().iterator();
-	while (clientIds.hasNext()) {
-	    String clientId = (String) clientIds.next();
-	    Iterator messages = context.getMessages(clientId);
-	    while (messages.hasNext()) {
-		FacesMessage message = (FacesMessage) messages.next();
-		if (message.getSeverity()
-			.compareTo(FacesMessage.SEVERITY_ERROR) >= 0) {
-		    return (true);
-		}
-	    }
-	}
-	return false;
-    }
-
-    /**
-         * Perform iteration on all children components and all data rows with
-         * given visitor.
-         * 
-         * @param faces
-         * @param visitor
-         */
-    protected void iterate(FacesContext faces, ComponentVisitor visitor,
-	    Object argument) {
-
-	// stop if not rendered
-	if (!this.isRendered()) {
-	    return;
-	}
-	// reset rowIndex
-	this.captureOrigValue(faces);
-	this.setRowKey(faces, null);
-	try {
-	    Iterator fixedChildren = fixedChildren();
-	    while (fixedChildren.hasNext()) {
-		UIComponent component = (UIComponent) fixedChildren.next();
-		visitor.processComponent(faces, component, argument);
-	    }
-
-	    walk(faces, visitor, argument);
-	} catch (Exception e) {
-	    throw new FacesException(e);
-	} finally {
-	    this.setRowKey(faces, null);
-	    this.restoreOrigValue(faces);
-	}
-    }
-
-    /**
-         * Walk ( visit ) this component on all data-avare children for each
-         * row.
-         * 
-         * @param faces
-         * @param visitor
-         * @throws IOException
-         */
-    public void walk(FacesContext faces, DataVisitor visitor, Object argument)
-	    throws IOException {
-	getExtendedDataModel().walk(faces, visitor,
-		getComponentState().getRange(), argument);
-    }
-
-    protected void processDecodes(FacesContext faces, Object argument) {
-	if (!this.isRendered())
-	    return;
-	this.resetComponent(faces);
-	this.iterate(faces, decodeVisitor, argument);
-	this.decode(faces);
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#processDecodes(javax.faces.context.FacesContext)
-         */
-    public void processDecodes(FacesContext faces) {
-	processDecodes(faces, null);
-    }
-
-    /**
-         * Reset per-request fields in component.
-         * 
-         * @param faces
-         * 
-         */
-    protected void resetComponent(FacesContext faces) {
-	// resetDataModel();
-	if (null != this.childState) {
-	    childState.remove(getBaseClientId(faces));
-	}
-	this._encoded = null;
-    }
-
-    protected void processUpdates(FacesContext faces, Object argument) {
-	if (!this.isRendered())
-	    return;
-	this.iterate(faces, updateVisitor, argument);
-	ExtendedDataModel dataModel = getExtendedDataModel();
-	// If no validation errors, update values for serializable model,
-	// restored from view.
-	if (dataModel instanceof SerializableDataModel && (!keepSaved(faces))) {
-	    SerializableDataModel serializableModel = (SerializableDataModel) dataModel;
-	    serializableModel.update();
-	}
-    }
-
-    public void processUpdates(FacesContext faces) {
-	processUpdates(faces, null);
-    }
-
-    protected void processValidators(FacesContext faces, Object argument) {
-	if (!this.isRendered())
-	    return;
-	this.iterate(faces, validateVisitor, argument);
-    }
-
-    public void processValidators(FacesContext faces) {
-	processValidators(faces, null);
-    }
-
-    public void encodeBegin(FacesContext context) throws IOException {
-	resetDataModel();
-	// if(!keepSaved(context)){
-	// childState.remove(getBaseClientId(context));
-	// }
-	// Mark component as used, if parent UIData change own range states not
-	// accessed at
-	// encode phase must be unsaved.
-	getEncodedIds().add(getBaseClientId(context));
-	// getComponentState().setUsed(true);
-	super.encodeBegin(context);
-    }
-
-    /**
-         * This method must create iterator for all non-data avare children of
-         * this component ( header/footer facets for components and columns in
-         * dataTable, facets for tree etc.
-         * 
-         * @return iterator for all components not sensitive for row data.
-         */
-    protected abstract Iterator fixedChildren();
-
-    /**
-         * This method must create iterator for all children components,
-         * processed "per row" It can be children of UIColumn in dataTable,
-         * nodes in tree
-         * 
-         * @return iterator for all components processed per row.
-         */
-    protected abstract Iterator dataChildren();
-
-    private final static SavedState NullState = new SavedState();
-
-    // from RI
-    /**
-         * This class keep values of {@link EditableValueHolder} row-sensitive
-         * fields.
-         * 
-         * @author shura
-         * 
-         */
-    private final static class SavedState implements Serializable {
-
-	private Object submittedValue;
-
-	private static final long serialVersionUID = 2920252657338389849L;
-
-	Object getSubmittedValue() {
-	    return (this.submittedValue);
-	}
-
-	void setSubmittedValue(Object submittedValue) {
-	    this.submittedValue = submittedValue;
-	}
-
-	private boolean valid = true;
-
-	boolean isValid() {
-	    return (this.valid);
-	}
-
-	void setValid(boolean valid) {
-	    this.valid = valid;
-	}
-
-	private Object value;
-
-	Object getValue() {
-	    return (this.value);
-	}
-
-	public void setValue(Object value) {
-	    this.value = value;
-	}
-
-	private boolean localValueSet;
-
-	boolean isLocalValueSet() {
-	    return (this.localValueSet);
-	}
-
-	public void setLocalValueSet(boolean localValueSet) {
-	    this.localValueSet = localValueSet;
-	}
-
-	public String toString() {
-	    return ("submittedValue: " + submittedValue + " value: " + value
-		    + " localValueSet: " + localValueSet);
-	}
-
-	public void populate(EditableValueHolder evh) {
-	    this.value = evh.getLocalValue();
-	    this.valid = evh.isValid();
-	    this.submittedValue = evh.getSubmittedValue();
-	    this.localValueSet = evh.isLocalValueSet();
-	}
-
-	public void apply(EditableValueHolder evh) {
-	    evh.setValue(this.value);
-	    evh.setValid(this.valid);
-	    evh.setSubmittedValue(this.submittedValue);
-	    evh.setLocalValueSet(this.localValueSet);
-	}
-
-    }
-
-    /*
-         * (non-Javadoc)
-         * 
-         * @see javax.faces.component.UIData#queueEvent(javax.faces.event.FacesEvent)
-         */
-    public void queueEvent(FacesEvent event) {
-	if (event.getComponent() != this) {
-	    event = new IndexedEvent(this, event, getRowKey());
-	}
-	// Send event directly to parent, to avoid wrapping in superclass.
-	UIComponent parent = getParent();
-	if (parent == null) {
-	    throw new IllegalStateException(
-		    "No parent component for queue event");
-	} else {
-	    parent.queueEvent(event);
-	}
-    }
-
-    public void broadcast(FacesEvent event) throws AbortProcessingException {
-
-	if (!(event instanceof IndexedEvent)) {
-	    if (!broadcastLocal(event)) {
-		super.broadcast(event);
-	    }
-	    return;
-	}
-
-	// Set up the correct context and fire our wrapped event
-	IndexedEvent revent = (IndexedEvent) event;
-	Object oldRowKey = getRowKey();
-	FacesContext faces = FacesContext.getCurrentInstance();
-	captureOrigValue(faces);
-	Object eventRowKey = revent.getKey();
-	setRowKey(faces, eventRowKey);
-	FacesEvent rowEvent = revent.getTarget();
-	rowEvent.getComponent().broadcast(rowEvent);
-	// For Ajax events, keep row value.
-	if (!(rowEvent.getPhaseId() == PhaseId.RENDER_RESPONSE)) {
-	    this._ajaxRowKey = eventRowKey;
-	    this._ajaxRowKeysMap.put(getBaseClientId(faces), eventRowKey);
-	}
-	setRowKey(faces, oldRowKey);
-	restoreOrigValue(faces);
-	// }
-	return;
-    }
-
-    /**
-         * Process events targetted for concrete implementation. Hook method
-         * called from {@link #broadcast(FacesEvent)}
-         * 
-         * @param event -
-         *                processed event.
-         * @return true if event processed, false if component must continue
-         *         processing.
-         */
-    protected boolean broadcastLocal(FacesEvent event) {
-	return false;
-    }
-
-    /**
-         * Wrapper for event from child component, with value of current row
-         * key.
-         * 
-         * @author shura
-         * 
-         */
-    protected static final class IndexedEvent extends FacesEvent {
-
-	private static final long serialVersionUID = -8318895390232552385L;
-
-	private final FacesEvent target;
-
-	private final Object key;
-
-	public IndexedEvent(UIDataAdaptor owner, FacesEvent target, Object key) {
-	    super(owner);
-	    this.target = target;
-	    this.key = key;
-	}
-
-	public PhaseId getPhaseId() {
-	    return (this.target.getPhaseId());
-	}
-
-	public void setPhaseId(PhaseId phaseId) {
-	    this.target.setPhaseId(phaseId);
-	}
-
-	public boolean isAppropriateListener(FacesListener listener) {
-	    return this.target.isAppropriateListener(listener);
-	}
-
-	public void processListener(FacesListener listener) {
-	    UIDataAdaptor owner = (UIDataAdaptor) this.getComponent();
-	    Object prevIndex = owner._rowKey;
-	    try {
-		owner.setRowKey(this.key);
-		this.target.processListener(listener);
-	    } finally {
-		owner.setRowKey(prevIndex);
-	    }
-	}
-
-	public Object getKey() {
-	    return key;
-	}
-
-	public FacesEvent getTarget() {
-	    return target;
-	}
-
-    }
-
-    /**
-         * "memento" pattern class for state of component.
-         * 
-         * @author shura
-         * 
-         */
-    private static class DataState implements Serializable {
-
-	/**
-         * 
-         */
-	private static final long serialVersionUID = 17070532L;
-
-	private Object superState;
-
-	private Map componentStates = new HashMap();
-
-	private Set ajaxKeys;
-
-	public String rowKeyVar;
-
-	public String stateVar;
-
-    }
-
-    /**
-         * Serialisable model and component state per iteration of parent
-         * UIData.
-         * 
-         * @author shura
-         * 
-         */
-    private static class PerIdState implements Serializable {
-	/**
-         * 
-         */
-	private static final long serialVersionUID = 9037454770537726418L;
-
-	/**
-         * Flag setted to true if componentState implements StateHolder
-         */
-	private boolean stateInHolder = false;
-
-	/**
-         * Serializable componentState or
-         */
-	private Object componentState;
-
-	private SerializableDataModel model;
-    }
-
-    public void restoreState(FacesContext faces, Object object) {
-	DataState state = (DataState) object;
-	super.restoreState(faces, state.superState);
-	this._ajaxKeys = state.ajaxKeys;
-	this._statesMap = new HashMap();
-	this._rowKeyVar = state.rowKeyVar;
-	this._stateVar = state.stateVar;
-	// Restore serializable models and component states for all rows of
-	// parent UIData ( single if this
-	// component not child of iterable )
-	for (Iterator iter = state.componentStates.entrySet().iterator(); iter
-		.hasNext();) {
-	    Map.Entry stateEntry = (Map.Entry) iter.next();
-	    PerIdState idState = (PerIdState) stateEntry.getValue();
-	    DataComponentState compState;
-	    if (idState.stateInHolder) {
-		// TODO - change RichFaces Tree component, for remove reference
-		// to component from state.
-		compState = createComponentState();
-		((StateHolder) compState).restoreState(faces,
-			idState.componentState);
-	    } else {
-		compState = (DataComponentState) idState.componentState;
-	    }
-	    Object key = stateEntry.getKey();
-	    this._statesMap.put(key, compState);
-	    this._modelsMap.put(key, idState.model);
-	}
-    }
-
-    public Object saveState(FacesContext faces) {
-	DataState state = new DataState();
-	state.superState = super.saveState(faces);
-	state.ajaxKeys = this._ajaxKeys;
-	state.rowKeyVar = this._rowKeyVar;
-	state.stateVar = this._stateVar;
-	Set encodedIds = getEncodedIds();
-	// Save all states of component and data model for all valies of
-	// clientId, encoded in this request.
-	for (Iterator iter = this._statesMap.entrySet().iterator(); iter
-		.hasNext();) {
-	    Map.Entry stateEntry = (Map.Entry) iter.next();
-	    DataComponentState dataComponentState = ((DataComponentState) stateEntry
-		    .getValue());
-	    Object stateKey = stateEntry.getKey();
-	    if (encodedIds.isEmpty() || encodedIds.contains(stateKey)) {
-		PerIdState idState = new PerIdState();
-		idState.model = getExtendedDataModel().getSerializableModel(
-			dataComponentState.getRange());
-		// Save component state , depended if implemented interfaces.
-		if (null == dataComponentState) {
-		    idState.componentState = null;
-		} else if (dataComponentState instanceof Serializable) {
-		    idState.componentState = dataComponentState;
-		} else if (dataComponentState instanceof StateHolder) {
-		    // TODO - change RichFaces Tree component, for remove
-		    // reference to component from state.
-		    // Change this code to reference for saveAttachedState.
-		    idState.componentState = ((StateHolder) dataComponentState)
-			    .saveState(faces);
-		    idState.stateInHolder = true;
-		}
-		if (null != idState.model || null != idState.componentState) {
-		    state.componentStates.put(stateKey, idState);
-		}
-	    }
-	}
-	return state;
-    }
-
-}

Copied: branches/refactor1/framework/impl/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java (from rev 1415, branches/refactor1/framework/api/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java)
===================================================================
--- branches/refactor1/framework/impl/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java	                        (rev 0)
+++ branches/refactor1/framework/impl/src/main/java/org/ajax4jsf/ajax/repeat/UIDataAdaptor.java	2007-06-30 00:03:04 UTC (rev 1427)
@@ -0,0 +1,1322 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * 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.ajax4jsf.ajax.repeat;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIData;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+import javax.faces.event.PhaseId;
+import javax.faces.model.DataModel;
+import javax.faces.model.ListDataModel;
+import javax.faces.render.Renderer;
+
+import org.ajax4jsf.framework.renderer.AjaxRenderer;
+
+/**
+ * Base class for iterable components, like dataTable, Tomahawk dataList,
+ * Facelets repeat, tree etc., with support for partial rendering on AJAX
+ * responces for one or more selected iterations.
+ * 
+ * @author shura
+ * 
+ */
+public abstract class UIDataAdaptor extends UIData implements AjaxDataEncoder {
+
+    /**
+         * 
+         */
+    public static final String COMPONENT_STATE_ATTRIBUTE = "componentState";
+
+    public final static DataModel EMPTY_MODEL = new ListDataModel(
+	    Collections.EMPTY_LIST);
+
+    /**
+         * Base class for visit data model at phases decode, validation and
+         * update model
+         * 
+         * @author shura
+         * 
+         */
+    protected abstract class ComponentVisitor implements DataVisitor {
+
+	public void process(FacesContext context, Object rowKey, Object argument)
+		throws IOException {
+	    setRowKey(context, rowKey);
+	    if (isRowAvailable()) {
+		Iterator childIterator = dataChildren();
+		while (childIterator.hasNext()) {
+		    UIComponent component = (UIComponent) childIterator.next();
+		    processComponent(context, component, argument);
+		}
+
+	    }
+	}
+
+	public abstract void processComponent(FacesContext context,
+		UIComponent c, Object argument) throws IOException;
+
+    }
+
+    /**
+         * Visitor for process decode on children components.
+         */
+    protected ComponentVisitor decodeVisitor = new ComponentVisitor() {
+
+	public void processComponent(FacesContext context, UIComponent c,
+		Object argument) {
+	    c.processDecodes(context);
+	}
+
+    };
+
+    /**
+         * Visitor for process validation phase
+         */
+    protected ComponentVisitor validateVisitor = new ComponentVisitor() {
+
+	public void processComponent(FacesContext context, UIComponent c,
+		Object argument) {
+	    c.processValidators(context);
+	}
+
+    };
+
+    /**
+         * Visitor for process update model phase.
+         */
+    protected ComponentVisitor updateVisitor = new ComponentVisitor() {
+
+	public void processComponent(FacesContext context, UIComponent c,
+		Object argument) {
+	    c.processUpdates(context);
+	}
+
+    };
+
+    /**
+         * Base client id's of this component, for wich invoked encode...
+         * methods. Component will save state and serialisable models for this
+         * keys only.
+         */
+    private Set _encoded;
+
+    /**
+         * Storage for data model instances with different client id's of this
+         * component. In case of child for UIData component, this map will keep
+         * data models for different iterations between phases.
+         */
+    private Map _modelsMap = new HashMap();
+
+    /**
+         * Reference for curent data model
+         */
+    private ExtendedDataModel _currentModel = null;
+
+    /**
+         * States of this component for diferent iterations, same as for models.
+         */
+    private Map _statesMap = new HashMap();
+
+    /**
+         * Reference for current component state.
+         */
+    private DataComponentState _currentState = null;
+
+    /**
+         * Name of EL variable for current component state.
+         */
+    private String _stateVar;
+
+    private String _rowKeyVar;
+
+    /**
+         * Key for current value in model.
+         */
+    private Object _rowKey = null;
+
+    /**
+         * Values of row keys, encoded on ajax response rendering.
+         */
+    private Set _ajaxKeys = null;
+
+    private Object _ajaxRowKey = null;
+
+    private Map _ajaxRowKeysMap = new HashMap();
+
+    /**
+         * Get name of EL variable for component state.
+         * 
+         * @return the varState
+         */
+    public String getStateVar() {
+	return _stateVar;
+    }
+
+    /**
+         * @param varStatus
+         *                the varStatus to set
+         */
+    public void setStateVar(String varStatus) {
+	this._stateVar = varStatus;
+    }
+
+    /**
+         * @return the rowKeyVar
+         */
+    public String getRowKeyVar() {
+	return this._rowKeyVar;
+    }
+
+    /**
+         * @param rowKeyVar
+         *                the rowKeyVar to set
+         */
+    public void setRowKeyVar(String rowKeyVar) {
+	this._rowKeyVar = rowKeyVar;
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#getRowCount()
+         */
+    public int getRowCount() {
+	return getExtendedDataModel().getRowCount();
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#getRowData()
+         */
+    public Object getRowData() {
+	return getExtendedDataModel().getRowData();
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#isRowAvailable()
+         */
+    public boolean isRowAvailable() {
+	return this.getExtendedDataModel().isRowAvailable();
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#setRowIndex(int)
+         */
+    public void setRowIndex(int index) {
+	FacesContext faces = FacesContext.getCurrentInstance();
+	ExtendedDataModel localModel = getExtendedDataModel();
+	// if(key == localModel.getRowIndex()){
+	// return;
+	// }
+	// save child state
+	this.saveChildState(faces);
+	// Set current model row by int, but immediately get value from model.
+	// for compability, complex models must provide values map between
+	// integer and key value.
+	localModel.setRowIndex(index);
+	this._rowKey = localModel.getRowKey();
+	this._clientId = null;
+	boolean rowSelected = this._rowKey != null;
+
+	setupVariable(faces, localModel, rowSelected);
+	// restore child state
+	this.restoreChildState(faces);
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#getRowIndex()
+         */
+    public int getRowIndex() {
+	return getExtendedDataModel().getRowIndex();
+    }
+
+    /**
+         * Same as for int index, but for complex model key.
+         * 
+         * @return
+         */
+    public Object getRowKey() {
+	return this._rowKey;
+    }
+
+    public void setRowKey(Object key) {
+	setRowKey(FacesContext.getCurrentInstance(), key);
+    }
+
+    /**
+         * Setup current roy by key. Perform same functionality as
+         * {@link UIData#setRowIndex(int)}, but for key object - it may be not
+         * only row number in sequence data, but, for example - path to current
+         * node in tree.
+         * 
+         * @param faces -
+         *                current FacesContext
+         * @param key
+         *                new key value.
+         */
+    public void setRowKey(FacesContext faces, Object key) {
+	ExtendedDataModel localModel = getExtendedDataModel();
+	// save child state
+	this.saveChildState(faces);
+	this._rowKey = key;
+	this._clientId = null;
+	localModel.setRowKey(key);
+
+	boolean rowSelected = key != null;
+
+	setupVariable(faces, localModel, rowSelected);
+	// restore child state
+	this.restoreChildState(faces);
+
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.ajax.repeat.AjaxDataEncoder#getAjaxKeys()
+         */
+    public Set getAjaxKeys() {
+	Set keys = null;
+	if (this._ajaxKeys != null) {
+	    keys = (this._ajaxKeys);
+	} else {
+		ValueBinding vb = getValueBinding("ajaxKeys");
+		if (vb != null) {
+		    keys = (Set) (vb.getValue(getFacesContext()));
+		} else if(null != _ajaxRowKey){
+		    // If none of above exist , use row with submitted AjaxComponent
+		    keys = new HashSet(1);
+		    keys.add(_ajaxRowKey);
+		}
+	}
+	return keys;
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.ajax.repeat.AjaxDataEncoder#setAjaxKeys(java.util.Set)
+         */
+    public void setAjaxKeys(Set ajaxKeys) {
+	this._ajaxKeys = ajaxKeys;
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxChildrenEncoder#encodeAjaxChild(javax.faces.context.FacesContext,
+         *      java.lang.String, java.util.Set, java.util.Set)
+         */
+    public void encodeAjaxChild(FacesContext context, String path,
+	    final Set ids, final Set renderedAreas) throws IOException {
+	resetDataModel();
+
+	Renderer renderer = getRenderer(context);
+	if (null != renderer && renderer instanceof AjaxRenderer) {
+	    // If renderer support partial encoding - call them.
+	    AjaxRenderer childrenRenderer = (AjaxRenderer) renderer;
+	    childrenRenderer.encodeAjaxChildren(context, this, path, ids,
+		    renderedAreas);
+	}
+	/*else {
+	    // Use simple ajax children encoding for iterate other keys.
+	    final AjaxRenderer childrenRenderer = getChildrenRenderer();
+	    final String childrenPath = path + getId() + NamingContainer.SEPARATOR_CHAR;
+	    ComponentVisitor ajaxVisitor = new ComponentVisitor() {
+
+		public void processComponent(FacesContext context,
+			UIComponent c, Object argument) throws IOException {
+		    childrenRenderer.encodeAjaxComponent(context, c, childrenPath,
+			    ids, renderedAreas);
+		}
+
+	    };
+	    Set ajaxKeys = getAjaxKeys();
+	    if (null != ajaxKeys) {
+		captureOrigValue();
+		Object savedKey = getRowKey();
+		setRowKey(context, null);
+		Iterator fixedChildren = fixedChildren();
+		while (fixedChildren.hasNext()) {
+		    UIComponent component = (UIComponent) fixedChildren.next();
+		    ajaxVisitor.processComponent(context, component, null);
+		}
+		for (Iterator iter = ajaxKeys.iterator(); iter.hasNext();) {
+		    Object key = (Object) iter.next();
+		    ajaxVisitor.process(context, key, null);
+		}
+		setRowKey(savedKey);
+		restoreOrigValue();
+	    } else {
+		iterate(context, ajaxVisitor, null);
+	    }
+	}*/
+    }
+
+    /**
+         * Instance of default renderer in ajax responses.
+         */
+    private AjaxRenderer _childrenRenderer = null;
+
+    /**
+         * getter for simple {@link AjaxChildrenRenderer} instance in case of
+         * ajax responses. If default renderer not support search of children
+         * for encode in ajax response, component will use this instance by
+         * default.
+         * 
+         * @return
+         */
+//    protected AjaxRenderer getChildrenRenderer() {
+//	if (_childrenRenderer == null) {
+//	    _childrenRenderer = new AjaxChildrenRenderer() {
+//
+//		protected Class getComponentClass() {
+//		    return UIDataAdaptor.class;
+//		}
+//
+//	    };
+//
+//	}
+//
+//	return _childrenRenderer;
+//    }
+
+    /**
+         * @return Set of values for clientId's of this component, for wich was
+         *         invoked "encode" methods.
+         */
+    protected Set getEncodedIds() {
+	if (_encoded == null) {
+	    _encoded = new HashSet();
+	}
+
+	return _encoded;
+    }
+
+    /**
+         * Setup EL variable for different iteration. Value of row data and
+         * component state will be put into request scope attributes with names
+         * given by "var" and "varState" bean properties.
+         * 
+         * @param faces
+         *                current faces context
+         * @param localModel
+         * @param rowSelected
+         */
+    protected void setupVariable(FacesContext faces, DataModel localModel,
+	    boolean rowSelected) {
+	Map attrs = faces.getExternalContext().getRequestMap();
+	if (rowSelected && isRowAvailable()) {
+	    // Current row data.
+	    setupVariable(getVar(), attrs, localModel.getRowData());
+	    // Component state variable.
+	    setupVariable(getStateVar(), attrs, getComponentState());
+	    // Row key Data variable.
+	    setupVariable(getRowKeyVar(), attrs, getRowKey());
+
+	} else {
+	    removeVariable(getVar(), attrs);
+	    removeVariable(getStateVar(), attrs);
+	    removeVariable(getRowKeyVar(), attrs);
+	}
+    }
+
+    /**
+         * @param var
+         * @param attrs
+         * @param rowData
+         */
+    private void setupVariable(String var, Map attrs, Object rowData) {
+	if (var != null) {
+	    attrs.put(var, rowData);
+	}
+    }
+
+    /**
+         * @param var
+         * @param attrs
+         * @param rowData
+         */
+    private void removeVariable(String var, Map attrs) {
+	if (var != null) {
+	    attrs.remove(var);
+	}
+    }
+
+    /**
+         * Reset data model. this method must be called twice per request -
+         * before decode phase and before component encoding.
+         */
+    protected void resetDataModel() {
+	this.setExtendedDataModel(null);
+    }
+
+    /**
+         * Set data model. Model value will be stored in Map with key as current
+         * clientId for this component, to keep models between phases for same
+         * iteration in case if this component child for other UIData
+         * 
+         * @param model
+         */
+    protected void setExtendedDataModel(ExtendedDataModel model) {
+	this._currentModel = model;
+	this._modelsMap.put(getBaseClientId(getFacesContext()), model);
+    }
+
+    /**
+         * Get current data model, or create it by {@link #createDataModel()}
+         * method. For different iterations in ancestor UIData ( if present )
+         * will be returned different models.
+         * 
+         * @return current data model.
+         */
+    protected ExtendedDataModel getExtendedDataModel() {
+	if (this._currentModel == null) {
+	    String baseClientId = getBaseClientId(getFacesContext());
+	    ExtendedDataModel model = (ExtendedDataModel) this._modelsMap
+		    .get(baseClientId);
+	    if (null == model) {
+		model = createDataModel();
+		this._modelsMap.put(baseClientId, model);
+	    }
+	    this._currentModel = model;
+	}
+	return this._currentModel;
+    }
+
+    /**
+         * Hook mathod for create data model in concrete implementations.
+         * 
+         * @return
+         */
+    protected abstract ExtendedDataModel createDataModel();
+
+    /**
+         * Set current state ( at most cases, visual representation ) of this
+         * component. Same as for DataModel, component will keep states for
+         * different iterations.
+         * 
+         * @param state
+         */
+    public void setComponentState(DataComponentState state) {
+	this._currentState = state;
+	this._statesMap.put(getBaseClientId(getFacesContext()),
+		this._currentState);
+    }
+
+    /**
+         * @return current state of this component.
+         */
+    public DataComponentState getComponentState() {
+	DataComponentState state = null;
+	if (this._currentState == null) {
+	    // Check for binding state to user bean.
+	    ValueBinding valueBinding = getValueBinding(UIDataAdaptor.COMPONENT_STATE_ATTRIBUTE);
+	    FacesContext facesContext = getFacesContext();
+	    if (null != valueBinding) {
+		state = (DataComponentState) valueBinding
+			.getValue(facesContext);
+		if (null == state) {
+		    // Create default state
+		    state = createComponentState();
+		    if (!valueBinding.isReadOnly(facesContext)) {
+			// Store created state in user bean.
+			valueBinding.setValue(facesContext, state);
+		    }
+		}
+	    } else {
+		// Check for stored state in map for parent iterations
+		String baseClientId = getBaseClientId(facesContext);
+		state = (DataComponentState) this._statesMap.get(baseClientId);
+		if (null == state) {
+		    // Create default component state
+		    state = createComponentState();
+		    this._statesMap.put(baseClientId, state);
+		}
+		this._currentState = state;
+	    }
+	} else {
+	    state = this._currentState;
+	}
+	return state;
+    }
+
+    /**
+         * Hook method for create default state in concrete implementations.
+         * 
+         * @return
+         */
+    protected abstract DataComponentState createComponentState();
+
+    private String _clientId = null;
+
+    public String getClientId(FacesContext faces) {
+	if (null == _clientId) {
+	    StringBuffer id = new StringBuffer(getBaseClientId(faces));
+	    Object rowKey = getRowKey();
+	    if (rowKey != null) {
+		id.append(NamingContainer.SEPARATOR_CHAR).append(
+			rowKey.toString());
+	    }
+	    Renderer renderer;
+	    if (null != (renderer = getRenderer(faces))) {
+		_clientId = renderer.convertClientId(faces, id.toString());
+	    } else {
+		_clientId = id.toString();
+	    }
+
+	}
+	return _clientId;
+    }
+
+    private String _baseClientId = null;
+
+    /**
+         * Get base clietntId of this component ( withowt iteration part )
+         * 
+         * @param faces
+         * @return
+         */
+    public String getBaseClientId(FacesContext faces) {
+	// Return any previously cached client identifier
+	if (_baseClientId == null) {
+
+	    // Search for an ancestor that is a naming container
+	    UIComponent ancestorContainer = this;
+	    StringBuffer parentIds = new StringBuffer();
+	    while (null != (ancestorContainer = ancestorContainer.getParent())) {
+		if (ancestorContainer instanceof NamingContainer) {
+		    parentIds.append(ancestorContainer.getClientId(faces))
+			    .append(NamingContainer.SEPARATOR_CHAR);
+		    break;
+		}
+	    }
+	    String id = getId();
+	    if (null != id) {
+		_baseClientId = parentIds.append(id).toString();
+	    } else {
+		_baseClientId = parentIds.append(
+			faces.getViewRoot().createUniqueId()).toString();
+	    }
+	}
+	return (_baseClientId);
+
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponentBase#setId(java.lang.String)
+         */
+    public void setId(String id) {
+	// If component created by restoring tree or JSP, initial Id is null.
+	boolean haveId = null != super.getId();
+	super.setId(id);
+	_baseClientId = null;
+	_clientId = null;
+	if (haveId) {
+	    // parent UIData ( if present ) will be set same Id at iteration
+	    // -
+	    // we use it for
+	    // switch to different model and state.
+	    String baseClientId = getBaseClientId(getFacesContext());
+	    this._currentState = (DataComponentState) this._statesMap
+		    .get(baseClientId);
+	    this._currentModel = (ExtendedDataModel) this._modelsMap
+		    .get(baseClientId);
+	    if (null != this._currentModel) {
+		this._rowKey = this._currentModel.getRowKey();
+		// restoreChildState();
+	    }
+	    // Restore value for row with submitted AjaxComponent.
+	    this._ajaxRowKey = _ajaxRowKeysMap.get(baseClientId);
+	}
+    }
+
+    private Object origValue;
+
+    /**
+         * Save current state of data variable.
+         */
+    public void captureOrigValue() {
+	captureOrigValue(FacesContext.getCurrentInstance());
+    }
+
+    /**
+         * Save current state of data variable.
+         * 
+         * @param faces
+         *                current faces context
+         */
+    public void captureOrigValue(FacesContext faces) {
+	String var = getVar();
+	if (var != null) {
+	    Map attrs = faces.getExternalContext().getRequestMap();
+	    this.origValue = attrs.get(var);
+	}
+    }
+
+    /**
+         * Restore value of data variable after processing phase.
+         */
+    public void restoreOrigValue() {
+	restoreOrigValue(FacesContext.getCurrentInstance());
+    }
+
+    /**
+         * Restore value of data variable after processing phase.
+         * 
+         * @param faces
+         *                current faces context
+         */
+    public void restoreOrigValue(FacesContext faces) {
+	String var = getVar();
+	if (var != null) {
+	    Map attrs = faces.getExternalContext().getRequestMap();
+	    if (this.origValue != null) {
+		attrs.put(var, this.origValue);
+	    } else {
+		attrs.remove(var);
+	    }
+	}
+    }
+
+    /**
+         * Saved values of {@link EditableValueHolder} fields per iterations.
+         */
+    private Map childState;
+
+    /**
+         * @param faces
+         * @return Saved values of {@link EditableValueHolder} fields per
+         *         iterations.
+         */
+    protected Map getChildState(FacesContext faces) {
+	if (this.childState == null) {
+	    this.childState = new HashMap();
+	}
+	String baseClientId = getBaseClientId(faces);
+	Map currentChildState = (Map) childState.get(baseClientId);
+	if (null == currentChildState) {
+	    currentChildState = new HashMap();
+	    childState.put(baseClientId, currentChildState);
+	}
+	return currentChildState;
+    }
+
+    /**
+         * Save values of {@link EditableValueHolder} fields before change
+         * current row.
+         * 
+         * @param faces
+         */
+    protected void saveChildState(FacesContext faces) {
+
+	Iterator itr = dataChildren();
+	while (itr.hasNext()) {
+	    Map childState = this.getChildState(faces);
+	    this.saveChildState(faces, (UIComponent) itr.next(), childState);
+	}
+    }
+
+    /**
+         * Recursive method for Iterate on children for save
+         * {@link EditableValueHolder} fields states.
+         * 
+         * @param faces
+         * @param c
+         * @param childState
+         */
+    private void saveChildState(FacesContext faces, UIComponent c,
+	    Map childState) {
+
+	if (c instanceof EditableValueHolder && !c.isTransient()) {
+	    String clientId = c.getClientId(faces);
+	    SavedState ss = (SavedState) childState.get(clientId);
+	    if (ss == null) {
+		ss = new SavedState();
+		childState.put(clientId, ss);
+	    }
+	    ss.populate((EditableValueHolder) c);
+	}
+
+	// continue hack
+	Iterator itr = c.getChildren().iterator();
+	while (itr.hasNext()) {
+	    saveChildState(faces, (UIComponent) itr.next(), childState);
+	}
+	itr = c.getFacets().values().iterator();
+	while (itr.hasNext()) {
+	    saveChildState(faces, (UIComponent) itr.next(), childState);
+	}
+    }
+
+    /**
+         * Restore values of {@link EditableValueHolder} fields after change
+         * current row.
+         * 
+         * @param faces
+         */
+    protected void restoreChildState(FacesContext faces) {
+
+	Iterator itr = dataChildren();
+	while (itr.hasNext()) {
+	    Map childState = this.getChildState(faces);
+	    this.restoreChildState(faces, (UIComponent) itr.next(), childState);
+	}
+    }
+
+    /**
+         * Recursive part of
+         * {@link #restoreChildState(FacesContext, UIComponent, Map)}
+         * 
+         * @param faces
+         * @param c
+         * @param childState
+         * 
+         */
+    private void restoreChildState(FacesContext faces, UIComponent c,
+	    Map childState) {
+	// 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 = (SavedState) childState.get(clientId);
+	    if (ss != null) {
+		ss.apply(evh);
+	    } else {
+		NullState.apply(evh);
+	    }
+	}
+
+	// continue hack
+	Iterator itr = c.getChildren().iterator();
+	while (itr.hasNext()) {
+	    restoreChildState(faces, (UIComponent) itr.next(), childState);
+	}
+	itr = c.getFacets().values().iterator();
+	while (itr.hasNext()) {
+	    restoreChildState(faces, (UIComponent) itr.next(), childState);
+	}
+    }
+
+    /**
+         * Check for validation errors on children components. If true, saved
+         * values must be keep on render phase
+         * 
+         * @param context
+         * @return
+         */
+    private boolean keepSaved(FacesContext context) {
+
+	Iterator clientIds = this.getChildState(context).keySet().iterator();
+	while (clientIds.hasNext()) {
+	    String clientId = (String) clientIds.next();
+	    Iterator messages = context.getMessages(clientId);
+	    while (messages.hasNext()) {
+		FacesMessage message = (FacesMessage) messages.next();
+		if (message.getSeverity()
+			.compareTo(FacesMessage.SEVERITY_ERROR) >= 0) {
+		    return (true);
+		}
+	    }
+	}
+	return false;
+    }
+
+    /**
+         * Perform iteration on all children components and all data rows with
+         * given visitor.
+         * 
+         * @param faces
+         * @param visitor
+         */
+    protected void iterate(FacesContext faces, ComponentVisitor visitor,
+	    Object argument) {
+
+	// stop if not rendered
+	if (!this.isRendered()) {
+	    return;
+	}
+	// reset rowIndex
+	this.captureOrigValue(faces);
+	this.setRowKey(faces, null);
+	try {
+	    Iterator fixedChildren = fixedChildren();
+	    while (fixedChildren.hasNext()) {
+		UIComponent component = (UIComponent) fixedChildren.next();
+		visitor.processComponent(faces, component, argument);
+	    }
+
+	    walk(faces, visitor, argument);
+	} catch (Exception e) {
+	    throw new FacesException(e);
+	} finally {
+	    this.setRowKey(faces, null);
+	    this.restoreOrigValue(faces);
+	}
+    }
+
+    /**
+         * Walk ( visit ) this component on all data-avare children for each
+         * row.
+         * 
+         * @param faces
+         * @param visitor
+         * @throws IOException
+         */
+    public void walk(FacesContext faces, DataVisitor visitor, Object argument)
+	    throws IOException {
+	getExtendedDataModel().walk(faces, visitor,
+		getComponentState().getRange(), argument);
+    }
+
+    protected void processDecodes(FacesContext faces, Object argument) {
+	if (!this.isRendered())
+	    return;
+	this.resetComponent(faces);
+	this.iterate(faces, decodeVisitor, argument);
+	this.decode(faces);
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#processDecodes(javax.faces.context.FacesContext)
+         */
+    public void processDecodes(FacesContext faces) {
+	processDecodes(faces, null);
+    }
+
+    /**
+         * Reset per-request fields in component.
+         * 
+         * @param faces
+         * 
+         */
+    protected void resetComponent(FacesContext faces) {
+	// resetDataModel();
+	if (null != this.childState) {
+	    childState.remove(getBaseClientId(faces));
+	}
+	this._encoded = null;
+    }
+
+    protected void processUpdates(FacesContext faces, Object argument) {
+	if (!this.isRendered())
+	    return;
+	this.iterate(faces, updateVisitor, argument);
+	ExtendedDataModel dataModel = getExtendedDataModel();
+	// If no validation errors, update values for serializable model,
+	// restored from view.
+	if (dataModel instanceof SerializableDataModel && (!keepSaved(faces))) {
+	    SerializableDataModel serializableModel = (SerializableDataModel) dataModel;
+	    serializableModel.update();
+	}
+    }
+
+    public void processUpdates(FacesContext faces) {
+	processUpdates(faces, null);
+    }
+
+    protected void processValidators(FacesContext faces, Object argument) {
+	if (!this.isRendered())
+	    return;
+	this.iterate(faces, validateVisitor, argument);
+    }
+
+    public void processValidators(FacesContext faces) {
+	processValidators(faces, null);
+    }
+
+    public void encodeBegin(FacesContext context) throws IOException {
+	resetDataModel();
+	// if(!keepSaved(context)){
+	// childState.remove(getBaseClientId(context));
+	// }
+	// Mark component as used, if parent UIData change own range states not
+	// accessed at
+	// encode phase must be unsaved.
+	getEncodedIds().add(getBaseClientId(context));
+	// getComponentState().setUsed(true);
+	super.encodeBegin(context);
+    }
+
+    /**
+         * This method must create iterator for all non-data avare children of
+         * this component ( header/footer facets for components and columns in
+         * dataTable, facets for tree etc.
+         * 
+         * @return iterator for all components not sensitive for row data.
+         */
+    protected abstract Iterator fixedChildren();
+
+    /**
+         * This method must create iterator for all children components,
+         * processed "per row" It can be children of UIColumn in dataTable,
+         * nodes in tree
+         * 
+         * @return iterator for all components processed per row.
+         */
+    protected abstract Iterator dataChildren();
+
+    private final static SavedState NullState = new SavedState();
+
+    // from RI
+    /**
+         * This class keep values of {@link EditableValueHolder} row-sensitive
+         * fields.
+         * 
+         * @author shura
+         * 
+         */
+    private final static class SavedState implements Serializable {
+
+	private Object submittedValue;
+
+	private static final long serialVersionUID = 2920252657338389849L;
+
+	Object getSubmittedValue() {
+	    return (this.submittedValue);
+	}
+
+	void setSubmittedValue(Object submittedValue) {
+	    this.submittedValue = submittedValue;
+	}
+
+	private boolean valid = true;
+
+	boolean isValid() {
+	    return (this.valid);
+	}
+
+	void setValid(boolean valid) {
+	    this.valid = valid;
+	}
+
+	private Object value;
+
+	Object getValue() {
+	    return (this.value);
+	}
+
+	public void setValue(Object value) {
+	    this.value = value;
+	}
+
+	private boolean localValueSet;
+
+	boolean isLocalValueSet() {
+	    return (this.localValueSet);
+	}
+
+	public void setLocalValueSet(boolean localValueSet) {
+	    this.localValueSet = localValueSet;
+	}
+
+	public String toString() {
+	    return ("submittedValue: " + submittedValue + " value: " + value
+		    + " localValueSet: " + localValueSet);
+	}
+
+	public void populate(EditableValueHolder evh) {
+	    this.value = evh.getLocalValue();
+	    this.valid = evh.isValid();
+	    this.submittedValue = evh.getSubmittedValue();
+	    this.localValueSet = evh.isLocalValueSet();
+	}
+
+	public void apply(EditableValueHolder evh) {
+	    evh.setValue(this.value);
+	    evh.setValid(this.valid);
+	    evh.setSubmittedValue(this.submittedValue);
+	    evh.setLocalValueSet(this.localValueSet);
+	}
+
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIData#queueEvent(javax.faces.event.FacesEvent)
+         */
+    public void queueEvent(FacesEvent event) {
+	if (event.getComponent() != this) {
+	    event = new IndexedEvent(this, event, getRowKey());
+	}
+	// Send event directly to parent, to avoid wrapping in superclass.
+	UIComponent parent = getParent();
+	if (parent == null) {
+	    throw new IllegalStateException(
+		    "No parent component for queue event");
+	} else {
+	    parent.queueEvent(event);
+	}
+    }
+
+    public void broadcast(FacesEvent event) throws AbortProcessingException {
+
+	if (!(event instanceof IndexedEvent)) {
+	    if (!broadcastLocal(event)) {
+		super.broadcast(event);
+	    }
+	    return;
+	}
+
+	// Set up the correct context and fire our wrapped event
+	IndexedEvent revent = (IndexedEvent) event;
+	Object oldRowKey = getRowKey();
+	FacesContext faces = FacesContext.getCurrentInstance();
+	captureOrigValue(faces);
+	Object eventRowKey = revent.getKey();
+	setRowKey(faces, eventRowKey);
+	FacesEvent rowEvent = revent.getTarget();
+	rowEvent.getComponent().broadcast(rowEvent);
+	// For Ajax events, keep row value.
+	if (!(rowEvent.getPhaseId() == PhaseId.RENDER_RESPONSE)) {
+	    this._ajaxRowKey = eventRowKey;
+	    this._ajaxRowKeysMap.put(getBaseClientId(faces), eventRowKey);
+	}
+	setRowKey(faces, oldRowKey);
+	restoreOrigValue(faces);
+	// }
+	return;
+    }
+
+    /**
+         * Process events targetted for concrete implementation. Hook method
+         * called from {@link #broadcast(FacesEvent)}
+         * 
+         * @param event -
+         *                processed event.
+         * @return true if event processed, false if component must continue
+         *         processing.
+         */
+    protected boolean broadcastLocal(FacesEvent event) {
+	return false;
+    }
+
+    /**
+         * Wrapper for event from child component, with value of current row
+         * key.
+         * 
+         * @author shura
+         * 
+         */
+    protected static final class IndexedEvent extends FacesEvent {
+
+	private static final long serialVersionUID = -8318895390232552385L;
+
+	private final FacesEvent target;
+
+	private final Object key;
+
+	public IndexedEvent(UIDataAdaptor owner, FacesEvent target, Object key) {
+	    super(owner);
+	    this.target = target;
+	    this.key = key;
+	}
+
+	public PhaseId getPhaseId() {
+	    return (this.target.getPhaseId());
+	}
+
+	public void setPhaseId(PhaseId phaseId) {
+	    this.target.setPhaseId(phaseId);
+	}
+
+	public boolean isAppropriateListener(FacesListener listener) {
+	    return this.target.isAppropriateListener(listener);
+	}
+
+	public void processListener(FacesListener listener) {
+	    UIDataAdaptor owner = (UIDataAdaptor) this.getComponent();
+	    Object prevIndex = owner._rowKey;
+	    try {
+		owner.setRowKey(this.key);
+		this.target.processListener(listener);
+	    } finally {
+		owner.setRowKey(prevIndex);
+	    }
+	}
+
+	public Object getKey() {
+	    return key;
+	}
+
+	public FacesEvent getTarget() {
+	    return target;
+	}
+
+    }
+
+    /**
+         * "memento" pattern class for state of component.
+         * 
+         * @author shura
+         * 
+         */
+    private static class DataState implements Serializable {
+
+	/**
+         * 
+         */
+	private static final long serialVersionUID = 17070532L;
+
+	private Object superState;
+
+	private Map componentStates = new HashMap();
+
+	private Set ajaxKeys;
+
+	public String rowKeyVar;
+
+	public String stateVar;
+
+    }
+
+    /**
+         * Serialisable model and component state per iteration of parent
+         * UIData.
+         * 
+         * @author shura
+         * 
+         */
+    private static class PerIdState implements Serializable {
+	/**
+         * 
+         */
+	private static final long serialVersionUID = 9037454770537726418L;
+
+	/**
+         * Flag setted to true if componentState implements StateHolder
+         */
+	private boolean stateInHolder = false;
+
+	/**
+         * Serializable componentState or
+         */
+	private Object componentState;
+
+	private SerializableDataModel model;
+    }
+
+    public void restoreState(FacesContext faces, Object object) {
+	DataState state = (DataState) object;
+	super.restoreState(faces, state.superState);
+	this._ajaxKeys = state.ajaxKeys;
+	this._statesMap = new HashMap();
+	this._rowKeyVar = state.rowKeyVar;
+	this._stateVar = state.stateVar;
+	// Restore serializable models and component states for all rows of
+	// parent UIData ( single if this
+	// component not child of iterable )
+	for (Iterator iter = state.componentStates.entrySet().iterator(); iter
+		.hasNext();) {
+	    Map.Entry stateEntry = (Map.Entry) iter.next();
+	    PerIdState idState = (PerIdState) stateEntry.getValue();
+	    DataComponentState compState;
+	    if (idState.stateInHolder) {
+		// TODO - change RichFaces Tree component, for remove reference
+		// to component from state.
+		compState = createComponentState();
+		((StateHolder) compState).restoreState(faces,
+			idState.componentState);
+	    } else {
+		compState = (DataComponentState) idState.componentState;
+	    }
+	    Object key = stateEntry.getKey();
+	    this._statesMap.put(key, compState);
+	    this._modelsMap.put(key, idState.model);
+	}
+    }
+
+    public Object saveState(FacesContext faces) {
+	DataState state = new DataState();
+	state.superState = super.saveState(faces);
+	state.ajaxKeys = this._ajaxKeys;
+	state.rowKeyVar = this._rowKeyVar;
+	state.stateVar = this._stateVar;
+	Set encodedIds = getEncodedIds();
+	// Save all states of component and data model for all valies of
+	// clientId, encoded in this request.
+	for (Iterator iter = this._statesMap.entrySet().iterator(); iter
+		.hasNext();) {
+	    Map.Entry stateEntry = (Map.Entry) iter.next();
+	    DataComponentState dataComponentState = ((DataComponentState) stateEntry
+		    .getValue());
+	    Object stateKey = stateEntry.getKey();
+	    if (encodedIds.isEmpty() || encodedIds.contains(stateKey)) {
+		PerIdState idState = new PerIdState();
+		idState.model = getExtendedDataModel().getSerializableModel(
+			dataComponentState.getRange());
+		// Save component state , depended if implemented interfaces.
+		if (null == dataComponentState) {
+		    idState.componentState = null;
+		} else if (dataComponentState instanceof Serializable) {
+		    idState.componentState = dataComponentState;
+		} else if (dataComponentState instanceof StateHolder) {
+		    // TODO - change RichFaces Tree component, for remove
+		    // reference to component from state.
+		    // Change this code to reference for saveAttachedState.
+		    idState.componentState = ((StateHolder) dataComponentState)
+			    .saveState(faces);
+		    idState.stateInHolder = true;
+		}
+		if (null != idState.model || null != idState.componentState) {
+		    state.componentStates.put(stateKey, idState);
+		}
+	    }
+	}
+	return state;
+    }
+
+}

Modified: branches/refactor1/ui/core/src/main/java/org/ajax4jsf/renderkit/html/RepeatRenderer.java
===================================================================
--- branches/refactor1/ui/core/src/main/java/org/ajax4jsf/renderkit/html/RepeatRenderer.java	2007-06-29 23:59:08 UTC (rev 1426)
+++ branches/refactor1/ui/core/src/main/java/org/ajax4jsf/renderkit/html/RepeatRenderer.java	2007-06-30 00:03:04 UTC (rev 1427)
@@ -29,14 +29,13 @@
 
 import org.ajax4jsf.ajax.repeat.DataVisitor;
 import org.ajax4jsf.ajax.repeat.UIRepeat;
-import org.ajax4jsf.framework.renderer.AjaxChildrenRenderer;
 import org.ajax4jsf.framework.renderer.RendererBase;
 
 /**
  * @author shura
  * 
  */
-public class RepeatRenderer extends AjaxChildrenRenderer {
+public class RepeatRenderer extends RendererBase {
 
 	public void encodeChildren(FacesContext context, UIComponent component)
 			throws IOException {




More information about the richfaces-svn-commits mailing list