You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/10/19 07:20:03 UTC
svn commit: r465496 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/aspect/org/apache/tapestry/internal/aspects/
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/annotations/
main/java/org/apache/tapestry/corelib/components/ ma...
Author: hlship
Date: Wed Oct 18 22:20:00 2006
New Revision: 465496
URL: http://svn.apache.org/viewvc?view=rev&rev=465496
Log:
Add support for basic session persistence, and sset the default for action requests to be a redirect to the containing page.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Persist.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldBundleImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldChangeImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
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/internal/services/WebSessionImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldBundle.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldChange.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebSession.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/screencast.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldBundleImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebRequestImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebSessionImplTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalConcurrence.aj
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Link.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Retain.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ModelMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebResponseImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/Page.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebResponse.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/templates.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ActionPage.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/IOCUtilitiesTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentEventImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/PageImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/EventHandlerTarget.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObjectSubclass.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/StaticModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/StrategyRegistryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalConcurrence.aj
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalConcurrence.aj?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalConcurrence.aj (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalConcurrence.aj Wed Oct 18 22:20:00 2006
@@ -4,7 +4,7 @@
// 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
+// 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,
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Link.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Link.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Link.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Link.java Wed Oct 18 22:20:00 2006
@@ -25,8 +25,6 @@
* <p>
* Query parameter values are kept separate from the path portion to support encoding those values
* into hidden form fields (where appropriate).
- *
- *
*/
public interface Link
{
@@ -46,6 +44,9 @@
String getParameterValue(String name);
- /** Returns the link as a URI. The URI includes any query parameters. */
+ /** Returns the link as a normal URI. The URI includes any query parameters. */
String toURI();
+
+ /** Returns the link as a redirect URI. The URI includes any query parameters. */
+ String toRedirectURI();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.java Wed Oct 18 22:20:00 2006
@@ -25,5 +25,5 @@
public final class TapestryConstants
{
/** Default client event name, used in most situations. */
- public static final String DEFAULT_ACTION = "action";
+ public static final String DEFAULT_EVENT = "action";
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Persist.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Persist.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Persist.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Persist.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,41 @@
+// 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.
+
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.apache.tapestry.services.WebSession;
+
+/**
+ * Identifies a field as persistent, meaning its value persists from one request to the next.
+ * Different strategies exist for how this is accomplished, the most common being the default,
+ * "session", which stores the field's value in the {@link WebSession}.
+ */
+@Target(FIELD)
+@Documented
+@Retention(RUNTIME)
+public @interface Persist {
+
+ /**
+ * The strategy used to persist the value; the default is "session", meaning indefintely inside
+ * the {@link WebSession}.
+ */
+ String value() default "session";
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Retain.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Retain.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Retain.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Retain.java Wed Oct 18 22:20:00 2006
@@ -26,8 +26,13 @@
* This is most often associated with fields that are <em>lazily loaded</em>. By marking such
* fields with the Retain annotation, the fields will <em>not</em> be discarded at the end of the
* request.
- *
- *
+ * <p>
+ * This is quite different from {@link Persist}, because the value that's allowed to be retained is
+ * not stored persistently; it is simply not cleared out. A subsequent request, even from the same
+ * user, may be processed by a different instance of the page where the value is still null.
+ * <p>
+ * This annotation should only be used with lazily-evaluated objects that contain no client-specific
+ * information.
*/
@Target(FIELD)
@Retention(RUNTIME)
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java Wed Oct 18 22:20:00 2006
@@ -14,7 +14,7 @@
package org.apache.tapestry.corelib.components;
-import static org.apache.tapestry.TapestryConstants.DEFAULT_ACTION;
+import static org.apache.tapestry.TapestryConstants.DEFAULT_EVENT;
import java.util.List;
@@ -51,7 +51,7 @@
{
Object[] contextArray = _context == null ? new Object[0] : _context.toArray();
- Link link = _resources.createActionLink(DEFAULT_ACTION, false, contextArray);
+ Link link = _resources.createActionLink(DEFAULT_EVENT, false, contextArray);
writer.element("a", "href", link.toURI());
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java Wed Oct 18 22:20:00 2006
@@ -15,13 +15,13 @@
package org.apache.tapestry.internal;
import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.services.PersistentFieldManager;
/**
* An extension of {@link org.apache.tapestry.ComponentResources} that represents additional methods
* that are private to the framework and not exposed in any public APIs. Ideally, there will not be
* any need for this interface (we'll see as we go).
- *
- *
*/
public interface InternalComponentResources extends ComponentResources
{
@@ -66,5 +66,25 @@
* @see org.apache.tapestry.runtime.PageLifecycleListener#containingPageDidLoad()
*/
boolean isLoaded();
+
+ /**
+ * Posts a change to a persistent field. If the component is still loading, then this change is
+ * ignored. Otherwise, it is propogated, via the
+ * {@link Page#postFieldChange(org.apache.tapestry.internal.structure.ComponentPageElement, String, Object) page}
+ * to the {@link PersistentFieldManager}.
+ */
+ void postFieldChange(String fieldName, Object newValue);
+
+ /** Checks to see if there is a value stored for the indicated field. */
+ boolean hasFieldChange(String fieldName);
+
+ /**
+ * Get the current persisted value of the field.
+ *
+ * @param fieldName
+ * the name of the field to access
+ * @return the value stored for the field, or null if no value is currently stored
+ */
+ Object getFieldChange(String fieldName);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java Wed Oct 18 22:20:00 2006
@@ -21,7 +21,6 @@
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.List;
import java.util.Map;
@@ -35,8 +34,6 @@
/**
* Contains static methods used within this package.
- *
- *
*/
@Utility
public final class IOCUtilities
@@ -178,25 +175,6 @@
}
/**
- * Converts an enumeration (of Strings) into a sorted list of Strings.
- */
- public static List<String> toList(Enumeration e)
- {
- List<String> result = newList();
-
- while (e.hasMoreElements())
- {
- String name = (String) e.nextElement();
-
- result.add(name);
- }
-
- Collections.sort(result);
-
- return result;
- }
-
- /**
* Invoked by a proxy when the registry has shutdown.
*
* @throws IllegalStateException
@@ -240,7 +218,7 @@
* to strings.
*
* @param map
- * the map to extract keys from
+ * the map to extract keys from (may be null)
* @return the sorted keys, or the empty set if map is null
*/
@SuppressNullCheck
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ModelMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ModelMessages.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ModelMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ModelMessages.java Wed Oct 18 22:20:00 2006
@@ -45,4 +45,9 @@
{
return MESSAGES.format("duplicate-component-id", id, componentClassName);
}
+
+ static String missingPersistentField(String fieldName)
+ {
+ return MESSAGES.format("missing-persistent-field", fieldName);
+ }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java Wed Oct 18 22:20:00 2006
@@ -23,7 +23,9 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.Resource;
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.model.ComponentModel;
import org.apache.tapestry.model.EmbeddedComponentModel;
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.model.MutableEmbeddedComponentModel;
@@ -32,11 +34,11 @@
/**
* Internal implementation of {@link org.apache.tapestry.model.MutableComponentModel}.
- *
- *
*/
public final class MutableComponentModelImpl implements MutableComponentModel
{
+ private final ComponentModel _parentModel;
+
private final Resource _baseResource;
private final String _componentClassName;
@@ -47,11 +49,17 @@
private Map<String, EmbeddedComponentModel> _embeddedComponents;
- public MutableComponentModelImpl(String componentClassName, Log log, Resource baseResource)
+ /** Maps from field name to strategy. */
+ private Map<String, String> _persistentFields;
+
+ @SuppressNullCheck
+ public MutableComponentModelImpl(String componentClassName, Log log, Resource baseResource,
+ ComponentModel parentModel)
{
_componentClassName = componentClassName;
_log = log;
_baseResource = baseResource;
+ _parentModel = parentModel;
}
@Override
@@ -96,12 +104,12 @@
public ParameterModel getParameterModel(String parameterName)
{
- // TODO: Parameters defined in base model
+ ParameterModel result = IOCUtilities.get(_parameters, parameterName);
- if (_parameters == null)
- return null;
+ if (result == null && _parentModel != null)
+ result = _parentModel.getParameterModel(parameterName);
- return _parameters.get(parameterName);
+ return result;
}
public List<String> getParameterNames()
@@ -113,6 +121,9 @@
if (_parameters != null)
names.addAll(_parameters.keySet());
+ if (_parentModel != null)
+ names.addAll(_parentModel.getParameterNames());
+
Collections.sort(names);
return names;
@@ -140,16 +151,65 @@
public List<String> getEmbeddedComponentIds()
{
- // TODO: Parent compent model?
+ List<String> result = newList();
+
+ if (_embeddedComponents != null)
+ result.addAll(_embeddedComponents.keySet());
+
+ if (_parentModel != null)
+ result.addAll(_parentModel.getEmbeddedComponentIds());
+
+ Collections.sort(result);
- return IOCUtilities.sortedKeys(_embeddedComponents);
+ return result;
}
public EmbeddedComponentModel getEmbeddedComponentModel(String componentId)
{
- // TODO: Parent compent model?
+ EmbeddedComponentModel result = IOCUtilities.get(_embeddedComponents, componentId);
+
+ if (result == null && _parentModel != null)
+ result = _parentModel.getEmbeddedComponentModel(componentId);
+
+ return result;
+ }
+
+ public String getFieldPersistenceStrategy(String fieldName)
+ {
+ String result = IOCUtilities.get(_persistentFields, fieldName);
+
+ if (result == null && _parentModel != null)
+ result = _parentModel.getFieldPersistenceStrategy(fieldName);
+
+ if (result == null)
+ throw new IllegalArgumentException(ModelMessages.missingPersistentField(fieldName));
+
+ return result;
+ }
+
+ public List<String> getPersistentFieldNames()
+ {
+ List<String> result = newList();
+
+ if (_persistentFields != null)
+ result.addAll(_persistentFields.keySet());
+
+ if (_parentModel != null)
+ result.addAll(_parentModel.getPersistentFieldNames());
+
+ Collections.sort(result);
+
+ return result;
+ }
+
+ public void setFieldPersistenceStrategy(String fieldName, String strategy)
+ {
+ // TODO: Check for name collision here, or in parent
+
+ if (_persistentFields == null)
+ _persistentFields = newMap();
- return IOCUtilities.get(_embeddedComponents, componentId);
+ _persistentFields.put(fieldName, strategy);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java Wed Oct 18 22:20:00 2006
@@ -115,7 +115,7 @@
Resource baseResource = new ClasspathResource(classname.replace(".", "/") + ".class");
- MutableComponentModel model = new MutableComponentModelImpl(classname, log, baseResource);
+ MutableComponentModel model = new MutableComponentModelImpl(classname, log, baseResource, null);
_workerChain.transform(transformation, model);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentEventDispatcher.java Wed Oct 18 22:20:00 2006
@@ -17,6 +17,7 @@
import java.io.IOException;
import org.apache.tapestry.ComponentEventHandler;
+import org.apache.tapestry.Link;
import org.apache.tapestry.internal.structure.ComponentPageElement;
import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.services.Dispatcher;
@@ -26,19 +27,18 @@
/**
* Processes component action events sent as requests from the client. Action events include an
* event type, identify a page and a component, and may provide additional context strings.
- *
- *
*/
public class ComponentEventDispatcher implements Dispatcher
{
- private final PageResponseRenderer _renderer;
private final RequestPageCache _cache;
- public ComponentEventDispatcher(final PageResponseRenderer renderer, final RequestPageCache cache)
+ private final LinkFactory _linkFactory;
+
+ public ComponentEventDispatcher(final RequestPageCache cache, LinkFactory linkFactory)
{
- _renderer = renderer;
_cache = cache;
+ _linkFactory = linkFactory;
}
public boolean dispatch(WebRequest request, WebResponse response) throws IOException
@@ -82,12 +82,11 @@
element.triggerEvent(eventType, context, handler);
- // TODO: maybe the return value from triggerEvent should be true if any handler was found,
- // false if no handler was found. The latter feels like an error condition.
+ Link link = _linkFactory.createPageLink(page);
- // Once the pieces fall into place, we won't just blindly re-render the page.
+ String URL = link.toRedirectURI();
- _renderer.renderPageResponse(page, response);
+ response.sendRedirect(URL);
return true;
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java Wed Oct 18 22:20:00 2006
@@ -52,6 +52,8 @@
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.ComponentClassTransformWorker;
import org.apache.tapestry.services.MarkupWriterFactory;
+import org.apache.tapestry.services.PersistentFieldManager;
+import org.apache.tapestry.services.PersistentFieldStrategy;
import org.apache.tapestry.services.RequestExceptionHandler;
import org.apache.tapestry.services.WebContext;
import org.apache.tapestry.services.WebRequest;
@@ -156,10 +158,11 @@
public PageLoader buildPageLoader(@InjectService("PageElementFactory")
PageElementFactory pageElementFactory, @InjectService("tapestry.BindingSource")
BindingSource bindingSource, @InjectService("LinkFactory")
- LinkFactory linkFactory)
+ LinkFactory linkFactory, @Inject("infrastructure:persistentFieldManager")
+ PersistentFieldManager persistentFieldManager)
{
PageLoaderImpl service = new PageLoaderImpl(_componentTemplateSource, pageElementFactory,
- bindingSource, linkFactory);
+ bindingSource, linkFactory, persistentFieldManager);
// Recieve invalidations when the class loader is discarded (due to a component class
// change).
@@ -426,7 +429,7 @@
}
};
- // Do be honest, order probably doesn't matter.
+ // To be honest, order probably doesn't matter.
configuration.add("Keyword", keywordFactory);
configuration.add("This", thisFactory);
@@ -444,9 +447,18 @@
}
/** Service used to create links for components and pages. */
-
public LinkFactory buildLinkFactory()
{
return new LinkFactoryImpl(_request, _response, _componentClassResolver);
+ }
+
+ /**
+ * This exists as its own service just so that we can monitor it using logging.
+ * <p>
+ * TODO: Move this to TapestryModule?
+ */
+ public PersistentFieldStrategy buildSessionPersistentFieldStrategy()
+ {
+ return new SessionPersistentFieldStrategy(_request);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactory.java Wed Oct 18 22:20:00 2006
@@ -16,11 +16,10 @@
import org.apache.tapestry.Link;
import org.apache.tapestry.internal.structure.ComponentPageElement;
+import org.apache.tapestry.internal.structure.Page;
/**
* A source for {@link Link} objects.
- *
- *
*/
public interface LinkFactory
{
@@ -41,4 +40,12 @@
*/
Link createActionLink(ComponentPageElement component, String action, boolean forForm,
Object... context);
+
+ /**
+ * Creates a link to a page. TODO: What about context? Additional query parameters?
+ *
+ * @param page
+ * @return
+ */
+ Link createPageLink(Page page);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java Wed Oct 18 22:20:00 2006
@@ -17,6 +17,7 @@
import org.apache.tapestry.Link;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.structure.ComponentPageElement;
+import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.WebRequest;
import org.apache.tapestry.services.WebResponse;
@@ -47,8 +48,9 @@
{
Defense.notBlank(action, "action");
- String logicalPageName = _componentClassResolver.resolvePageClassNameToPageName(component
- .getContainingPage().getName());
+ String pageName = component.getContainingPage().getName();
+
+ String logicalPageName = _componentClassResolver.resolvePageClassNameToPageName(pageName);
StringBuilder builder = new StringBuilder();
@@ -71,6 +73,23 @@
// TODO: Much more: query parameter for case where active page != component page.
// Letting listeners add extra parameters.
+
+ return new LinkImpl(_response, builder.toString());
+ }
+
+ public Link createPageLink(Page page)
+ {
+ Defense.notNull(page, "page");
+
+ String pageName = page.getName();
+ String logicalPageName = _componentClassResolver.resolvePageClassNameToPageName(pageName);
+
+ StringBuilder builder = new StringBuilder();
+
+ builder.append(_request.getContextPath());
+ builder.append("/");
+ builder.append(logicalPageName);
+ builder.append(".html");
return new LinkImpl(_response, builder.toString());
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java Wed Oct 18 22:20:00 2006
@@ -22,8 +22,6 @@
/**
* Starting implementation of {@link Link}. Currently does not support query parameters.
- *
- *
*/
public class LinkImpl implements Link
{
@@ -50,6 +48,11 @@
public String toURI()
{
return _response.encodeURL(_path);
+ }
+
+ public String toRedirectURI()
+ {
+ return _response.encodeRedirectURL(_path);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java Wed Oct 18 22:20:00 2006
@@ -43,6 +43,7 @@
import org.apache.tapestry.model.ComponentModel;
import org.apache.tapestry.model.EmbeddedComponentModel;
import org.apache.tapestry.services.BindingSource;
+import org.apache.tapestry.services.PersistentFieldManager;
import org.apache.tapestry.util.CollectionFactory;
import org.apache.tapestry.util.IdAllocator;
@@ -60,6 +61,8 @@
private final LinkFactory _linkFactory;
+ private final PersistentFieldManager _persistentFieldManager;
+
private Page _page;
private Locale _locale;
@@ -67,12 +70,13 @@
@SuppressNullCheck
public PageLoaderImpl(ComponentTemplateSource templateSource,
PageElementFactory pageElementFactory, BindingSource bindingSource,
- LinkFactory linkFactory)
+ LinkFactory linkFactory, PersistentFieldManager persistentFieldManager)
{
_templateSource = templateSource;
_pageElementFactory = pageElementFactory;
_bindingSource = bindingSource;
_linkFactory = linkFactory;
+ _persistentFieldManager = persistentFieldManager;
}
/**
@@ -96,7 +100,7 @@
{
_locale = locale;
- _page = new PageImpl(pageClassName, _locale, _linkFactory);
+ _page = new PageImpl(pageClassName, _locale, _linkFactory, _persistentFieldManager);
loadRootComponent(pageClassName);
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistWorker.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistWorker.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,134 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import static java.lang.String.format;
+
+import java.lang.reflect.Modifier;
+
+import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.TransformConstants;
+import org.apache.tapestry.services.TransformUtils;
+import org.apache.tapestry.util.BodyBuilder;
+
+/**
+ * Converts fields with the {@link Persist} annotation into persistent fields.
+ */
+public class PersistWorker implements ComponentClassTransformWorker
+{
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ for (String name : transformation.findFieldsWithAnnotation(Persist.class))
+ {
+ makeFieldPersistent(name, transformation, model);
+ }
+ }
+
+ /**
+ * Making a field persistent:
+ * <ul>
+ * <li>Need a secondary default field that stores the initial value</li>
+ * <li>Store the active value into the default field when the page finishes loading</li>
+ * <li>Roll the active value back to the default when the page detaches</li>
+ * <ii>On changes to the active field, post the change via the InternalComponentResources</li>
+ * <li>When the page attaches, pull the persisted value for the field out of the
+ * {@link PersistentFieldBundle}</li>
+ * </ul>
+ *
+ * @param fieldName
+ * @param transformation
+ * @param model
+ */
+ private void makeFieldPersistent(String fieldName, ClassTransformation transformation,
+ MutableComponentModel model)
+ {
+ String fieldType = transformation.getFieldType(fieldName);
+ Persist annotation = transformation.getFieldAnnotation(fieldName, Persist.class);
+
+ // Record the type of persistence, until needed later.
+
+ model.setFieldPersistenceStrategy(fieldName, annotation.value());
+
+ String defaultFieldName = transformation.addField(Modifier.PRIVATE, fieldType, fieldName
+ + "_default");
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, format(
+ "%s = %s;",
+ defaultFieldName,
+ fieldName));
+
+ transformation.extendMethod(
+ TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
+ format("%s = %s;", fieldName, defaultFieldName));
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ String writeMethodName = transformation.newMemberName("_write_"
+ + InternalUtils.stripMemberPrefix(fieldName));
+
+ BodyBuilder builder = new BodyBuilder();
+
+ builder.begin();
+ builder.addln("%s.postFieldChange(\"%s\", ($w) $1);", resourcesFieldName, fieldName);
+ builder.addln("%s = $1;", fieldName);
+ builder.end();
+
+ transformation.addMethod(new MethodSignature(Modifier.PRIVATE, "void", writeMethodName,
+ new String[]
+ { fieldType }, null), builder.toString());
+
+ transformation.replaceWriteAccess(fieldName, writeMethodName);
+
+ builder.clear();
+ builder.begin();
+
+ // Check to see if there's a recorded change for this component, this field.
+
+ builder.addln("if (%s.hasFieldChange(\"%s\"))", resourcesFieldName, fieldName);
+
+ String wrapperType = TransformUtils.getWrapperTypeName(fieldType);
+
+ // Get the value, cast it to the correct type (or wrapper type)
+ builder.add(
+ " %s = ((%s) %s.getFieldChange(\"%1$s\"))",
+ fieldName,
+ wrapperType,
+ resourcesFieldName);
+
+ // For primtive types, add in the method call to unwrap the wrapper type to a primitive type
+
+ String unwrapMethodName = TransformUtils.getUnwrapperMethodName(fieldType);
+
+ if (unwrapMethodName == null)
+ builder.addln(";");
+ else
+ builder.addln(".%s();", unwrapMethodName);
+
+ builder.end();
+
+ transformation.extendMethod(
+ TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE,
+ builder.toString());
+
+ transformation.claimField(fieldName, annotation);
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldBundleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldBundleImpl.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldBundleImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldBundleImpl.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,69 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+
+@SuppressNullCheck
+public class PersistentFieldBundleImpl implements PersistentFieldBundle
+{
+ /**
+ * Keyed on componentId + fieldName.
+ */
+ private final Map<String, Object> _values = newMap();
+
+ public PersistentFieldBundleImpl(Collection<PersistentFieldChange> changes)
+ {
+ for (PersistentFieldChange change : changes)
+ {
+ String key = buildKey(change.getComponentId(), change.getFieldName());
+
+ _values.put(key, change.getValue());
+ }
+ }
+
+ private String buildKey(String componentId, String fieldName)
+ {
+ StringBuilder builder = new StringBuilder();
+ if (componentId != null)
+ builder.append(componentId);
+ builder.append(':');
+ builder.append(fieldName);
+
+ return builder.toString();
+ }
+
+ public boolean containsValue(String componentId, String fieldName)
+ {
+ String key = buildKey(componentId, fieldName);
+
+ return _values.containsKey(key);
+ }
+
+ public Object getValue(String componentId, String fieldName)
+ {
+ String key = buildKey(componentId, fieldName);
+
+ return _values.get(key);
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldChangeImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldChangeImpl.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldChangeImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldChangeImpl.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,55 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.util.Defense;
+
+@SuppressNullCheck
+public class PersistentFieldChangeImpl implements PersistentFieldChange
+{
+ private final String _componentId;
+
+ private final String _fieldName;
+
+ private final Object _value;
+
+ public PersistentFieldChangeImpl(final String componentId, final String fieldName,
+ final Object value)
+ {
+ Defense.notNull(componentId, "componentId");
+ Defense.notBlank(fieldName, "fieldName");
+
+ _componentId = componentId;
+ _fieldName = fieldName;
+ _value = value;
+ }
+
+ public String getComponentId()
+ {
+ return _componentId;
+ }
+
+ public String getFieldName()
+ {
+ return _fieldName;
+ }
+
+ public Object getValue()
+ {
+ return _value;
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,72 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldManager;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.util.CollectionFactory;
+
+@SuppressNullCheck
+public class PersistentFieldManagerImpl implements PersistentFieldManager
+{
+ private final Map<String, PersistentFieldStrategy> _strategies;
+
+ public PersistentFieldManagerImpl(final Map<String, PersistentFieldStrategy> strategies)
+ {
+ _strategies = strategies;
+ }
+
+ private PersistentFieldStrategy getStrategy(String strategyName)
+ {
+ PersistentFieldStrategy result = _strategies.get(strategyName);
+
+ if (result == null)
+ {
+ String catalog = IOCUtilities.joinSorted(_strategies.keySet());
+
+ throw new RuntimeException(ServicesMessages.unknownPersistentFieldStrategy(
+ strategyName,
+ catalog));
+ }
+
+ return result;
+ }
+
+ public PersistentFieldBundle gatherChanges(String pageName)
+ {
+ Collection<PersistentFieldChange> allChanges = CollectionFactory.newList();
+
+ for (PersistentFieldStrategy strategy : _strategies.values())
+ {
+ allChanges.addAll(strategy.gatherFieldChanges(pageName));
+ }
+
+ return new PersistentFieldBundleImpl(allChanges);
+ }
+
+ public void postChange(String pageName, String componentId, String fieldName, String strategy,
+ Object newValue)
+ {
+ getStrategy(strategy).postChange(pageName, componentId, fieldName, newValue);
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Wed Oct 18 22:20:00 2006
@@ -208,4 +208,9 @@
{
return MESSAGES.format("component-event-is-aborted", methodDescription);
}
+
+ static String unknownPersistentFieldStrategy(String stategyName, String catalog)
+ {
+ return MESSAGES.format("unknown-persistent-field-strategy", stategyName, catalog);
+ }
}
Added: 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=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,105 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.Defense.notBlank;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebSession;
+
+/**
+ * A strategy for storing persistent page properties into the {@link WebSession session}.
+ * <p>
+ * Builds attribute names as:
+ * <code>state:<em>page-name</em>:<em>component-id</em>:<em>field-name</em></code>
+ */
+@SuppressNullCheck
+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 WebRequest _request;
+
+ public SessionPersistentFieldStrategy(final WebRequest request)
+ {
+ _request = request;
+ }
+
+ public Collection<PersistentFieldChange> gatherFieldChanges(String pageName)
+ {
+ WebSession session = _request.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);
+
+ WebSession session = _request.getSession(true);
+
+ session.setAttribute(builder.toString(), newValue);
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java Wed Oct 18 22:20:00 2006
@@ -17,15 +17,15 @@
import java.util.List;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
-import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.internal.util.InternalUtils;
import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebSession;
/**
* Basic implementation of {@link org.apache.tapestry.services.WebRequest} that wraps around an
* {@link javax.servlet.http.HttpServletRequest}.
- *
- *
*/
public class WebRequestImpl implements WebRequest
{
@@ -38,7 +38,7 @@
public List<String> getParameterNames()
{
- return IOCUtilities.toList(_request.getParameterNames());
+ return InternalUtils.toList(_request.getParameterNames());
}
public String getParameter(String name)
@@ -59,6 +59,13 @@
public String getContextPath()
{
return _request.getContextPath();
+ }
+
+ public WebSession getSession(boolean create)
+ {
+ HttpSession session = _request.getSession(create);
+
+ return session == null ? null : new WebSessionImpl(session);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebResponseImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebResponseImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebResponseImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebResponseImpl.java Wed Oct 18 22:20:00 2006
@@ -42,4 +42,15 @@
{
return _response.encodeURL(URL);
}
+
+ public String encodeRedirectURL(String URL)
+ {
+ return _response.encodeRedirectURL(URL);
+ }
+
+ public void sendRedirect(String URL) throws IOException
+ {
+ _response.sendRedirect(URL);
+ }
+
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebSessionImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebSessionImpl.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebSessionImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebSessionImpl.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,73 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.services.WebSession;
+
+/**
+ * A thin wrapper around {@link HttpSession}.
+ */
+public class WebSessionImpl implements WebSession
+{
+ private final HttpSession _session;
+
+ public WebSessionImpl(final HttpSession session)
+ {
+ _session = session;
+ }
+
+ public Object getAttribute(String name)
+ {
+ return _session.getAttribute(name);
+ }
+
+ public List<String> getAttributeNames()
+ {
+ return InternalUtils.toList(_session.getAttributeNames());
+ }
+
+ public void setAttribute(String name, Object value)
+ {
+ _session.setAttribute(name, value);
+ }
+
+ public List<String> getAttributeNames(String prefix)
+ {
+ List<String> result = newList();
+
+ Enumeration e = _session.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ String name = (String) e.nextElement();
+
+ if (name.startsWith(prefix))
+ result.add(name);
+ }
+
+ Collections.sort(result);
+
+ return result;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Wed Oct 18 22:20:00 2006
@@ -55,8 +55,6 @@
* <p>
* TODO: Possibly break this into two classes: the page element and the internal component resources
* implementation. For the moment, it works as a single class.
- *
- *
*/
public class ComponentPageElementImpl extends BaseLocatable implements ComponentPageElement,
PageLifecycleListener
@@ -562,7 +560,7 @@
if (event.isAborted())
return true;
-
+
component = component.getContainer();
}
@@ -579,6 +577,25 @@
throw new IllegalArgumentException(StructureMessages.noSuchComponent(this, embeddedId));
return embeddedElement;
+ }
+
+ public void postFieldChange(String fieldName, Object newValue)
+ {
+ // While loading the page (i.e., when setting field defaults), ignore these
+ // changes.
+
+ if (_loaded)
+ _page.postFieldChange(this, fieldName, newValue);
+ }
+
+ public Object getFieldChange(String fieldName)
+ {
+ return _page.getFieldChange(this, fieldName);
+ }
+
+ public boolean hasFieldChange(String fieldName)
+ {
+ return getFieldChange(fieldName) != null;
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/Page.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/Page.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/Page.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/Page.java Wed Oct 18 22:20:00 2006
@@ -28,8 +28,9 @@
* One of the most important aspects of a Page is that it <em>does not</em> have to be coded in a
* thread-safe manner. Pages are always accessed within a single thread, associated with a single
* incoming request.
- *
- *
+ * <p>
+ * The Page object is never visible to end-user code. The page also exists to provide a kind of
+ * service to components embedded (directly or indirectly) within the page.
*/
public interface Page
{
@@ -109,4 +110,27 @@
*/
Link createActionLink(ComponentPageElement element, String action, boolean forForm,
Object... context);
+
+ /**
+ * Posts a change to a persistent field.
+ *
+ * @param element
+ * the component element containing the field
+ * @param fieldName
+ * the name of the field
+ * @param newValue
+ * the new value for the field
+ */
+ void postFieldChange(ComponentPageElement element, String fieldName, Object newValue);
+
+ /**
+ * Gets a change for a field within the component.
+ *
+ * @param element
+ * the element for which a persistent field value is required
+ * @param fieldName
+ * the name of the persistent field
+ * @return the value, or null if no value is stored
+ */
+ Object getFieldChange(ComponentPageElement element, String fieldName);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java Wed Oct 18 22:20:00 2006
@@ -24,6 +24,8 @@
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.services.LinkFactory;
import org.apache.tapestry.runtime.PageLifecycleListener;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldManager;
/** */
@SuppressNullCheck
@@ -35,15 +37,25 @@
private final LinkFactory _linkFactory;
+ private final PersistentFieldManager _persistentFieldManager;
+
private ComponentPageElement _rootElement;
private final List<PageLifecycleListener> _listeners = newList();
- public PageImpl(String name, Locale locale, LinkFactory linkFactory)
+ /**
+ * Obtained from the {@link PersistentFieldManager} when first needed, discarded at the end of
+ * the request.
+ */
+ private PersistentFieldBundle _fieldBundle;
+
+ public PageImpl(String name, Locale locale, LinkFactory linkFactory,
+ PersistentFieldManager persistentFieldManager)
{
_name = name;
_locale = locale;
_linkFactory = linkFactory;
+ _persistentFieldManager = persistentFieldManager;
}
@Override
@@ -91,6 +103,8 @@
{
for (PageLifecycleListener listener : _listeners)
listener.containingPageDidDetach();
+
+ _fieldBundle = null;
}
public void loaded()
@@ -114,6 +128,23 @@
Object... context)
{
return _linkFactory.createActionLink(element, action, forForm, context);
+ }
+
+ public void postFieldChange(ComponentPageElement element, String fieldName, Object newValue)
+ {
+ String strategy = element.getComponentModel().getFieldPersistenceStrategy(fieldName);
+
+ String componentId = element.getNestedId();
+
+ _persistentFieldManager.postChange(_name, componentId, fieldName, strategy, newValue);
+ }
+
+ public Object getFieldChange(ComponentPageElement element, String fieldName)
+ {
+ if (_fieldBundle == null)
+ _fieldBundle = _persistentFieldManager.gatherChanges(_name);
+
+ return _fieldBundle.getValue(element.getNestedId(), fieldName);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java Wed Oct 18 22:20:00 2006
@@ -14,7 +14,12 @@
package org.apache.tapestry.internal.util;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.annotations.Utility;
@@ -101,6 +106,25 @@
public static String createMemberName(String memberName)
{
return NAME_PREFIX + stripMemberPrefix(memberName);
+ }
+
+ /**
+ * Converts an enumeration (of Strings) into a sorted list of Strings.
+ */
+ public static List<String> toList(Enumeration e)
+ {
+ List<String> result = newList();
+
+ while (e.hasMoreElements())
+ {
+ String name = (String) e.nextElement();
+
+ result.add(name);
+ }
+
+ Collections.sort(result);
+
+ return result;
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java Wed Oct 18 22:20:00 2006
@@ -33,10 +33,8 @@
* "ClassFactory" service.
* <p>
* ObjectProviders exist to provide abstractions on top of the raw IoC services. Examples to follow,
- * especially XXX which provides the ability to easily override services within a Tapestry
- * application.
- *
- *
+ * especially "infrastructure:" which provides the ability to easily override services within a
+ * Tapestry application.
*/
public interface ObjectProvider
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java Wed Oct 18 22:20:00 2006
@@ -18,13 +18,13 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.Resource;
+import org.apache.tapestry.annotations.Persist;
/**
* Defines a component in terms of its capabilities, parameters, sub-components, etc. During
* <em>runtime</em>, the component model is immutable. During <em>construction</em> time, when
* the class is being transformed a loaded, the model is mutable.
*
- *
* @see
*/
public interface ComponentModel
@@ -67,4 +67,21 @@
* @return the embedded component model, or null if no component exists with that id
*/
EmbeddedComponentModel getEmbeddedComponentModel(String componentId);
+
+ /**
+ * Returns a list of the names of all persistent fields (within this class, or any super-class).
+ * The names are sorted alphabetically.
+ *
+ * @see Persist
+ */
+ List<String> getPersistentFieldNames();
+
+ /**
+ * Returns the persistent strategy associated with the field.
+ *
+ * @param fieldName
+ * @return the corresponding strategy
+ * @throw IllegalArgumentException if the named field is not marked as persistent
+ */
+ String getFieldPersistenceStrategy(String fieldName);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java Wed Oct 18 22:20:00 2006
@@ -17,8 +17,6 @@
/**
* Mutable version of {@link org.apache.tapestry.model.ComponentModel} used during the
* transformation phase.
- *
- *
*/
public interface MutableComponentModel extends ComponentModel
{
@@ -47,4 +45,9 @@
*/
MutableEmbeddedComponentModel addEmbeddedComponent(String id, String type,
String componentClassName);
+
+ /**
+ * @see ComponentModel#getFieldPersistenceStrategy(String)
+ */
+ void setFieldPersistenceStrategy(String fieldName, String strategy);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java Wed Oct 18 22:20:00 2006
@@ -16,8 +16,6 @@
/**
* A set of methods that allow components to know about page-level operations.
- *
- *
*/
public interface PageLifecycleListener
{
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldBundle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldBundle.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldBundle.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldBundle.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,45 @@
+// 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.
+
+package org.apache.tapestry.services;
+
+/**
+ * Encapsulates persisted property information for an entire page.
+ */
+public interface PersistentFieldBundle
+{
+ /**
+ * Checks to see if a persistent value has been stored for the indicated component and field.
+ * TODO: This method can probably be removed; it doesn't look like its used (instead, we if
+ * check getValue() returns null).
+ *
+ * @param componentId
+ * the nested id of the component (within the page), may be null or blank for the
+ * root component of the page
+ * @param fieldName
+ * the name of the field whose value was persisted
+ * @return true if a change has been stored
+ */
+ boolean containsValue(String componentId, String fieldName);
+
+ /**
+ * @param componentId
+ * the nested if of the component (within the page), may be null or blank for the
+ * root component of the page
+ * @param fieldName
+ * the name of the field whose value was persisted
+ * @return the persisted value, possibly null
+ */
+ Object getValue(String componentId, String fieldName);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldChange.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldChange.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldChange.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldChange.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,31 @@
+// 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.
+
+package org.apache.tapestry.services;
+
+/**
+ * Represents a previously stored change to a persistent field, within the context of a particular
+ * page of the application.
+ */
+public interface PersistentFieldChange
+{
+ /** Returns the nested id of the component, or the empty string for the page's root component. */
+ String getComponentId();
+
+ /** Returns the name of the field for which a change was recorded. */
+ String getFieldName();
+
+ /** Returns the new value for the field (which may be null). */
+ Object getValue();
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,49 @@
+// 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.
+
+package org.apache.tapestry.services;
+
+/**
+ * Handle persistent property changes. Primarily, delegates to a number of
+ * {@link PersistentFieldStrategy} instances.
+ */
+public interface PersistentFieldManager
+{
+ /**
+ * Posts a change of a persistent property.
+ *
+ * @param pageName
+ * the name of the page containing the component
+ * @param componentId
+ * the nested id path of the component (or null for the page's root component)
+ * @param fieldName
+ * the name of the field whose persistent value has changed
+ * @param strategy
+ * the name of the stategy used to persist the property value
+ * @param newValue
+ * the new value for the field, possibly null
+ */
+ void postChange(String pageName, String componentId, String fieldName, String strategy,
+ 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.
+ *
+ * @param pageName
+ * the name of the page to gather changes for
+ * @return a bundle identifying all such changes
+ */
+ PersistentFieldBundle gatherChanges(String pageName);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,42 @@
+// 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.
+
+package org.apache.tapestry.services;
+
+import java.util.Collection;
+
+public interface PersistentFieldStrategy
+{
+ /**
+ * Posts a change of a persistent property.
+ *
+ * @param pageName
+ * the name of the page containing the component
+ * @param componentId
+ * the nested id path of the component (or null for the page's root component)
+ * @param fieldName
+ * the name of the field whose persistent value has changed
+ * @param strategy
+ * the name of the stategy used to persist the property value
+ * @param newValue
+ * the new value for the field, possibly null
+ */
+ 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).
+ */
+ Collection<PersistentFieldChange> gatherFieldChanges(String pageName);
+}