[richfaces-svn-commits] JBoss Rich Faces SVN: r4651 - in trunk/sandbox/ui/columns/src/main: java/org/richfaces and 5 other directories.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Mon Dec 10 09:28:48 EST 2007


Author: andrei_exadel
Date: 2007-12-10 09:28:48 -0500 (Mon, 10 Dec 2007)
New Revision: 4651

Added:
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/ForEachIterator.java
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/SimpleForEachIterator.java
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/tag/
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/tag/AbstractColumnsTag.java
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/facelets/
   trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/facelets/ColumnsHandler.java
Modified:
   trunk/sandbox/ui/columns/src/main/config/component/columns.xml
Log:
RF-1201

Modified: trunk/sandbox/ui/columns/src/main/config/component/columns.xml
===================================================================
--- trunk/sandbox/ui/columns/src/main/config/component/columns.xml	2007-12-10 14:21:32 UTC (rev 4650)
+++ trunk/sandbox/ui/columns/src/main/config/component/columns.xml	2007-12-10 14:28:48 UTC (rev 4651)
@@ -2,7 +2,7 @@
 <!DOCTYPE components PUBLIC "-//AJAX4JSF//CDK Generator config/EN"  "https://ajax4jsf.dev.java.net/nonav/dtds/component-config.dtd" >
 <components>
 	<component>
-		<name>org.richfaces.Columns</name>
+		<name>org.richfaces.Column</name>
 		<family>org.richfaces.Column</family>
 		<classname>org.richfaces.component.html.HtmlColumns</classname>
 		<superclass>org.richfaces.component.UIColumns</superclass>
@@ -11,18 +11,49 @@
     ]]>
 		</description>
 		<renderer>
-			<name>org.richfaces.ColumnRenderer</name>
+			<name>org.richfaces.renderkit.CellRenderer</name>
 		</renderer>
 		<tag>
 			<name>columns</name>
 			<classname>org.richfaces.taglib.ColumnsTag</classname>
 			<superclass>
-				org.ajax4jsf.webapp.taglib.HtmlComponentTagBase
+				org.richfaces.tag.AbstractColumnsTag
 			</superclass>
 			<test/>
 		</tag>
-		&ui_component_attributes;
+		<taghandler generate="false">
+			<classname>org.richfaces.taglib.html.facelets.ColumnsHandler</classname>
+		</taghandler>
+		&ui_data_attributes;
 		&html_universal_attributes;
+		<property>
+			<name>value</name>
+			<classname>java.lang.Object</classname>
+			<description>
+				The current value for this component
+			</description>
+		</property>
+		<property>
+			<name>var</name>
+			<classname>java.lang.Object</classname>
+			<description>
+				The current value for this component
+			</description>
+		</property>
+		<property>
+			<name>index</name>
+			<classname>java.lang.Object</classname>
+			<description>
+				The current counter
+			</description>
+		</property>
+		<property>
+			<name>end</name>
+			<classname>java.lang.Object</classname>
+			<description>
+				Count of columns
+			</description>
+		</property>
 		<property disabled="true">
 			<name>header</name>
 		</property>
@@ -62,7 +93,6 @@
 			</description>
 			<defaultvalue>"100px"</defaultvalue>
 		</property>		
-		
 		<property>
 			<name>sortable</name>
 			<classname>boolean</classname>
@@ -75,6 +105,8 @@
 			<name>sortExpression</name>
 			<classname>java.lang.String</classname>
 			<description>Attribute defines a bean property which is used for sorting of a column</description>
-		</property>		
+		</property>
 	</component>
+	
+	
 </components>

Added: trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/ForEachIterator.java
===================================================================
--- trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/ForEachIterator.java	                        (rev 0)
+++ trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/ForEachIterator.java	2007-12-10 14:28:48 UTC (rev 4651)
@@ -0,0 +1,20 @@
+/*
+ * ForEachIterator.java		Date created: 07.12.2007
+ * Last modified by: $Author$
+ * $Revision$	$Date$
+ */
+
+package org.richfaces.iterator;
+
+import javax.servlet.jsp.JspTagException;
+
+/**
+ * TODO Class description goes here.
+ * @author "Andrey Markavtsov"
+ *
+ */
+public interface ForEachIterator {
+    public boolean hasNext() throws JspTagException;
+
+    public Object next() throws JspTagException;
+}

Added: trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/SimpleForEachIterator.java
===================================================================
--- trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/SimpleForEachIterator.java	                        (rev 0)
+++ trunk/sandbox/ui/columns/src/main/java/org/richfaces/iterator/SimpleForEachIterator.java	2007-12-10 14:28:48 UTC (rev 4651)
@@ -0,0 +1,242 @@
+/*
+ * ForEachIterator.java		Date created: 06.12.2007
+ * Last modified by: $Author$
+ * $Revision$	$Date$
+ */
+
+package org.richfaces.iterator;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.jsp.JspTagException;
+
+/**
+ * TODO Class description goes here.
+ * 
+ * @author "Andrey Markavtsov"
+ * 
+ */
+public class SimpleForEachIterator implements ForEachIterator {
+
+    private Iterator i;
+
+    public static ForEachIterator supportedTypeForEachIterator(Object o)
+	    throws JspTagException {
+
+	/*
+	 * This is, of necessity, just a big, simple chain, matching in order.
+	 * Since we are passed on Object because of all the various types we
+	 * support, we cannot rely on the language's mechanism for resolving
+	 * overloaded methods. (Method overloading resolves via early binding,
+	 * so the type of the 'o' reference, not the type of the eventual value
+	 * that 'o' references, is all that's available.)
+	 * 
+	 * Currently, we 'match' on the object we have through an if/else chain
+	 * that picks the first interface (or class match) found for an Object.
+	 */
+
+	ForEachIterator items;
+
+	if (o instanceof Object[])
+	    items = toForEachIterator((Object[]) o);
+	else if (o instanceof boolean[])
+	    items = toForEachIterator((boolean[]) o);
+	else if (o instanceof byte[])
+	    items = toForEachIterator((byte[]) o);
+	else if (o instanceof char[])
+	    items = toForEachIterator((char[]) o);
+	else if (o instanceof short[])
+	    items = toForEachIterator((short[]) o);
+	else if (o instanceof int[])
+	    items = toForEachIterator((int[]) o);
+	else if (o instanceof long[])
+	    items = toForEachIterator((long[]) o);
+	else if (o instanceof float[])
+	    items = toForEachIterator((float[]) o);
+	else if (o instanceof double[])
+	    items = toForEachIterator((double[]) o);
+	else if (o instanceof Collection)
+	    items = toForEachIterator((Collection) o);
+	else if (o instanceof Iterator)
+	    items = toForEachIterator((Iterator) o);
+	else if (o instanceof Enumeration)
+	    items = toForEachIterator((Enumeration) o);
+	else if (o instanceof Map)
+	    items = toForEachIterator((Map) o);
+	/*
+	 * else if (o instanceof ResultSet) items =
+	 * toForEachIterator((ResultSet) o);
+	 */
+	else if (o instanceof String)
+	    items = toForEachIterator((String) o);
+	else
+	    items = toForEachIterator(o);
+
+	return (items);
+    }
+    
+    
+    /*
+     * Creates a ForEachIterator of Integers from 'begin' to 'end'
+     * in support of cases where our tag handler isn't passed an
+     * explicit collection over which to iterate.
+     */
+    public static ForEachIterator beginEndForEachIterator(int end) {
+        /*
+         * To plug into existing support, we need to keep 'begin', 'end',
+         * and 'step' as they are.  So we'll simply create an Integer[]
+         * from 0 to 'end', inclusive, and let the existing implementation
+         * handle the subsetting and stepping operations.  (Other than
+         * localizing the cost of creating this Integer[] to the start
+         * of the operation instead of spreading it out over the lifetime
+         * of the iteration, this implementation isn't worse than one that
+         * created new Integers() as needed from next().  Such an adapter
+         * to ForEachIterator could easily be written but, like I said,
+         * wouldn't provide much benefit.)
+         */
+        Integer[] ia = new Integer[end+1];
+        for (int i = 0; i < end; i++)
+            ia[i] = new Integer(i);
+        return new SimpleForEachIterator(Arrays.asList(ia).iterator());
+    }
+
+
+    // *********************************************************************
+    // Private conversion methods to handle the various types we support
+
+    // catch-all method whose invocation currently signals a 'matching error'
+    protected static ForEachIterator toForEachIterator(Object o)
+	    throws JspTagException {
+	throw new JspTagException("FOREACH_BAD_ITEMS");
+    }
+
+    // returns an iterator over an Object array (via List)
+    protected static ForEachIterator toForEachIterator(Object[] a) {
+	return new SimpleForEachIterator(Arrays.asList(a).iterator());
+    }
+
+    // returns an iterator over a boolean[] array, wrapping items in Boolean
+    protected static ForEachIterator toForEachIterator(boolean[] a) {
+	Boolean[] wrapped = new Boolean[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Boolean(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a byte[] array, wrapping items in Byte
+    protected static ForEachIterator toForEachIterator(byte[] a) {
+	Byte[] wrapped = new Byte[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Byte(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a char[] array, wrapping items in Character
+    protected static ForEachIterator toForEachIterator(char[] a) {
+	Character[] wrapped = new Character[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Character(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a short[] array, wrapping items in Short
+    protected static ForEachIterator toForEachIterator(short[] a) {
+	Short[] wrapped = new Short[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Short(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over an int[] array, wrapping items in Integer
+    protected static ForEachIterator toForEachIterator(int[] a) {
+	Integer[] wrapped = new Integer[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Integer(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a long[] array, wrapping items in Long
+    protected static ForEachIterator toForEachIterator(long[] a) {
+	Long[] wrapped = new Long[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Long(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a float[] array, wrapping items in Float
+    protected static ForEachIterator toForEachIterator(float[] a) {
+	Float[] wrapped = new Float[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Float(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // returns an iterator over a double[] array, wrapping items in Double
+    protected static ForEachIterator toForEachIterator(double[] a) {
+	Double[] wrapped = new Double[a.length];
+	for (int i = 0; i < a.length; i++)
+	    wrapped[i] = new Double(a[i]);
+	return new SimpleForEachIterator(Arrays.asList(wrapped).iterator());
+    }
+
+    // retrieves an iterator from a Collection
+    protected static ForEachIterator toForEachIterator(Collection c) {
+	return new SimpleForEachIterator(c.iterator());
+    }
+
+    // simply passes an Iterator through...
+    protected static ForEachIterator toForEachIterator(Iterator i) {
+	return new SimpleForEachIterator(i);
+    }
+
+    // converts an Enumeration to an Iterator via a local adapter
+    protected static ForEachIterator toForEachIterator(Enumeration e) {
+
+	// local adapter
+	class EnumerationAdapter implements ForEachIterator {
+	    private Enumeration e;
+
+	    public EnumerationAdapter(Enumeration e) {
+		this.e = e;
+	    }
+
+	    public boolean hasNext() {
+		return e.hasMoreElements();
+	    }
+
+	    public Object next() {
+		return e.nextElement();
+	    }
+	}
+
+	return new EnumerationAdapter(e);
+    }
+
+    // retrieves an iterator over the Map.Entry items in a Map
+    protected static ForEachIterator toForEachIterator(Map m) {
+	return new SimpleForEachIterator(m.entrySet().iterator());
+    }
+
+    protected static ForEachIterator toForEachIterator(String s) {
+	StringTokenizer st = new StringTokenizer(s, ",");
+	return toForEachIterator(st); // convert from Enumeration
+    }
+
+    public SimpleForEachIterator(Iterator i) {
+	this.i = i;
+    }
+
+    public boolean hasNext() {
+	return i.hasNext();
+    }
+
+    public Object next() {
+	return i.next();
+    }
+
+}

Added: trunk/sandbox/ui/columns/src/main/java/org/richfaces/tag/AbstractColumnsTag.java
===================================================================
--- trunk/sandbox/ui/columns/src/main/java/org/richfaces/tag/AbstractColumnsTag.java	                        (rev 0)
+++ trunk/sandbox/ui/columns/src/main/java/org/richfaces/tag/AbstractColumnsTag.java	2007-12-10 14:28:48 UTC (rev 4651)
@@ -0,0 +1,1394 @@
+/*
+ * AbstractColumnsTag.java		Date created: 26.11.2007
+ * Last modified by: $Author$
+ * $Revision$	$Date$
+ */
+
+package org.richfaces.tag;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.webapp.UIComponentClassicTagBase;
+import javax.faces.webapp.UIComponentTag;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.BodyContent;
+import javax.servlet.jsp.tagext.IterationTag;
+
+import org.richfaces.iterator.ForEachIterator;
+import org.richfaces.iterator.SimpleForEachIterator;
+
+
+/**
+ * Class provides implementation for columns tag
+ * 
+ * @author "Andrey Markavtsov"
+ * 
+ */
+public abstract class AbstractColumnsTag extends UIComponentClassicTagBase
+	implements IterationTag {
+    
+    /** Column component type */
+    private static final String _componentType = "org.richfaces.Column";
+
+    /** Current column counter */
+    private Integer index = -1;
+
+    /** Data table */
+    private UIComponent dataTable;
+
+    /** Previous created column */
+    private UIComponent previous;
+
+    /**
+     * <p>
+     * The {@link UIComponent} that is being encoded by this tag, if any.
+     * </p>
+     */
+    private UIComponent component = null;
+
+    /** Flag indicates if columns are already created */
+    private boolean created = false;
+
+    /** Iterator for columns's tag value attribute */
+    protected ForEachIterator items; // our 'digested' items
+
+    /** Value attribute value */
+    protected Object rawItems; // our 'raw' items
+
+    /** End attribute - defines count of column if value attr hasn't been defined*/
+    private ValueExpression end;
+
+    /** Index attr - defines page variable for current column counter */
+    private ValueExpression _index;
+
+    /** Var attr - defines page variable for current item */
+    private String indexId;
+
+    /** Integer value of end attr. */
+    private Integer _end;
+
+    /** String value of var attr */
+    private String itemId = null;
+
+    /** Expression for var item */
+    private IteratedExpression iteratedExpression;
+
+    /**
+     * <p>
+     * The <code>Lst</code> of {@link UIComponent} ids created or located by
+     * nested {@link UIComponentTag}s while processing the current request.
+     * </p>
+     */
+    // public List<String> createdComponents = null;
+    /**
+     * Caches the nearest enclosing {@link UIComponentRichClassicTagBase} of
+     * this tag. This is used for duplicate id detection.
+     */
+    private UIComponentClassicTagBase parentTag = null;
+
+    /**
+     * <p>
+     * Return the {@link UIComponent} instance that is associated with this tag
+     * instance. This method is designed to be used by tags nested within this
+     * tag, and only returns useful results between the execution of
+     * <code>doStartTag()</code> and <code>doEndTag()</code> on this tag
+     * instance.
+     * </p>
+     */
+    public UIComponent getComponentInstance() {
+
+	return (this.component);
+
+    }
+
+    /**
+     * <p>
+     * The request scope attribute under which a component tag stack for the
+     * current request will be maintained.
+     * </p>
+     */
+    private static final String COMPONENT_TAG_STACK_ATTR = "javax.faces.webapp.COMPONENT_TAG_STACK";
+
+    /**
+     * <p>
+     * The value binding expression (if any) used to wire up this component to a
+     * {@link UIComponent} property of a JavaBean class.
+     * </p>
+     */
+    private ValueExpression binding = null;
+
+    /**
+     * <p>
+     * An override for the rendered attribute associated with our
+     * {@link UIComponent}.
+     * </p>
+     */
+    private ValueExpression rendered = null;
+
+    /**
+     * style CSS style(s) is/are to be applied when this component is rendered
+     */
+    private ValueExpression _style;
+
+    /**
+     * CSS style(s) is/are to be applied when this component is rendered Setter
+     * for style
+     * 
+     * @param style -
+     *                new value
+     */
+    public void setStyle(ValueExpression __style) {
+	this._style = __style;
+    }
+
+    /**
+     * breakBefore if "true" next column begins from the first row
+     */
+    private ValueExpression _breakBefore;
+
+    /**
+     * if "true" next column begins from the first row Setter for breakBefore
+     * 
+     * @param breakBefore -
+     *                new value
+     */
+    public void setBreakBefore(ValueExpression __breakBefore) {
+	this._breakBefore = __breakBefore;
+    }
+
+    /**
+     * colspan Corresponds to the HTML colspan attribute
+     */
+    private ValueExpression _colspan;
+
+    /**
+     * Corresponds to the HTML colspan attribute Setter for colspan
+     * 
+     * @param colspan -
+     *                new value
+     */
+    public void setColspan(ValueExpression __colspan) {
+	this._colspan = __colspan;
+    }
+
+    /**
+     * dir Direction indication for text that does not inherit directionality.
+     * Valid values are "LTR" (left-to-right) and "RTL" (right-to-left)
+     */
+    private ValueExpression _dir;
+
+    /**
+     * Direction indication for text that does not inherit directionality. Valid
+     * values are "LTR" (left-to-right) and "RTL" (right-to-left) Setter for dir
+     * 
+     * @param dir -
+     *                new value
+     */
+    public void setDir(ValueExpression __dir) {
+	this._dir = __dir;
+    }
+
+    /**
+     * first A zero-relative row number of the first row to display
+     */
+    private ValueExpression _first;
+
+    /**
+     * A zero-relative row number of the first row to display Setter for first
+     * 
+     * @param first -
+     *                new value
+     */
+    public void setFirst(ValueExpression __first) {
+	this._first = __first;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.faces.webapp.UIComponentClassicTagBase#createComponent(javax.faces.context.FacesContext,
+     *      java.lang.String)
+     */
+    @Override
+    protected UIComponent createComponent(FacesContext context, String newId)
+	    throws JspException {
+	// TODO Auto-generated method stub
+	return context.getApplication().createComponent(_componentType);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.faces.webapp.UIComponentTagBase#getComponentType()
+     */
+    @Override
+    public String getComponentType() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.faces.webapp.UIComponentTagBase#getRendererType()
+     */
+    @Override
+    public String getRendererType() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    /**
+     * footerClass Space-separated list of CSS style class(es) that are be
+     * applied to any footer generated for this table
+     */
+    private ValueExpression _footerClass;
+
+    /**
+     * Space-separated list of CSS style class(es) that are be applied to any
+     * footer generated for this table Setter for footerClass
+     * 
+     * @param footerClass -
+     *                new value
+     */
+    public void setFooterClass(ValueExpression __footerClass) {
+	this._footerClass = __footerClass;
+    }
+
+    /**
+     * headerClass Space-separated list of CSS style class(es) that are be
+     * applied to any header generated for this table
+     */
+    private ValueExpression _headerClass;
+
+    /**
+     * Space-separated list of CSS style class(es) that are be applied to any
+     * header generated for this table Setter for headerClass
+     * 
+     * @param headerClass -
+     *                new value
+     */
+    public void setHeaderClass(ValueExpression __headerClass) {
+	this._headerClass = __headerClass;
+    }
+
+    /**
+     * lang Code describing the language used in the generated markup for this
+     * component
+     */
+    private ValueExpression _lang;
+
+    /**
+     * Code describing the language used in the generated markup for this
+     * component Setter for lang
+     * 
+     * @param lang -
+     *                new value
+     */
+    public void setLang(ValueExpression __lang) {
+	this._lang = __lang;
+    }
+
+    /**
+     * rows A number of rows to display, or zero for all remaining rows in the
+     * table
+     */
+    private ValueExpression _rows;
+
+    /**
+     * A number of rows to display, or zero for all remaining rows in the table
+     * Setter for rows
+     * 
+     * @param rows -
+     *                new value
+     */
+    public void setRows(ValueExpression __rows) {
+	this._rows = __rows;
+    }
+
+    /**
+     * rowspan Corresponds to the HTML rowspan attribute
+     */
+    private ValueExpression _rowspan;
+
+    /**
+     * Corresponds to the HTML rowspan attribute Setter for rowspan
+     * 
+     * @param rowspan -
+     *                new value
+     */
+    public void setRowspan(ValueExpression __rowspan) {
+	this._rowspan = __rowspan;
+    }
+
+    /**
+     * sortExpression Attribute defines a bean property which is used for
+     * sorting of a column
+     */
+    private ValueExpression _sortExpression;
+
+    /**
+     * Attribute defines a bean property which is used for sorting of a column
+     * Setter for sortExpression
+     * 
+     * @param sortExpression -
+     *                new value
+     */
+    public void setSortExpression(ValueExpression __sortExpression) {
+	this._sortExpression = __sortExpression;
+    }
+
+    /**
+     * sortable Boolean attribute. If "true" it's possible to sort the column
+     * content after click on the header. Default value is "true"
+     */
+    private ValueExpression _sortable;
+
+    /**
+     * Boolean attribute. If "true" it's possible to sort the column content
+     * after click on the header. Default value is "true" Setter for sortable
+     * 
+     * @param sortable -
+     *                new value
+     */
+    public void setSortable(ValueExpression __sortable) {
+	this._sortable = __sortable;
+    }
+
+    /**
+     * styleClass Corresponds to the HTML class attribute
+     */
+    private ValueExpression _styleClass;
+
+    /**
+     * Corresponds to the HTML class attribute Setter for styleClass
+     * 
+     * @param styleClass -
+     *                new value
+     */
+    public void setStyleClass(ValueExpression __styleClass) {
+	this._styleClass = __styleClass;
+    }
+
+    /**
+     * title Advisory title information about markup elements generated for this
+     * component
+     */
+    private ValueExpression _title;
+
+    /**
+     * Advisory title information about markup elements generated for this
+     * component Setter for title
+     * 
+     * @param title -
+     *                new value
+     */
+    public void setTitle(ValueExpression __title) {
+	this._title = __title;
+    }
+
+    /**
+     * value The current value for this component
+     */
+    private ValueExpression _value;
+
+    /**
+     * The current value for this component Setter for value
+     * 
+     * @param value -
+     *                new value
+     */
+    public void setValue(ValueExpression __value) {
+	this._value = __value;
+    }
+
+    /**
+     * var A request-scope attribute via which the data object for the current
+     * row will be used when iterating
+     */
+    private ValueExpression _var;
+
+    /**
+     * A request-scope attribute via which the data object for the current row
+     * will be used when iterating Setter for var
+     * 
+     * @param var -
+     *                new value
+     */
+    public void setVar(ValueExpression __var) {
+	this._var = __var;
+    }
+
+    /*
+     * width Attribute defines width of column. Default value is "100px".
+     */
+    private ValueExpression _width;
+
+    /**
+     * Attribute defines width of column. Default value is "100px". Setter for
+     * width
+     * 
+     * @param width -
+     *                new value
+     */
+    public void setWidth(ValueExpression __width) {
+	this._width = __width;
+    }
+
+    /**
+     * Default constructor for AbstractColumnsTag class
+     */
+    public AbstractColumnsTag() {
+	super();
+    }
+
+    /**
+     * <p>
+     * Set an override for the rendered attribute.
+     * </p>
+     * 
+     * @param rendered
+     *                The new value for rendered attribute
+     */
+    public void setRendered(ValueExpression rendered) {
+	this.rendered = rendered;
+    }
+
+    /**
+     * <p>
+     * Set the value expression for our component.
+     * </p>
+     * 
+     * @param binding
+     *                The new value expression
+     * 
+     * @throws JspException
+     *                 if an error occurs
+     */
+    public void setBinding(ValueExpression binding) throws JspException {
+	this.binding = binding;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.jsp.tagext.BodyTagSupport#doAfterBody()
+     */
+    @Override
+    public int doAfterBody() throws JspException {
+
+	 if (hasNext()) {
+	    loop();
+	} else
+	    return EVAL_BODY_INCLUDE;
+
+	exposeVariables();
+
+	return EVAL_BODY_AGAIN;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.faces.webapp.UIComponentClassicTagBase#addFacet(java.lang.String)
+     */
+    protected void addFacet(String name) {
+	super.addFacet(name);
+	
+	// add created component in facet in childrenList to reduce duplicated Id exp. 
+	if (this.component != null && this.component.getFacets() != null) {
+	    Map<String, UIComponent> facets = this.component.getFacets();
+	    Iterator<UIComponent> it = facets.values().iterator();
+	    while (it.hasNext()) {
+		super.addChild(it.next());
+	    }
+	}
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.jsp.tagext.BodyTagSupport#doInitBody()
+     */
+    @Override
+    public void doInitBody() throws JspException {
+	// TODO Auto-generated method stub
+	super.doInitBody();
+
+    }
+
+    /**
+     * Removes any attributes that this LoopTagSupport set.
+     * 
+     * <p>
+     * These attributes are intended to support scripting variables with NESTED
+     * scope, so we don't want to pollute attribute space by leaving them lying
+     * around.
+     */
+    public void doFinally() {
+	/*
+	 * Make sure to un-expose variables, restoring them to their prior
+	 * values, if applicable.
+	 */
+	unExposeVariables();
+    }
+
+    /**
+     * Removes page attributes that we have exposed and, if applicable, restores
+     * them to their prior values (and scopes).
+     */
+    private void unExposeVariables() {
+	// "nested" variables are now simply removed
+	if (itemId != null) {
+	    pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
+	    VariableMapper vm = pageContext.getELContext().getVariableMapper();
+	    if (vm != null)
+		vm.setVariable(itemId, null);
+	}
+	if (indexId != null) {
+	    pageContext.removeAttribute(indexId, PageContext.PAGE_SCOPE);
+	    VariableMapper vm = pageContext.getELContext().getVariableMapper();
+	    if (vm != null)
+		vm.setVariable(indexId, null);
+	}
+    }
+
+    /**
+     * Method is invoking by each iteration of body again rendering  
+     * @throws JspTagException
+     */
+    private void loop() throws JspTagException {
+	if (!atFirst()) {
+	    popUIComponentClassicTagBase();
+	}
+	UIComponent component = createColumn();
+	pushUIComponentClassicTagBase(this);
+	dataTable.getChildren().add(component);
+
+	next();
+    }
+
+    /**
+     * Creates column instance
+     * @return
+     */
+    private UIComponent createColumn() {
+	UIComponent component = getFacesContext().getApplication()
+		.createComponent(_componentType);
+	component.setId(getFacesContext().getViewRoot().createUniqueId());
+
+	initColumnByThis(component);
+		
+	this.component = component;
+	this.parentTag = getParentUIComponentClassicTagBase(pageContext);
+	this.previous = component;
+
+	return component;
+    }
+    
+    /**
+     * Inits column component by columns tag attrs 
+     * @param column
+     */
+    void initColumnByThis (UIComponent column) {
+	column.setValueExpression("style",_style);
+	column.setValueExpression("styleClass",_styleClass);
+	column.setValueExpression("colspan",_colspan);
+	column.setValueExpression("rowspan",_rowspan);
+	column.setValueExpression("breakBefore",_breakBefore);
+	column.setValueExpression("headerClass",_headerClass);
+	column.setValueExpression("footerClass",_footerClass);
+	column.setValueExpression("width",_width);
+	column.setValueExpression("sortable",_sortable);
+	column.setValueExpression("sortExpression",_sortExpression);
+	column.setValueExpression("rendered",rendered);
+    }
+    
+
+    /**
+     * Returns true if this is the first loop of columns tag
+     * @return
+     */
+    private boolean atFirst() {
+	return (index == -1);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
+     */
+    @Override
+    public int doStartTag() throws JspException {
+	
+	prepare();
+	
+	if (created) {
+	    dataTable.getChildren().clear();
+	    created = false;
+	}
+
+	// get the item we're interested in
+	if (!hasNext()) {
+	    return SKIP_BODY;
+	}
+
+	loop();
+
+	exposeVariables();
+
+	return EVAL_BODY_INCLUDE;
+    }
+
+    /**
+     * Method prepares all we need for starting of tag rendering 
+     * @throws JspTagException
+     */
+    private void prepare() throws JspTagException {
+	dataTable = getParentUIComponentClassicTagBase(pageContext)
+		.getComponentInstance();
+	created = (dataTable.getChildCount() > 0);
+
+	initVariables();
+
+	// produce the right sort of ForEachIterator
+	if (_value != null) {
+	    // If this is a deferred expression, make a note and get
+	    // the 'items' instance.
+	    if (_value instanceof ValueExpression) {
+		rawItems = _value.getValue(pageContext.getELContext());
+	    }
+	    // extract an iterator over the 'items' we've got
+	    items = SimpleForEachIterator
+		    .supportedTypeForEachIterator(rawItems);
+	} else {
+	    // no 'items', so use 'begin' and 'end'
+	    items = SimpleForEachIterator.beginEndForEachIterator(_end);
+	}
+
+	/*
+	 * ResultSet no more supported in <c:forEach> // step must be 1 when
+	 * ResultSet is passed in if (rawItems instanceof ResultSet && step !=
+	 * 1) throw new JspTagException(
+	 * Resources.getMessage("FOREACH_STEP_NO_RESULTSET"));
+	 */
+
+    }
+
+    /**
+     * Extracts integer value from end attr 
+     */
+    private void initEnd() {
+	if (end != null) {
+	    if (end instanceof ValueExpression)
+		try {
+		    String t = (String) end.getValue(getELContext());
+		    _end = Integer.parseInt(t);
+		    if (_end < 0) {
+			_end = 0;   // If end is negative set up zero
+		    }
+		} catch (Exception e) {
+		    _end = 0;
+		}
+	} else {
+	    _end = 0;
+	}
+    }
+
+    /**
+     * Extracts string value from var attr
+     */
+    private void initVar() {
+	if (_var != null) {
+	    try {
+		itemId = (String) _var.getValue(getELContext());
+	    } catch (ClassCastException e) {
+		itemId = null;
+	    }
+
+	}
+    }
+    /**
+     * Extracts string value from index attr
+     */
+    private void initIndex() {
+	if (_index != null) {
+	    try {
+		indexId = (String) _index.getValue(getELContext());
+	    } catch (ClassCastException e) {
+		indexId = null;
+	    }
+
+	}
+    }
+
+    /**
+     * Extracts tags attributes values
+     */
+    private void initVariables() {
+	initEnd();
+	initIndex();
+	initVar();
+    }
+
+    /**
+     * Return true if we didn't complete column's count  
+     * @return
+     * @throws JspTagException
+     */
+    private boolean hasNext() throws JspTagException {
+	return items.hasNext();
+    }
+
+    /**
+     * Iterate to next column 
+     * @return
+     * @throws JspTagException
+     */
+    private Object next() throws JspTagException {
+	Object o = items.next();
+	index++;
+	return o;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.jsp.tagext.BodyTagSupport#getBodyContent()
+     */
+    @Override
+    public BodyContent getBodyContent() {
+	// TODO Auto-generated method stub
+	return super.getBodyContent();
+    }
+
+    /* (non-Javadoc)
+     * @see javax.faces.webapp.UIComponentClassicTagBase#setProperties(javax.faces.component.UIComponent)
+     */
+    protected void setProperties(UIComponent component) {
+
+    }
+
+    /* (non-Javadoc)
+     * @see javax.faces.webapp.UIComponentClassicTagBase#hasBinding()
+     */
+    protected boolean hasBinding() {
+	return false;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.faces.webapp.UIComponentClassicTagBase#doEndTag()
+     */
+    @Override
+    public int doEndTag() throws JspException {
+	if (!atFirst()) {
+	    popUIComponentClassicTagBase();
+	}
+	return EVAL_PAGE;
+    }
+
+    /**
+     * Sets page request variables 
+     * @throws JspTagException
+     */
+    private void exposeVariables() throws JspTagException {
+
+	/*
+	 * We need to support null items returned from next(); we do this simply
+	 * by passing such non-items through to the scoped variable as
+	 * effectively 'null' (that is, by calling removeAttribute()).
+	 * 
+	 * Also, just to be defensive, we handle the case of a null 'status'
+	 * object as well.
+	 * 
+	 * We call getCurrent() and getLoopStatus() (instead of just using
+	 * 'item' and 'status') to bridge to subclasses correctly. A subclass
+	 * can override getCurrent() or getLoopStatus() but still depend on our
+	 * doStartTag() and doAfterBody(), which call this method
+	 * (exposeVariables()), to expose 'item' and 'status' correctly.
+	 */
+
+	// Set up var variable
+	
+	if (itemId != null) {
+	    if (index == null)
+		pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
+	    else if (_value != null) {
+		VariableMapper vm = pageContext.getELContext()
+			.getVariableMapper();
+		if (vm != null) {
+		    ValueExpression ve = getVarExpression(_value);
+		    vm.setVariable(itemId, ve);
+		}
+	    } else
+		pageContext.setAttribute(itemId, index);
+	}
+
+	// Set up index variable
+	
+	if (indexId != null) {
+	    if (index == null)
+		pageContext.removeAttribute(indexId, PageContext.PAGE_SCOPE);
+	    else {
+		IteratedIndexExpression indexExpression = new IteratedIndexExpression(
+			index);
+		VariableMapper vm = pageContext.getELContext()
+			.getVariableMapper();
+		if (vm != null) {
+		    vm.setVariable(indexId, indexExpression);
+		}
+		pageContext.setAttribute(indexId, index);
+	    }
+	}
+
+    }
+
+    /**
+     * Return expression for page variables 
+     * @param expr
+     * @return
+     */
+    private ValueExpression getVarExpression(ValueExpression expr) {
+	Object o = expr.getValue(pageContext.getELContext());
+	if (o.getClass().isArray() || o instanceof List) {
+	    return new IndexedValueExpression(_value, index);
+	}
+
+	if (o instanceof Collection || o instanceof Iterator
+		|| o instanceof Enumeration || o instanceof Map
+		|| o instanceof String) {
+
+	    if (iteratedExpression == null) {
+		iteratedExpression = new IteratedExpression(_value, getDelims());
+	    }
+	    return new IteratedValueExpression(iteratedExpression, index);
+	}
+
+	throw new ELException("FOREACH_BAD_ITEMS");
+    }
+
+    /*
+     * Get the delimiter for string tokens. Used only for constructing the
+     * deferred expression for it.
+     */
+    protected String getDelims() {
+	return ",";
+    }
+
+    /**
+     * <p>
+     * Pop the top {@link UIComponentTag} instance off of our component tag
+     * stack, deleting the stack if this was the last entry.
+     * </p>
+     */
+    private void popUIComponentClassicTagBase() {
+	FacesContext context = FacesContext.getCurrentInstance();
+	Map<String, Object> requestMap = context.getExternalContext()
+		.getRequestMap();
+	List list = (List) requestMap.get(COMPONENT_TAG_STACK_ATTR);
+	if (list != null) {
+	    list.remove(list.size() - 1);
+	    if (list.size() < 1) {
+		requestMap.remove(COMPONENT_TAG_STACK_ATTR);
+	    }
+	}
+
+    }
+
+    /**
+     * <p>
+     * Push the specified {@link UIComponentTag} instance onto our component tag
+     * stack, creating a stack if necessary.
+     * </p>
+     */
+    private void pushUIComponentClassicTagBase(UIComponentClassicTagBase tag) {
+	FacesContext context = FacesContext.getCurrentInstance();
+	Map<String, Object> requestMap = context.getExternalContext()
+		.getRequestMap();
+	List<UIComponentClassicTagBase> list = TypedCollections
+		.dynamicallyCastList((List) requestMap
+			.get(COMPONENT_TAG_STACK_ATTR),
+			UIComponentClassicTagBase.class);
+	if (list == null) {
+	    // noinspection CollectionWithoutInitialCapacity
+	    list = new ArrayList<UIComponentClassicTagBase>();
+	    requestMap.put(COMPONENT_TAG_STACK_ATTR, list);
+	}
+	list.add(tag);
+
+    }
+
+    /**
+     * @return the end
+     */
+    public ValueExpression getEnd() {
+	return end;
+    }
+
+    /**
+     * @param end
+     *                the end to set
+     */
+    public void setEnd(ValueExpression end) {
+	this.end = end;
+    }
+
+    /**
+     * @return the index
+     */
+    public ValueExpression getIndex() {
+	return _index;
+    }
+
+    /**
+     * @param index
+     *                the index to set
+     */
+    public void setIndex(ValueExpression index) {
+	this._index = index;
+    }
+
+}
+
+class TypedCollections {
+
+    /**
+     * Dynamically check that the members of the collection are all instances of
+     * the given type (or null).
+     */
+    private static boolean checkCollectionMembers(Collection<?> c, Class<?> type) {
+	for (Object element : c) {
+	    if (element != null && !type.isInstance(element)) {
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    /**
+     * Dynamically check that the members of the collection are all instances of
+     * the given type (or null), and that the collection itself is of the given
+     * collection type.
+     * 
+     * @param <E>
+     *                the collection's element type
+     * @param c
+     *                the collection to cast
+     * @param type
+     *                the class of the collection's element type.
+     * @return the dynamically-type checked collection.
+     * @throws java.lang.ClassCastException
+     */
+    @SuppressWarnings("unchecked")
+    static <E, TypedC extends Collection<E>> TypedC dynamicallyCastCollection(
+	    Collection<?> c, Class<E> type, Class<TypedC> collectionType) {
+	if (c == null)
+	    return null;
+	if (!collectionType.isInstance(c))
+	    throw new ClassCastException(c.getClass().getName());
+	assert checkCollectionMembers(c, type) : "The collection contains members with a type other than "
+		+ type.getName();
+
+	return collectionType.cast(c);
+    }
+
+    /**
+     * Dynamically check that the members of the list are all instances of the
+     * given type (or null).
+     * 
+     * @param <E>
+     *                the list's element type
+     * @param list
+     *                the list to cast
+     * @param type
+     *                the class of the list's element type.
+     * @return the dynamically-type checked list.
+     * @throws java.lang.ClassCastException
+     */
+    @SuppressWarnings("unchecked")
+    static <E> List<E> dynamicallyCastList(List<?> list, Class<E> type) {
+	return dynamicallyCastCollection(list, type, List.class);
+    }
+
+    /**
+     * Dynamically check that the members of the set are all instances of the
+     * given type (or null).
+     * 
+     * @param <E>
+     *                the set's element type
+     * @param set
+     *                the set to cast
+     * @param type
+     *                the class of the set's element type.
+     * @return the dynamically-type checked set.
+     * @throws java.lang.ClassCastException
+     */
+    @SuppressWarnings("unchecked")
+    static <E> Set<E> dynamicallyCastSet(Set<?> set, Class<E> type) {
+	return dynamicallyCastCollection(set, type, Set.class);
+    }
+
+    /**
+     * Dynamically check that the keys and values in the map are all instances
+     * of the correct types (or null).
+     * 
+     * @param <K>
+     *                the map's key type
+     * @param <V>
+     *                the map's value type
+     * @param map
+     *                the map to cast
+     * @param keyType
+     *                the class of the map's key type.
+     * @param keyType
+     *                the class of the map's key type.
+     * @return the dynamically-type checked map.
+     * @throws java.lang.ClassCastException
+     */
+    @SuppressWarnings("unchecked")
+    static <K, V> Map<K, V> dynamicallyCastMap(Map<?, ?> map, Class<K> keyType,
+	    Class<V> valueType) {
+	if (map == null) {
+	    return null;
+	}
+	assert checkCollectionMembers(map.keySet(), keyType) : "The map contains keys with a type other than "
+		+ keyType.getName();
+	assert checkCollectionMembers(map.values(), valueType) : "The map contains values with a type other than "
+		+ valueType.getName();
+
+	return (Map<K, V>) map;
+    }
+}
+
+/**
+ * @author Kin-man Chung
+ * @version $Id: IteratedExpression.java,v 1.3 2005/12/08 01:20:43 kchung Exp $
+ */
+final class IteratedExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final ValueExpression orig;
+    protected final String delims;
+
+    private Object base;
+    private int index;
+    private Iterator iter;
+
+    public IteratedExpression(ValueExpression orig, String delims) {
+	this.orig = orig;
+	this.delims = delims;
+    }
+
+    /**
+     * Evaluates the stored ValueExpression and return the indexed item.
+     * 
+     * @param context
+     *                The ELContext used to evaluate the ValueExpression
+     * @param i
+     *                The index of the item to be retrieved
+     */
+    public Object getItem(ELContext context, int i) {
+
+	if (base == null) {
+	    base = orig.getValue(context);
+	    if (base == null) {
+		return null;
+	    }
+	    iter = toIterator(base);
+	    index = 0;
+	}
+	if (index > i) {
+	    // Restart from index 0
+	    iter = toIterator(base);
+	    index = 0;
+	}
+	while (iter.hasNext()) {
+	    Object item = iter.next();
+	    if (index++ == i) {
+		return item;
+	    }
+	}
+	return null;
+    }
+
+    public ValueExpression getValueExpression() {
+	return orig;
+    }
+
+    private Iterator toIterator(final Object obj) {
+
+	Iterator iter;
+	if (obj instanceof String) {
+	    iter = toIterator(new StringTokenizer((String) obj, delims));
+	} else if (obj instanceof Iterator) {
+	    iter = (Iterator) obj;
+	} else if (obj instanceof Collection) {
+	    iter = toIterator(((Collection) obj).iterator());
+	} else if (obj instanceof Enumeration) {
+	    iter = toIterator((Enumeration) obj);
+	} else if (obj instanceof Map) {
+	    iter = ((Map) obj).entrySet().iterator();
+	} else {
+	    throw new ELException("Bad items");
+	}
+	return iter;
+    }
+
+    private Iterator toIterator(final Enumeration obj) {
+	return new Iterator() {
+	    public boolean hasNext() {
+		return obj.hasMoreElements();
+	    }
+
+	    public Object next() {
+		return obj.nextElement();
+	    }
+
+	    public void remove() {
+	    }
+	};
+    }
+}
+
+/**
+ * @author Kin-man Chung
+ * @version $Id: IteratedValueExpression.java,v 1.2 2005/12/08 01:20:43 kchung
+ *          Exp $
+ */
+final class IteratedValueExpression extends ValueExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final int i;
+    protected final IteratedExpression iteratedExpression;
+
+    public IteratedValueExpression(IteratedExpression iteratedExpr, int i) {
+	this.i = i;
+	this.iteratedExpression = iteratedExpr;
+    }
+
+    public Object getValue(ELContext context) {
+	return iteratedExpression.getItem(context, i);
+    }
+
+    public void setValue(ELContext context, Object value) {
+    }
+
+    public boolean isReadOnly(ELContext context) {
+	return true;
+    }
+
+    public Class getType(ELContext context) {
+	return null;
+    }
+
+    public Class getExpectedType() {
+	return Object.class;
+    }
+
+    public String getExpressionString() {
+	return iteratedExpression.getValueExpression().getExpressionString();
+    }
+
+    public boolean equals(Object obj) {
+	return iteratedExpression.getValueExpression().equals(obj);
+    }
+
+    public int hashCode() {
+	return iteratedExpression.getValueExpression().hashCode();
+    }
+
+    public boolean isLiteralText() {
+	return false;
+    }
+}
+
+/**
+ * @author Andrey Markavtsov
+ * @version $Id: IteratedIndexExpression.java,v 1.2 2007/12/06 01:20:43
+ *          
+ */
+final class IteratedIndexExpression extends ValueExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final Integer i;
+
+    public IteratedIndexExpression(int i) {
+	this.i = i;
+    }
+
+    public Object getValue(ELContext context) {
+	return i;
+    }
+
+    public void setValue(ELContext context, Object value) {
+    }
+
+    public boolean isReadOnly(ELContext context) {
+	return true;
+    }
+
+    public Class getType(ELContext context) {
+	return null;
+    }
+
+    public Class getExpectedType() {
+	return Object.class;
+    }
+
+    public String getExpressionString() {
+	return i.toString();
+    }
+
+    public boolean equals(Object obj) {
+	return i.equals(obj);
+    }
+
+    public int hashCode() {
+	return i.hashCode();
+    }
+
+    public boolean isLiteralText() {
+	return false;
+    }
+}
+
+/**
+ * @author Jacob Hookom
+ * @version $Id: IndexedValueExpression.java,v 1.3 2005/08/24 04:38:52 jhook Exp $
+ */
+final class IndexedValueExpression extends ValueExpression {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    private final Integer i;
+
+    private final ValueExpression orig;
+
+    /**
+     * 
+     */
+    public IndexedValueExpression(ValueExpression orig, int i) {
+        this.i = new Integer(i);
+        this.orig = orig;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getValue(javax.el.ELContext)
+     */
+    public Object getValue(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().getValue(context, base, i);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#setValue(javax.el.ELContext,
+     *      java.lang.Object)
+     */
+    public void setValue(ELContext context, Object value) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            context.getELResolver().setValue(context, base, i, value);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#isReadOnly(javax.el.ELContext)
+     */
+    public boolean isReadOnly(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().isReadOnly(context, base, i);
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getType(javax.el.ELContext)
+     */
+    public Class getType(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().getType(context, base, i);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getExpectedType()
+     */
+    public Class getExpectedType() {
+        return Object.class;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#getExpressionString()
+     */
+    public String getExpressionString() {
+        return this.orig.getExpressionString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        return this.orig.equals(obj);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#hashCode()
+     */
+    public int hashCode() {
+        return this.orig.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#isLiteralText()
+     */
+    public boolean isLiteralText() {
+        return false;
+    }
+
+}

Added: trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/facelets/ColumnsHandler.java
===================================================================
--- trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/facelets/ColumnsHandler.java	                        (rev 0)
+++ trunk/sandbox/ui/columns/src/main/java/org/richfaces/taglib/html/facelets/ColumnsHandler.java	2007-12-10 14:28:48 UTC (rev 4651)
@@ -0,0 +1,765 @@
+/*
+ * ColumnsHandler.java		Date created: 07.12.2007
+ * Last modified by: $Author$
+ * $Revision$	$Date$
+ */
+
+package org.richfaces.taglib.html.facelets;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.servlet.jsp.JspTagException;
+
+import org.richfaces.iterator.ForEachIterator;
+import org.richfaces.iterator.SimpleForEachIterator;
+
+import com.sun.facelets.FaceletContext;
+import com.sun.facelets.tag.TagAttribute;
+import com.sun.facelets.tag.jsf.ComponentConfig;
+import com.sun.facelets.tag.jsf.ComponentHandler;
+
+
+/**
+ * TODO Class description goes here.
+ * 
+ * @author "Andrey Markavtsov"
+ * 
+ */
+public class ColumnsHandler extends ComponentHandler {
+
+    /** value attribute */
+    private TagAttribute value;
+
+    /** end attribute */
+    private TagAttribute end;
+
+    /** var attribute */
+    private TagAttribute var;
+
+    /** index attribute */
+    private TagAttribute index;
+
+    /** colspan attribute */
+    private TagAttribute colspan;
+
+    /** rowspan attribute */
+    private TagAttribute rowspan;
+
+    /** breakBefore attribute */
+    private TagAttribute breakBefore;
+
+    /** headerClass attribute */
+    private TagAttribute headerClass;
+
+    /** footerClass attribute */
+    private TagAttribute footerClass;
+
+    /** width attribute */
+    private TagAttribute width;
+
+    /** sortable attribute */
+    private TagAttribute sortable;
+
+    /** sortExpression attribute */
+    private TagAttribute sortExpression;
+
+    /** style attribute */
+    private TagAttribute style;
+
+    /** styleClass attribute */
+    private TagAttribute styleClass;
+
+    /** rendered attribute */
+    private TagAttribute rendered;
+
+    /** Iterator for columns's tag value attribute */
+    protected ForEachIterator items; // our 'digested' items
+
+    /** Value attribute value */
+    protected Object rawItems; // our 'raw' items
+
+    /** Var attr - defines page variable for current item */
+    private String _indexId;
+
+    /** Integer value of end attr. */
+    private Integer _end;
+
+    /** String value of var attr */
+    private String _itemId = null;
+
+    /** Current column counter */
+    private Integer _index = 0;
+
+    /** Prepared flag */
+    private boolean prepared = false;
+
+    /** Variables counter */
+    private int vCounter;
+
+    /** Expression for var item */
+    private IteratedExpression iteratedExpression;
+
+    /**
+     * TODO Description goes here.
+     * 
+     * @param config
+     */
+    public ColumnsHandler(ComponentConfig config) {
+	super(config);
+	this.breakBefore = getAttribute("breakBefore");
+	this.value = getAttribute("value");
+	this.var = getAttribute("var");
+	this.index = getAttribute("index");
+	this.rowspan = getAttribute("rowspan");
+	this.colspan = getAttribute("colspan");
+	this.headerClass = getAttribute("headerClass");
+	this.footerClass = getAttribute("footerClass");
+	this.width = getAttribute("width");
+	this.sortable = getAttribute("sortable");
+	this.sortExpression = getAttribute("sortExpression");
+	this.style = getAttribute("style");
+	this.styleClass = getAttribute("styleClass");
+
+	// TODO Auto-generated constructor stub
+    }
+
+    /**
+     * Extracts tags attributes values
+     */
+    private void initVariables(FaceletContext ctx) {
+	initEnd(ctx);
+	initIndex(ctx);
+	initVar(ctx);
+    }
+
+    /**
+     * Method prepares all we need for starting of tag rendering
+     * 
+     * @throws JspTagException
+     */
+    private void prepare(FaceletContext ctx) {
+
+	initVariables(ctx);
+
+	try {
+
+	    // produce the right sort of ForEachIterator
+	    if (value != null) {
+		// If this is a deferred expression, make a note and get
+		// the 'items' instance.
+
+		rawItems = value.getObject(ctx);
+
+		// extract an iterator over the 'items' we've got
+		items = SimpleForEachIterator
+			.supportedTypeForEachIterator(rawItems);
+	    } else {
+		// no 'items', so use 'begin' and 'end'
+		items = SimpleForEachIterator.beginEndForEachIterator(_end);
+	    }
+	} catch (Exception e) {
+	    // TODO: handle exception
+	}
+
+	if (hasNext()) {
+	    exposeVariables(ctx, 0);
+	    next(ctx);
+	}
+
+    }
+
+    /**
+     * Return true if we didn't complete column's count
+     * 
+     * @return
+     * @throws JspTagException
+     */
+    private boolean hasNext() {
+	try {
+	    return items.hasNext();
+	} catch (Exception e) {
+	    return false;
+	}
+
+    }
+
+    /**
+     * Iterate to next column
+     * 
+     * @return
+     * @throws JspTagException
+     */
+    private Object next(FaceletContext ctx) {
+	try {
+	    Object o = items.next();
+	    _index++;
+	    return o;
+	} catch (Exception e) {
+	    return null;
+	}
+    }
+
+    /**
+     * Extracts integer value from end attr
+     */
+    private void initEnd(FaceletContext ctx) {
+	if (end != null) {
+	    try {
+		_end = (Integer) end.getObject(ctx);
+		if (_end < 0) {
+		    _end = 0; // If end is negative set up zero
+		}
+	    } catch (Exception e) {
+		_end = 0;
+	    }
+	} else {
+	    _end = 0;
+	}
+    }
+
+    /**
+     * Extracts string value from var attr
+     */
+    private void initVar(FaceletContext ctx) {
+	if (var != null) {
+	    try {
+		_itemId = (String) var.getObject(ctx);
+	    } catch (ClassCastException e) {
+		_itemId = null;
+	    }
+
+	}
+    }
+
+    /**
+     * Extracts string value from index attr
+     */
+    private void initIndex(FaceletContext ctx) {
+	if (index != null) {
+	    try {
+		_indexId = (String) index.getObject(ctx);
+	    } catch (ClassCastException e) {
+		_indexId = null;
+	    }
+
+	}
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.sun.facelets.tag.jsf.ComponentHandler#applyNextHandler(com.sun.facelets.FaceletContext,
+     *      javax.faces.component.UIComponent)
+     */
+    @Override
+    protected void applyNextHandler(FaceletContext ctx, UIComponent c)
+	    throws IOException, FacesException, ELException {
+	// TODO Auto-generated method stub
+	super.applyNextHandler(ctx, c);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.sun.facelets.tag.jsf.ComponentHandler#onComponentCreated(com.sun.facelets.FaceletContext,
+     *      javax.faces.component.UIComponent,
+     *      javax.faces.component.UIComponent)
+     */
+    @Override
+    protected void onComponentCreated(FaceletContext ctx, UIComponent c,
+	    UIComponent parent) {
+	// prepare if did not
+	if (!prepared) {
+	    prepare(ctx);
+	    prepared = true;
+	}
+
+	// for each
+	try {
+	    if (hasNext()) {
+		next(ctx);
+		initColumn(ctx, c);
+		super.apply(ctx, parent);
+	    } else {
+		vCounter = 1;
+	    }
+	} catch (Exception e) {
+	    // TODO: handle exception
+	}
+    }
+
+    /**
+     * Sets page request variables
+     * 
+     * @throws JspTagException
+     */
+    private void exposeVariables(FaceletContext ctx, int k) {
+
+	
+	VariableMapper vm = ctx.getVariableMapper();
+
+	if (_itemId != null) {
+	    if (vm != null) {
+		ValueExpression srcVE = value.getValueExpression(ctx,
+			Object.class);
+		ValueExpression ve = getVarExpression(ctx, srcVE, k);
+		vm.setVariable(_itemId, ve);
+	    }
+
+	}
+
+	// Set up index variable
+
+	if (_indexId != null) {
+	    if (vm != null) {
+		ValueExpression ve = new IteratedIndexExpression(k);
+		vm.setVariable(_indexId, ve);
+	    }
+
+	}
+
+    }
+
+    /**
+     * Return expression for page variables
+     * 
+     * @param expr
+     * @return
+     */
+    private ValueExpression getVarExpression(FaceletContext ctx,
+	    ValueExpression expr, int k) {
+	Object o = expr.getValue(ctx.getFacesContext().getELContext());
+	if (o.getClass().isArray() || o instanceof List) {
+	    return new IndexedValueExpression(expr, k);
+	}
+
+	if (o instanceof Collection || o instanceof Iterator
+		|| o instanceof Enumeration || o instanceof Map
+		|| o instanceof String) {
+
+	    if (iteratedExpression == null) {
+		iteratedExpression = new IteratedExpression(expr, ",");
+	    }
+	    return new IteratedValueExpression(iteratedExpression, k);
+	}
+
+	throw new ELException("FOREACH_BAD_ITEMS");
+    }
+
+    /**
+     * Returns true if this is the first loop of columns tag
+     * 
+     * @return
+     */
+    private boolean atFirst() {
+	return (_index == 0);
+    }
+
+    /**
+     * Release iteration variables
+     */
+    private void release() {
+	this.items = null;
+	this._index = 0;
+	this.prepared = false;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.sun.facelets.tag.jsf.ComponentHandler#onComponentPopulated(com.sun.facelets.FaceletContext,
+     *      javax.faces.component.UIComponent,
+     *      javax.faces.component.UIComponent)
+     */
+    @Override
+    protected void onComponentPopulated(FaceletContext ctx, UIComponent c,
+	    UIComponent parent) {
+
+	// remove created component if columns count is zero
+	if (atFirst()) {
+	    c.setRendered(false);
+	} 
+
+	if (vCounter == _index || atFirst()) {
+	    release();
+	    return;
+	}
+	
+	exposeVariables(ctx, vCounter);
+	vCounter++;
+	
+
+    }
+
+    /**
+     * Inits created column by this tag attributes
+     * 
+     * @param ctx
+     * @param column
+     */
+    private void initColumn(FaceletContext ctx, UIComponent column) {
+	setColumnAttribute(width, column, ctx);
+	setColumnAttribute(colspan, column, ctx);
+	setColumnAttribute(rowspan, column, ctx);
+	setColumnAttribute(style, column, ctx);
+	setColumnAttribute(styleClass, column, ctx);
+	setColumnAttribute(breakBefore, column, ctx);
+	setColumnAttribute(headerClass, column, ctx);
+	setColumnAttribute(footerClass, column, ctx);
+	setColumnAttribute(sortable, column, ctx);
+	setColumnAttribute(sortExpression, column, ctx);
+	setColumnAttribute(rendered, column, ctx);
+
+    }
+
+    /**
+     * Sets attribute to column
+     * 
+     * @param attr
+     * @param column
+     * @param ctx
+     */
+    private void setColumnAttribute(TagAttribute attr, UIComponent column,
+	    FaceletContext ctx) {
+	if (attr != null) {
+	    if (attr.isLiteral()) {
+		column.setValueExpression(attr.getLocalName(), attr
+			.getValueExpression(ctx, String.class));
+	    } else {
+		column.setValueExpression(attr.getLocalName(), attr
+			.getValueExpression(ctx, ValueExpression.class));
+	    }
+	}
+    }
+
+}
+
+/**
+ * @author Kin-man Chung
+ * @version $Id: IteratedExpression.java,v 1.3 2005/12/08 01:20:43 kchung Exp $
+ */
+final class IteratedExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final ValueExpression orig;
+    protected final String delims;
+
+    private Object base;
+    private int index;
+    private Iterator iter;
+
+    public IteratedExpression(ValueExpression orig, String delims) {
+	this.orig = orig;
+	this.delims = delims;
+    }
+
+    /**
+     * Evaluates the stored ValueExpression and return the indexed item.
+     * 
+     * @param context
+     *                The ELContext used to evaluate the ValueExpression
+     * @param i
+     *                The index of the item to be retrieved
+     */
+    public Object getItem(ELContext context, int i) {
+
+	if (base == null) {
+	    base = orig.getValue(context);
+	    if (base == null) {
+		return null;
+	    }
+	    iter = toIterator(base);
+	    index = 0;
+	}
+	if (index > i) {
+	    // Restart from index 0
+	    iter = toIterator(base);
+	    index = 0;
+	}
+	while (iter.hasNext()) {
+	    Object item = iter.next();
+	    if (index++ == i) {
+		return item;
+	    }
+	}
+	return null;
+    }
+
+    public ValueExpression getValueExpression() {
+	return orig;
+    }
+
+    private Iterator toIterator(final Object obj) {
+
+	Iterator iter;
+	if (obj instanceof String) {
+	    iter = toIterator(new StringTokenizer((String) obj, delims));
+	} else if (obj instanceof Iterator) {
+	    iter = (Iterator) obj;
+	} else if (obj instanceof Collection) {
+	    iter = toIterator(((Collection) obj).iterator());
+	} else if (obj instanceof Enumeration) {
+	    iter = toIterator((Enumeration) obj);
+	} else if (obj instanceof Map) {
+	    iter = ((Map) obj).entrySet().iterator();
+	} else {
+	    throw new ELException("Bad items");
+	}
+	return iter;
+    }
+
+    private Iterator toIterator(final Enumeration obj) {
+	return new Iterator() {
+	    public boolean hasNext() {
+		return obj.hasMoreElements();
+	    }
+
+	    public Object next() {
+		return obj.nextElement();
+	    }
+
+	    public void remove() {
+	    }
+	};
+    }
+}
+
+/**
+ * @author Kin-man Chung
+ * @version $Id: IteratedValueExpression.java,v 1.2 2005/12/08 01:20:43 kchung
+ *          Exp $
+ */
+final class IteratedValueExpression extends ValueExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final int i;
+    protected final IteratedExpression iteratedExpression;
+
+    public IteratedValueExpression(IteratedExpression iteratedExpr, int i) {
+	this.i = i;
+	this.iteratedExpression = iteratedExpr;
+    }
+
+    public Object getValue(ELContext context) {
+	return iteratedExpression.getItem(context, i);
+    }
+
+    public void setValue(ELContext context, Object value) {
+    }
+
+    public boolean isReadOnly(ELContext context) {
+	return true;
+    }
+
+    public Class getType(ELContext context) {
+	return null;
+    }
+
+    public Class getExpectedType() {
+	return Object.class;
+    }
+
+    public String getExpressionString() {
+	return iteratedExpression.getValueExpression().getExpressionString();
+    }
+
+    public boolean equals(Object obj) {
+	return iteratedExpression.getValueExpression().equals(obj);
+    }
+
+    public int hashCode() {
+	return iteratedExpression.getValueExpression().hashCode();
+    }
+
+    public boolean isLiteralText() {
+	return false;
+    }
+}
+
+/**
+ * @author Andrey Markavtsov
+ * @version $Id: IteratedIndexExpression.java,v 1.2 2007/12/06 01:20:43
+ * 
+ */
+final class IteratedIndexExpression extends ValueExpression {
+
+    private static final long serialVersionUID = 1L;
+    protected final Integer i;
+
+    public IteratedIndexExpression(int i) {
+	this.i = i;
+    }
+
+    public Object getValue(ELContext context) {
+	return i;
+    }
+
+    public void setValue(ELContext context, Object value) {
+    }
+
+    public boolean isReadOnly(ELContext context) {
+	return true;
+    }
+
+    public Class getType(ELContext context) {
+	return null;
+    }
+
+    public Class getExpectedType() {
+	return Object.class;
+    }
+
+    public String getExpressionString() {
+	return i.toString();
+    }
+
+    public boolean equals(Object obj) {
+	return i.equals(obj);
+    }
+
+    public int hashCode() {
+	return i.hashCode();
+    }
+
+    public boolean isLiteralText() {
+	return false;
+    }
+}
+
+/**
+ * @author Jacob Hookom
+ * @version $Id: IndexedValueExpression.java,v 1.3 2005/08/24 04:38:52 jhook Exp $
+ */
+final class IndexedValueExpression extends ValueExpression {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    private final Integer i;
+
+    private final ValueExpression orig;
+
+    /**
+     * 
+     */
+    public IndexedValueExpression(ValueExpression orig, int i) {
+        this.i = new Integer(i);
+        this.orig = orig;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getValue(javax.el.ELContext)
+     */
+    public Object getValue(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().getValue(context, base, i);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#setValue(javax.el.ELContext,
+     *      java.lang.Object)
+     */
+    public void setValue(ELContext context, Object value) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            context.getELResolver().setValue(context, base, i, value);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#isReadOnly(javax.el.ELContext)
+     */
+    public boolean isReadOnly(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().isReadOnly(context, base, i);
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getType(javax.el.ELContext)
+     */
+    public Class getType(ELContext context) {
+        Object base = this.orig.getValue(context);
+        if (base != null) {
+            context.setPropertyResolved(false);
+            return context.getELResolver().getType(context, base, i);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.ValueExpression#getExpectedType()
+     */
+    public Class getExpectedType() {
+        return Object.class;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#getExpressionString()
+     */
+    public String getExpressionString() {
+        return this.orig.getExpressionString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        return this.orig.equals(obj);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#hashCode()
+     */
+    public int hashCode() {
+        return this.orig.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.el.Expression#isLiteralText()
+     */
+    public boolean isLiteralText() {
+        return false;
+    }
+
+}




More information about the richfaces-svn-commits mailing list