changeset 394:14eecfde4607

Render links to step back to previous states into gui. Added controller to advance back to these states. gnv/trunk@538 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 13 Jan 2010 22:17:02 +0000
parents d812c5b62eb4
children 79378c4babde
files gnv/ChangeLog gnv/src/main/java/de/intevation/gnv/action/NextArtifactStepAction.java gnv/src/main/java/de/intevation/gnv/action/PreviousArtifactStepAction.java gnv/src/main/java/de/intevation/gnv/action/sessionmodel/SessionModelFactory.java gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/ArtifactDatabaseClient.java gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/DefaultArtifactDatabaseClient.java gnv/src/main/java/de/intevation/gnv/util/XSLTransformer.java gnv/src/main/webapp/WEB-INF/config/struts-config.xml gnv/src/main/webapp/WEB-INF/config/templates/describe-ui-static.xsl gnv/src/main/webapp/styles/default.css
diffstat 10 files changed, 303 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/gnv/ChangeLog	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/ChangeLog	Wed Jan 13 22:17:02 2010 +0000
@@ -1,3 +1,36 @@
+2010-01-13  Ingo Weinzierl <ingo_weinzierl@web.de>
+
+	* src/main/java/de/intevation/gnv/artifactdatabase/client/ArtifactDatabaseClient.java,
+	  src/main/java/de/intevation/gnv/artifactdatabase/client/DefaultArtifactDatabaseClient.java:
+	  Added 'doAdvance' method to be able to advance only - without feed or
+	  describe. We need this method to step back to previous states. Advance was 
+	  bundled with feed and describe, before.
+
+	* src/main/java/de/intevation/gnv/action/sessionmodel/SessionModelFactory.java:
+	  Some code refactoring.
+
+	* src/main/java/de/intevation/gnv/util/XSLTransformer.java,
+	  src/main/java/de/intevation/gnv/action/NextArtifactStepAction.java: Set
+	  parameter of xsl transformer which contains the url to step back to a 
+	  previous state. This parameter is used in xsl sheet to render a
+	  link into the user interface.
+
+	* src/main/java/de/intevation/gnv/action/PreviousArtifactStepAction.java:
+	  New controller to step back to a previous state.
+
+	* src/main/webapp/WEB-INF/config/struts-config.xml: Added a new action which
+	  calls PreviousArtifactStepAction to step back to previous states.
+
+	* src/main/webapp/WEB-INF/config/templates/describe-ui-static.xsl:
+	  Refactored gui rendering. The static part of the parameter list is
+	  rendered in a table with three columns (icon to step back, parameter name,
+	  selected value). The target state to step back to is contained as
+	  attribute 'art:state' in 'xform:select', 'xfom:select1' and 'xform:group'
+	  nodes.
+
+	* src/main/webapp/styles/default.css: Added a style class to adapt the first 
+	  column of the static part's table.
+
 2009-01-13	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* src/main/webapp/WEB-INF/jsp/mainlayout.jsp: Shortened
--- a/gnv/src/main/java/de/intevation/gnv/action/NextArtifactStepAction.java	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/action/NextArtifactStepAction.java	Wed Jan 13 22:17:02 2010 +0000
@@ -106,6 +106,10 @@
                     Node currentUI = artifactDescription.getCurrentUI();
                     if (currentUI != null){
                         XSLTransformer transformer = new XSLTransformer();
+                        String url = response.encodeURL(
+                            mapping.findForward("back").getPath());
+                        transformer.addParameter("back-url", url);
+
                         Node dynamicUINode =  new XMLUtils().getNodeXPath(currentUI,"art:dynamic");
                         if (dynamicUINode != null){
                             String ui = transformer
@@ -161,6 +165,9 @@
                     Node currentUI = artifactDescription.getCurrentUI();
                     if (currentUI != null){
                         XSLTransformer transformer = new XSLTransformer();
+                        String url = response.encodeURL(
+                            mapping.findForward("back").getPath());
+                        transformer.addParameter("back-url", url);
                         Node dynamicUINode =  new XMLUtils().getNodeXPath(currentUI,"art:dynamic");
                         if (dynamicUINode != null){
                             String ui = transformer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/action/PreviousArtifactStepAction.java	Wed Jan 13 22:17:02 2010 +0000
@@ -0,0 +1,126 @@
+package de.intevation.gnv.action;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.w3c.dom.Node;
+
+import de.intevation.gnv.action.sessionmodel.SessionModel;
+import de.intevation.gnv.action.sessionmodel.SessionModelFactory;
+import de.intevation.gnv.artifactdatabase.client.ArtifactDatabaseClient;
+import de.intevation.gnv.artifactdatabase.client.ArtifactDatabaseClientFactory;
+import de.intevation.gnv.artifactdatabase.objects.ArtifactDescription;
+import de.intevation.gnv.artifactdatabase.objects.ArtifactObject;
+import de.intevation.gnv.artifactdatabase.objects.ArtifactStatisticsSet;
+import de.intevation.gnv.artifactdatabase.objects.DefaultInputParameter;
+import de.intevation.gnv.artifactdatabase.objects.InputParameter;
+import de.intevation.gnv.util.ArtifactNamespaceContext;
+import de.intevation.gnv.util.XMLUtils;
+import de.intevation.gnv.util.XSLTransformer;
+
+/**
+ * @author Ingo Weinzierl <ingo.weinzierl@intevation.de>
+ *
+ */
+public class PreviousArtifactStepAction extends ArtifactDatabaseActionBase {
+
+    public static final String XPATH_DYNAMIC_UI = "art:dynamic";
+    public static final String XPATH_STATIC_UI  = "art:static";
+
+    public static final String URL_STATE_KEY = "target";
+
+    private static Logger logger =
+        Logger.getLogger(PreviousArtifactStepAction.class);
+
+
+    public PreviousArtifactStepAction() {
+        super();
+    }
+
+
+    @Override
+    public ActionForward execute(
+        ActionMapping       mapping,
+        ActionForm          form,
+        HttpServletRequest  request,
+        HttpServletResponse response
+    ) throws Exception {
+
+        String id = request.getSession().getId();
+
+        SessionModel session =
+            SessionModelFactory.getInstance().getSessionModel(request);
+
+            // TODO check if target is reachable
+
+            ArtifactDatabaseClientFactory f =
+                ArtifactDatabaseClientFactory.getInstance();
+            ArtifactDatabaseClient client   =
+                f.getArtifactDatabaseClient(getLocale(request));
+
+            ArtifactObject artifactFactory = session.getSelectedArtifactFactory();
+            ArtifactObject currentArtifact = session.getCurrentArtifact();
+
+            String target = (String) request.getParameter(URL_STATE_KEY);
+            logger.debug("Step back to previous state: " + target);
+
+            client.doAdvance(
+                artifactFactory,
+                currentArtifact,
+                target
+            );
+
+            ArtifactDescription description = client.getCurrentStepDescription(
+                artifactFactory,
+                currentArtifact,
+                true
+            );
+
+            Node currentUI = description.getCurrentUI();
+            if (currentUI != null) {
+                XSLTransformer transformer = new XSLTransformer();
+                Node dynamicNode = (Node) XMLUtils.xpath(
+                    currentUI,
+                    XPATH_DYNAMIC_UI,
+                    XPathConstants.NODE,
+                    ArtifactNamespaceContext.INSTANCE
+                );
+
+                if (dynamicNode != null) {
+                    String dynamicUI = transformer.transform(
+                        dynamicNode, "UTF-8", request.getRealPath(
+                            "WEB-INF/config/templates/describe-ui.xsl")
+                    );
+                    request.setAttribute("ui", dynamicUI);
+                }
+
+                Node staticNode = (Node) XMLUtils.xpath(
+                    currentUI,
+                    XPATH_STATIC_UI,
+                    XPathConstants.NODE,
+                    ArtifactNamespaceContext.INSTANCE
+                );
+
+                if (staticNode != null){
+                    String staticUI = transformer.transform(
+                        staticNode, "UTF-8", request.getRealPath(
+                            "WEB-INF/config/templates/describe-ui-static.xsl")
+                    );
+                    request.setAttribute("staticui", staticUI);
+                }
+            }
+
+        return super.execute(mapping, form, request, response);
+    }
+}
--- a/gnv/src/main/java/de/intevation/gnv/action/sessionmodel/SessionModelFactory.java	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/action/sessionmodel/SessionModelFactory.java	Wed Jan 13 22:17:02 2010 +0000
@@ -36,7 +36,7 @@
      * 
      * @return an singleton Instance of this Class
      */
-    public static SessionModelFactory getInstance() {
+    public synchronized static SessionModelFactory getInstance() {
         if (instance == null) {
             instance = new SessionModelFactory();
         }
@@ -49,12 +49,11 @@
      * @return the ArtifactDatabaseClient
      */
     public SessionModel getSessionModel(HttpServletRequest request) {
-        synchronized (this.getClass()) {
+        synchronized (request) {
             SessionModel sm = null;
-            if (request.getSession().getAttribute(SESSION_MODEL_ID) != null) {
-                sm = (SessionModel) request.getSession().getAttribute(
-                        SESSION_MODEL_ID);
-                ;
+            Object obj = request.getSession().getAttribute(SESSION_MODEL_ID);
+            if (obj instanceof SessionModel) {
+                sm = (SessionModel) obj;
             } else {
                 sm = new DefaultSessionModel();
                 request.getSession().setAttribute(SESSION_MODEL_ID, sm);
--- a/gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/ArtifactDatabaseClient.java	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/ArtifactDatabaseClient.java	Wed Jan 13 22:17:02 2010 +0000
@@ -3,6 +3,7 @@
  */
 package de.intevation.gnv.artifactdatabase.client;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Collection;
 import java.util.Locale;
@@ -69,6 +70,12 @@
                                           Collection<InputParameter> inputParameter)
                                                                                     throws ArtifactDatabaseClientException;
 
+    public void doAdvance(
+        ArtifactObject factory,
+        ArtifactObject artifact,
+        String         target
+    ) throws IOException, ArtifactDatabaseClientException;
+
     /**
      * @param artifactFactory
      * @param currentArtifact
--- a/gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/DefaultArtifactDatabaseClient.java	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/artifactdatabase/client/DefaultArtifactDatabaseClient.java	Wed Jan 13 22:17:02 2010 +0000
@@ -491,20 +491,18 @@
             this.doFeed(artifactFactory, currentArtifact, inputParameter);
             
             // 2. Noch einmal Describe um das jetzt zu erreichende Ziel zu ermitteln
-            ArtifactDescription ad = this.getCurrentStepDescription(artifactFactory, 
-                                                                    new Artifact(currentArtifact.getId(), 
-                                                                                 currentArtifact.getHash()),
-                                                                    false);
+            ArtifactDescription ad = getCurrentStepDescription(
+                artifactFactory,
+                new Artifact(currentArtifact.getId(),
+                currentArtifact.getHash()),
+                false
+            );
+
             target = ad.getReachableStates().iterator().next();
             
             // 3 Advance
-            String url = this.getArtifactUrl(artifactFactory, currentArtifact);
-            Document advanceDocument = this.createAdvanceRequestBody(
-                    currentArtifact, target);
-            InputStream advanceResult = this
-                    .doPostRequest(url, advanceDocument);
-            this.check4ExceptionReport(new XMLUtils()
-                    .readDocument(advanceResult));
+            doAdvance(artifactFactory, currentArtifact, target);
+            
             // 3 Describe
             return this.getCurrentStepDescription(artifactFactory,
                     currentArtifact,true);
@@ -514,6 +512,18 @@
         }
     }
 
+
+    public void doAdvance(
+        ArtifactObject factory,
+        ArtifactObject artifact,
+        String         target
+    ) throws IOException, ArtifactDatabaseClientException {
+        String url                = getArtifactUrl(factory, artifact);
+        Document advanceDocument  = createAdvanceRequestBody(artifact, target);
+        InputStream advanceResult = doPostRequest(url, advanceDocument);
+        check4ExceptionReport(new XMLUtils().readDocument(advanceResult));
+    }
+
     private Document createFeedRequestBody(
                                            ArtifactObject currentArtifact,
                                            Collection<InputParameter> inputParameter) {
--- a/gnv/src/main/java/de/intevation/gnv/util/XSLTransformer.java	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/java/de/intevation/gnv/util/XSLTransformer.java	Wed Jan 13 22:17:02 2010 +0000
@@ -6,6 +6,9 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -17,6 +20,8 @@
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
+import de.intevation.gnv.action.sessionmodel.SessionModelFactory;
+
 import org.apache.log4j.Logger;
 import org.w3c.dom.Node;
 
@@ -30,6 +35,9 @@
      */
     private static Logger log = Logger.getLogger(XSLTransformer.class);
 
+
+    private Map<String, String> params;
+
     /**
      * Constructor
      */
@@ -46,6 +54,13 @@
             TransformerFactory xformFactory = TransformerFactory.newInstance();
             Transformer transformer = xformFactory
                     .newTransformer(templateSource);
+
+            if (params != null) {
+                for(Map.Entry<String, String> entry: params.entrySet()) {
+                    transformer.setParameter(entry.getKey(), entry.getValue());
+                }
+            }
+
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             StreamResult scrResult = new StreamResult(baos);
             // log.debug(xmlUtils.writeNode2String(toTransform));
@@ -65,4 +80,12 @@
         return resultValue;
     }
 
+
+    public void addParameter(String name, String value) {
+        if (params == null) {
+            params = new HashMap<String, String>(3);
+        }
+
+        params.put(name, value);
+    }
 }
--- a/gnv/src/main/webapp/WEB-INF/config/struts-config.xml	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/webapp/WEB-INF/config/struts-config.xml	Wed Jan 13 22:17:02 2010 +0000
@@ -33,6 +33,14 @@
                 name="success"
                 path="/WEB-INF/jsp/mainlayout.jsp"/>
         </action>
+        <action path="/back"
+                 type="de.intevation.gnv.action.PreviousArtifactStepAction"
+                 scope="request"
+                 validate="false">
+            <forward
+                name="success"
+                path="/WEB-INF/jsp/mainlayout.jsp"/>
+        </action>
         <action path="/next" 
                 type="de.intevation.gnv.action.NextArtifactStepAction"
                 scope="request"
@@ -40,6 +48,9 @@
            <forward
                 name="success"
                 path="/WEB-INF/jsp/mainlayout.jsp"/>
+            <forward
+                name="back"
+                path="/gnv/back.do"/>
         </action>
                 <action path="/out" 
                 type="de.intevation.gnv.action.DoOutputAction"
--- a/gnv/src/main/webapp/WEB-INF/config/templates/describe-ui-static.xsl	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/webapp/WEB-INF/config/templates/describe-ui-static.xsl	Wed Jan 13 22:17:02 2010 +0000
@@ -4,71 +4,85 @@
                 xmlns="http://www.w3.org/2002/xforms" 
                 xmlns:xform="http://www.w3.org/2002/xforms" 
                 xmlns:art="http://www.intevation.de/2009/artifacts">
-    <xsl:output method="html" version="1.0" encoding="UTF-8" omit-xml-declaration="no"/>
+
+    <xsl:output method="html" version="1.0" encoding="UTF-8" omit-xml-declaration="no" />
+
+    <xsl:param name="back-url"/>
+
+    <!-- start parsing document -->
+    <xsl:template match="*">
+        <table class="static">
+            <xsl:apply-templates />
+        </table>
+    </xsl:template>
+
     
+    <!-- match multi select boxes -->
     <xsl:template match="xform:select">
-        <xsl:variable name="selectName" select="@ref"/>
-            <div id="timeseriesfilter">
-                <table>
-                    <tr>
-                        <th class="parameter"><xsl:value-of select="xform:label"/>:</th>
-                        <td>
-                            <table>
-                                <xsl:apply-templates select="xform:choices/xform:item" mode="table"/>
-                            </table>
-                        </td>
-                    </tr>
-                </table>
-             </div> 
+        <xsl:variable name="state" select="@art:state" />
+        <tr>
+            <td class="historyback">
+                <xsl:if test="$state != ''">
+                    <a href="{$back-url}?target={$state}">[X]</a>
+                </xsl:if>
+            </td>
+            <th class="parameter"><xsl:value-of select="xform:label" /></th>
+            <td><xsl:apply-templates select="xform:choices" /></td>
+        </tr>
     </xsl:template>
 
 
-    <xsl:template match="xform:item" mode="table">
-        <xsl:if test="@selected = 'true'">
-            <tr>
-                <td class="value"><xsl:value-of select="./xform:label"/></td>
-            </tr>
-        </xsl:if>
-    </xsl:template>
-    
-
+    <!-- match select boxes -->
     <xsl:template match="xform:select1">
-        <xsl:variable name="selectName" select="@ref"/>
-            <div id="timeseriesfilter">
-                <table>
-                    <tr>
-                        <th class="parameter"><xsl:value-of select="xform:label"/>:</th>
-                        <td><xsl:value-of select="./xform:choices/xform:item/xform:label" /></td>
-                    </tr>
-                </table>
-             </div>
+        <xsl:variable name="state" select="@art:state" />
+        <tr>
+            <td class="historyback">
+                <xsl:if test="$state != ''">
+                    <a href="{$back-url}?target={$state}">[X]</a>
+                </xsl:if>
+            </td>
+            <th class="parameter"><xsl:value-of select="xform:label" /></th>
+            <td><xsl:apply-templates select="xform:choices" /></td>
+        </tr>
     </xsl:template>
-    
 
-    <xsl:template match="xform:group">
-        <xsl:variable name="inputName" select="xform:label"/>
-        <div id="timeseriesfilter">
-            <table>
-                <tr>
-                    <th class="parameter"><xsl:value-of select="xform:label"/>:</th>
-                    <td>
-                        <table>
-                            <xsl:apply-templates select="xform:input" mode="table"/>
-                        </table>
-                    </td>
-                </tr>
-            </table>
-        </div>
+    
+    <!-- match item list of select boxes or multi select boxes -->
+    <xsl:template match="xform:choices">
+        <table class="choices"><xsl:apply-templates select="xform:item" /></table>
     </xsl:template>
 
 
-    <xsl:template match="xform:input" mode="table">
+    <!-- match item of select boxes or multi select boxes -->
+    <xsl:template match="xform:item">
         <tr>
-            <td class="value">
-                <xsl:value-of select="./xform:label"/>&#160;<xsl:value-of select="./xform:value"/>
+            <td class="value"><xsl:value-of select="xform:label" /></td>
+        </tr>
+    </xsl:template>
+
+
+    <!-- match group items -->
+    <xsl:template match="xform:group">
+        <xsl:variable name="state" select="@art:state" />
+        <tr>
+            <td class="historyback">
+                <xsl:if test="$state != ''">
+                    <a href="{$back-url}?target={$state}">[X]</a>
+                </xsl:if>
+            </td>
+            <th class="parameter"><xsl:value-of select="xform:label" /></th>
+            <td>
+                <table><xsl:apply-templates select="xform:input" /></table>
             </td>
         </tr>
     </xsl:template>
 
 
+    <!-- match single group item -->
+    <xsl:template match="xform:input">
+        <tr>
+            <td class="value"><xsl:value-of select="xform:label" />&#160;<xsl:value-of select="xform:value" /></td>
+        </tr>
+    </xsl:template>
+
 </xsl:stylesheet>
--- a/gnv/src/main/webapp/styles/default.css	Wed Jan 13 11:29:40 2010 +0000
+++ b/gnv/src/main/webapp/styles/default.css	Wed Jan 13 22:17:02 2010 +0000
@@ -98,9 +98,14 @@
     font-size: 0.8em;
 }
 
+.historyback {
+    padding-left:   10px;
+    vertical-align: top;
+}
+
 .parameter {
     font-size:      0.8em;
-    padding-left:   10px;
+    padding-left:   5px;
     text-align:     left;
     vertical-align: top;
     width:          100px;

http://dive4elements.wald.intevation.org