Author: awiner
Date: Thu Oct  5 16:25:55 2006
New Revision: 453425

URL: http://svn.apache.org/viewvc?view=rev&rev=453425
Log:
- Re-add <tr:forEach> tag, reimplemented for JSP 2.1 VariableMapper API and 
ValueExpressions.  Turns out we do need it, because c:forEach doesn't support 
varStatus with JSF, just var.  Grrr....  <tr:forEach> supports varStatus too.
- Change UIXEditableValue code from ValueBindings over to ValueExpressions

Added:
    
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/site/xdoc/tagdoc/tr_forEach.xml
    
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
Modified:
    incubator/adffaces/branches/faces-1_2/trinidad/pom.xml
    
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXEditableValueTemplate.java
    
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-demo/src/main/webapp/surveydemo/surveyPage1.jspx
    incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/pom.xml
    
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/conf/META-INF/tr-base.tld

Modified: incubator/adffaces/branches/faces-1_2/trinidad/pom.xml
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/pom.xml?view=diff&rev=453425&r1=453424&r2=453425
==============================================================================
--- incubator/adffaces/branches/faces-1_2/trinidad/pom.xml (original)
+++ incubator/adffaces/branches/faces-1_2/trinidad/pom.xml Thu Oct  5 16:25:55 
2006
@@ -430,6 +430,13 @@
         <scope>provided</scope>
       </dependency>
 
+      <dependency>
+        <groupId>jstl</groupId>
+        <artifactId>jstl</artifactId>
+        <version>1.2</version>
+        <scope>provided</scope>
+      </dependency>
+
 
       <dependency>
         <groupId>com.sun.facelets</groupId>

Modified: 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXEditableValueTemplate.java
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXEditableValueTemplate.java?view=diff&rev=453425&r1=453424&r2=453425
==============================================================================
--- 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXEditableValueTemplate.java
 (original)
+++ 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXEditableValueTemplate.java
 Thu Oct  5 16:25:55 2006
@@ -17,6 +17,8 @@
 
 import java.util.Iterator;
 
+import javax.el.ValueExpression;
+
 import javax.faces.application.Application;
 import javax.faces.application.FacesMessage;
 import javax.faces.component.EditableValueHolder;
@@ -25,7 +27,6 @@
 import javax.faces.convert.ConverterException;
 import javax.faces.el.EvaluationException;
 import javax.faces.el.MethodBinding;
-import javax.faces.el.ValueBinding;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
 import javax.faces.event.ValueChangeEvent;
@@ -111,6 +112,7 @@
 
     // Submitted value == null means "the component was not submitted
     // at all";  validation should not continue
+
     Object submittedValue = getSubmittedValue();
     if (submittedValue == null)
       return;
@@ -239,21 +241,21 @@
     if (!isValid() || !isLocalValueSet())
       return;
 
-    ValueBinding binding = getFacesBean().getValueBinding(VALUE_KEY);
-    if (binding == null)
+    ValueExpression expression = getFacesBean().getValueExpression(VALUE_KEY);
+    if (expression == null)
       return;
 
     try
     {
       Object localValue = getLocalValue();
-      binding.setValue(context, localValue);
+      expression.setValue(context.getELContext(), localValue);
       setValue(null);
       setLocalValueSet(false);
       if (_LOG.isFiner())
       {
         _LOG.finer("Wrote value {0} to model {1} in component {2}",
                    new Object[]{localValue,
-                                binding.getExpressionString(),
+                                expression.getExpressionString(),
                                 this});
       }
     }
@@ -263,8 +265,8 @@
       // bean attribute level validation:
       if (_LOG.isFine())
       {
-        _LOG.fine("Error updating binding ({0})",
-                    binding.getExpressionString());
+        _LOG.fine("Error updating expression ({0})",
+                    expression.getExpressionString());
         _LOG.fine(e);
       }
 
@@ -381,7 +383,6 @@
     {
       newValue = renderer.getConvertedValue(context, this,
                                             submittedValue);
-
       if (_LOG.isFine())
       {
         _LOG.fine("Renderer " + renderer + " returned value " + newValue + "(" 
+
@@ -466,7 +467,7 @@
   {
     Object o = getAttributes().get("label");
     if (o == null)
-      o = getValueBinding("label");
+      o = getValueExpression("label");
 
     return o;
   }
@@ -475,7 +476,7 @@
   {
     Object o = getAttributes().get("requiredMessageDetail");
       if (o == null)
-       o = getValueBinding("requiredMessageDetail");
+       o = getValueExpression("requiredMessageDetail");
 
     return o;
   }
@@ -527,13 +528,13 @@
       return converter;
     }
 
-    ValueBinding valueBinding = getValueBinding("value");
-    if (valueBinding == null)
+    ValueExpression valueExpression = getValueExpression("value");
+    if (valueExpression == null)
     {
       return null;
     }
 
-    Class<?> converterType = valueBinding.getType(context);
+    Class<?> converterType = valueExpression.getType(context.getELContext());
     // if converterType is null, String, or Object, assume
     // no conversion is needed
     if (converterType == null ||

Added: 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/site/xdoc/tagdoc/tr_forEach.xml
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/site/xdoc/tagdoc/tr_forEach.xml?view=auto&rev=453425
==============================================================================
--- 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/site/xdoc/tagdoc/tr_forEach.xml
 (added)
+++ 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-api/src/site/xdoc/tagdoc/tr_forEach.xml
 Thu Oct  5 16:25:55 2006
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  Copyright 2006 The Apache Software Foundation.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<document>
+ <properties>
+  <title>tr:forEach</title>
+ </properties>
+ <body>
+ <section name="Summary">
+ <p>
+   <b>Tag name:</b> &lt;tr:forEach&gt;
+   <br/>
+<p>
+        The forEach tag is a replacement for the JSTL
+&lt;c:forEach&gt; tag.  Though as of JSF 1.2/JSP 2.1/JSTL 1.2,
+&lt;c:forEach&gt; can be used with any JSF components or tags,
+it does not support "varStatus".  This tag adds support for varStatus
+(other than "current" which is not supported).
+(<b>Note</b>: this tag is not supported in Facelets, because c:forEach
+is fully functional in Facelets.)  Unlike the old Trinidad tr:forEach
+built with JSF 1.1, however, this tag can be used with any JSP 2.1-based
+tag, JSF or non-JSF.  This tag also has a limitation not found in 
&lt;c:forEach&gt;:  &lt;tr:forEach&gt; does not currently support arbitrary
+java.util.Collections; it can only iterate over java.util.Lists or
+arrays.</p>
+<h4>Example:</h4><source>
+            &lt;tr:selectOneListbox value="#{someValue}"&gt;
+              &lt;tr:forEach var="item" items="#{model.listOfItems}"&gt;
+                &lt;tr:selectItem value="#{item.value}" 
text="#{item.text}"/&gt;
+              &lt;/tr:forEach&gt;
+            &lt;/tr:selectOneListbox&gt;</source><source>
+            &lt;tr:forEach varStatus="vs" begin="1" end="5"&gt;
+              &lt;tr:outputText id="ot2" value="#{vs.index} #{vs.count} 
#{vs.begin} #{vs.current}"/&gt;
+            &lt;/tr:forEach&gt;</source>
+ </p>
+ </section>
+ <section name="Attributes">
+<table>
+<tr>
+<th>Name</th>
+<th>Type</th>
+<th>Supports EL?</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>begin</td><td>int</td><td>No</td><td>
+
+          index at which iteration begins
+        </td>
+</tr>
+<tr>
+<td>end</td><td>int</td><td>No</td><td>
+
+          index at which iteration ends
+        </td>
+</tr>
+<tr>
+<td>items</td><td>Object</td><td>Only EL</td><td>
+
+          the collection to iterate over
+        </td>
+</tr>
+<tr>
+<td>step</td><td>int</td><td>No</td><td>
+
+          number to increment on each iteration
+        </td>
+</tr>
+<tr>
+<td>var</td><td>String</td><td>No</td><td>
+
+          name of the variable exposed when iterating
+        </td>
+</tr>
+<tr>
+<td>varStatus</td><td>String</td><td>No</td><td>
+
+          name of the loop status exposed when iterating. The properties
+               'index','count','begin','end','step','first','last'
+               are available through this
+        </td>
+</tr>
+</table>
+ </section>
+ </body>
+</document>

Modified: 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-demo/src/main/webapp/surveydemo/surveyPage1.jspx
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-demo/src/main/webapp/surveydemo/surveyPage1.jspx?view=diff&rev=453425&r1=453424&r2=453425
==============================================================================
--- 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-demo/src/main/webapp/surveydemo/surveyPage1.jspx
 (original)
+++ 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-demo/src/main/webapp/surveydemo/surveyPage1.jspx
 Thu Oct  5 16:25:55 2006
@@ -25,17 +25,17 @@
        
         <tr:panelPage>
       
-        <tr:panelHeader text="Question 5 of 5">
+        <tr:panelHeader text="Question 1 of 5">
           <tr:panelFormLayout>
           
             <tr:selectOneRadio label="#{survey.q0.prompt}" 
                                   required="true"
                                   value="#{survey.a0}" >
-              <c:forEach var="item" varStatus="iter"
+              <tr:forEach var="item" varStatus="iter"
                           items="#{survey.q0.answerStrings}">
                 <!-- The strange EL syntax for "value" forces it to be a 
string -->
                 <tr:selectItem label="#{item}" value="#{''}#{iter.index}"/>
-              </c:forEach>
+              </tr:forEach>
             </tr:selectOneRadio >
           
           </tr:panelFormLayout>

Modified: incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/pom.xml
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/pom.xml?view=diff&rev=453425&r1=453424&r2=453425
==============================================================================
--- incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/pom.xml 
(original)
+++ incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/pom.xml Thu 
Oct  5 16:25:55 2006
@@ -170,6 +170,11 @@
     </dependency>
 
     <dependency>
+      <groupId>jstl</groupId>
+      <artifactId>jstl</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.myfaces.trinidad</groupId>
       <artifactId>trinidad-build</artifactId>
     </dependency>

Modified: 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/conf/META-INF/tr-base.tld
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/conf/META-INF/tr-base.tld?view=diff&rev=453425&r1=453424&r2=453425
==============================================================================
--- 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/conf/META-INF/tr-base.tld
 (original)
+++ 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/conf/META-INF/tr-base.tld
 Thu Oct  5 16:25:55 2006
@@ -26,6 +26,68 @@
   <uri>http://myfaces.apache.org/trinidad</uri>

         

    <tag>

+      <name>forEach</name>

+      
<tag-class>org.apache.myfaces.trinidadinternal.taglib.ForEachTag</tag-class>

+      <description>

+The forEach tag is a replacement for the JSTL &amp;lt;c:forEach&amp;gt; tag. 
+As of JSF 1.2/JSP 2.1/JSTL 1.2, the regular &amp;lt;c:forEach&amp;gt; tag
+does work with JSF components.  However, it does not support varStatus
+with JSF!  (Unlike c:forEach, tr:forEach doesn't currently support anything
+for "items" other than arrays and lists.)
+      </description>

+

+      <attribute>

+        <description>

+          the items over which iteration takes place 

+        </description>

+        <name>items</name>

+        <deferred-value/>
+      </attribute>

+

+      <attribute>

+        <description>

+          the name of the variable to expose

+        </description>

+        <name>var</name>

+        <rtexprvalue>false</rtexprvalue>

+      </attribute>

+

+      <attribute>

+        <description>

+          Name of the exported scoped variable for the

+          status of the iteration.

+        </description>

+        <name>varStatus</name>

+        <rtexprvalue>false</rtexprvalue>

+      </attribute>

+

+      <attribute>

+        <description>

+          the beginning index 

+        </description>

+        <name>begin</name>

+        <rtexprvalue>false</rtexprvalue>

+      </attribute>

+

+      <attribute>

+        <description>

+          the ending index 

+        </description>

+        <name>end</name>

+        <rtexprvalue>false</rtexprvalue>

+      </attribute>

+

+      <attribute>

+        <description>

+          the number of steps per iteration

+        </description>

+        <name>step</name>

+        <rtexprvalue>false</rtexprvalue>

+      </attribute>

+

+   </tag>

+
+   <tag>

       <description>

         The setActionListener tag provides a declarative syntax for assigning 
values before an action fires

       </description>


Added: 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
URL: 
http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java?view=auto&rev=453425
==============================================================================
--- 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
 (added)
+++ 
incubator/adffaces/branches/faces-1_2/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
 Thu Oct  5 16:25:55 2006
@@ -0,0 +1,403 @@
+/*

+ * Copyright  2003-2006 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.myfaces.trinidadinternal.taglib;

+

+import java.io.Serializable;

+

+import java.lang.reflect.Array;

+

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import javax.el.ELContext;

+import javax.el.PropertyNotWritableException;

+import javax.el.ValueExpression;

+import javax.el.VariableMapper;

+

+import javax.faces.context.FacesContext;

+import javax.faces.webapp.UIComponentTag;

+

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.JspTagException;

+import javax.servlet.jsp.tagext.TagSupport;

+import javax.servlet.jsp.jstl.core.IndexedValueExpression;

+

+import org.apache.myfaces.trinidad.logging.TrinidadLogger;

+import org.apache.myfaces.trinidad.webapp.ELContextTag;

+import org.apache.myfaces.trinidadinternal.el.Tokenizer;

+import org.apache.myfaces.trinidadinternal.el.Tokenizer.Token;

+

+//JSTL Core Library - <c:forEach> Tag

+//===================================

+//Syntax 1: Iterate over a collection of objects

+//

+//<c:forEach [var="varName "] items="collection"

+//  [varStatus="varStatusName"]

+//  [begin="begin"] [end="end"] [step=" step"]>

+//  body content

+//</c:forEach>

+//

+//Syntax 2: Iterate a fixed number of times

+//

+//<c:forEach [var="varName"]

+//  [varStatus="varStatusName"]

+//  begin=" begin" end="end" [step="step"]>

+//  body content

+//</c:forEach>

+

+/**

+ *

+ * @author The Oracle ADF Faces Team

+ */

+public class ForEachTag extends TagSupport

+{

+  public void setItems(ValueExpression items)

+  {

+    if (items.isLiteralText())

+      throw new IllegalArgumentException(

+        "\"items\" must be an EL expression");

+    _items = items;

+  }

+

+  public void setBegin(Integer begin)

+  {

+    _begin = begin;

+  }

+

+  public void setEnd(Integer end)

+  {

+    _end = end;

+  }

+

+  public void setStep(Integer step)

+  {

+    _step = step;

+  }

+

+  public void setVar(String var)

+  {

+    _var = var;

+  }

+

+  public void setVarStatus(String varStatus)

+  {

+    _varStatus = varStatus;

+  }

+

+  @Override

+  public int doStartTag() throws JspException

+  {

+    _validateAttributes();

+

+    FacesContext context = FacesContext.getCurrentInstance();

+    _currentBegin = (_begin == null) ? 0 : _begin.intValue();

+    int length;

+

+    if (null != _items)

+    {

+      Object items = _items.getValue(pageContext.getELContext());

+

+      //pu: If items is specified and resolves to null, it is treated as an

+      //  empty collection, i.e., no iteration is performed.

+      if (items == null)

+      {

+        if (_LOG.isFine())

+          _LOG.fine("Items expression " + _items + " resolved to null.");

+        return SKIP_BODY;

+      }

+

+      _itemsValue = items;

+      // =-=AEW <c:forEach> supports arbitrary collections;  but

+      // JSF only supports List in its EL.

+      if (items instanceof List)

+        length = ((List) items).size();

+      else if (items.getClass().isArray())

+        length = Array.getLength(items);

+      else

+        throw new JspException("\"items\" must point to a List or array");

+      if (length == 0)

+      {

+        if (_LOG.isFine())

+          _LOG.fine("Items found at " + _items + " is empty.");

+        return SKIP_BODY;

+      }

+      //pu: If valid 'items' was specified, and so was 'begin', get out if size

+      //  of collection were to be less than the begin. A mimic of c:forEach.

+      if (length < _currentBegin)

+      {

+        if (_LOG.isFine())

+          _LOG.fine("Size of 'items' is less than 'begin'");

+        return SKIP_BODY;

+      }

+

+      _currentEnd = (_end == null) ? length - 1 : _end.intValue();

+      //pu: If 'end' were specified, but is beyond the size of collection, 
limit

+      //  the iteration to where the collection ends. A mimic of c:forEach and

+      //  fix for bug 4029853.

+      if (length < _currentEnd)

+        _currentEnd = length - 1;

+    }

+    else

+    {

+      _currentEnd = (_end == null) ? 0 : _end.intValue();

+    }

+    _currentIndex = _currentBegin;

+    _currentStep = (_step == null) ? 1 : _step.intValue();

+    //pu: Now check the valid relation between 'begin','end' and validity of 
'step'

+    _validateRangeAndStep();

+    // If we can bail, do it now

+    if (_currentEnd < _currentIndex)

+      return SKIP_BODY;

+

+    // Save off the previous deferred variables

+    VariableMapper vm = 

+      pageContext.getELContext().getVariableMapper();

+    if (_var != null)

+      _previousDeferredVar = vm.resolveVariable(_var);

+

+    if (null != _varStatus)

+    {

+      _previousDeferredVarStatus = vm.resolveVariable(_varStatus);

+      _propertyReplacementMap = new HashMap<String, Object>(9, 1);

+      _propertyReplacementMap.put("begin", _currentBegin);

+      _propertyReplacementMap.put("end", _currentEnd);

+      _propertyReplacementMap.put("step", _currentStep);

+      _propertyReplacementMap.put("count", _currentCount);

+      _propertyReplacementMap.put("index", _currentIndex);

+      // FIXME: Can we support "current" efficiently?

+      //      _propertyReplacementMap.put("current", _varReplacement);

+      _propertyReplacementMap.put("first", _isFirst);

+      _propertyReplacementMap.put("last", _isLast);

+    }

+

+    if (_LOG.isFiner())

+    {

+      _LOG.finer("Iterating from " + _currentIndex + " to " + _currentEnd +

+                 " by " + _currentStep);

+    }

+

+    // Update the variables

+    _updateVars();

+

+    return EVAL_BODY_INCLUDE;

+  }

+

+  @Override

+  public int doAfterBody()

+  {

+    _currentIndex += _currentStep;

+

+    //pu: if there is no varStatus set, no point in keeping loop status

+    //  variables updated.

+    if (null != _varStatus)

+    {

+      //pu: _isFirst is not yet updated after first iteration

+      boolean isSecondIteration = (_isFirst)? true:false;

+      if (isSecondIteration)

+      {

+        _propertyReplacementMap.put("first", _isFirst);

+      }

+      if (_isLast)

+      {

+        _propertyReplacementMap.put("last", _isLast);

+      }

+      _propertyReplacementMap.put("count", _currentCount);

+      _propertyReplacementMap.put("index", _currentIndex);

+      // FIXME Can we support "current" efficiently?

+      //      _propertyReplacementMap.put("current", _varReplacement);

+    }

+

+    // If we're at the end, bail

+    if (_currentEnd < _currentIndex)

+    {

+      // Restore EL state

+      VariableMapper vm = 

+        pageContext.getELContext().getVariableMapper();

+      if (_var != null)

+        vm.setVariable(_var, _previousDeferredVar);

+      if (_varStatus != null)

+        vm.setVariable(_varStatus, _previousDeferredVarStatus);

+

+      return SKIP_BODY;

+    }

+    

+    // Otherwise, update the variables and go again

+    _updateVars();

+

+    return EVAL_BODY_AGAIN;

+  }

+

+  /**

+   * Release state.

+   */

+  @Override

+  public void release()

+  {

+    super.release();

+    _begin = null;

+    _end = null;

+    _step = null;

+    _items = null;

+    _itemsValue = null;

+    _var = null;

+    _varStatus = null;

+    _propertyReplacementMap = null;

+    _previousDeferredVar = null;

+    _previousDeferredVarStatus = null;

+  }

+

+  // Push new values into the VariableMapper and the pageContext

+  private void _updateVars()

+  {

+    VariableMapper vm = 

+      pageContext.getELContext().getVariableMapper();

+    if (_var != null)

+    {

+      ValueExpression iterated = new IndexedValueExpression(_items,

+                                                            _currentIndex);

+      vm.setVariable(_var, iterated);

+      

+      Object items = _itemsValue;

+      Object item;

+      if (items instanceof List)

+        item = ((List) items).get(_currentIndex);

+      else

+        item = Array.get(items, _currentIndex);

+

+      pageContext.setAttribute(_var, item);

+    }

+    

+    if (_varStatus != null)

+    {

+      pageContext.setAttribute(_varStatus, _propertyReplacementMap);

+      ValueExpression constant = new Constants(

+                                      new HashMap(_propertyReplacementMap));

+      vm.setVariable(_varStatus, constant);

+    }

+  }

+

+  private void _validateAttributes() throws JspTagException

+  {

+    if (null == _items)

+    {

+      if (null == _begin || null == _end)

+      {

+        throw new JspTagException(

+          "'begin' and 'end' should be specified if 'items' is not specified");

+      }

+    }

+    //pu: This is our own check - c:forEach behavior un-defined & 
unpredictable.

+    if (_var == _varStatus)

+    {

+      throw new JspTagException(

+        "'var' and 'varStatus' must not have same value");

+    }

+  }

+

+  private void _validateRangeAndStep() throws JspTagException

+  {

+    if (_currentBegin < 0)

+      throw new JspTagException("'begin' < 0");

+    if (_currentStep < 1)

+      throw new JspTagException("'step' < 1");

+  }

+

+  // Basic ValueExpression that always returns a constant object

+  static private class Constants extends ValueExpression

+                                 implements Serializable

+  {

+    public Constants(Object o)

+    {

+      _o = o;

+    }

+

+    public Object getValue(ELContext context)

+    {

+      return _o;

+    }

+

+    public void setValue(ELContext context, Object value)

+    {

+      throw new PropertyNotWritableException();

+    }

+

+    public boolean isReadOnly(ELContext context)

+    {

+      return true;

+    }

+

+    public Class getType(ELContext context)

+    {

+      return _o.getClass();

+    }

+

+    public Class getExpectedType()

+    {

+      return _o.getClass();

+    }

+

+    public String getExpressionString()

+    {

+      return null;

+    }

+

+    public boolean equals(Object obj)

+    {

+      return obj == this;

+    }

+

+    public int hashCode()

+    {

+      return _o.hashCode();

+    }

+

+    public boolean isLiteralText()

+    {

+      return true;

+    }

+

+    private Object _o;

+  }

+

+  private int _currentBegin;

+  private int _currentIndex;

+  private int _currentEnd;

+  private int _currentStep;

+  private int _currentCount;

+  private boolean _isFirst;

+  private boolean _isLast;

+

+

+  private ValueExpression _items;

+  private Object          _itemsValue;

+

+  private Integer _begin;

+  private Integer _end;

+  private Integer _step;

+  private String _var;

+  private String _varStatus;

+  

+  // Saved values on the VariableMapper

+  private ValueExpression _previousDeferredVar;

+  private ValueExpression _previousDeferredVarStatus;

+

+  // Map for properties referred off from 'varStatus' and their replacements

+  private Map<String, Object> _propertyReplacementMap;

+

+  private static final TrinidadLogger _LOG = 
TrinidadLogger.createTrinidadLogger(ForEachTag.class);

+

+}



Reply via email to