Author: hlship
Date: Fri Feb 23 11:39:28 2007
New Revision: 511066

URL: http://svn.apache.org/viewvc?view=rev&rev=511066
Log:
Simplify action URLs for the standard case (the event type "action").
Update a bunch of out-of-date documentation.

Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryConstants.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/corelib/components/Form.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java

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=511066&r1=511065&r2=511066
==============================================================================
--- 
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
 Fri Feb 23 11:39:28 2007
@@ -19,8 +19,8 @@
  */
 public final class TapestryConstants
 {
-    /** Default client event name, used in most situations. */
-    public static final String DEFAULT_EVENT = "action";
+    /** Default client event name, "action", used in most situations. */
+    public static final String ACTION_EVENT = "action";
 
     /**
      * Event triggered when a page is activated (for rendering). The component 
event handler will be

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=511066&r1=511065&r2=511066
==============================================================================
--- 
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
 Fri Feb 23 11:39:28 2007
@@ -14,7 +14,7 @@
 
 package org.apache.tapestry.corelib.components;
 
-import static org.apache.tapestry.TapestryConstants.DEFAULT_EVENT;
+import static org.apache.tapestry.TapestryConstants.ACTION_EVENT;
 
 import java.util.List;
 
@@ -67,7 +67,7 @@
 
         Object[] contextArray = _context == null ? new Object[0] : 
_context.toArray();
 
-        Link link = _resources.createActionLink(DEFAULT_EVENT, false, 
contextArray);
+        Link link = _resources.createActionLink(ACTION_EVENT, false, 
contextArray);
 
         writer.element("a", "href", link, "id", clientId);
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
 Fri Feb 23 11:39:28 2007
@@ -202,7 +202,7 @@
         String name = _pageRenderSupport.allocateClientId(_resources.getId());
 
         Link link = _resources
-                .createActionLink(TapestryConstants.DEFAULT_EVENT, true, 
contextArray);
+                .createActionLink(TapestryConstants.ACTION_EVENT, true, 
contextArray);
         writer.element("form", "name", name, "id", name, "method", "post", 
"action", link);
 
         _resources.renderInformalParameters(writer);

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridPager.java
 Fri Feb 23 11:39:28 2007
@@ -124,7 +124,7 @@
             return;
         }
 
-        Link link = 
_resources.createActionLink(TapestryConstants.DEFAULT_EVENT, false, pageIndex);
+        Link link = 
_resources.createActionLink(TapestryConstants.ACTION_EVENT, false, pageIndex);
 
         writer.element("a", "href", link, "title", 
_messages.format("goto-page", pageIndex));
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkHandlerImpl.java
 Fri Feb 23 11:39:28 2007
@@ -97,7 +97,7 @@
         if (holder.hasValue())
             return holder.get();
 
-        element.triggerEvent(actionLinkTarget.getAction(), 
invocation.getContext(), handler);
+        element.triggerEvent(actionLinkTarget.getEventType(), 
invocation.getContext(), handler);
 
         ActionResponseGenerator result = holder.get();
 

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ActionLinkTarget.java
 Fri Feb 23 11:39:28 2007
@@ -14,12 +14,15 @@
 
 package org.apache.tapestry.internal.services;
 
+import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+
 /**
  * It represents an invocation target for an action link.
  */
 public class ActionLinkTarget implements InvocationTarget
 {
-    private final String _action;
+    private final String _eventType;
 
     private final String _pageName;
 
@@ -27,7 +30,7 @@
 
     public ActionLinkTarget(String action, String pageName, String 
componentNestedId)
     {
-        _action = action;
+        _eventType = action;
         _pageName = pageName;
         _componentNestedId = componentNestedId;
 
@@ -38,18 +41,32 @@
         StringBuilder builder = new StringBuilder();
 
         builder.append(_pageName.toLowerCase());
-        builder.append(".");
-        // Already lower case by design.
-        builder.append(_componentNestedId);
-        builder.append(".");
-        builder.append(_action);
+
+        boolean hasComponentId = InternalUtils.isNonBlank(_componentNestedId);
+
+        if (hasComponentId)
+        {
+
+            builder.append(".");
+            // Already lower case by design.
+            builder.append(_componentNestedId);
+        }
+
+        // If no nested component id, then must append the action; the ':' and 
the action become the
+        // delimiter between the page name and the event context.
+
+        if (!hasComponentId || 
!_eventType.equals(TapestryConstants.ACTION_EVENT))
+        {
+            builder.append(":");
+            builder.append(_eventType);
+        }
 
         return builder.toString();
     }
 
-    public String getAction()
+    public String getEventType()
     {
-        return _action;
+        return _eventType;
     }
 
     public String getComponentNestedId()

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
 Fri Feb 23 11:39:28 2007
@@ -16,6 +16,7 @@
 
 import java.io.IOException;
 
+import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.TapestryUtils;
 import org.apache.tapestry.services.ActionResponseGenerator;
@@ -42,26 +43,68 @@
     {
         String path = request.getPath();
 
-        int dotx = path.indexOf('.');
-
-        if (dotx < 0)
-            return false;
+        String logicalPageName = null;
+        String nestedComponentId = "";
+        String eventType = TapestryConstants.ACTION_EVENT;
 
-        // Skip the leading slash, the rest is logical page name.
+        // Will always have a dot or a colon
 
-        String logicalPageName = path.substring(1, dotx);
-
-        int slashx = path.indexOf('/', dotx + 1);
-        if (slashx < 0)
-            slashx = path.length();
+        int dotx = path.indexOf('.');
+        int colonx = path.indexOf(':');
 
-        int lastDotx = path.lastIndexOf('.', slashx);
+        int contextStart = -1;
 
-        String nestedComponentId = dotx != lastDotx ? path.substring(dotx + 1, 
lastDotx) : "";
+        if (dotx > 0)
+        {
+            logicalPageName = path.substring(1, dotx);
+
+            int slashx = path.indexOf('/', dotx + 1);
+
+            // The nested id ends at the colon (if present) or
+            // the first slash (if present) or the end of the path.
+
+            if (slashx < 0)
+            {
+                slashx = path.length() ;
+            }
+            else
+            {
+                contextStart = slashx + 1;
+            }
+
+            int nestedIdEnd = slashx;
+
+            if (colonx > 0 && colonx < slashx)
+            {
+                nestedIdEnd = colonx;
+                eventType = path.substring(colonx + 1, slashx);
+            }
+
+            nestedComponentId = path.substring(dotx + 1, nestedIdEnd);
+        }
+        else if (colonx > 0)
+        {
+            // No dot, but a colon. Therefore no nested component id, but an 
action name and
+            // maybe some event context.
+
+            int slashx = path.indexOf('/', colonx + 1);
+            if (slashx < 0)
+            {
+                slashx = path.length();
+            }
+            else
+            {
+                contextStart = slashx + 1;
+            }
+
+            eventType = path.substring(colonx + 1, slashx);
+            logicalPageName = path.substring(1, colonx);
+        }
 
-        String eventType = path.substring(lastDotx + 1, slashx);
+        if (logicalPageName == null)
+            return false;
 
-        String[] context = slashx < path.length() ? 
decodeContext(path.substring(slashx + 1))
+        String[] eventContext = contextStart > 0 ? 
decodeContext(path.substring(contextStart))
                 : _emptyString;
 
         String activationContextValue = 
request.getParameter(InternalConstants.PAGE_CONTEXT_NAME);
@@ -73,7 +116,7 @@
                 logicalPageName,
                 nestedComponentId,
                 eventType,
-                context,
+                eventContext,
                 activationContext);
 
         responseGenerator.sendClientResponse(response);

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
 Fri Feb 23 11:39:28 2007
@@ -43,10 +43,12 @@
      *            identifies the target of the event: a component with a page
      * @param context
      *            context information supplied by the component to be provided 
back when the event
-     *            on the component is triggered
+     *            on the component is triggered, or contains the activation 
context when the
+     *            invocation is for a page render request
      * @param activationContext
      *            page activation context for the page containing the 
component, supplied via a
-     *            passivate event to the page's root component
+     *            passivate event to the page's root component (used when an 
action component
+     *            invocation is for a page with an activation context)
      */
     public ComponentInvocation(InvocationTarget target, String[] context, 
String[] activationContext)
     {

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt Fri 
Feb 23 11:39:28 2007
@@ -64,7 +64,7 @@
   {
     ApplicationStateCreator<MyState> creator = new 
ApplicationStateCreator<MyState>()
     {
-      MyState create()
+      public MyState create()
       {
         return new MyState(new Date());
       }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/dom.apt Fri Feb 
23 11:39:28 2007
@@ -142,6 +142,11 @@
   The writef() method formats an number of arguments.  It uses a 
java.util.Formatter.  It is a convience for formatting that ultimately
   invokes write().
   
+* writeRaw()
+
+  The writeRaw() method writes unfiltered text into the DOM.  When the DOM is 
rendered to markup, the provided string is written to the
+  output stream exactly as-is. Care should be taken, as this can easily result 
invalid markup, or even markup that is not well formed.
+  
 * comment()
 
   Adds an XML comment.  The comment delimiters will be supplied by Tapestry:

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt Fri Feb 
23 11:39:28 2007
@@ -7,44 +7,71 @@
   Component events are the means by which components are made aware of 
behaviors by the user, such
   as clicking links and submitting forms.
   
+  Component events are used for two purposes:
+  
+  * They represent requests initiated by the user, triggered by links and 
forms in the client web browser.
+    These are described more fully in {{{pagenav.html}page navigation}} and in 
+    {{{request.html}requst processing}}.
+    
+  * They represent flow-of-control within a request, allowing one component to 
notify its container
+    about some kind of circumstance ("a form was submitted"), or to collect 
some piece for data
+    from the container.
+    
+  []
+  
+  Often, a navigation request (originating with the user) will spawn a number 
of flow-of-control
+  requests.  For example, a Form component will be triggered by an action 
request, and will then
+  send notification events to announce when the form submission is about to be 
processed, and
+  whether it was succesful or not.
+  
   In Tapestry 4, you would configure a parameter of a component with the name 
of a method to invoke
   when a certain event occured, usually a request from the client.
   
   This has some limitations, including the fact that only a single method 
could be invoked.
   
-  Tapestry 5 introduces the
-  {{{../apidocs/org/apache/tapestry/annotations/OnEvent.html}OnEvent 
annotation}} which is used
-  to mark methods as <event handler methods>.  As with other annotations, 
these methods
-  may be private or public.
-  
-  Rather than configure a component to invoke a particular method, you 
annotate one or more
-  methods to listen for events from that component.
+  Tapestry 5 introduces the concept of <event handler methods>, identified via 
a naming convention, or
+  via the 
+  {{{../apidocs/org/apache/tapestry/annotations/OnEvent.html}OnEvent 
annotation}}.  Event handler methods
+  have any visibility, even private (normally they are given package private 
visibility, to support testing).
+  
+  Rather than configure a component to invoke a particular method, you 
identify one or more
+  methods to listen for events from that component. A single event handler 
method may receive notifications from
+  many different components.
   
-  For example, here's a portion of a page that lets the user choose a value 
between 1 and 10:
+  For example, here's a portion of a page (let's call it "Chooser") that lets 
the user choose a number between 1 and 10:
   
 +---+
 <p> Choose a number from 1 to 10: </p>
 
 <p>
     <t:comp type="Count" end="10" value="index">
-        <t:comp id="choose" type="ActionLink" context="index">${index}</t:comp>
+        <a t:id="select" t:type="actionlink" context="index">${index}</t:comp>
     </t:comp>
 </p>
 +---+
 
   The ActionLink component creates an action URL.
   
-  The URL identifies the page that contains the component, the type of event
-  ("action", the default), the id of the component ("choose"), plus the 
additional context value.
-  A sample URL: <<<http://localhost:8080/ActionPage.action/choose/3>>>.
+  The URL identifies the page that contains the component ("chooser"), the 
type of event
+  (unless it is "action", the default and most common event type),
+  the id of the component within the page ("select"), plus the additional 
context value(s).
   
+  A sample URL: <<<http://localhost:8080/chooser.select/3>>>.
+
   When there are additional context values, they are appended to the path.
+  
+  This demonstrates a critical difference between Tapestry and a more 
traditional, action oriented framework.
+  This URL doesn't say what happens when the link is clicked, it identifies 
<which component is responsible>.
+
+  There's no simple mapping from URL to a piece of code; instead the component 
sends notifications, in the form
+  of invocations of event handler methods,   
+  
    
   A Java method can be invoked when the link for the component is clicked by 
the user:
   
 +---+
-  @OnEvent(component = "choose")
-  void choose(int value)
+  @OnEvent(component = "select")
+  void valueChosen(int value)
   {
     _value = value;
   }
@@ -52,21 +79,21 @@
 
   Tapestry has done two things here:
   
-  * It has identified method choose() as the method to invoke.
+  * It has identified method valueChosen() as the method to invoke.
   
   * It has converted the context value from a string to an integer and passed 
it into the method.
   
   []
   
-  In the above example, the choose() method will be invoked on <any event> 
that originates
+  In the above example, the valueChosen() method will be invoked on <any 
event> that originates
   inn component <<<choose>>>.  Since ActionLink components only emit a single 
type of event, "action", 
   this will not be a problem.
   
   Some components can emit more than one type of event, in which case you will 
want to be more specific:
   
 +---+
-  @OnEvent(value = "action", component = "choose")
-  void choose(int value)
+  @OnEvent(value = "action", component = "select")
+  void valueChosen(int value)
   {
     _value = value;
   }
@@ -74,6 +101,12 @@
   
   The value attribute of the OnEvent annotation is the name of the event to 
match.
   
+  "action" is the name of the default event type; the ActionLink and Form 
components each use this event type.
+  If you omit the component part of the OnEvent annotation, then you'll 
recieve notifications from
+  <all> contained components, possibly including nested components (due to 
event bubbling).
+  
+  You should qualify exactly which component(s) you wish to recieve events 
from.
+  
 Event Handler Method Convention Names  
   
   As an alternative to the use of annotations, you may name your events in a 
specific fashion, and Tapestry will invoke your methods just as if
@@ -85,14 +118,19 @@
   The previous example may be rewritten as:
   
 +---+
-  void onActionFromChoose(int value)
+  void onActionFromSelect(int value)
   {
     _value = value;
   }
 +---+  
   
+  If you event type is named "onAny", it will receive all types of events. 
This is rarely what you want!
+  
+  If for some unfathomable reason you want to be notified of the same event 
from multiple components in the same method, you'll need to use the OnEvent 
annotation.  
+  
+  Note from Howard: I've found that I prefer the naming convention approach, 
and reserve the annotation just for situations that don't otherwise fit.  
   
-Context
+Event Context
 
   The context values (the context parameter to the ActionLink component) can 
be any object.
   However, only a simple conversion to string occurs.  This is in contrast to 
Tapestry 4, which had
@@ -110,7 +148,7 @@
   
   Alternately, an event handler method may take a parameter of type 
java.lang.Object[].  This parameter
   will receive the entire context array. This is useful when, for example, the 
context
-  is off different lengths at different times. You should use either explicit, 
typed parameters or
+  is of different lengths at different times. You should use either explicit, 
typed parameters or
   a single parameter of type Object[].
   
 Event Bubbling
@@ -118,76 +156,7 @@
   The event will bubble up the hierarchy, until it is aborted. The event is 
aborted
   when an event handler method returns a non-null value.
   
-  The value returned from an event handler method determines how Tapestry will 
render a response.
-  
-Event Handler Returns Types
+  For page navigation events, the value returned from an event handler method 
{{{pagenav.html}determines how Tapestry will render a response}}.
 
-  An event handler may return a number of different types:
-  
-  * A page component, via the 
{{{../apidocs/org/apache/tapestry/annotations/InjectPage.html}InjectPage}} 
annotation
-  
-  * A string, the <logical> name of a page (not the fully qualified class name)
-
-  * <More types to be determined>
-  
-  []
-  
-  Returning a page will abort the event and direct Tapestry to render the 
returned page.  It's completely acceptible to invoke
-  methods on the page before returning it (often to inform it about what it 
should display), but remember that rendering of the page
-  <<will occur in a subsequent request>>, which often requires that you store 
information persistently between requests.
-  
-  Returning a string is much the same, except that the string is used to 
locate the page to be activated. This is easy to use
-  when there is no need to invoke methods on the page before returning it.
-  
-  <TODO: Describe differences between client-originating events and 
flow-of-control events from components.>
-  
-End of Action Request
-
-  The default behavior at the end of an action request is to set up the page 
containing
-  the component to render.  This is normally the page that contains the 
component, but the active page
-  (the page that renders the response) may be altered based on the value 
returned from an component event
-  handler method.
-  
-  <<This is very important:>> The rendering occurs in a <<new>> request. The 
normal response
-  to an action request is a client-side redirect to re-render the page. Thus 
an action is <<two>>
-  requests: one to process the action and update server-side state, and a 
second request to render
-  the resulting page.
-  
-  It is very important that you make use of 
-  {{{persist.html}page persistence}} to allow information from the action 
request
-  to survive to the next render request.
-  
-Passivate and Activate Events
-
-  When a link to a page is created, the page will be sent a passivate event. 
The event handler method for the
-  passivate event may return a single value, or a list or array of values. 
-  These objects will become the context portion of the URI.  When a page is 
later rendered, the context is extracted from the URI and
-  passed to any activate event handlers.  In this way, information about the 
page can be encoded into URIs for the page, in a light-weight
-  (and human readable) manner.
-  
-  This was created with the intent of handling pages that exist to view (or 
perhaps to edit) a specific instance of some type; in the
-  context of a CRUD application, the context is used to store the primary key 
of some entity object:
-    
-+---+
-  public class ViewCustomer
-  {
-    private Customer _customer;
-    
-    @Inject
-    private CustomerDAO _customerDAO;
     
-    long onPassivate()
-    {
-      return _customer.getId();
-    }
-  
-    void onActivate(long customerId)
-    {
-      _customer = _customerDAO.get(customerId);
-    }
-  }
-+---+
-  
-  Render page request URI's for this page would be created as 
<<</ViewCustomer.html/1234>>>.
-  
    

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt Fri 
Feb 23 11:39:28 2007
@@ -202,7 +202,7 @@
 
   This is a minimal approach, perhaps good enough for a prototype. 
   
-  When the user clicks a link, the action request URL will initially be 
something like "http://.../productlisting/select.action/99"; and the final
+  When the user clicks a link, the action request URL will initially be 
something like "http://.../productlisting.select/99"; and the final
   render request URL will be something like "http://.../productdetails";.  
Notice that the product id ("99") does not appear in the render request URL.
   
   It has some minor flaws:

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt Fri 
Feb 23 11:39:28 2007
@@ -34,6 +34,12 @@
   
   Reloading is based on package name; the packages that are reloaded are 
derived from the {{{conf.html}application configuration}}.
   
+File System Only
+
+  Reloading of classes and other files applies only to files that are actually 
on the file system, and not files
+  obtained from JAR files.  This is perfect during development, where the 
files in question are in your local workspace.
+  In a deployed application, you are somewhat subject to the implementation of 
your servlet container or application server.  
+  
 Class Loader Issues
 
   Tapestry uses an extra class loader to load page and component classes.

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/request.apt Fri 
Feb 23 11:39:28 2007
@@ -107,11 +107,18 @@
   
   The URL identifies the name of the page, then a series of component ids (the 
path from the page down to the specific component), then the name of the event 
to be
   triggered on the component. The remaining path elements are used as the 
context for the <event> (not for the page activation, which
-  does not currently apply). For example, "/griddemo.FOO.BAR.action/3" would 
locate page "griddemo", then component "FOO.BAR", and trigger an event named 
"action", with
+  does not currently apply). For example, "/griddemo.FOO.BAR/3" would locate 
page "griddemo", then component "FOO.BAR", and trigger an event named "action" 
(the default event type,
+  which is omitted from the URL), with
   the context "3".
   
+  If the page in question has an activation context, it is supplied as an 
additional query parameter on the link.
+  
+  In cases where the event type is not the default, "action", it will appear 
between the nested component id and the event context, preceded by a colon. 
Example:
+  "/example/foo.bar:magic/99" would trigger an event of type "magic".  This is 
not common in the vanilla Tapestry framework, but will likely be more common
+  as Ajax features (which would not use the normal request logic) are 
implemented.
+    
   The response from a component action request is typically, but not 
universally, used to send a redirect to the client; the redirect URL is a page 
render URL
-  to display the response to the event.  
+  to display the response to the event.  This is detailed under 
{{{pagenav.html}page navigation}}.  
    
    
 RequestGlobals Service

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt Fri Feb 23 
11:39:28 2007
@@ -8,36 +8,17 @@
   
   tapestry-core is built upon the {{{../tapestry-ioc/index.html}Tapestry IoC 
Container}}.
 
-Changes from Tapestry 4 to Tapestry 5
-
-  Tapestry 5 represents a significant advance over Tapestry 4.  The goal is to 
make Tapestry 5
-  <significantly> easier to use than Tapestry 4 (or any other Java web 
framework).
-  We're keeping the <essence> of Tapestry 4, but starting with a brand new 
code base designed
-  to provide a stable, powerful, extensible platform for many years to come.
-  
-  Here's a few of the planned and implemented features:
-  
-  * Simplified, minimal API based on annotations
-  
-  * <<No>> base class requirement; components are true, pure Pojos (Plain Old 
Java Objects)
-  
-  * Abstract classes ... gone!  Classes are normal, concrete classes.
-  
-  * <<No>> XML descriptors for pages and components ... just the annotations.
-  
-  * Less configuration all around.
-  
-  * Automatic reloading of templates and even <Java classes>
-  
-  * Super-duper Ajax integration built on {{{http://dojotoolkit.org} Dojo}}
-  
-  * Easy & fast unit testing of individual pages or components
-  
 New And Of Note
 
   Progress on Tapestry 5 is really taking off. This space lists some cool new 
features that have been added
   recently.
   
+  * The default ExceptionReport page has been improved to show details of the 
incoming request,
+    and to display file content when an exception includes a location.
+  
+  * Action request URLs have been shortened and simplified for the common 
case. They may also include a query
+    parameter to identify the page's activation context.
+  
   * {{{component-parameters.html}Component Reference Documentation}}, 
generated via a Maven plugin, is now available.
   
   * The return values for the "after" set of {{{guide/rendering.html}render 
phase methods}} have changed: all render phase 
@@ -82,6 +63,31 @@
   
   * The @ComponentClass anntotation, seen in the earlier 
{{{../screencast.html}screencasts}} has been removed.
   
+Changes from Tapestry 4 to Tapestry 5
+
+  Tapestry 5 represents a significant advance over Tapestry 4.  The goal is to 
make Tapestry 5
+  <significantly> easier to use than Tapestry 4 (or any other Java web 
framework).
+  We're keeping the <essence> of Tapestry 4, but starting with a brand new 
code base designed
+  to provide a stable, powerful, extensible platform for many years to come.
+  
+  Here's a few of the planned and implemented features:
+  
+  * Simplified, minimal API based on annotations
+  
+  * <<No>> base class requirement; components are true, pure Pojos (Plain Old 
Java Objects)
+  
+  * Abstract classes ... gone!  Classes are normal, concrete classes.
+  
+  * <<No>> XML descriptors for pages and components ... just the annotations.
+  
+  * Less configuration all around.
+  
+  * Automatic reloading of templates and even <Java classes>
+  
+  * Super-duper Ajax integration built on {{{http://dojotoolkit.org} Dojo}}
+  
+  * Easy & fast unit testing of individual pages or components
+    
 Adaptive API
 
   A key feature of Tapestry 5 is <adaptive API>.

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
 Fri Feb 23 11:39:28 2007
@@ -19,6 +19,7 @@
 
 import java.io.IOException;
 
+import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.apache.tapestry.services.ActionResponseGenerator;
@@ -30,7 +31,7 @@
 public class ComponentActionDispatcherTest extends InternalBaseTestCase
 {
     @Test
-    public void no_dot_in_path() throws Exception
+    public void no_dot_or_colon_in_path() throws Exception
     {
         ActionLinkHandler handler = newActionLinkHandler();
         Request request = newRequest();
@@ -55,38 +56,102 @@
     @Test
     public void event_on_page() throws Exception
     {
-        test("/foo/MyPage.anevent", "foo/MyPage", "", "anevent");
+        test("/foo/MyPage:anevent", "foo/MyPage", "", "anevent");
     }
 
     @Test
     public void event_on_component_within_page() throws Exception
     {
-        test("/foo/MyPage.fred.anevent", "foo/MyPage", "fred", "anevent");
+        test("/foo/MyPage.fred:anevent", "foo/MyPage", "fred", "anevent");
+    }
+
+    @Test
+    public void default_event_with_nested_id() throws Exception
+    {
+        test("/foo/MyPage.fred", "foo/MyPage", "fred", 
TapestryConstants.ACTION_EVENT);
+    }
+
+    @Test
+    public void default_event_with_nested_id_and_context() throws Exception
+    {
+        test(
+                "/foo/MyPage.fred/fee/fie/foe/fum",
+                "foo/MyPage",
+                "fred",
+                TapestryConstants.ACTION_EVENT,
+                "fee",
+                "fie",
+                "foe",
+                "fum");
+    }
+
+    @Test
+    public void default_event_with_context_that_includes_a_colon() throws 
Exception
+    {
+        test(
+                "/foo/MyPage.underdog/a:b:c/d",
+                "foo/MyPage",
+                "underdog",
+                TapestryConstants.ACTION_EVENT,
+                "a:b:c",
+                "d");
     }
 
     @Test
     public void event_on_nested_component_within_page() throws Exception
     {
-        test("/foo/MyPage.barney.fred.anevent", "foo/MyPage", "barney.fred", 
"anevent");
+        test("/foo/MyPage.barney.fred:anevent", "foo/MyPage", "barney.fred", 
"anevent");
     }
 
     @Test
     public void page_event_with_context() throws Exception
     {
-        test("/foo/MyPage.trigger/foo", "foo/MyPage", "", "trigger", "foo");
+        test("/foo/MyPage:trigger/foo", "foo/MyPage", "", "trigger", "foo");
     }
 
     @Test
     public void nested_component_event_with_context() throws Exception
     {
         test(
-                "/foo/MyPage.nested.trigger/foo/bar/baz",
+                "/foo/MyPage.nested:trigger/foo/bar/baz",
                 "foo/MyPage",
                 "nested",
                 "trigger",
                 "foo",
                 "bar",
                 "baz");
+    }
+
+    @Test
+    public void page_activation_context_in_request() throws Exception
+    {
+        ActionLinkHandler handler = newActionLinkHandler();
+        Request request = newRequest();
+        Response response = newResponse();
+        ActionResponseGenerator generator = 
newMock(ActionResponseGenerator.class);
+
+        train_getPath(request, "/mypage:eventname");
+
+        train_getParameter(request, InternalConstants.PAGE_CONTEXT_NAME, 
"alpha/beta");
+
+        expect(
+                handler.handle(
+                        eq("mypage"),
+                        eq(""),
+                        eq("eventname"),
+                        aryEq(new String[0]),
+                        aryEq(new String[]
+                        { "alpha", "beta" }))).andReturn(generator);
+
+        generator.sendClientResponse(response);
+
+        replay();
+
+        Dispatcher dispatcher = new ComponentActionDispatcher(handler);
+
+        assertTrue(dispatcher.dispatch(request, response));
+
+        verify();
     }
 
     private void test(String requestPath, String logicalPageName, String 
nestedComponentId,

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java?view=diff&rev=511066&r1=511065&r2=511066
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
 Fri Feb 23 11:39:28 2007
@@ -67,7 +67,8 @@
                 PAGE_LOGICAL_NAME,
                 "foo.bar",
                 "someaction",
-                "/sub/mypage.foo.bar.someaction");
+                "/sub/mypage.foo.bar:someaction");
+
     }
 
     @Test
@@ -79,10 +80,38 @@
                 PAGE_LOGICAL_NAME,
                 "foo.bar",
                 "publish",
-                "/sub/mypage.foo.bar.publish/fred/5",
+                "/sub/mypage.foo.bar:publish/fred/5",
+                "fred",
+                5);
+    }
+
+    @Test
+    public void action_link_with_default_action()
+    {
+        testActionLink(
+                PAGE_CLASS_NAME,
+                "",
+                PAGE_LOGICAL_NAME,
+                "foo.bar",
+                TapestryConstants.ACTION_EVENT,
+                "/sub/mypage.foo.bar/fred/5",
                 "fred",
                 5);
     }
+    
+    @Test
+    public void page_level_event_always_includes_action()
+    {
+        testActionLink(
+                PAGE_CLASS_NAME,
+                "",
+                PAGE_LOGICAL_NAME,
+                "",
+                TapestryConstants.ACTION_EVENT,
+                "/sub/mypage:action/barney/99",
+                "barney",
+                99);
+    }
 
     @Test
     public void action_link_named_context_no_ids()
@@ -93,7 +122,7 @@
                 PAGE_LOGICAL_NAME,
                 "foo.bar",
                 "someaction",
-                "/fred/sub/mypage.foo.bar.someaction");
+                "/fred/sub/mypage.foo.bar:someaction");
     }
 
     @SuppressWarnings("unchecked")


Reply via email to