Author: craigmcc
Date: Wed Dec 20 23:13:45 2006
New Revision: 489271
URL: http://svn.apache.org/viewvc?view=rev&rev=489271
Log:
Implement three strategies for dealing with the back button issues described
in SHALE-61 for saving extra state in the JSF component tree:
* "none" (default) - as before, save nothing
* "top" - save the state name of the topmost stack element, plus the stack
depth to catch cases where the user crosses subdialog boundaries
* "stack" - save the entire position stack, *including* the user data object
at each level
Need to document this on the website page, but I believe this is sufficient
support for handling back buttons in dialogs for the "basic" implementation,
for the 1.0.4 upcoming release.
Modified:
shale/framework/trunk/shale-apps/shale-test-dialog-basic/pom.xml
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/WEB-INF/web.xml
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/wizardpage2.jsp
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogContext.java
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Globals.java
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Position.java
Modified: shale/framework/trunk/shale-apps/shale-test-dialog-basic/pom.xml
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-dialog-basic/pom.xml?view=diff&rev=489271&r1=489270&r2=489271
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-dialog-basic/pom.xml (original)
+++ shale/framework/trunk/shale-apps/shale-test-dialog-basic/pom.xml Wed Dec 20
23:13:45 2006
@@ -87,6 +87,12 @@
<dependency>
<groupId>org.apache.shale</groupId>
+ <artifactId>shale-core</artifactId>
+ <version>${version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.shale</groupId>
<artifactId>shale-dialog</artifactId>
<version>${version}</version>
</dependency>
Modified:
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/WEB-INF/web.xml
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/WEB-INF/web.xml?view=diff&rev=489271&r1=489270&r2=489271
==============================================================================
---
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/WEB-INF/web.xml
(original)
+++
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/WEB-INF/web.xml
Wed Dec 20 23:13:45 2006
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -18,12 +17,7 @@
$Id$
-->
-
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Display name for this application -->
<display-name>Shale Test App (Dialog Basic Implementation)</display-name>
@@ -47,6 +41,12 @@
<param-value>/WEB-INF/dialog-config.xml</param-value>
</context-param>
-->
+
+ <context-param>
+ <description>Strategy for saving dialog-specific state across
requests.</description>
+ <param-name>org.apache.shale.dialog.basic.STRATEGY</param-name>
+ <param-value>top</param-value>
+ </context-param>
<!-- JavaServer Faces Servlet Configuration -->
<servlet>
Modified:
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/wizardpage2.jsp
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/wizardpage2.jsp?view=diff&rev=489271&r1=489270&r2=489271
==============================================================================
---
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/wizardpage2.jsp
(original)
+++
shale/framework/trunk/shale-apps/shale-test-dialog-basic/src/main/webapp/wizardpage2.jsp
Wed Dec 20 23:13:45 2006
@@ -21,6 +21,7 @@
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
+<%@ taglib prefix="s" uri="http://shale.apache.org/core" %>
<f:view>
<html>
@@ -84,6 +85,11 @@
<%-- FIXME - add parameters to the above URL --%>
</h:panelGroup>
<h:message for="zipCode"/>
+
+ <h:outputText value=""/>
+ <s:token id="token"/>
+ <h:message id="message"
+ for="token"/>
<h:outputText value=""/>
<h:panelGroup>
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=489271&r1=489270&r2=489271
==============================================================================
---
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
Wed Dec 20 23:13:45 2006
@@ -165,6 +165,14 @@
/**
+ * <p>The strategy identifier for dealing with saving and restoring
+ * state information across requests. This value is lazily
+ * instantiated, and can be recalculated on demand as needed.</p>
+ */
+ private transient String strategy = null;
+
+
+ /**
* <p>An empty parameter list to pass to the action method called by
* a method binding expression.</p>
*/
@@ -259,7 +267,22 @@
/** [EMAIL PROTECTED] */
public Object getOpaqueState() {
- return null; // Do not do anything yet, just fulfill the API contract
+ if ("top".equals(strategy())) {
+ if (log().isInfoEnabled()) {
+ log().info("getOpaqueState<top> returns " + new
TopState(peek().getState().getName(), positions.size()));
+ }
+ return new TopState(peek().getState().getName(), positions.size());
+ } else if ("stack".equals(strategy())) {
+ if (log().isInfoEnabled()) {
+ log().info("getOpaqueStrategy<stack> returns stack of " +
positions.size());
+ }
+ return positions;
+ } else {
+ if (log().isInfoEnabled()) {
+ log().info("getOpaqueStrategy<none> returns nothing");
+ }
+ return null;
+ }
}
@@ -267,7 +290,29 @@
/** [EMAIL PROTECTED] */
public void setOpaqueState(Object opaqueState) {
- ; // Do not do anything yet, just fulfill the API contract
+ if ("top".equals(strategy())) {
+ TopState topState = (TopState) opaqueState;
+ if (log().isInfoEnabled()) {
+ log().info("setOpaqueState<top> restores " + topState);
+ }
+ if (topState.stackDepth != positions.size()) {
+ throw new IllegalStateException("Restored stack depth expects "
+ + positions.size() + " but is actually "
+ + topState.stackDepth);
+ }
+ Position top = peek();
+ top.setState(top.getDialog().findState(topState.stateName));
+ } else if ("stack".equals(strategy())) {
+ if (log().isInfoEnabled()) {
+ log().info("setOpaqueState<stack> restores stack of " +
((List) opaqueState).size());
+ }
+ positions = (List) opaqueState;
+ } else {
+ if (log().isInfoEnabled()) {
+ log().info("setOpaqueState<none> restores nothing");
+ }
+ ; // Do nothing
+ }
}
@@ -668,6 +713,25 @@
/**
+ * <p>Return the strategy identifier for dealing with saving state
+ * information across requests.</p>
+ */
+ private String strategy() {
+
+ if (this.strategy == null) {
+ this.strategy =
FacesContext.getCurrentInstance().getExternalContext().getInitParameter(Globals.STRATEGY);
+ if (this.strategy == null) {
+ this.strategy = "none";
+ } else {
+ this.strategy = this.strategy.toLowerCase();
+ }
+ }
+ return this.strategy;
+
+ }
+
+
+ /**
* <p>Transition the specified [EMAIL PROTECTED] Position}, based on the
specified
* logical outcome, to the appropriate next [EMAIL PROTECTED] State}.</p>
*
@@ -719,6 +783,65 @@
fireOnEntry(toStateId);
}
+
+
+ // ------------------------------------------------ State Storage
Subclasses
+
+
+ /**
+ * <p>Class that represents the saved opaque state information when the
+ * <code>top</code> strategy is selected.</p>
+ */
+ public class TopState implements Serializable {
+
+ /**
+ * <p>Construct an uninitialized instance of this state class.</p>
+ */
+ public TopState() {
+ ;
+ }
+
+
+ /**
+ * <p>Construct an initialized instance of this state class.</p>
+ *
+ * @param stateName Name of the current state in the topmost position
+ * @param stackDepth Depth of the position stack
+ */
+ public TopState(String stateName, int stackDepth) {
+ this.stateName = stateName;
+ this.stackDepth = stackDepth;
+ }
+
+
+ /**
+ * <p>The name of the current state within the topmost
+ * <code>Position</code> on the stack.</p>
+ */
+ public String stateName;
+
+
+ /**
+ * <p>The stack depth of the <code>Position</code> stack. This is
+ * used to detect scenarios where using the back and forward buttons
+ * navigates across a subdialog boundary, which means that the
+ * saved <code>stateName</code> is likely no longer relevant.</p>
+ */
+ public int stackDepth;
+
+
+ /**
+ * <p>Return a string representation of this instance.</p>
+ */
+ public String toString() {
+ return "TopState[stateName=" + this.stateName
+ + ", stackDepth=" + this.stackDepth + "]";
+ }
+
+
+
+ }
+
}
Modified:
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Globals.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Globals.java?view=diff&rev=489271&r1=489270&r2=489271
==============================================================================
---
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Globals.java
(original)
+++
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Globals.java
Wed Dec 20 23:13:45 2006
@@ -43,4 +43,25 @@
"org.apache.shale.dialog.basic.DIALOGS";
+ /**
+ * <p>Context initialization parameter name under which a strategy name
+ * for dealing with saving and restoring dialog context state information
+ * is specified. Valid values are:</p>
+ * <ul>
+ * <li><code>none</code> - No extra information is stored (default).</li>
+ * <li><code>top</code> - Information from the top-most [EMAIL PROTECTED]
Position}
+ * on the stack, plus enough information to detect crossing a subdialog
+ * boundary. Such a case will cause an exception to be thrown.</li>
+ * <li><code>stack</code> - The entire stack of [EMAIL PROTECTED]
Position}s, including
+ * the corresponding data objects.<li>
+ * </ul>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - The feature set supported by
+ * this context initialization parameter is experimental, and no guarantees
+ * of backwards compatibility in future versions should be assumed.</p>
+ */
+ public static final String STRATEGY =
+ "org.apache.shale.dialog.basic.STRATEGY";
+
+
}
Modified:
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Position.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Position.java?view=diff&rev=489271&r1=489270&r2=489271
==============================================================================
---
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Position.java
(original)
+++
shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/Position.java
Wed Dec 20 23:13:45 2006
@@ -160,6 +160,13 @@
* @return The current [EMAIL PROTECTED] State} within the owning [EMAIL
PROTECTED] Dialog}
*/
State getState() {
+ if (this.state == null) {
+ Dialog dialog = getDialog();
+ if (dialog == null) {
+ return null;
+ }
+ this.state = dialog.findState(this.stateName);
+ }
return this.state;
}