Author: hlship
Date: Wed Jan 24 16:17:13 2007
New Revision: 499626

URL: http://svn.apache.org/viewvc?view=rev&rev=499626
Log:
Add support for flash persistence (really useful for error or confirmation 
messages).

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java?view=auto&rev=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
 Wed Jan 24 16:17:13 2007
@@ -0,0 +1,114 @@
+// Copyright 2007 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.tapestry.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.services.Session;
+
+/**
+ * Base class for strategies that store their values as keys in the session. 
Implements a uniform
+ * format for the keys, based on a prefix to identify the particular strategy.
+ */
+public abstract class AbstractSessionPersistentFieldStrategy implements 
PersistentFieldStrategy
+{
+    private final String _prefix;
+
+    private final SessionHolder _sessionHolder;
+
+    protected AbstractSessionPersistentFieldStrategy(String prefix, 
SessionHolder sessionHolder)
+    {
+        _prefix = prefix;
+        _sessionHolder = sessionHolder;
+    }
+
+    public final Collection<PersistentFieldChange> gatherFieldChanges(String 
pageName)
+    {
+        Session session = _sessionHolder.getSession(false);
+
+        if (session == null)
+            return Collections.emptyList();
+
+        List<PersistentFieldChange> result = newList();
+
+        String fullPrefix = _prefix + pageName + ":";
+
+        for (String name : session.getAttributeNames(fullPrefix))
+        {
+            PersistentFieldChange change = buildChange(name, 
session.getAttribute(name));
+
+            result.add(change);
+
+            didReadChange(session, name);
+        }
+
+        return result;
+    }
+
+    /**
+     * Called after each key is read by [EMAIL PROTECTED] 
#gatherFieldChanges(String)}. This implementation
+     * does nothing, subclasses may override.
+     * 
+     * @param session
+     *            the session from which a value was just read
+     * @param attributeName
+     *            the name of the attribute used to read a value
+     */
+    protected void didReadChange(Session session, String attributeName)
+    {
+    }
+
+    private PersistentFieldChange buildChange(String name, Object attribute)
+    {
+        // TODO: Regexp is probably too expensive for what we need here. Maybe 
an IOC InternalUtils
+        // method for this purpose?
+
+        String[] chunks = name.split(":");
+
+        // Will be empty string for the root component
+        String componentId = chunks[2];
+        String fieldName = chunks[3];
+
+        return new PersistentFieldChangeImpl(componentId, fieldName, 
attribute);
+    }
+
+    public final void postChange(String pageName, String componentId, String 
fieldName,
+            Object newValue)
+    {
+        notBlank(pageName, "pageName");
+        notBlank(fieldName, "fieldName");
+
+        StringBuilder builder = new StringBuilder(_prefix);
+        builder.append(pageName);
+        builder.append(':');
+
+        if (componentId != null)
+            builder.append(componentId);
+
+        builder.append(':');
+        builder.append(fieldName);
+
+        Session session = _sessionHolder.getSession(true);
+
+        session.setAttribute(builder.toString(), newValue);
+    }
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java?view=auto&rev=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
 Wed Jan 24 16:17:13 2007
@@ -0,0 +1,44 @@
+// Copyright 2007 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.tapestry.internal.services;
+
+import org.apache.tapestry.services.Session;
+
+/**
+ * The "flash" strategy stores data inside the [EMAIL PROTECTED] Session 
session}, just like
+ * [EMAIL PROTECTED] SessionPersistentFieldStrategy}, but also removes the 
values from the session on first
+ * use. In this way, a short-term value (such as an error message) will 
"survive" from an action
+ * request to a render request and then disappear.
+ */
+public class FlashPersistentFieldStrategy extends 
AbstractSessionPersistentFieldStrategy
+{
+    /**
+     * Prefix used to identify keys stored in the session.
+     */
+    static final String PREFIX = "flash:";
+
+    public FlashPersistentFieldStrategy(SessionHolder sessionHolder)
+    {
+        super(PREFIX, sessionHolder);
+    }
+
+    @Override
+    protected void didReadChange(Session session, String attributeName)
+    {
+        // For flash persistence, after reading a value, get rid of it.
+        session.setAttribute(attributeName, null);
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
 Wed Jan 24 16:17:13 2007
@@ -12,92 +12,27 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
-import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+package org.apache.tapestry.internal.services;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.tapestry.services.PersistentFieldChange;
-import org.apache.tapestry.services.PersistentFieldStrategy;
 import org.apache.tapestry.services.Session;
-
-/**
- * A strategy for storing persistent page properties into the [EMAIL 
PROTECTED] Session session}.
- * <p>
- * Builds attribute names as:
- * 
<code>state:<em>page-name</em>:<em>component-id</em>:<em>field-name</em></code>
- */
-
-public class SessionPersistentFieldStrategy implements PersistentFieldStrategy
-{
-    /**
-     * Prefix used to identify keys stored in the session that are being used 
to store persistent
-     * field data.
-     */
-    public static final String PREFIX = "state:";
 
-    private final SessionHolder _sessionHolder;
-
-    public SessionPersistentFieldStrategy(final SessionHolder sessionHolder)
-    {
-        _sessionHolder = sessionHolder;
-    }
-
-    public Collection<PersistentFieldChange> gatherFieldChanges(String 
pageName)
-    {
-        Session session = _sessionHolder.getSession(false);
-
-        if (session == null)
-            return Collections.emptyList();
-
-        List<PersistentFieldChange> result = newList();
-
-        String fullPrefix = PREFIX + pageName + ":";
-
-        for (String name : session.getAttributeNames(fullPrefix))
-        {
-            PersistentFieldChange change = buildChange(name, 
session.getAttribute(name));
-
-            result.add(change);
-        }
-
-        return result;
-    }
-
-    private PersistentFieldChange buildChange(String name, Object attribute)
-    {
-
-        String[] chunks = name.split(":");
-
-        // Will be empty string for the root component
-        String componentId = chunks[2];
-        String fieldName = chunks[3];
-
-        return new PersistentFieldChangeImpl(componentId, fieldName, 
attribute);
-    }
-
-    public void postChange(String pageName, String componentId, String 
fieldName, Object newValue)
-    {
-        notBlank(pageName, "pageName");
-        notBlank(fieldName, "fieldName");
-
-        StringBuilder builder = new StringBuilder(PREFIX);
-        builder.append(pageName);
-        builder.append(':');
-
-        if (componentId != null)
-            builder.append(componentId);
-
-        builder.append(':');
-        builder.append(fieldName);
-
-        Session session = _sessionHolder.getSession(true);
-
-        session.setAttribute(builder.toString(), newValue);
-    }
-
-}
+/**
+ * A strategy for storing persistent page properties into the [EMAIL 
PROTECTED] Session session}.
+ * <p>
+ * Builds attribute names as:
+ * 
<code>state:<em>page-name</em>:<em>component-id</em>:<em>field-name</em></code>
+ */
+
+public class SessionPersistentFieldStrategy extends 
AbstractSessionPersistentFieldStrategy
+{
+    /**
+     * Prefix used to identify keys stored in the session that are being used 
to store persistent
+     * field data.
+     */
+    static final String PREFIX = "state:";
+
+    public SessionPersistentFieldStrategy(SessionHolder sessionHolder)
+    {
+        super(PREFIX, sessionHolder);
+    }
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
 Wed Jan 24 16:17:13 2007
@@ -77,6 +77,7 @@
 import org.apache.tapestry.internal.services.EnvironmentImpl;
 import org.apache.tapestry.internal.services.EnvironmentalWorker;
 import org.apache.tapestry.internal.services.FieldValidatorSourceImpl;
+import org.apache.tapestry.internal.services.FlashPersistentFieldStrategy;
 import org.apache.tapestry.internal.services.HeartbeatImpl;
 import org.apache.tapestry.internal.services.InfrastructureImpl;
 import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
@@ -827,6 +828,7 @@
             SessionHolder sessionHolder)
     {
         configuration.add("session", new 
SessionPersistentFieldStrategy(sessionHolder));
+        configuration.add("flash", new 
FlashPersistentFieldStrategy(sessionHolder));
     }
 
     public ComponentSource buildComponentSource(
@@ -836,19 +838,6 @@
         return new ComponentSourceImpl(pageCache);
     }
 
-    /** Contributes handlers for type Component and type String. */
-    // private void contributeComponentEventHandler(
-    // MappedConfiguration<Class, ComponentEventHandler> configuration,
-    // @InjectService("ComponentInstanceEventHandler")
-    // ComponentEventHandler componentInstanceEventHandler)
-    // {
-    // configuration.add(Component.class, componentInstanceEventHandler);
-    // configuration.add(String.class, new 
StringEventHandler(_requestPageCache));
-    // }
-    // public ComponentEventHandler buildComponentInstanceEventHandler(Log log)
-    // {
-    // return new ComponentInstanceEventHandler(_requestPageCache, log);
-    // }
     public ComponentMessagesSource buildComponentMessagesSource(
             @InjectService("tapestry.internal.UpdateListenerHub")
             UpdateListenerHub updateListenerHub)

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt Wed 
Jan 24 16:17:13 2007
@@ -43,6 +43,15 @@
   A suitably long session attribute name is used; it incorporates the
   name of the page, the nested component id, and the name of the field.
   
+* flash strategy
+
+  The flash strategy stores information in the session as well, just for not 
very long.  Values are
+  stored into the session, but then deleted from the session as they are first 
used to restore
+  a page's state.
+  
+  The flash is typically used to store temporary messages that should only be 
displayed to the user
+  once.
+  
 Persistence Search
 
   By default the value for the Persist annotation is the empty string. When 
this is true,

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html?view=auto&rev=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html 
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html 
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,18 @@
+<html t:type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+    
+    <h1>Flash Demo</h1>
+
+    <p>
+        The message: [${message}]
+    </p>    
+    
+    <p>
+        Click <a t:type="ActionLink" t:id="show">here</a> to show the message.
+    </p>
+    
+    <p>
+        Click <a id="refresh" href="FlashDemo.html">here</a> to refresh the 
page.  Boy do we need a PageLink component!
+    </p>
+
+    
+</html>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Wed Jan 24 
16:17:13 2007
@@ -50,15 +50,13 @@
                             operations when invoking render phase methods </li>
                         <li><a href="SimpleForm.html">SimpleForm</a> -- first 
pass at writing Form
                             and TextField components </li>
-
+                        <li>
+                            <a href="NumberSelect.html">NumberSelect</a> -- 
passivate/activate page
+                            context demo </li>                 
                     </ul>
                 </td>
                 <td>
-                    <ul>
-                        <li>
-                            <a href="NumberSelect.html">NumberSelect</a> -- 
passivate/activate page
-                            context demo </li>
-                        <li>
+                    <ul><li>
                             <a href="Localization.html">Localization</a> -- 
accessing localized
                             messages from the component catalog </li>
                         <li>
@@ -92,6 +90,9 @@
                         <li>
                             <a href="ToDoList.html">ToDo List</a> -- Loops and 
Submit inside Form
                             using a primary key encoder </li>
+                        <li>
+                            <a href="FlashDemo.html">FlashDemo</a> -- 
demonstrate "flash" persistence
+                        </li>
                     </ul>
                 </td>
             </tr>

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Wed Jan 24 16:17:13 2007
@@ -548,6 +548,25 @@
         test_loop_inside_form("ToDo List (Volatile)");
     }
 
+    /** This also verifies the use of meta data to set the default strategy. */
+    @Test
+    public void flash_persistence()
+    {
+        _selenium.open(BASE_URL);
+
+        clickAndWait("link=FlashDemo");
+
+        assertTextPresent("[]");
+
+        clickAndWait("show");
+
+        assertTextPresent("[You clicked the link!]");
+
+        clickAndWait("refresh");
+
+        assertTextPresent("[]");
+    }
+
     private void assertSourcePresent(String... expected)
     {
         String source = _selenium.getHtmlSource();

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java?view=auto&rev=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
 Wed Jan 24 16:17:13 2007
@@ -0,0 +1,35 @@
+// Copyright 2007 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.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Persist;
+
[EMAIL PROTECTED](meta = "tapestry.persistence-strategy=flash")
+public class FlashDemo
+{
+    @Persist
+    private String _message;
+
+    public String getMessage()
+    {
+        return _message;
+    }
+
+    void onAction()
+    {
+        _message = "You clicked the link!";
+    }
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java?view=auto&rev=499626
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
 Wed Jan 24 16:17:13 2007
@@ -0,0 +1,96 @@
+// Copyright 2007 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.tapestry.internal.services;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.services.Request;
+import org.apache.tapestry.services.Session;
+import org.testng.annotations.Test;
+
+/**
+ * A more minimal test, since common behavior is already tested by
+ * [EMAIL PROTECTED] SessionPersistentFieldStrategyTest}.
+ */
+public class FlashPersistentFieldStrategyTest extends InternalBaseTestCase
+{
+    @Test
+    public void post_change_to_root_component()
+    {
+        Session session = newSession();
+        Request request = newRequest();
+        Object value = new Object();
+
+        train_getSession(request, true, session);
+
+        session.setAttribute("flash:foo.Bar::field", value);
+
+        replay();
+
+        PersistentFieldStrategy strategy = new 
FlashPersistentFieldStrategy(request);
+
+        strategy.postChange("foo.Bar", null, "field", value);
+
+        verify();
+    }
+
+    @Test
+    public void gather_changes_with_active_session()
+    {
+        Session session = newSession();
+        Request request = newRequest();
+
+        train_getSession(request, false, session);
+        train_getAttributeNames(
+                session,
+                "flash:foo.Bar:",
+                "flash:foo.Bar::root",
+                "flash:foo.Bar:nested:down");
+
+        train_getAttribute(session, "flash:foo.Bar::root", "ROOT");
+        session.setAttribute("flash:foo.Bar::root", null);
+
+        train_getAttribute(session, "flash:foo.Bar:nested:down", "DOWN");
+        session.setAttribute("flash:foo.Bar:nested:down", null);
+
+        replay();
+
+        PersistentFieldStrategy strategy = new 
FlashPersistentFieldStrategy(request);
+
+        Collection<PersistentFieldChange> changes = 
strategy.gatherFieldChanges("foo.Bar");
+
+        assertEquals(changes.size(), 2);
+
+        Iterator<PersistentFieldChange> i = changes.iterator();
+
+        PersistentFieldChange change1 = i.next();
+
+        assertEquals(change1.getComponentId(), "");
+        assertEquals(change1.getFieldName(), "root");
+        assertEquals(change1.getValue(), "ROOT");
+
+        PersistentFieldChange change2 = i.next();
+
+        assertEquals(change2.getComponentId(), "nested");
+        assertEquals(change2.getFieldName(), "down");
+        assertEquals(change2.getValue(), "DOWN");
+
+        verify();
+    }
+}


Reply via email to