You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ar...@apache.org on 2012/09/24 18:02:27 UTC
svn commit: r1389453 - in /myfaces/trinidad/branches/ar_1940:
trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/
trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/
trinidad-examples/trinidad-demo/src/main/weba...
Author: arobinson74
Date: Mon Sep 24 16:02:26 2012
New Revision: 1389453
URL: http://svn.apache.org/viewvc?rev=1389453&view=rev
Log:
Commit changes that have been in my working copy
Added:
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx (with props)
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx (with props)
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx (with props)
Modified:
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/ForEachBean.java
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml
myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach.jspx
myfaces/trinidad/branches/ar_1940/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
Modified: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/ForEachBean.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/ForEachBean.java?rev=1389453&r1=1389452&r2=1389453&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/ForEachBean.java (original)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/tagDemos/ForEachBean.java Mon Sep 24 16:02:26 2012
@@ -1,10 +1,14 @@
package org.apache.myfaces.trinidaddemo.tagDemos;
+import java.io.Serializable;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.visit.VisitCallback;
@@ -25,17 +29,19 @@ import org.apache.myfaces.trinidad.model
public class ForEachBean
+ implements Serializable
{
public static class Person
+ implements Serializable
{
public Person(
String key,
String firstName,
String lastName)
{
- this._firstName = firstName;
- this._lastName = lastName;
- this._key = key;
+ _firstName = firstName;
+ _lastName = lastName;
+ _key = key;
}
public final String getKey()
@@ -62,24 +68,43 @@ public class ForEachBean
private final String _key;
private final String _firstName;
private final String _lastName;
+
+ @SuppressWarnings("compatibility:-1476456984616362784")
+ private static final long serialVersionUID = 1L;
}
public ForEachBean()
{
- _simpleList = Arrays.asList(
- "One", "Two", "Three", "Four");
- _model = new RowKeyPropertyModel(
- Arrays.asList(
- new Person("a", "John", "Doe"),
- new Person("b", "Jane", "Doe"),
- new Person("c", "Bob", "Smith"),
- new Person("d", "Alice", "Jones")),
- "key");
+ _list = new ArrayList<Person>(
+ Arrays.asList(
+ new Person("a", "John", "Doe"),
+ new Person("b", "Jane", "Doe"),
+ new Person("c", "Bob", "Smith"),
+ new Person("d", "Alice", "Jones")));
+
+ _model = new RowKeyPropertyModel(new ArrayList<Person>(_list), "key");
+ _map = new LinkedHashMap<String, Person>();
+
+ _applySortToNonCollectionModelObjects();
+ }
+
+ public final void setCurrentExample(String currentExample)
+ {
+ _currentExample = currentExample;
+ }
+
+ public final String getCurrentExample()
+ {
+ return _currentExample;
}
public final void setSortProperty(String sortProperty)
{
- this._sortProperty = sortProperty;
+ if ("".equals(sortProperty))
+ {
+ sortProperty = null;
+ }
+ _sortProperty = sortProperty;
}
public final String getSortProperty()
@@ -89,7 +114,7 @@ public class ForEachBean
public final void setSortAscending(boolean sortAscending)
{
- this._sortAscending = sortAscending;
+ _sortAscending = sortAscending;
}
public final boolean isSortAscending()
@@ -97,63 +122,119 @@ public class ForEachBean
return _sortAscending;
}
- public List<String> getSimpleList()
+ public List<Person> getList()
{
- return _simpleList;
+ return _list;
}
- public void updateSortOrder(
- ActionEvent evt)
+ public void updateSortOrder(ActionEvent evt)
{
- UIXCommand sourceComponent = (UIXCommand) evt.getComponent();
+ UIXCommand sourceComponent = (UIXCommand)evt.getComponent();
+ RowKeyPropertyModel model = _getCollectionModel();
if (_sortProperty == null)
{
- _model.setSortCriteria(null);
+ model.setSortCriteria(null);
}
else
{
- _model.setSortCriteria(
- Collections.singletonList(new SortCriterion(_sortProperty, _sortAscending)));
+ model.setSortCriteria(Collections.singletonList(new SortCriterion(_sortProperty,
+ _sortAscending)));
}
// Now fire a component event to re-order the components
- Object origRowKey = _model.getRowKey();
final FacesContext facesContext = FacesContext.getCurrentInstance();
+ List<String> orderedKeys = _applySortToNonCollectionModelObjects();
- final List<String> orderedKeys = new ArrayList<String>(_model.getRowCount());
- for (_model.setRowIndex(0);
- _model.isRowAvailable();
- _model.setRowIndex(_model.getRowIndex() + 1))
- {
- Person person = (Person)_model.getRowData();
- orderedKeys.add(person.getKey());
- System.out.println("Person: " + person);
- }
- _model.setRowKey(origRowKey);
-
- for (UIComponent targetComponent :
- RequestContext.getCurrentInstance().getPartialTargets(sourceComponent))
+ for (UIComponent targetComponent:
+ RequestContext.getCurrentInstance().getPartialTargets(sourceComponent))
{
String clientId = targetComponent.getClientId();
- System.out.println("CLIENT ID: " + clientId);
+ //System.out.println("CLIENT ID: " + clientId);
VisitTreeUtils.visitSingleComponent(facesContext, clientId,
- new ReorderChildrenVisitCallback(orderedKeys));
+ new ReorderChildrenVisitCallback(orderedKeys));
}
}
+ public Map<String, Person> getMap()
+ {
+ return _map;
+ }
+
public SortableModel getModel()
{
+ return _getCollectionModel();
+ }
+
+ /**
+ * Applies the sort to the person list and the person map based on the sort order of the
+ * collection model.
+ * @return the sorted keys of the people to use for component reordering
+ */
+ private List<String> _applySortToNonCollectionModelObjects()
+ {
+ RowKeyPropertyModel model = _getCollectionModel();
+
+ Object origRowKey = model.getRowKey();
+ List<String> orderedKeys = new ArrayList<String>(model.getRowCount());
+ _list.clear();
+ _map.clear();
+ try
+ {
+ for (model.setRowIndex(0);
+ model.isRowAvailable();
+ model.setRowIndex(_model.getRowIndex() + 1))
+ {
+ Person person = (Person)model.getRowData();
+ orderedKeys.add(person.getKey());
+ //System.out.println("Person: " + person);
+ _list.add(person);
+ _map.put(person.getKey(), person);
+ }
+ }
+ finally
+ {
+ try
+ {
+ model.setRowKey(origRowKey);
+ }
+ catch (Throwable t)
+ {
+ ;
+ }
+ }
+
+ return orderedKeys;
+ }
+
+ private RowKeyPropertyModel _getCollectionModel()
+ {
+ if (_model == null)
+ {
+ // Model will be null as it is not serializable and the view state is not preserved in
+ // the server memory
+ _model = new RowKeyPropertyModel(new ArrayList<Person>(_list), "key");
+
+ if (_sortProperty == null)
+ {
+ _model.setSortCriteria(null);
+ }
+ else
+ {
+ _model.setSortCriteria(Collections.singletonList(new SortCriterion(_sortProperty,
+ _sortAscending)));
+ }
+ }
+
return _model;
}
private static class ReorderChildrenVisitCallback
implements VisitCallback, Comparator<String>
{
- private ReorderChildrenVisitCallback(
- List<String> orderedKeys)
+ private ReorderChildrenVisitCallback(List<String> orderedKeys)
{
- this._orderedKeys = orderedKeys;
+ _orderedKeys = orderedKeys;
}
@Override
@@ -161,25 +242,20 @@ public class ForEachBean
VisitContext visitContext,
UIComponent target)
{
- System.out.println("**************VISIT " + target.getClientId());
+ //System.out.println("**************VISIT " + target.getClientId());
FacesContext facesContext = visitContext.getFacesContext();
List<String> childrenIds = new ArrayList<String>();
- for (UIComponent child : target.getChildren())
+ for (UIComponent child: target.getChildren())
{
// Safe to call get ID out of context
childrenIds.add(child.getId());
}
Collections.sort(childrenIds, this);
- System.out.println("Sorted list:");
- for (String clientId : childrenIds)
- {
- System.out.println(" " + clientId);
- }
ChangeManager apm = RequestContext.getCurrentInstance().getChangeManager();
apm.addComponentChange(facesContext, target,
- new ReorderChildrenComponentChange(childrenIds));
+ new ReorderChildrenComponentChange(childrenIds));
return VisitResult.COMPLETE;
}
@@ -201,8 +277,13 @@ public class ForEachBean
private final List<String> _orderedKeys;
}
- private final List<String> _simpleList;
- private final RowKeyPropertyModel _model;
+ private final List<Person> _list;
+ private transient RowKeyPropertyModel _model;
+ private final Map<String, Person> _map;
+ private String _currentExample = "home";
private String _sortProperty;
private boolean _sortAscending;
-}
+
+ @SuppressWarnings("compatibility:-8911883817863052298")
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
Modified: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml?rev=1389453&r1=1389452&r2=1389453&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml (original)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml Mon Sep 24 16:02:26 2012
@@ -3143,6 +3143,8 @@
<managed-bean>
<managed-bean-name>forEachBean</managed-bean-name>
<managed-bean-class>org.apache.myfaces.trinidaddemo.tagDemos.ForEachBean</managed-bean-class>
- <managed-bean-scope>request</managed-bean-scope>
+ <!-- Use session scope since the session change manager is used, so that the bean stays in
+ sync with the change state -->
+ <managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
Modified: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach.jspx?rev=1389453&r1=1389452&r2=1389453&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach.jspx (original)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach.jspx Mon Sep 24 16:02:26 2012
@@ -24,104 +24,58 @@
<f:view>
<tr:document title="ForEach Demo">
<tr:form>
- <tr:panelGroupLayout layout="vertical" partialTriggers="refreshButton">
- <f:facet name="separator">
- <tr:separator/>
+ <tr:panelBorderLayout>
+ <f:facet name="top">
+ <tr:panelGroupLayout layout="vertical" inlineStyle="padding-bottom: 2em;">
+ <tr:navigationPane hint="buttons">
+ <tr:commandNavigationItem text="Component Guide" action="guide"/>
+ <tr:commandNavigationItem destination="http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_forEach.html"
+ text="Tag Documentation"/>
+ </tr:navigationPane>
+ </tr:panelGroupLayout>
</f:facet>
- <tr:navigationPane hint="buttons">
- <tr:commandNavigationItem immediate="true" text="Component Guide" action="guide"/>
- <tr:commandNavigationItem immediate="true"
- destination="http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_forEach.html"
- text="Tag Documentation"/>
- </tr:navigationPane>
- <tr:goLink destination="http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_breadCrumbs.html"
- text="Tag Documentation"/>
- <tr:outputFormatted styleUsage="instruction" value="<b>forEach</b>"/>
- <tr:panelGroupLayout layout="vertical">
- <f:facet name="separator">
- <tr:spacer height="12" />
- </f:facet>
- <tr:panelHeader text="Simple for each loop, no items">
- <tr:panelGroupLayout layout="vertical">
- <tr:forEach var="item" begin="0" end="2">
- <tr:outputText id="outputText" value="Client ID: #{component.clientId}"/>
- </tr:forEach>
- </tr:panelGroupLayout>
- </tr:panelHeader>
- <tr:panelHeader text="Simple for each loop, items from list">
- <tr:panelGroupLayout layout="vertical">
- <tr:forEach var="item" items="#{forEachBean.simpleList}">
- <tr:outputText id="outputText1" value="Client ID: #{component.clientId}"/>
- </tr:forEach>
- </tr:panelGroupLayout>
- </tr:panelHeader>
- <tr:panelHeader text="Simple for each loop, items from list, fixed IDs">
- <tr:panelGroupLayout layout="vertical">
- <tr:forEach var="item" items="#{forEachBean.simpleList}" varStatus="vs">
- <tr:outputText id="outputText2_${vs.key}"
- value="Client ID: #{component.clientId}. Text: #{item}"/>
- </tr:forEach>
- </tr:panelGroupLayout>
- </tr:panelHeader>
- <tr:panelHeader text="Var status properties with list items">
- <tr:panelGroupLayout layout="vertical">
- <tr:forEach var="item" items="#{forEachBean.simpleList}" varStatus="vs">
- <tr:panelGroupLayout>
- <f:facet name="separator">
- <tr:spacer width="10"/>
- </f:facet>
- <tr:outputText value="Index: #{vs.index}"/>
- <tr:outputText value="Count: #{vs.count}"/>
- <tr:outputText value="Key: #{vs.key}"/>
- <tr:outputText value="First: #{vs.first}"/>
- <tr:outputText value="Last: #{vs.last}"/>
- </tr:panelGroupLayout>
- <tr:separator rendered="#{not vs.last}" />
- </tr:forEach>
- </tr:panelGroupLayout>
- </tr:panelHeader>
- <tr:panelHeader text="Reorder example with CollectionModel">
- <tr:panelGroupLayout layout="vertical">
- <tr:panelGroupLayout layout="vertical" id="personForEachParent"
- partialTriggers="applySort">
- <tr:forEach var="person" items="#{forEachBean.model}" varStatus="vs">
- <tr:panelGroupLayout id="personPgl">
- <f:facet name="separator">
- <tr:spacer width="10"/>
- </f:facet>
- <tr:outputText id="firstName"
- value="First name: #{person.firstName}"/>
- <tr:outputText id="lastName"
- value="Last name: #{person.lastName}"/>
- <tr:outputText id="clientId"
- value="(Panel group layout client ID: #{component.parent.clientId})"/>
- </tr:panelGroupLayout>
- <tr:separator id="sep1" rendered="#{not vs.last}" />
- </tr:forEach>
+ <f:facet name="start">
+ <tr:panelGroupLayout layout="scroll" inlineStyle="width: 250px; display: block">
+ <f:facet name="separator">
+ <tr:spacer height="6px"/>
+ </f:facet>
+ <tr:commandLink text="Re-order collection model"
+ shortDesc="Example of reordering support with a collection model backed for each loop"
+ partialSubmit="true" id="reorderCollectionModelLink">
+ <f:setPropertyActionListener target="#{forEachBean.currentExample}"
+ value="reorderCollectionModel"/>
+ </tr:commandLink>
+ <tr:commandLink text="Re-order map"
+ shortDesc="Example of reordering support with a map backed for each loop"
+ partialSubmit="true" id="reorderMapLink">
+ <f:setPropertyActionListener target="#{forEachBean.currentExample}"
+ value="reorderMap"/>
+ </tr:commandLink>
+ </tr:panelGroupLayout>
+ </f:facet>
+ <tr:panelGroupLayout layout="scroll"
+ partialTriggers="reorderMapLink reorderCollectionModelLink">
+ <tr:switcher defaultFacet="home" facetName="#{forEachBean.currentExample}">
+ <f:facet name="home">
+ <tr:outputText value="Choose an example from the side panel."/>
+ </f:facet>
+ <f:facet name="reorderMap">
+ <tr:panelGroupLayout layout="vertical">
+ <f:subview id="rm">
+ <jsp:include page="forEach/reorderMap.jspx"/>
+ </f:subview>
+ </tr:panelGroupLayout>
+ </f:facet>
+ <f:facet name="reorderCollectionModel">
+ <tr:panelGroupLayout layout="vertical">
+ <f:subview id="rcm">
+ <jsp:include page="forEach/reorder.jspx"/>
+ </f:subview>
</tr:panelGroupLayout>
- </tr:panelGroupLayout>
- <tr:panelFormLayout>
- <tr:selectOneRadio label="Property:" value="#{forEachBean.sortProperty}">
- <tr:selectItem label="(none)" value="#{null}" />
- <tr:selectItem label="First name" value="firstName" />
- <tr:selectItem label="Last name" value="lastName" />
- </tr:selectOneRadio>
- <tr:selectOneRadio label="Order:" value="#{forEachBean.sortAscending}">
- <tr:selectItem label="Ascending" value="#{true}" />
- <tr:selectItem label="Descending" value="#{false}" />
- </tr:selectOneRadio>
- <f:facet name="footer">
- <tr:commandLink id="applySort"
- text="Apply sort"
- partialSubmit="true"
- actionListener="#{forEachBean.updateSortOrder}"/>
- </f:facet>
- </tr:panelFormLayout>
- </tr:panelHeader>
- <tr:commandButton text="Refresh" partialSubmit="true" id="refreshButton"
- shortDesc="Test PPR of the for each loop by refreshing the page content"/>
+ </f:facet>
+ </tr:switcher>
</tr:panelGroupLayout>
- </tr:panelGroupLayout>
+ </tr:panelBorderLayout>
</tr:form>
</tr:document>
</f:view>
Added: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx?rev=1389453&view=auto
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx (added)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx Mon Sep 24 16:02:26 2012
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:tr="http://myfaces.apache.org/trinidad" version="2.1">
+ <tr:panelHeader text="Reorder example with CollectionModel">
+ <tr:panelGroupLayout layout="vertical">
+ <f:facet name="separator">
+ <tr:spacer height="1em"/>
+ </f:facet>
+ <tr:outputText value="This example shows the how a for each tag may be backed by a collection
+ model to permit reordering of components in JSP while retaining
+ component state with the item in the for each loop instead of the
+ index." />
+ <tr:outputText value="Normally, in a JSTL for each loop, the components are mapped to the
+ index of a for each loop. By using keys from a collection model, the
+ Trinidad for each loop is able to tie the components to the key of an
+ item in the collection rather than the index. This allows the items
+ to be reordered and have the component state stay with the object." />
+ <tr:outputText value="Note that the components must be reordered in the parent's children
+ list as well. Otherwise, the component state will be correct, but
+ the component will render in the wrong location." />
+ <tr:outputText value="Try disclosing an item in the list below and then change the sorting.
+ The disclosure state should stay with the item and not with the index,
+ so if you disclose the show detail in 'Alice Jones', then her
+ disclosure should remain disclosed during sorting." />
+ </tr:panelGroupLayout>
+ <tr:panelGroupLayout layout="vertical" inlineStyle="padding-left: 2em; padding-top: 1em">
+ <tr:panelHeader text="Components built from the for each loop">
+ <tr:panelGroupLayout layout="vertical" id="personForEachParent"
+ partialTriggers="applySort"
+ inlineStyle="padding-bottom: 1em">
+ <tr:forEach var="person" items="#{forEachBean.model}" varStatus="vs">
+ <tr:panelGroupLayout id="personPgl">
+ <f:facet name="separator">
+ <tr:spacer width="10"/>
+ </f:facet>
+ <tr:outputText id="firstName"
+ value="First name: #{person.firstName}"/>
+ <tr:outputText id="lastName"
+ value="Last name: #{person.lastName}"/>
+ <tr:outputText id="clientId"
+ value="(Panel group layout client ID: #{component.parent.clientId})"/>
+ </tr:panelGroupLayout>
+ <tr:showDetail id="showDisclosure" disclosed="false" disclosedText="Disclosed text"
+ undisclosedText="Undisclosed text">
+ <tr:outputText value="The disclosed state of this text should stay with the item
+ during sorting, not with the index."
+ inlineStyle="padding-left: 1em"/>
+ </tr:showDetail>
+ <tr:separator id="sep1" rendered="#{not vs.last}" />
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ </tr:panelGroupLayout>
+ <tr:panelHeader text="Sorting options">
+ <tr:panelFormLayout>
+ <tr:selectOneRadio label="Property:" value="#{forEachBean.sortProperty}">
+ <tr:selectItem label="(none)" value="#{null}" />
+ <tr:selectItem label="First name" value="firstName" />
+ <tr:selectItem label="Last name" value="lastName" />
+ </tr:selectOneRadio>
+ <tr:selectOneRadio label="Order:" value="#{forEachBean.sortAscending}">
+ <tr:selectItem label="Ascending" value="#{true}" />
+ <tr:selectItem label="Descending" value="#{false}" />
+ </tr:selectOneRadio>
+ <f:facet name="footer">
+ <tr:commandLink id="applySort"
+ text="Apply sort"
+ partialSubmit="true"
+ actionListener="#{forEachBean.updateSortOrder}"/>
+ </f:facet>
+ </tr:panelFormLayout>
+ </tr:panelHeader>
+ </tr:panelHeader>
+</jsp:root>
\ No newline at end of file
Propchange: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorder.jspx
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx?rev=1389453&view=auto
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx (added)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx Mon Sep 24 16:02:26 2012
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:tr="http://myfaces.apache.org/trinidad" version="2.1">
+ <tr:panelHeader text="Reorder example with map">
+ <tr:panelGroupLayout layout="vertical">
+ <f:facet name="separator">
+ <tr:spacer height="1em"/>
+ </f:facet>
+ <tr:outputText value="This example shows the how a for each tag may be backed by a map
+ to permit reordering of components in JSP while retaining
+ component state with the item in the for each loop instead of the
+ index." />
+ <tr:outputText value="Normally, in a JSTL for each loop, the components are mapped to the
+ index of a for each loop. By using keys from a java map, the
+ Trinidad for each loop is able to tie the components to the key of an
+ item in the collection rather than the index. This allows the items
+ to be reordered and have the component state stay with the object." />
+ <tr:outputText value="Note that the components must be reordered in the parent's children
+ list as well. Otherwise, the component state will be correct, but
+ the component will render in the wrong location. Also, the map
+ must keep its iteration order constant. For example, it is
+ recommended to use a LinkedHashMap instead of a HashMap so that
+ the order of iteration is maintained." />
+ <tr:outputText value="Try disclosing an item in the list below and then change the sorting.
+ The disclosure state should stay with the item and not with the index,
+ so if you disclose the show detail in 'Alice Jones', then her
+ disclosure should remain disclosed during sorting." />
+ </tr:panelGroupLayout>
+ <tr:panelGroupLayout layout="vertical" inlineStyle="padding-left: 2em; padding-top: 1em">
+ <tr:panelHeader text="Components built from the for each loop">
+ <tr:panelGroupLayout layout="vertical" id="personForEachParent"
+ partialTriggers="applySort"
+ inlineStyle="padding-bottom: 1em">
+ <tr:forEach var="person" items="#{forEachBean.map}" varStatus="vs">
+ <tr:panelGroupLayout id="personPgl">
+ <f:facet name="separator">
+ <tr:spacer width="10"/>
+ </f:facet>
+ <tr:outputText id="firstName"
+ value="First name: #{person.firstName}"/>
+ <tr:outputText id="lastName"
+ value="Last name: #{person.lastName}"/>
+ <tr:outputText id="clientId"
+ value="(Panel group layout client ID: #{component.parent.clientId}) Vs: #{empty vs}"/>
+ </tr:panelGroupLayout>
+ <tr:showDetail id="showDisclosure" disclosed="false" disclosedText="Disclosed text"
+ undisclosedText="Undisclosed text">
+ <tr:outputText value="The disclosed state of this text should stay with the item
+ during sorting, not with the index."
+ inlineStyle="padding-left: 1em"/>
+ </tr:showDetail>
+ <tr:separator id="sep1" rendered="#{not vs.last}" />
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ </tr:panelGroupLayout>
+ <tr:panelHeader text="Sorting options">
+ <tr:panelFormLayout>
+ <tr:selectOneRadio label="Property:" value="#{forEachBean.sortProperty}">
+ <tr:selectItem label="(none)" value="#{null}" />
+ <tr:selectItem label="First name" value="firstName" />
+ <tr:selectItem label="Last name" value="lastName" />
+ </tr:selectOneRadio>
+ <tr:selectOneRadio label="Order:" value="#{forEachBean.sortAscending}">
+ <tr:selectItem label="Ascending" value="#{true}" />
+ <tr:selectItem label="Descending" value="#{false}" />
+ </tr:selectOneRadio>
+ <f:facet name="footer">
+ <tr:commandLink id="applySort"
+ text="Apply sort"
+ partialSubmit="true"
+ actionListener="#{forEachBean.updateSortOrder}"/>
+ </f:facet>
+ </tr:panelFormLayout>
+ </tr:panelHeader>
+ </tr:panelHeader>
+</jsp:root>
\ No newline at end of file
Propchange: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach/reorderMap.jspx
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx?rev=1389453&view=auto
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx (added)
+++ myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx Mon Sep 24 16:02:26 2012
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:tr="http://myfaces.apache.org/trinidad" version="1.2">
+ <jsp:directive.page contentType="text/html;charset=utf-8"/>
+ <f:view>
+ <tr:document title="ForEach Demo">
+ <tr:form>
+ <tr:panelGroupLayout layout="vertical" partialTriggers="refreshButton">
+ <f:facet name="separator">
+ <tr:separator/>
+ </f:facet>
+ <tr:navigationPane hint="buttons">
+ <tr:commandNavigationItem immediate="true" text="Component Guide" action="guide"/>
+ <tr:commandNavigationItem immediate="true"
+ destination="http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_forEach.html"
+ text="Tag Documentation"/>
+ </tr:navigationPane>
+ <tr:goLink destination="http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_breadCrumbs.html"
+ text="Tag Documentation"/>
+ <tr:outputFormatted styleUsage="instruction" value="<b>forEach</b>"/>
+ <tr:panelGroupLayout layout="vertical">
+ <f:facet name="separator">
+ <tr:spacer height="12" />
+ </f:facet>
+ <tr:panelHeader text="Simple for each loop, no items">
+ <tr:panelGroupLayout layout="vertical">
+ <tr:forEach var="item" begin="0" end="2">
+ <tr:outputText id="outputText" value="Client ID: #{component.clientId}"/>
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ <tr:panelHeader text="Simple for each loop, items from list">
+ <tr:panelGroupLayout layout="vertical">
+ <tr:forEach var="item" items="#{forEachBean.simpleList}">
+ <tr:outputText id="outputText1" value="Client ID: #{component.clientId}"/>
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ <tr:panelHeader text="Simple for each loop, items from list, fixed IDs">
+ <tr:panelGroupLayout layout="vertical">
+ <tr:forEach var="item" items="#{forEachBean.simpleList}" varStatus="vs">
+ <tr:outputText id="outputText2_${vs.key}"
+ value="Client ID: #{component.clientId}. Text: #{item}"/>
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ <tr:panelHeader text="Var status properties with list items">
+ <tr:panelGroupLayout layout="vertical">
+ <tr:forEach var="item" items="#{forEachBean.simpleList}" varStatus="vs">
+ <tr:panelGroupLayout>
+ <f:facet name="separator">
+ <tr:spacer width="10"/>
+ </f:facet>
+ <tr:outputText value="Index: #{vs.index}"/>
+ <tr:outputText value="Count: #{vs.count}"/>
+ <tr:outputText value="Key: #{vs.key}"/>
+ <tr:outputText value="First: #{vs.first}"/>
+ <tr:outputText value="Last: #{vs.last}"/>
+ </tr:panelGroupLayout>
+ <tr:separator rendered="#{not vs.last}" />
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelHeader>
+ <tr:panelHeader text="Reorder example with CollectionModel">
+ <tr:panelGroupLayout layout="vertical">
+ <tr:panelGroupLayout layout="vertical" id="personForEachParent"
+ partialTriggers="applySort">
+ <tr:forEach var="person" items="#{forEachBean.model}" varStatus="vs">
+ <tr:panelGroupLayout id="personPgl">
+ <f:facet name="separator">
+ <tr:spacer width="10"/>
+ </f:facet>
+ <tr:outputText id="firstName"
+ value="First name: #{person.firstName}"/>
+ <tr:outputText id="lastName"
+ value="Last name: #{person.lastName}"/>
+ <tr:outputText id="clientId"
+ value="(Panel group layout client ID: #{component.parent.clientId})"/>
+ </tr:panelGroupLayout>
+ <tr:separator id="sep1" rendered="#{not vs.last}" />
+ </tr:forEach>
+ </tr:panelGroupLayout>
+ </tr:panelGroupLayout>
+ <tr:panelFormLayout>
+ <tr:selectOneRadio label="Property:" value="#{forEachBean.sortProperty}">
+ <tr:selectItem label="(none)" value="#{null}" />
+ <tr:selectItem label="First name" value="firstName" />
+ <tr:selectItem label="Last name" value="lastName" />
+ </tr:selectOneRadio>
+ <tr:selectOneRadio label="Order:" value="#{forEachBean.sortAscending}">
+ <tr:selectItem label="Ascending" value="#{true}" />
+ <tr:selectItem label="Descending" value="#{false}" />
+ </tr:selectOneRadio>
+ <f:facet name="footer">
+ <tr:commandLink id="applySort"
+ text="Apply sort"
+ partialSubmit="true"
+ actionListener="#{forEachBean.updateSortOrder}"/>
+ </f:facet>
+ </tr:panelFormLayout>
+ </tr:panelHeader>
+ <tr:commandButton text="Refresh" partialSubmit="true" id="refreshButton"
+ shortDesc="Test PPR of the for each loop by refreshing the page content"/>
+ </tr:panelGroupLayout>
+ </tr:panelGroupLayout>
+ </tr:form>
+ </tr:document>
+ </f:view>
+</jsp:root>
Propchange: myfaces/trinidad/branches/ar_1940/trinidad-examples/trinidad-demo/src/main/webapp/demos/tags/forEach2.jspx
------------------------------------------------------------------------------
svn:eol-style = native
Modified: myfaces/trinidad/branches/ar_1940/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_1940/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java?rev=1389453&r1=1389452&r2=1389453&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_1940/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java (original)
+++ myfaces/trinidad/branches/ar_1940/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/taglib/ForEachTag.java Mon Sep 24 16:02:26 2012
@@ -22,10 +22,13 @@ import java.io.Serializable;
import java.lang.reflect.Array;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.el.ELContext;
import javax.el.PropertyNotWritableException;
@@ -41,6 +44,7 @@ import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.JspIdConsumer;
+import org.apache.myfaces.trinidad.component.UIXComponent;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.webapp.TrinidadIterationTag;
@@ -251,6 +255,10 @@ public class ForEachTag
_parentComponent = _getParentComponent();
+ // Remember the non-Trinidad components before execution so that we may determine which
+ // are created during this tags for each execution
+ _previousIterationNonTrinidadChildren = _getNonTrinidadChildren();
+
_updateVars(true);
return EVAL_BODY_INCLUDE;
@@ -260,6 +268,10 @@ public class ForEachTag
public int doAfterBody()
{
_LOG.finest("doAfterBody processing");
+
+ // Process any non-Trinidad components that were added during the last body execution
+ _processNonTrinidadComponents();
+
_currentIndex += _currentStep;
++_currentCount;
_isFirst = false;
@@ -279,6 +291,7 @@ public class ForEachTag
{
popComponentSuffix();
_suffixPushed = false;
+ _previousIterationNonTrinidadChildren = null;
}
return SKIP_BODY;
@@ -314,6 +327,8 @@ public class ForEachTag
_iterationMap = null;
_itemsWrapper = null;
+ _previousIterationNonTrinidadChildren = null;
+
_parentComponent = null;
_suffixPushed = false;
@@ -370,7 +385,7 @@ public class ForEachTag
}
@Override
- public void afterChildComponentProcessed(
+ public final void afterChildComponentProcessed(
UIComponent component)
{
// This code is called when a component is created or found, see which it is.
@@ -395,6 +410,27 @@ public class ForEachTag
}
}
+ private Set<UIComponent> _getNonTrinidadChildren()
+ {
+ if (_parentComponent == null)
+ {
+ return Collections.emptySet();
+ }
+
+ Set<UIComponent> components = new HashSet<UIComponent>(_parentComponent.getChildCount());
+ for (UIComponent child : _parentComponent.getChildren())
+ {
+ if (child instanceof UIXComponent)
+ {
+ continue;
+ }
+
+ components.add(child);
+ }
+
+ return components;
+ }
+
private UIComponent _getParentComponent()
{
UIComponentClassicTagBase tag = UIComponentClassicTagBase.getParentUIComponentClassicTagBase(
@@ -402,11 +438,101 @@ public class ForEachTag
return tag == null ? null : tag.getComponentInstance();
}
+ /**
+ * Get the key for the current item in the items. For non-key based collections, this is the
+ * index. If there is no items attribute, this simply returns the current index as well.
+ *
+ * @return the key or index
+ */
+ private Serializable _getKey()
+ {
+ return (_itemsWrapper == null) ?
+ _currentIndex :
+ _asSerializable(_itemsWrapper.getKey(_currentIndex));
+ }
+
+ /**
+ * Although in-efficient in how we process UIXComponent children, this function allows
+ * non-Trinidad components to correctly map their value expressions to the iteration of the
+ * for each loop better than the JSTL tag does in JSF. In order to do this, this function must
+ * determine what non-UIXComponents belong to the current iteration of the loop.
+ *
+ * @see #afterChildComponentProcessed(UIComponent)
+ * @see #childComponentProcessed(UIComponent)
+ */
+ private void _processNonTrinidadComponents()
+ {
+ Serializable key = null;
+
+ // If _previousIterationNonTrinidadChildren is non-null then this is not the first
+ // execution of this code in this request. We need to determine what components were added
+ // during this iteration
+ Set<UIComponent> childrenComponents = _getNonTrinidadChildren();
+ if (childrenComponents.isEmpty())
+ {
+ _previousIterationNonTrinidadChildren.clear();
+ return;
+ }
+
+ for (UIComponent child : childrenComponents)
+ {
+ Map<String, Object> attrs = child.getAttributes();
+ if (_previousIterationNonTrinidadChildren.contains(child))
+ {
+ // This child component is either one that was created in a previous request, or
+ // one that was not created by this for each loop, we need to determine which one.
+ NonTrinidadIterationData data = (NonTrinidadIterationData)attrs.get(_iterationMapKey);
+
+ // If the data is null, then this for each tag did not create the component and we
+ // do not need to do anything.
+ if (data == null)
+ {
+ continue;
+ }
+
+ // Get the key for the current item, if we have not already
+ if (key == null)
+ {
+ key = _getKey();
+ }
+
+ // Since we clear the iteration map in the start tag processing, we need to re-map
+ // the iteration ID from the component back to the current iteration data.
+ // First, we need to ensure that this component belongs to the current iteration. If
+ // it doesn't, we do not need to do anything as the component "belongs" to a different
+ // iteration
+ if (key.equals(data.getKey()))
+ {
+ // The keys are the same, update the map.
+ _iterationMap.put(data.getIterationId(), _iterationData);
+ }
+ }
+ else
+ {
+ // This is a component that was added to the parent while this for each loop was processing
+ // the last iteration. We need to record the key and the iteration ID so that we can map
+ // this component to its var status
+
+ // Get the key for the current item, if we have not already
+ if (key == null)
+ {
+ key = _getKey();
+ }
+
+ attrs.put(_iterationMapKey, new NonTrinidadIterationData(key, _iterationId));
+ }
+ }
+
+ // Update the map so we know for the next iteration what components are being created
+ _previousIterationNonTrinidadChildren = childrenComponents;
+ }
+
// Push new values into the VariableMapper and the pageContext
private void _updateVars(
boolean createNewIterationData)
{
VariableMapper vm = pageContext.getELContext().getVariableMapper();
+ Serializable key = null;
// Generate a new iteration ID
_updateIterationId();
@@ -422,13 +548,14 @@ public class ForEachTag
if (_itemsWrapper.isKeyBased())
{
// Use a key to get the value
- Serializable key = _asSerializable(_itemsWrapper.getKey(_currentIndex));
- expr = new KeyedValueExpression(_items, key);
+ key = _getKey();
+ expr = new KeyedValueExpression(_items, _getKey());
}
else
{
// Use indirection to get the index from the iteration data using the iteration ID
- // so that the expression is not hard-coded to one index
+ // so that the expression is not hard-coded to one index. This allows the tag to
+ // support components that are re-ordered (index changes during multiple requests)
expr = new IndexedValueExpression(_iterationId, _iterationMapKey, _items);
}
@@ -445,17 +572,14 @@ public class ForEachTag
}
}
- Object key = _itemsWrapper == null ?
- _currentIndex : _itemsWrapper.getKey(_currentIndex);
-
- if (!(key instanceof Serializable))
- {
- throw new IllegalStateException("For each loop keys must be serializable");
- }
-
if (createNewIterationData || _iterationData == null)
{
- _iterationData = new IterationMetaData((Serializable)key, _isFirst, _isLast,
+ if (key == null)
+ {
+ key = _getKey();
+ }
+
+ _iterationData = new IterationMetaData(key, _isFirst, _isLast,
_currentBegin, _currentCount, _currentIndex, _currentEnd);
}
@@ -495,9 +619,22 @@ public class ForEachTag
// To do, support non-key pass-through
if (_itemsWrapper != null && _itemsWrapper.isIdSuffixSupported())
{
+ if (key == null)
+ {
+ key = _getKey();
+ }
+
pushComponentSuffix("_" + key.toString());
_suffixPushed = true;
}
+
+ if (_previousIterationNonTrinidadChildren == null)
+ {
+ // If _previousIterationNonTrinidadChildren is null, then this is the first execution
+ // of this function for this tag in this request, store off the non-Trinidad children
+ // components so that we can attempt to determine the ones that are added
+ _previousIterationNonTrinidadChildren = _getNonTrinidadChildren();
+ }
}
private Integer _evaluateInteger(
@@ -964,7 +1101,7 @@ public class ForEachTag
return;
}
- if (index < _currentIndex)
+ if (_iter == null || index < _currentIndex)
{
// Need to re-create the iterator
_iter = _map.entrySet().iterator();
@@ -1154,6 +1291,31 @@ public class ForEachTag
private Serializable _key;
}
+ private static class NonTrinidadIterationData
+ implements Serializable
+ {
+ public NonTrinidadIterationData(
+ Serializable key,
+ Integer iterationId)
+ {
+ _key = key;
+ _iterationId = iterationId;
+ }
+
+ public Serializable getKey()
+ {
+ return _key;
+ }
+
+ public Integer getIterationId()
+ {
+ return _iterationId;
+ }
+
+ private final Serializable _key;
+ private final Integer _iterationId;
+ }
+
private int _currentBegin;
private int _currentIndex;
private int _currentEnd;
@@ -1176,6 +1338,8 @@ public class ForEachTag
private UIComponent _parentComponent;
+ private Set<UIComponent> _previousIterationNonTrinidadChildren;
+
private Integer _iterationId;
private IterationMetaData _iterationData;
private Map<String, Object> _viewAttributes;
@@ -1192,7 +1356,22 @@ public class ForEachTag
private ValueExpression _previousDeferredVarStatus;
private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(ForEachTag.class);
- private static final String _VIEW_ATTR_KEY = ForEachTag.class.getName() + ".";
+
+ /**
+ * Due to the fact that JSP tag IDs may be reused in different JSP files, we must differentiate
+ * tags by not only their JSP IDs, but also a unique number per inc
+ */
+ private static final String JAVAX_FACES_PAGECONTEXT_MARKER =
+ "javax.faces.webapp.PAGECONTEXT_MARKER";
+
+ /**
+ * This is a <code>facesContext</code> scoped attribute which contains
+ * an AtomicInteger which we use to increment the PageContext
+ * count.
+ */
+ private static final String JAVAX_FACES_PAGECONTEXT_COUNTER =
+ "javax.faces.webapp.PAGECONTEXT_COUNTER";
+
private static final int _VIEW_ATTR_KEY_LENGTH = _VIEW_ATTR_KEY.length();
private static final String _ITERATION_ID_KEY =
ForEachTag.class.getName() + ".ITER";