Author: craigmcc
Date: Fri Dec 15 16:51:06 2006
New Revision: 487741

URL: http://svn.apache.org/viewvc?view=rev&rev=487741
Log:
Refine the dialog framework APIs as a foundation for improving handling of
browser navigation buttons:

* Provide an "escape hatch" (getOpaqueState/setOpaqueState) such that a
  DialogContext implementation can optionally request that additional
  information be saved and restored with each JSF component tree that
  is rendered.  There is a restriction that any such opaque state data
  must be Serializable.

* Modify the two existing implementations to obey the updated API
  contract,but otherwise do nothing at the moment.

* Refactor DialogPhaseListener a bit:

  - Make Constants.CONTEXT_ID_ATTR a private constant in this class.
    This information is a private implementation detail.

  - Create a private beforeRenderResponse() method, parallel to the
    existing afterRestoreView() method, in case we have to deal with
    more phases later.  These are private APIs, so no disruption of
    apps can occur

  - Implement the saving and restoring of opaque data, if requested
    by the DialogContext implementation.  If saved, it will be stored
    as another generic attribute on the view root component, but (again)
    this is an implementation detail not visible to callers.

SHALE-61


Modified:
    
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java
    
shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/SCXMLDialogContext.java
    
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/Constants.java
    
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/DialogContext.java
    
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/faces/DialogPhaseListener.java

Modified: 
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java
URL: 
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java?view=diff&rev=487741&r1=487740&r2=487741
==============================================================================
--- 
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java
 (original)
+++ 
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java
 Fri Dec 15 16:51:06 2006
@@ -257,6 +257,22 @@
 
 
     /** [EMAIL PROTECTED] */
+    public Object getOpaqueState() {
+
+        return null; // Do not do anything yet, just fulfill the API contract
+
+    }
+
+
+    /** [EMAIL PROTECTED] */
+    public void setOpaqueState(Object opaqueState) {
+
+        ; // Do not do anything yet, just fulfill the API contract
+
+    }
+
+
+    /** [EMAIL PROTECTED] */
     public DialogContext getParent() {
 
         if (this.parentDialogId != null) {

Modified: 
shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/SCXMLDialogContext.java
URL: 
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/SCXMLDialogContext.java?view=diff&rev=487741&r1=487740&r2=487741
==============================================================================
--- 
shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/SCXMLDialogContext.java
 (original)
+++ 
shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/SCXMLDialogContext.java
 Fri Dec 15 16:51:06 2006
@@ -230,6 +230,22 @@
 
 
     /** [EMAIL PROTECTED] */
+    public Object getOpaqueState() {
+
+        return null; // Do not do anything yet, just fulfill the API contract
+
+    }
+
+
+    /** [EMAIL PROTECTED] */
+    public void setOpaqueState(Object opaqueState) {
+
+        ; // Do not do anything yet, just fulfill the API contract
+
+    }
+
+
+    /** [EMAIL PROTECTED] */
     public DialogContext getParent() {
 
         if (this.parentDialogId != null) {

Modified: 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/Constants.java
URL: 
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/Constants.java?view=diff&rev=487741&r1=487740&r2=487741
==============================================================================
--- 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/Constants.java
 (original)
+++ 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/Constants.java
 Fri Dec 15 16:51:06 2006
@@ -34,16 +34,6 @@
 
 
     /**
-     * <p>Generic attribute name (on the view root component of the current
-     * JSF component tree) under which the context identifier for the
-     * dialog instance that is current for this view (if any) should be
-     * stored and retrieved.</p>
-     */
-    public static final String CONTEXT_ID_ATTR =
-            "org.apache.shale.dialog.CONTEXT_ID";
-
-
-    /**
      * <p>Request parameter containing the dialog identifier of an
      * existing [EMAIL PROTECTED] DialogContext} instance to be restored for
      * the current view.  Normally, this identifier will be passed

Modified: 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/DialogContext.java
URL: 
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/DialogContext.java?view=diff&rev=487741&r1=487740&r2=487741
==============================================================================
--- 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/DialogContext.java
 (original)
+++ 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/DialogContext.java
 Fri Dec 15 16:51:06 2006
@@ -85,6 +85,41 @@
 
 
     /**
+     * <p>Return an opaque object containing any state information (besides the
+     * context identifier, which is already saved) that this [EMAIL PROTECTED] 
DialogContext}
+     * instance would like to have saved in the JavaServer Faces component 
tree,
+     * and then restored (via a call to <code>setOpaqueData()</code> on the
+     * subsequent form submit.  If there is no such information to be recorded,
+     * return <code>null</code>.</p>
+     *
+     * <p><strong>IMPLEMENTATION NOTE</strong> - Because this object will be
+     * stored as part of the JSF component tree, it must be 
<code>Serializable</code>.</p>
+     *
+     * <p><strong>WARNING</strong> - This method should <strong>ONLY</strong>
+     * be called by the dialog framework infrastructure.  It should
+     * <strong>NOT</strong> be called by the application.</p>
+     */
+    public Object getOpaqueState();
+
+
+    /**
+     * <p>Restore state information that was previously returned by a call to
+     * <code>getOpaqueState()</code> on this [EMAIL PROTECTED] DialogContext} 
instance.
+     * If the previous call to <code>getOpaqueState()</code> returned 
<code>null</code>,
+     * this method will <strong>NOT</strong> be called.</p>
+     *
+     * <p><strong>WARNING</strong> - This method should <strong>ONLY</strong>
+     * be called by the dialog framework infrastructure.  It should
+     * <strong>NOT</strong> be called by the application.</p>
+     *
+     * @param opaqueState The opaque state object that was previously returned
+     *  by a call to <code>getOpaqueState()</code> after potentially being
+     *  serialized and deserialized by the JSF state saving functionality
+     */
+    public void setOpaqueState(Object opaqueState);
+
+
+    /**
      * <p>Return the parent [EMAIL PROTECTED] DialogContext} instance 
associated with this
      * child [EMAIL PROTECTED] DialogContext}, if any; otherwise, return 
<code>null</code>.</p>
      *

Modified: 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/faces/DialogPhaseListener.java
URL: 
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/faces/DialogPhaseListener.java?view=diff&rev=487741&r1=487740&r2=487741
==============================================================================
--- 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/faces/DialogPhaseListener.java
 (original)
+++ 
shale/framework/trunk/shale-dialog/src/main/java/org/apache/shale/dialog/faces/DialogPhaseListener.java
 Fri Dec 15 16:51:06 2006
@@ -61,6 +61,29 @@
     }
 
 
+    // ------------------------------------------------------ Manifest 
Constants
+
+
+    /**
+     * <p>Generic attribute name (on the view root component of the current
+     * JSF component tree) under which the context identifier for the
+     * dialog instance that is current for this view (if any) should be
+     * stored and retrieved.</p>
+     */
+    private static final String CONTEXT_ID_ATTR =
+            "org.apache.shale.dialog.CONTEXT_ID";
+
+
+    /**
+     * <p>Generic attribute name (on the view root component of the current
+     * JSF component tree) under which the opaque state information for the
+     * current [EMAIL PROTECTED] DialogContext} instance (if any) should be 
stored and
+     * retrieved.</p>
+     */
+    private static final String CONTEXT_OPAQUE_ATTR =
+            "org.apache.shale.dialog.OPAQUE_STATE";
+
+
     // ------------------------------------------------------ Instance 
Variables
 
 
@@ -120,26 +143,7 @@
         }
 
         if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
-            FacesContext context = event.getFacesContext();
-            DialogContext dcontext = (DialogContext)
-              
context.getExternalContext().getRequestMap().get(Constants.CONTEXT_BEAN);
-            Map map = context.getViewRoot().getAttributes();
-            if ((dcontext != null) && dcontext.isActive()) {
-                if (log.isDebugEnabled()) {
-                    log.debug("beforePhase() saving dialog context id '"
-                              + dcontext.getId()
-                              + "' for FacesContext instance '"
-                              + context + "'");
-                }
-                map.put(Constants.CONTEXT_ID_ATTR, dcontext.getId());
-            } else {
-                if (log.isTraceEnabled()) {
-                    log.trace("beforePhase() erasing dialog context id "
-                              + " for FacesContext instance '"
-                              + context + "'");
-                }
-                map.remove(Constants.CONTEXT_ID_ATTR);
-            }
+            beforeRenderResponse(event.getFacesContext());
         }
 
     }
@@ -176,7 +180,7 @@
         // but it might also have been passed as a request parameter in
         // the case of a redirect
         String id = (String)
-          context.getViewRoot().getAttributes().get(Constants.CONTEXT_ID_ATTR);
+          context.getViewRoot().getAttributes().get(CONTEXT_ID_ATTR);
         if (id == null) {
             id = (String) 
context.getExternalContext().getRequestParameterMap().
                     get(Constants.DIALOG_ID);
@@ -207,7 +211,7 @@
             // Start the new DialogContext instance
             dcontext.start(context);
             if (log.isDebugEnabled()) {
-                log.debug("afterPhase() creating dialog context with id '"
+                log.debug("afterRestoreView() creating dialog context with id 
'"
                           + id + "' for FacesContext instance '"
                           + context + "' associated with parent dialog context 
id '"
                           + parentId + "' and advancing to viewId '"
@@ -220,6 +224,44 @@
 
 
     /**
+     * <p>Before the <em>Render Response</em> phase, acquire the current
+     * dialog identifier (if any), along with any corresponding opaque
+     * state information, and store it in the view.</p>
+     *
+     * @param context <code>FacesContext</code> for the current request
+     */
+    private void beforeRenderResponse(FacesContext context) {
+
+        DialogContext dcontext = (DialogContext)
+          
context.getExternalContext().getRequestMap().get(Constants.CONTEXT_BEAN);
+        Map map = context.getViewRoot().getAttributes();
+        if ((dcontext != null) && dcontext.isActive()) {
+            if (log.isDebugEnabled()) {
+                log.debug("beforeRenderResponse() saving dialog context id '"
+                          + dcontext.getId()
+                          + "' for FacesContext instance '"
+                          + context + "'");
+            }
+            map.put(CONTEXT_ID_ATTR, dcontext.getId());
+            Object opaqueState = dcontext.getOpaqueState();
+            if (opaqueState != null) {
+                map.put(CONTEXT_OPAQUE_ATTR, opaqueState);
+            }
+        } else {
+            if (log.isTraceEnabled()) {
+                log.trace("beforeRenderResponse() erasing dialog context id "
+                          + " for FacesContext instance '"
+                          + context + "'");
+            }
+            map.remove(CONTEXT_ID_ATTR);
+            map.remove(CONTEXT_OPAQUE_ATTR);
+        }
+
+    }
+
+
+
+    /**
      * <p>Create and return a new [EMAIL PROTECTED] DialogContext} for the 
specified
      * dialog name and optional parent id.  If no such [EMAIL PROTECTED] 
DialogContext}
      * can be created, return <code>null</code> instead.</p>
@@ -250,7 +292,8 @@
 
     /**
      * <p>Restore access to the [EMAIL PROTECTED] DialogContext} with the 
specified id,
-     * if possible.</p>
+     * if possible.  If there was any opaque state information stored, update
+     * the corresponding [EMAIL PROTECTED] DialogContext} instance as well.</p>
      *
      * @param context FacesContext for the current request
      * @param dialogId Dialog identifier of the [EMAIL PROTECTED] 
DialogContext}
@@ -274,6 +317,10 @@
                       + context + "'");
         }
         
context.getExternalContext().getRequestMap().put(Constants.CONTEXT_BEAN, 
dcontext);
+        Object opaqueState = 
context.getViewRoot().getAttributes().get(CONTEXT_OPAQUE_ATTR);
+        if (opaqueState != null) {
+            dcontext.setOpaqueState(opaqueState);
+        }
 
     }
 


Reply via email to