From adffaces-commits-return-926-apmail-incubator-adffaces-commits-archive=incubator.apache.org@incubator.apache.org Thu Oct 05 23:26:02 2006 Return-Path: Delivered-To: apmail-incubator-adffaces-commits-archive@locus.apache.org Received: (qmail 94406 invoked from network); 5 Oct 2006 23:26:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 5 Oct 2006 23:26:02 -0000 Received: (qmail 96144 invoked by uid 500); 5 Oct 2006 23:26:01 -0000 Delivered-To: apmail-incubator-adffaces-commits-archive@incubator.apache.org Received: (qmail 96130 invoked by uid 500); 5 Oct 2006 23:26:01 -0000 Mailing-List: contact adffaces-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: adffaces-dev@incubator.apache.org Delivered-To: mailing list adffaces-commits@incubator.apache.org Received: (qmail 96121 invoked by uid 99); 5 Oct 2006 23:26:01 -0000 Received: from idunn.apache.osuosl.org (HELO idunn.apache.osuosl.org) (140.211.166.84) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Oct 2006 16:26:01 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=5.0 tests=ALL_TRUSTED,NO_REAL_NAME Received: from [140.211.166.113] ([140.211.166.113:51854] helo=eris.apache.org) by idunn.apache.osuosl.org (ecelerity 2.1.1.8 r(12930)) with ESMTP id ED/AD-04543-68495254 for ; Thu, 05 Oct 2006 16:25:58 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 908721A981A; Thu, 5 Oct 2006 16:25:56 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r453425 - in /incubator/adffaces/branches/faces-1_2/trinidad: ./ trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/ trinidad-api/src/site/xdoc/tagdoc/ trinidad-demo/src/main/webapp/surveydemo/ trinidad-impl/ trinida... Date: Thu, 05 Oct 2006 23:25:56 -0000 To: adffaces-commits@incubator.apache.org From: awiner@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061005232556.908721A981A@eris.apache.org> X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N 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 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.... 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 @@ provided + + jstl + jstl + 1.2 + provided + + com.sun.facelets 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 @@ + + + + + tr:forEach + + +
+

+ Tag name: <tr:forEach> +
+

+ The forEach tag is a replacement for the JSTL +<c:forEach> tag. Though as of JSF 1.2/JSP 2.1/JSTL 1.2, +<c:forEach> 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). +(Note: 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 <c:forEach>: <tr:forEach> does not currently support arbitrary +java.util.Collections; it can only iterate over java.util.Lists or +arrays.

+

Example:

+ <tr:selectOneListbox value="#{someValue}"> + <tr:forEach var="item" items="#{model.listOfItems}"> + <tr:selectItem value="#{item.value}" text="#{item.text}"/> + </tr:forEach> + </tr:selectOneListbox> + <tr:forEach varStatus="vs" begin="1" end="5"> + <tr:outputText id="ot2" value="#{vs.index} #{vs.count} #{vs.begin} #{vs.current}"/> + </tr:forEach> +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeSupports EL?Description
beginintNo + + index at which iteration begins +
endintNo + + index at which iteration ends +
itemsObjectOnly EL + + the collection to iterate over +
stepintNo + + number to increment on each iteration +
varStringNo + + name of the variable exposed when iterating +
varStatusStringNo + + name of the loop status exposed when iterating. The properties + 'index','count','begin','end','step','first','last' + are available through this +
+
+ +
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 @@ - + - - +
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 @@ + jstl + jstl + + + org.apache.myfaces.trinidad trinidad-build 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 @@ http://myfaces.apache.org/trinidad + forEach + org.apache.myfaces.trinidadinternal.taglib.ForEachTag + +The forEach tag is a replacement for the JSTL &lt;c:forEach&gt; tag. +As of JSF 1.2/JSP 2.1/JSTL 1.2, the regular &lt;c:forEach&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.) + + + + + the items over which iteration takes place + + items + + + + + + the name of the variable to expose + + var + false + + + + + Name of the exported scoped variable for the + status of the iteration. + + varStatus + false + + + + + the beginning index + + begin + false + + + + + the ending index + + end + false + + + + + the number of steps per iteration + + step + false + + + + + The setActionListener tag provides a declarative syntax for assigning values before an action fires 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 - Tag +//=================================== +//Syntax 1: Iterate over a collection of objects +// +// +// body content +// +// +//Syntax 2: Iterate a fixed number of times +// +// +// body content +// + +/** + * + * @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 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(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 _propertyReplacementMap; + + private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(ForEachTag.class); + +}