[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