changeset 32:88c530c25968

Added a service for the ADVANCE operation and a service that bundles FEED and ADVANCE in a single service. flys-client/trunk@1451 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 10 Mar 2011 10:53:41 +0000
parents e8745ca02f2b
children e29658e2623a
files flys-client/ChangeLog flys-client/src/main/java/de/intevation/flys/client/client/services/AdvanceService.java flys-client/src/main/java/de/intevation/flys/client/client/services/AdvanceServiceAsync.java flys-client/src/main/java/de/intevation/flys/client/client/services/StepForwardService.java flys-client/src/main/java/de/intevation/flys/client/client/services/StepForwardServiceAsync.java flys-client/src/main/java/de/intevation/flys/client/client/ui/CollectionView.java flys-client/src/main/java/de/intevation/flys/client/server/AdvanceServiceImpl.java flys-client/src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java flys-client/src/main/java/de/intevation/flys/client/server/StepForwardServiceImpl.java flys-client/src/main/webapp/WEB-INF/web.xml
diffstat 10 files changed, 419 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/flys-client/ChangeLog	Wed Mar 09 09:51:02 2011 +0000
+++ b/flys-client/ChangeLog	Thu Mar 10 10:53:41 2011 +0000
@@ -1,3 +1,26 @@
+2011-03-10  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/client/client/services/StepForwardServiceAsync.java,
+	  src/main/java/de/intevation/flys/client/client/services/StepForwardService.java,
+	  src/main/java/de/intevation/flys/client/server/StepForwardServiceImpl.java:
+	  New. This service bundles the artifact operations feed() and advance()
+	  into a single service.
+
+	* src/main/java/de/intevation/flys/client/client/services/AdvanceServiceAsync.java,
+	  src/main/java/de/intevation/flys/client/client/services/AdvanceService.java,
+	  src/main/java/de/intevation/flys/client/server/AdvanceServiceImpl.java:
+	  New. This service provides a method that triggers the advance() operation
+	  of the artifact server.
+
+	* src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java:
+	  Added code to parse the reachable states from DESCRIBE.
+
+	* src/main/java/de/intevation/flys/client/client/ui/CollectionView.java:
+	  Make use of the 'forward' service after choosing the module and the river.
+
+	* src/main/webapp/WEB-INF/web.xml: Registered the new services 'forward' and
+	  'advance'.
+
 2011-03-09  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/test/java/de/intevation/flys/client/FLYSJUnit.gwt.xml,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/AdvanceService.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,27 @@
+package de.intevation.flys.client.client.services;
+
+import com.google.gwt.user.client.rpc.RemoteService;
+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
+
+import de.intevation.flys.client.shared.model.Artifact;
+
+/**
+ * This interface provides artifact specific operation ADVANCE.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+@RemoteServiceRelativePath("advance")
+public interface AdvanceService extends RemoteService {
+
+    /**
+     * This method inserts new data into the an existing artifact.
+     *
+     * @param serverUrl The url of the artifact server.
+     * @param artifact The artifact.
+     * @param target The identifier of the target state.
+     *
+     * @return the artifact which description might have been changed.
+     */
+    public Artifact advance(String serverUrl, Artifact artifact, String target);
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/AdvanceServiceAsync.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,21 @@
+package de.intevation.flys.client.client.services;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import de.intevation.flys.client.shared.model.Artifact;
+
+
+/**
+ * This interface provides artifact specific operation ADVANCE.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public interface AdvanceServiceAsync {
+
+    public void advance(
+        String                  serverUrl,
+        Artifact                artifact,
+        String                  target,
+        AsyncCallback<Artifact> callback);
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/StepForwardService.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,28 @@
+package de.intevation.flys.client.client.services;
+
+import com.google.gwt.user.client.rpc.RemoteService;
+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
+
+import de.intevation.flys.client.shared.model.Artifact;
+import de.intevation.flys.client.shared.model.Data;
+
+/**
+ * This interface provides artifact specific operation FEED.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+@RemoteServiceRelativePath("forward")
+public interface StepForwardService extends RemoteService {
+
+    /**
+     * This method inserts new data into the an existing artifact.
+     *
+     * @param serverUrl The url of the artifact server.
+     * @param artifact The artifact.
+     * @param data The data that should be inserted.
+     *
+     * @return the artifact which description might have been changed.
+     */
+    public Artifact go(String serverUrl, Artifact artifact, Data[] data);
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/StepForwardServiceAsync.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,22 @@
+package de.intevation.flys.client.client.services;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import de.intevation.flys.client.shared.model.Artifact;
+import de.intevation.flys.client.shared.model.Data;
+
+
+/**
+ * This interface provides artifact specific operation FEED.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public interface StepForwardServiceAsync {
+
+    public void go(
+        String                  serverUrl,
+        Artifact                artifact,
+        Data[]                  data,
+        AsyncCallback<Artifact> callback);
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/CollectionView.java	Wed Mar 09 09:51:02 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/CollectionView.java	Thu Mar 10 10:53:41 2011 +0000
@@ -8,12 +8,7 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
 import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.IButton;
 import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
 import com.smartgwt.client.widgets.layout.Layout;
 import com.smartgwt.client.widgets.layout.VLayout;
 import com.smartgwt.client.widgets.tab.Tab;
@@ -26,7 +21,6 @@
 import de.intevation.flys.client.shared.model.DataItem;
 import de.intevation.flys.client.shared.model.DefaultData;
 import de.intevation.flys.client.shared.model.DefaultDataItem;
-import de.intevation.flys.client.shared.model.DefaultCollection;
 import de.intevation.flys.client.shared.model.River;
 
 import de.intevation.flys.client.client.Config;
@@ -40,6 +34,8 @@
 import de.intevation.flys.client.client.event.CollectionChangeHandler;
 import de.intevation.flys.client.client.services.ArtifactService;
 import de.intevation.flys.client.client.services.ArtifactServiceAsync;
+import de.intevation.flys.client.client.services.StepForwardService;
+import de.intevation.flys.client.client.services.StepForwardServiceAsync;
 import de.intevation.flys.client.client.services.CreateCollectionService;
 import de.intevation.flys.client.client.services.CreateCollectionServiceAsync;
 import de.intevation.flys.client.client.ui.ModuleSelection;
@@ -57,6 +53,10 @@
     protected ArtifactServiceAsync artifactService =
         GWT.create(ArtifactService.class);
 
+    /** The StepForwardService used to put data into an existing artifact. */
+    protected StepForwardServiceAsync forwardService =
+        GWT.create(StepForwardService.class);
+
     /** The ArtifactService used to communicate with the Artifact server. */
     protected CreateCollectionServiceAsync createCollectionService =
         GWT.create(CreateCollectionService.class);
@@ -240,7 +240,8 @@
                 String module = moduleItems[0].getStringValue();
                 String river  = riversItems[0].getStringValue();
 
-                String serverUrl = Config.getInstance().getServerUrl();
+                final String serverUrl = Config.getInstance().getServerUrl();
+                final Data[] feedData  = new Data[] { data[1] };
                 artifactService.create(
                     serverUrl, module.toLowerCase(),
                     new AsyncCallback<Artifact>() {
@@ -253,7 +254,18 @@
                             GWT.log("Successfully created a new artifact.");
                             setArtifact(artifact);
 
-                            GWT.log("TODO: FEED WITH RIVER!");
+                            forwardService.go(serverUrl, artifact, feedData,
+                            new AsyncCallback<Artifact>() {
+                                public void onFailure(Throwable caught) {
+                                    GWT.log("Could not feed the artifact.");
+                                    GWT.log(caught.getMessage());
+                                }
+
+                                public void onSuccess(Artifact artifact) {
+                                    GWT.log("Successfully feed the artifact.");
+                                    setArtifact(artifact);
+                                }
+                            });
                         }
                 });
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/server/AdvanceServiceImpl.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,70 @@
+package de.intevation.flys.client.server;
+
+import org.w3c.dom.Document;
+
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+import de.intevation.artifacts.common.ArtifactNamespaceContext;
+import de.intevation.artifacts.common.utils.ClientProtocolUtils;
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import de.intevation.artifacts.httpclient.exceptions.ConnectionException;
+import de.intevation.artifacts.httpclient.http.HttpClient;
+import de.intevation.artifacts.httpclient.http.HttpClientImpl;
+import de.intevation.artifacts.httpclient.http.response.DocumentResponseHandler;
+
+import de.intevation.flys.client.shared.model.Artifact;
+import de.intevation.flys.client.client.services.AdvanceService;
+
+
+/**
+ * This interface provides artifact specific operation ADVANCE.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class AdvanceServiceImpl
+extends      RemoteServiceServlet
+implements   AdvanceService
+{
+    public static final String XPATH_RESULT = "/art:result/text()";
+
+    public static final String OPERATION_FAILURE = "FAILED";
+
+
+    public Artifact advance(String serverUrl, Artifact artifact, String target){
+        Document advance = ClientProtocolUtils.newAdvanceDocument(
+            artifact.getUuid(),
+            artifact.getHash(),
+            target);
+
+        HttpClient client = new HttpClientImpl(serverUrl);
+
+        try {
+            Document description = (Document) client.advance(
+                new de.intevation.artifacts.httpclient.objects.Artifact(
+                    artifact.getUuid(),
+                    artifact.getHash()),
+                advance,
+                new DocumentResponseHandler());
+
+            if (description == null) {
+                return null;
+            }
+
+            String result = XMLUtils.xpathString(
+                description,
+                XPATH_RESULT,
+                ArtifactNamespaceContext.INSTANCE);
+
+            if (result == null || !result.equals(OPERATION_FAILURE)) {
+                return (Artifact) new FLYSArtifactCreator().create(description);
+            }
+        }
+        catch (ConnectionException ce) {
+            System.err.println(ce.getLocalizedMessage());
+        }
+
+        return null;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java	Wed Mar 09 09:51:02 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java	Thu Mar 10 10:53:41 2011 +0000
@@ -35,6 +35,8 @@
 
     public static final String XPATH_UIPROVIDER = "@art:uiprovider";
 
+    public static final String XPATH_REACHABLE_STATE = "art:state";
+
     /**
      * This method creates the {@link ArtifactDescription} of the DESCRIBE
      * document <i>doc</i>.
@@ -49,6 +51,7 @@
         Node currentState = ClientProtocolUtils.getCurrentState(doc);
         Node staticNode   = ClientProtocolUtils.getStaticUI(doc);
         Node dynamicNode  = ClientProtocolUtils.getDynamicUI(doc);
+        Node reachable    = ClientProtocolUtils.getReachableStates(doc);
 
         String state = (String) XMLUtils.xpath(
             currentState,
@@ -58,9 +61,10 @@
         System.out.println("Current state name: " + state);
 
         Data currentData = extractCurrentData(dynamicNode);
+        String[] states  = extractReachableStates(reachable);
 
         // TODO parse the static ui part
-        return new DefaultArtifactDescription(null, currentData, state, null);
+        return new DefaultArtifactDescription(null, currentData, state, states);
     }
 
 
@@ -134,5 +138,42 @@
             XPathConstants.STRING,
             ArtifactNamespaceContext.INSTANCE);
     }
+
+
+    /**
+     * This method extracts the reachable states of the current artifact.
+     *
+     * @param reachable The reachable states node.
+     *
+     * @return an array with identifiers of reachable states.
+     */
+    protected static String[] extractReachableStates(Node reachable) {
+        System.out.println("ArtifactDescriptionFactory - extractReachableStates()");
+
+        NodeList list = (NodeList) XMLUtils.xpath(
+            reachable,
+            XPATH_REACHABLE_STATE,
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        if (list == null || list.getLength() == 0) {
+            return null;
+        }
+
+        int count = list.getLength();
+
+        String[] states = new String[count];
+
+        for (int i = 0; i < count; i++) {
+            Node state = list.item(i);
+
+            String name = XMLUtils.xpathString(
+                state, "@art:name", ArtifactNamespaceContext.INSTANCE);
+
+            states[i] = name;
+        }
+
+        return states;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/server/StepForwardServiceImpl.java	Thu Mar 10 10:53:41 2011 +0000
@@ -0,0 +1,146 @@
+package de.intevation.flys.client.server;
+
+import org.w3c.dom.Document;
+
+import de.intevation.artifacts.common.ArtifactNamespaceContext;
+import de.intevation.artifacts.common.utils.ClientProtocolUtils;
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import de.intevation.artifacts.httpclient.exceptions.ConnectionException;
+import de.intevation.artifacts.httpclient.http.HttpClient;
+import de.intevation.artifacts.httpclient.http.HttpClientImpl;
+import de.intevation.artifacts.httpclient.http.response.DocumentResponseHandler;
+
+import de.intevation.flys.client.shared.model.Artifact;
+import de.intevation.flys.client.shared.model.ArtifactDescription;
+import de.intevation.flys.client.shared.model.Data;
+import de.intevation.flys.client.shared.model.DataItem;
+import de.intevation.flys.client.client.services.StepForwardService;
+
+
+/**
+ * This interface provides a method that bundles the artifact specific
+ * operations FEED and ADVANCE.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class StepForwardServiceImpl
+extends      AdvanceServiceImpl
+implements   StepForwardService
+{
+    /** XPath that points to the result text of a feed or advance operation.*/
+    public static final String XPATH_RESULT = "/art:result/text()";
+
+    /** A constant that marks errors.*/
+    public static final String OPERATION_FAILURE = "FAILED";
+
+
+    /**
+     * This method wraps the artifact operations FEED and ADVANCE. FEED is
+     * always triggerd, ADVANCE only, if there is at least one reachable state.
+     *
+     * @param serverUrl The url of the artifact server.
+     * @param artifact The artifact that needs to be fed.
+     * @param data An array of Data objects that contain the information that
+     *
+     * @return the modified artifact.
+     */
+    public Artifact go(String serverUrl, Artifact artifact, Data[] data) {
+        Artifact afterFeed = feed(serverUrl, artifact, data);
+
+        if (afterFeed == null) {
+            System.err.println("StepForwardService.feed() - FAILED");
+            // XXX Better handling here!
+            return null;
+        }
+
+        ArtifactDescription desc = afterFeed.getArtifactDescription();
+        String[] reachable       = desc.getReachableStates();
+
+        if (reachable == null || reachable.length == 0) {
+            System.out.println("Did not find any reachable state.");
+            return afterFeed;
+        }
+
+        // We use the first reachable state as default target, maybe we need to
+        // change this later.
+        return advance(serverUrl, afterFeed, reachable[0]);
+    }
+
+
+    /**
+     * This method triggers the FEED operation.
+     *
+     * @param serverUrl The url of the artifact server.
+     * @param artifact The artifact that needs to be fed.
+     * @param data An array of Data objects that contain the information that
+     * are used for the FEED operation.
+     *
+     * @return a new artifact parsed from the description of FEED.
+     */
+    protected Artifact feed(String serverUrl, Artifact artifact, Data[] data) {
+        Document feed = ClientProtocolUtils.newFeedDocument(
+            artifact.getUuid(),
+            artifact.getHash(),
+            createKVP(data));
+
+        HttpClient client = new HttpClientImpl(serverUrl);
+
+        try {
+            Document description = (Document) client.feed(
+                new de.intevation.artifacts.httpclient.objects.Artifact(
+                    artifact.getUuid(),
+                    artifact.getHash()),
+                feed,
+                new DocumentResponseHandler());
+
+            if (description == null) {
+                System.err.println("StepForwardService.feed() - FAILED");
+                return artifact;
+            }
+
+            String result = XMLUtils.xpathString(
+                description,
+                XPATH_RESULT,
+                ArtifactNamespaceContext.INSTANCE);
+
+            if (result == null || !result.equals(OPERATION_FAILURE)) {
+                System.out.println("StepForwardService.feed() - SUCCESS");
+                return (Artifact) new FLYSArtifactCreator().create(description);
+            }
+        }
+        catch (ConnectionException ce) {
+            System.err.println(ce.getLocalizedMessage());
+        }
+
+        System.err.println("StepForwardService.feed() - FAILED");
+
+        return artifact;
+    }
+
+
+    /**
+     * This method creates an array of key/value pairs from an array of Data
+     * objects. The string array is used as parameter for the feed() operation.
+     *
+     * @param data The data that should be transformed into the string array.
+     *
+     * @return a string array that contains key/value pairs.
+     */
+    protected String[][] createKVP(Data[] data) {
+        String[][] kvp = new String[data.length][];
+
+        int i = 0;
+
+        for (Data d: data) {
+            DataItem[] items = d.getItems();
+            String key       = d.getLabel();
+            String value     = items[0].getStringValue();
+
+            kvp[i++] = new String[] { key, value };
+        }
+
+        return kvp;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/webapp/WEB-INF/web.xml	Wed Mar 09 09:51:02 2011 +0000
+++ b/flys-client/src/main/webapp/WEB-INF/web.xml	Thu Mar 10 10:53:41 2011 +0000
@@ -46,6 +46,26 @@
     <url-pattern>/flys/rivers</url-pattern>
   </servlet-mapping>
 
+  <servlet>
+    <servlet-name>forward</servlet-name>
+    <servlet-class>de.intevation.flys.client.server.StepForwardServiceImpl</servlet-class>
+  </servlet>
+  
+  <servlet-mapping>
+    <servlet-name>forward</servlet-name>
+    <url-pattern>/flys/forward</url-pattern>
+  </servlet-mapping>
+
+  <servlet>
+    <servlet-name>advance</servlet-name>
+    <servlet-class>de.intevation.flys.client.server.AdvanceServiceImpl</servlet-class>
+  </servlet>
+  
+  <servlet-mapping>
+    <servlet-name>advance</servlet-name>
+    <url-pattern>/flys/advance</url-pattern>
+  </servlet-mapping>
+
   <!-- Default page to serve -->
   <welcome-file-list>
     <welcome-file>FLYS.html</welcome-file>

http://dive4elements.wald.intevation.org