Author: hlship
Date: Fri Feb 22 18:36:14 2008
New Revision: 630378

URL: http://svn.apache.org/viewvc?rev=630378&view=rev
Log:
TAPESTRY-1475: Tapestry is missing an API for clearing out persistent 
properties of a particular pag

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java
      - copied, changed from r630031, 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
 Fri Feb 22 18:36:14 2008
@@ -174,4 +174,11 @@
      *                 target paget
      */
     Link createPageLink(String pageName, boolean override, Object... context);
+
+    /**
+     * Discards all persistent field changes for the page containing the 
component.  Changes are eliminated from
+     * persistent storage (such as the [EMAIL PROTECTED] 
org.apache.tapestry.services.Session}) which will take effect in the
+     * <em>next</em> request (the attached page instance is not affected).
+     */
+    void discardPersistentFieldChanges();
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
 Fri Feb 22 18:36:14 2008
@@ -15,13 +15,13 @@
 package org.apache.tapestry.internal;
 
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.internal.services.PersistentFieldManager;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.RenderQueue;
-import org.apache.tapestry.services.PersistentFieldManager;
 
 /**
- * An extension of [EMAIL PROTECTED] org.apache.tapestry.ComponentResources} 
that represents additional methods
- * that are private to the framework and not exposed in any public APIs.
+ * An extension of [EMAIL PROTECTED] org.apache.tapestry.ComponentResources} 
that represents additional methods that are private to
+ * the framework and not exposed in any public APIs.
  */
 public interface InternalComponentResources extends ComponentResources, 
InternalComponentResourcesCommon
 {
@@ -39,10 +39,9 @@
     boolean hasFieldChange(String fieldName);
 
     /**
-     * Posts a change to a persistent field. If the component is still 
loading, then this change is
-     * ignored. Otherwise, it is propagated, via the
-     * [EMAIL PROTECTED] 
Page#persistFieldChange(org.apache.tapestry.ComponentResources, String, Object) 
page}
-     * to the [EMAIL PROTECTED] PersistentFieldManager}.
+     * Posts a change to a persistent field. If the component is still 
loading, then this change is ignored. Otherwise,
+     * it is propagated, via the [EMAIL PROTECTED] 
Page#persistFieldChange(org.apache.tapestry.ComponentResources, String, Object)
+     * page} to the [EMAIL PROTECTED] PersistentFieldManager}.
      */
     void persistFieldChange(String fieldName, Object newValue);
 
@@ -60,15 +59,15 @@
      * Used by generated component code to read a parameter value.
      *
      * @param parameterName   the name of the parameter to read
-     * @param desiredTypeName the class name of the desired value (classes 
will be resolved in the
-     *                        component class loader)
+     * @param desiredTypeName the class name of the desired value (classes 
will be resolved in the component class
+     *                        loader)
      * @return the value coerced to the correct type
      */
     Object readParameter(String parameterName, String desiredTypeName);
 
     /**
-     * Updates a parameter. It is an error to update a parameter which is not 
bound. The parameter
-     * [EMAIL PROTECTED] org.apache.tapestry.Binding binding} may also not 
support updates.
+     * Updates a parameter. It is an error to update a parameter which is not 
bound. The parameter [EMAIL PROTECTED]
+     * org.apache.tapestry.Binding binding} may also not support updates.
      *
      * @param <T>
      * @param parameterName  of parameter to update
@@ -77,9 +76,8 @@
     <T> void writeParameter(String parameterName, T parameterValue);
 
     /**
-     * Returns true if the named parameter's [EMAIL PROTECTED] 
org.apache.tapestry.Binding} is invariant, false
-     * if otherwise, or if the parameter is not bound. Invariant bindings are 
cached more
-     * aggressively than variant bindings.
+     * Returns true if the named parameter's [EMAIL PROTECTED] 
org.apache.tapestry.Binding} is invariant, false if otherwise, or if
+     * the parameter is not bound. Invariant bindings are cached more 
aggressively than variant bindings.
      *
      * @param parameterName the name of parameter to check for invariance
      * @return true if the binding is an invariant, false if the binding has 
no fixed value

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 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.
@@ -26,8 +26,8 @@
 import java.util.List;
 
 /**
- * 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.
+ * 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
 {
@@ -63,9 +63,23 @@
         return result;
     }
 
+    public void discardChanges(String pageName)
+    {
+        Session session = _request.getSession(false);
+
+        if (session == null) return;
+
+        String fullPrefix = _prefix + pageName + ":";
+
+        for (String name : session.getAttributeNames(fullPrefix))
+        {
+            session.setAttribute(name, null);
+        }
+    }
+
     /**
-     * Called after each key is read by [EMAIL PROTECTED] 
#gatherFieldChanges(String)}. This implementation
-     * does nothing, subclasses may override.
+     * 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

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 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.
@@ -32,9 +32,9 @@
 import java.util.Map;
 
 /**
- * Manages client-persistent values on behalf of a [EMAIL PROTECTED] 
ClientPersistentFieldStorageImpl}. Some
- * effort is made to ensure that we don't uncessarily convert between objects 
and Base64 (the
- * encoding used to record the value on the client).
+ * Manages client-persistent values on behalf of a [EMAIL PROTECTED] 
ClientPersistentFieldStorageImpl}. Some effort is made to
+ * ensure that we don't uncessarily convert between objects and Base64 (the 
encoding used to record the value on the
+ * client).
  */
 @Scope(PERTHREAD_SCOPE)
 public class ClientPersistentFieldStorageImpl implements 
ClientPersistentFieldStorage
@@ -150,6 +150,24 @@
         return result;
     }
 
+    public void discardChanges(String pageName)
+    {
+        refreshMap();
+
+        Collection<Key> removedKeys = CollectionFactory.newList();
+
+        for (Key key : _persistedValues.keySet())
+        {
+            if (key._pageName.equals(pageName)) removedKeys.add(key);
+        }
+
+        for (Key key : removedKeys)
+        {
+            _persistedValues.remove(key);
+            _clientData = null;
+        }
+    }
+
     public void postChange(String pageName, String componentId, String 
fieldName, Object newValue)
     {
         refreshMap();
@@ -170,6 +188,9 @@
         _clientData = null;
     }
 
+    /**
+     * Refreshes the _persistedValues map if it is not up to date.
+     */
     @SuppressWarnings("unchecked")
     private void refreshMap()
     {
@@ -182,6 +203,9 @@
         _mapUptoDate = true;
     }
 
+    /**
+     * Restores the _persistedValues map from the client data provided in the 
incoming Request.
+     */
     private void restoreMapFromClientData()
     {
         _persistedValues.clear();

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 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.
@@ -21,10 +21,9 @@
 import java.util.Collection;
 
 /**
- * Implements simple client-persistent properties. Most of the logic is 
delegated to an instance of
- * [EMAIL PROTECTED] ClientPersistentFieldStorage}. This division of layer 
allows this service to be a true
- * singleton, and a listener to the [EMAIL PROTECTED] LinkFactory}, and allow 
per-request state to be isolated
- * inside the other service.
+ * Implements simple client-persistent properties. Most of the logic is 
delegated to an instance of [EMAIL PROTECTED]
+ * ClientPersistentFieldStorage}. This division of layer allows this service 
to be a true singleton, and a listener to
+ * the [EMAIL PROTECTED] LinkFactory}, and allow per-request state to be 
isolated inside the other service.
  */
 public class ClientPersistentFieldStrategy implements PersistentFieldStrategy, 
LinkFactoryListener
 {
@@ -53,5 +52,10 @@
     public void createdPageLink(Link link)
     {
         _storage.updateLink(link);
+    }
+
+    public void discardChanges(String pageName)
+    {
+        _storage.discardChanges(pageName);
     }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -18,12 +18,11 @@
 import org.apache.tapestry.internal.events.InvalidationListener;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.services.ComponentClassResolver;
-import org.apache.tapestry.services.PersistentFieldManager;
 
 import java.util.Locale;
 
 public class PageLoaderImpl extends InvalidationEventHubImpl implements 
PageLoader,
-                                                                        
InvalidationListener
+        InvalidationListener
 {
     private final ComponentTemplateSource _templateSource;
 
@@ -61,8 +60,8 @@
     }
 
     /**
-     * When the page loader receives an invalidation event, it respawns the 
event for its listeners.
-     * Those listeners will include page caches and the like.
+     * When the page loader receives an invalidation event, it respawns the 
event for its listeners. Those listeners
+     * will include page caches and the like.
      */
     public void objectWasInvalidated()
     {

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
 Fri Feb 22 18:36:14 2008
@@ -34,7 +34,6 @@
 import org.apache.tapestry.model.EmbeddedComponentModel;
 import org.apache.tapestry.runtime.RenderQueue;
 import org.apache.tapestry.services.BindingSource;
-import org.apache.tapestry.services.PersistentFieldManager;
 import org.slf4j.Logger;
 
 import java.util.List;

Copied: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java
 (from r630031, 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java)
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java&r1=630031&r2=630378&rev=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -12,15 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.services;
+package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.services.PersistentFieldBundle;
 
 /**
- * Handle persistent property changes. Primarily, delegates to a number of
- * [EMAIL PROTECTED] PersistentFieldStrategy} instances.
+ * Handle persistent property changes. Primarily, delegates to a number of 
[EMAIL PROTECTED] org.apache.tapestry.services.PersistentFieldStrategy}
+ * instances.
  *
- * @see 
org.apache.tapestry.services.TapestryModule#contributePersistentFieldManager(org.apache.tapestry.ioc.MappedConfiguration,
 Request, PersistentFieldStrategy)
+ * @see 
org.apache.tapestry.services.TapestryModule#contributePersistentFieldManager(org.apache.tapestry.ioc.MappedConfiguration,
+ *      org.apache.tapestry.services.Request , 
org.apache.tapestry.services.PersistentFieldStrategy)
  */
 public interface PersistentFieldManager
 {
@@ -28,19 +30,26 @@
      * Posts a change of a persistent property.
      *
      * @param pageName  the logical name of the page containing the component
-     * @param resources the resources for the component or mixin (used to 
determine the persistence
-     *                  strategy)
+     * @param resources the resources for the component or mixin (used to 
determine the persistence strategy)
      * @param fieldName the name of the field whose persistent value has 
changed
      * @param newValue  the new value for the field, possibly null
      */
     void postChange(String pageName, ComponentResources resources, String 
fieldName, Object newValue);
 
     /**
-     * Locates all persistently stored changes to all properties within the 
page (for the current
-     * session and request) and gathers them together into a bundle.
+     * Locates all persistently stored changes to all properties within the 
page (for the current session and request)
+     * and gathers them together into a bundle.
      *
      * @param pageName the logical name of the page to gather changes for
      * @return a bundle identifying all such changes
      */
     PersistentFieldBundle gatherChanges(String pageName);
+
+    /**
+     * Discards all changes for the indicated page. This will not affect pages 
that have already been attached to this
+     * request, but will affect subsequent page attachments in this and later 
requests.
+     *
+     * @param pageName logical name of page whose persistent field data is to 
be discarded
+     */
+    void discardChanges(String pageName);
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
 Fri Feb 22 18:36:14 2008
@@ -18,7 +18,10 @@
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.model.ComponentModel;
-import org.apache.tapestry.services.*;
+import org.apache.tapestry.services.MetaDataLocator;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
 
 import java.util.Collection;
 import java.util.Map;
@@ -63,6 +66,14 @@
         }
 
         return new PersistentFieldBundleImpl(allChanges);
+    }
+
+    public void discardChanges(String pageName)
+    {
+        for (PersistentFieldStrategy strategy : _strategies.values())
+        {
+            strategy.discardChanges(pageName);
+        }
     }
 
     public void postChange(String pageName, ComponentResources resources, 
String fieldName,

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
 Fri Feb 22 18:36:14 2008
@@ -128,6 +128,11 @@
         return _page.createPageLink(pageName, override, context);
     }
 
+    public void discardPersistentFieldChanges()
+    {
+        _page.discardPersistentFieldChanges();
+    }
+
 
     public String getCompleteId()
     {

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
 Fri Feb 22 18:36:14 2008
@@ -154,4 +154,11 @@
      * Called as a component finishes rendering itself.
      */
     void decrementDirtyCount();
+
+    /**
+     * Discards all persistent field changes for the page containing the 
component.  Changes are eliminated from
+     * persistent storage (such as the [EMAIL PROTECTED] 
org.apache.tapestry.services.Session}) which will take effect in the
+     * <em>next</em> request (the attached page instance is not affected).
+     */
+    void discardPersistentFieldChanges();
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
 Fri Feb 22 18:36:14 2008
@@ -17,13 +17,13 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.services.LinkFactory;
+import org.apache.tapestry.internal.services.PersistentFieldManager;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.runtime.PageLifecycleListener;
 import org.apache.tapestry.services.PersistentFieldBundle;
-import org.apache.tapestry.services.PersistentFieldManager;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -46,8 +46,8 @@
     private int _dirtyCount;
 
     /**
-     * Obtained from the [EMAIL PROTECTED] PersistentFieldManager} when first 
needed, discarded at the end of
-     * the request.
+     * Obtained from the [EMAIL PROTECTED] 
org.apache.tapestry.internal.services.PersistentFieldManager} when first needed,
+     * discarded at the end of the request.
      */
     private PersistentFieldBundle _fieldBundle;
 
@@ -176,6 +176,11 @@
     public void decrementDirtyCount()
     {
         _dirtyCount--;
+    }
+
+    public void discardPersistentFieldChanges()
+    {
+        _persistentFieldManager.discardChanges(_logicalPageName);
     }
 
     public void incrementDirtyCount()

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
 Fri Feb 22 18:36:14 2008
@@ -1,26 +1,25 @@
-// Copyright 2006 The Apache Software Foundation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2006, 2008 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.services;
 
 import java.util.Collection;
 
 /**
  * Defines how changes to fields (within components, within pages) may have 
their values persisted between requests.
- * Different implementations store the field values
- * [EMAIL PROTECTED] 
org.apache.tapestry.internal.services.SessionPersistentFieldStrategy in the 
session},
- * [EMAIL PROTECTED] 
org.apache.tapestry.internal.services.ClientPersistentFieldStrategy on the 
client}, or
+ * Different implementations store the field values [EMAIL PROTECTED] 
org.apache.tapestry.internal.services.SessionPersistentFieldStrategy
+ * in the session}, [EMAIL PROTECTED] 
org.apache.tapestry.internal.services.ClientPersistentFieldStrategy on the 
client}, or
  * elsewhere.
  */
 public interface PersistentFieldStrategy
@@ -36,8 +35,16 @@
     void postChange(String pageName, String componentId, String fieldName, 
Object newValue);
 
     /**
-     * Finds all persistent changes previously stored for the named page (for 
the current active
-     * session or client).
+     * Finds all persistent changes previously stored for the named page (for 
the current active session or client).
      */
     Collection<PersistentFieldChange> gatherFieldChanges(String pageName);
+
+    /**
+     * Discards any saved changes for the name page. There is no expectation 
that data already gathered from the
+     * strategy and persumably dumped into component instance fields will be 
affected, but future field access (within
+     * this request or a later one) will show no data for the indicated page.
+     *
+     * @param pageName logical name of page whose field persistent data should 
be discarded
+     */
+    void discardChanges(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt 
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt Fri 
Feb 22 18:36:14 2008
@@ -95,4 +95,12 @@
   Servlet API.  Changing a persistent field's value to null <removes> the
   field's attribute from the session. On later requests, the field will reset 
to its
   default value. Since that is usually null, this is not a problem ... it is 
only a problem
-  if a field has a non-null default value and may be changed to null. 
\ No newline at end of file
+  if a field has a non-null default value and may be changed to null.
+
+Clearing Persistent Fields
+
+   If you reach a point where you know that all data for a page can be 
discarded, you can do exactly that.
+
+   The method <<<discardPersistentFieldChanges()>>> of ComponentResources will 
discard all persistent fields
+   for the page, regardless of which strategy is used to store the property. 
This will not affect the
+   page in memory, but takes effect for subsequent requests.
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml?rev=630378&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml 
(added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml Fri 
Feb 22 18:36:14 2008
@@ -0,0 +1,21 @@
+<html t:type="Border"
+      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+
+    <p>
+        Message:
+        <span id="message">${message}</span>
+    </p>
+
+    <ul>
+        <li>
+            <t:actionlink t:id="updateMessage" 
context="literal:updated">Update the message field</t:actionlink>
+        </li>
+        <li>
+            <t:actionlink t:id="discardChanges">Discard persistent field 
changes</t:actionlink>
+        </li>
+        <li>
+            <t:pagelink page="persistentdemo">Refresh page</t:pagelink>
+        </li>
+    </ul>
+</html>
+

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Fri Feb 22 18:36:14 2008
@@ -1729,4 +1729,27 @@
 
         assertText("message", "from getActionURL()");
     }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_persistent_field_changes()
+    {
+        start("Persistent Demo");
+
+        assertText("message", "");
+
+        clickAndWait("link=Update the message field");
+
+        assertText("message", "updated");
+
+        clickAndWait("link=Refresh page");
+
+        assertText("message", "updated");
+
+        clickAndWait("link=Discard persistent field changes");
+
+        assertText("message", "");
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java?rev=630378&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
 Fri Feb 22 18:36:14 2008
@@ -0,0 +1,43 @@
+// Copyright 2008 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.ComponentResources;
+import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.ioc.annotations.Inject;
+
+public class PersistentDemo
+{
+    @Persist
+    private String _message;
+
+    @Inject
+    private ComponentResources _resources;
+
+    void onActionFromUpdateMessage(String message)
+    {
+        _message = message;
+    }
+
+    void onActionFromDiscardChanges()
+    {
+        _resources.discardPersistentFieldChanges();
+    }
+
+    public String getMessage()
+    {
+        return _message;
+    }
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 Fri Feb 22 18:36:14 2008
@@ -62,6 +62,8 @@
     private static final List<Item> ITEMS = CollectionFactory.newList(
             new Item("actionpage", "Action Page", "tests fixture for 
ActionLink component"),
 
+            new Item("PersistentDemo", "Persistent Demo", "storing and 
clearing persistent properties"),
+
             new Item("ActionViaLinkDemo", "Action via Link Demo", "tests 
creating an action link explicitly"),
 
             new Item("FormFragmentDemo", "Form Fragment Demo", "page with 
dynamic form sections"),

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
 Fri Feb 22 18:36:14 2008
@@ -175,6 +175,35 @@
         verify();
     }
 
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        Request request = mockRequest(null);
+        Link link = mockLink();
+
+        String pageName = "Foo";
+        String componentId = "bar.baz";
+        String fieldName = "woops";
+
+        replay();
+
+        ClientPersistentFieldStorage storage = new 
ClientPersistentFieldStorageImpl(request);
+
+        storage.postChange(pageName, componentId, fieldName, 99);
+
+        storage.discardChanges(pageName);
+
+        storage.updateLink(link);
+
+        assertTrue(storage.gatherFieldChanges(pageName).isEmpty());
+
+        verify();
+    }
+
+
     @Test
     public void value_not_serializable()
     {

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
 Fri Feb 22 18:36:14 2008
@@ -19,7 +19,10 @@
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import org.apache.tapestry.model.ComponentModel;
-import org.apache.tapestry.services.*;
+import org.apache.tapestry.services.MetaDataLocator;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
 import org.testng.annotations.Test;
 
 import java.util.Collection;
@@ -60,6 +63,33 @@
                     ex.getMessage(),
                     "\'braveheart\' is not a defined persistent strategy.  
Defined strategies: bar, foo.");
         }
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        PersistentFieldStrategy strat1 = newPersistentFieldStrategy();
+        PersistentFieldStrategy strat2 = newPersistentFieldStrategy();
+
+        Map<String, PersistentFieldStrategy> strategies = newMap();
+        strategies.put("foo", strat1);
+        strategies.put("bar", strat2);
+
+        String pageName = "gnip.gnop";
+
+        strat1.discardChanges(pageName);
+        strat2.discardChanges(pageName);
+
+        replay();
+
+        PersistentFieldManager manager = new PersistentFieldManagerImpl(null, 
strategies);
+
+        manager.discardChanges(pageName);
 
         verify();
     }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
 Fri Feb 22 18:36:14 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -61,6 +61,49 @@
         SessionPersistentFieldStrategy strategy = new 
SessionPersistentFieldStrategy(request);
 
         strategy.postChange("foo.Bar", "fee.fum", "field", value);
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes_with_no_session()
+    {
+        Request request = mockRequest();
+
+        train_getSession(request, false, null);
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new 
SessionPersistentFieldStrategy(request);
+
+        strategy.discardChanges("foo.Bar");
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        Session session = mockSession();
+        Request request = mockRequest();
+
+        train_getSession(request, false, session);
+
+        train_getAttributeNames(session, "state:foo.Bar:", 
"state:foo.Bar:baz:field");
+
+        session.setAttribute("state:foo.Bar:baz:field", null);
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new 
SessionPersistentFieldStrategy(request);
+
+        strategy.discardChanges("foo.Bar");
 
         verify();
     }


Reply via email to