changeset 1402:15ef3d3081b7

Parse GetFeatureInfo response on our own and display resulting FeatureInfo objects in the GetFeatureInfoWindow. flys-client/trunk@3287 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Fri, 18 Nov 2011 11:39:10 +0000
parents 047a44270348
children 6a7cfe9d87fe
files flys-client/ChangeLog flys-client/src/main/java/de/intevation/flys/client/client/services/GFIService.java flys-client/src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfo.java flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java flys-client/src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java flys-client/src/main/java/de/intevation/flys/client/shared/model/FeatureInfo.java flys-client/src/main/webapp/FLYS.css
diffstat 8 files changed, 221 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/flys-client/ChangeLog	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/ChangeLog	Fri Nov 18 11:39:10 2011 +0000
@@ -1,3 +1,27 @@
+2011-11-18  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/client/shared/model/FeatureInfo.java:
+	  New. This object is used to store information retrieved by a
+	  GetFeatureInfo response. A FeatureInfo object consists of a layername
+	  and an attribute map.
+
+	* src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java,
+	  src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java,
+	  src/main/java/de/intevation/flys/client/client/services/GFIService.java:
+	  Modified the return value of this service. It will now return a list of
+	  FeatureInfo objects. This list is parsed from GetFeatureInfo response on
+	  our own. Relevant attributes of a feature are extracted.
+
+	* src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfo.java:
+	  Adjusted the return value of GFIService.
+
+	* src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java:
+	  Takes a list of FeatureInfo. Each FeatureInfo object is displayed in a
+	  row which contains all the attributes of the object.
+
+	* src/main/webapp/FLYS.css: Added a style class for the GetFeatureInfo
+	  response row displayed in GetFeatureInfoWindow.
+
 2011-11-17  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java,
--- a/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIService.java	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIService.java	Fri Nov 18 11:39:10 2011 +0000
@@ -7,13 +7,14 @@
 
 
 import de.intevation.flys.client.shared.exceptions.ServerException;
+import de.intevation.flys.client.shared.model.FeatureInfo;
 import de.intevation.flys.client.shared.model.Theme;
 
 
 @RemoteServiceRelativePath("getfeatureinfo")
 public interface GFIService extends RemoteService {
 
-    public String query(
+    public List<FeatureInfo> query(
         List<Theme> themes,
         String      format,
         String      bbox,
--- a/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java	Fri Nov 18 11:39:10 2011 +0000
@@ -4,7 +4,7 @@
 
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
-
+import de.intevation.flys.client.shared.model.FeatureInfo;
 import de.intevation.flys.client.shared.model.Theme;
 
 
@@ -22,7 +22,7 @@
         int                   width,
         int                   x,
         int                   y,
-        AsyncCallback<String> callback
+        AsyncCallback<List<FeatureInfo>> 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/map/GetFeatureInfo.java	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfo.java	Fri Nov 18 11:39:10 2011 +0000
@@ -12,6 +12,7 @@
 import org.gwtopenmaps.openlayers.client.Pixel;
 import org.gwtopenmaps.openlayers.client.event.MapClickListener;
 
+import de.intevation.flys.client.shared.model.FeatureInfo;
 import de.intevation.flys.client.shared.model.Theme;
 
 import de.intevation.flys.client.client.FLYSConstants;
@@ -66,13 +67,13 @@
             (int) map.getSize().getHeight(),
             (int) map.getSize().getWidth(),
             pixel.x(), pixel.y(),
-            new AsyncCallback<String>() {
+            new AsyncCallback<List<FeatureInfo>>() {
             public void onFailure(Throwable e) {
                 SC.warn(MSG.getString(e.getMessage()));
             }
 
-            public void onSuccess(String response) {
-                new GetFeatureInfoWindow(response).show();
+            public void onSuccess(List<FeatureInfo> features) {
+                new GetFeatureInfoWindow(features).show();
             }
         });
     }
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java	Fri Nov 18 11:39:10 2011 +0000
@@ -1,5 +1,9 @@
 package de.intevation.flys.client.client.ui.map;
 
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import com.google.gwt.core.client.GWT;
 
 import com.smartgwt.client.widgets.Label;
@@ -8,10 +12,11 @@
 import com.smartgwt.client.widgets.layout.VLayout;
 
 import org.gwtopenmaps.openlayers.client.feature.VectorFeature;
-import org.gwtopenmaps.openlayers.client.format.GML;
 import org.gwtopenmaps.openlayers.client.util.Attributes;
 import org.gwtopenmaps.openlayers.client.util.JSObject;
 
+import de.intevation.flys.client.shared.model.FeatureInfo;
+
 import de.intevation.flys.client.client.FLYSConstants;
 
 
@@ -19,12 +24,16 @@
 
     protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
-    protected VectorFeature[] features;
+    protected List<FeatureInfo> features;
 
 
-    public GetFeatureInfoWindow(String gml) {
+    public static final int ROW_HEIGHT = 25;
+
+
+    public GetFeatureInfoWindow(List<FeatureInfo> features) {
         super();
-        features = new GML().read(gml);
+        this.features = features;
+
         initLayout();
     }
 
@@ -32,31 +41,41 @@
     protected void initLayout() {
         VLayout root = new VLayout();
 
-        for (VectorFeature feature: features) {
+        int rows = 0;
+
+        for (FeatureInfo feature: features) {
             root.addMember(createFeatureRow(feature));
+            rows++;
         }
 
         addItem(root);
 
         setWidth(400);
-        setHeight(200);
+        setHeight(50 + rows * ROW_HEIGHT);
         setTitle(MSG.getFeatureInfoWindowTitle());
 
         centerInPage();
     }
 
 
-    protected HLayout createFeatureRow(VectorFeature feature) {
+    protected HLayout createFeatureRow(FeatureInfo feature) {
         HLayout r = new HLayout();
-        r.setHeight(25);
+        r.setHeight(ROW_HEIGHT);
+        r.setStyleName("featureinfo-row");
 
-        String[][] attrs = extractProperties(feature);
+        Label l = new Label("Layer: " + feature.getLayername());
+        l.setHeight(ROW_HEIGHT);
 
-        for (String[] attr: attrs) {
-            Label l = new Label(attr[0] + ": " + attr[1]);
-            l.setHeight(25);
-            l.setBorder("1px solid black");
-            r.addMember(l);
+        r.addMember(l);
+
+        Map<String, String> attrs = feature.getAttrs();
+        Set<Map.Entry<String, String>> entries = attrs.entrySet();
+
+        for (Map.Entry entry: entries) {
+            Label attr = new Label(entry.getKey() + ": " + entry.getValue());
+            attr.setHeight(ROW_HEIGHT);
+
+            r.addMember(attr);
         }
 
         return r;
--- a/flys-client/src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java	Fri Nov 18 11:39:10 2011 +0000
@@ -7,15 +7,22 @@
 import java.io.StringWriter;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.ArrayList;
 import java.util.List;
 
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
 import org.apache.log4j.Logger;
 
 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
 
+import de.intevation.artifacts.common.utils.XMLUtils;
 
 import de.intevation.flys.client.shared.exceptions.ServerException;
 import de.intevation.flys.client.shared.model.AttributedTheme;
+import de.intevation.flys.client.shared.model.FeatureInfo;
 import de.intevation.flys.client.shared.model.Theme;
 
 import de.intevation.flys.client.client.services.GFIService;
@@ -53,7 +60,7 @@
      *
      * @return
      */
-    public String query(
+    public List<FeatureInfo> query(
         List<Theme> themes,
         String      format,
         String      bbox,
@@ -68,6 +75,7 @@
 
         String path = createGetFeautureInfoURL(
             themes, format, bbox, projection, height, width, x, y);
+
         logger.debug("URL=" + path);
 
         try {
@@ -78,7 +86,7 @@
 
             InputStream is = conn.getInputStream();
 
-            return getResponseText(is);
+            return parseResponse(is);
 
         }
         catch (IOException ioe) {
@@ -89,51 +97,6 @@
     }
 
 
-    protected String getResponseText(InputStream is)
-    throws ServerException {
-        BufferedReader reader = null;
-        StringWriter   writer = new StringWriter();
-
-        try {
-            reader = new BufferedReader(new InputStreamReader(is));
-
-            String line = null;
-
-            if (reader.ready()) {
-                while ((line = reader.readLine()) != null) {
-                    String test = line.trim();
-                    if (test.startsWith("<") && !test.startsWith("</") 
-                        && test.indexOf("_feature") > 0)
-                    {
-                        writer.append("<gml:featureMember>");
-                    }
-                    writer.append(line);
-
-                    if (test.startsWith("</") && test.indexOf("_feature") > 0) {
-                        writer.append("</gml:featureMember>");
-                    }
-                }
-            }
-        }
-        catch (IOException ioe) {
-            logger.warn(ioe, ioe);
-            throw new ServerException(ERR_PARSING_RESPONSE_FAILED);
-        }
-        finally {
-            if (reader != null) {
-                try {
-                    reader.close();
-                }
-                catch (IOException ioe) {
-                    // do nothing here
-                }
-            }
-        }
-
-        return writer.toString();
-    }
-
-
     /**
      * @param map
      * @param themes
@@ -220,5 +183,97 @@
 
         return sb.toString();
     }
+
+
+    protected List<FeatureInfo> parseResponse(InputStream is) {
+        logger.debug("GFIServiceImpl.parseResponse");
+
+        Document response = XMLUtils.parseDocument(is);
+
+        List<FeatureInfo> features = new ArrayList<FeatureInfo>();
+
+        parseFeatureInfos(response, features);
+
+        return features;
+    }
+
+
+    protected void parseFeatureInfos(Node node, List<FeatureInfo> features) {
+        logger.debug("GFIServiceImpl.parseFeatureInfos");
+
+        String name = node.getNodeName();
+
+        if (name.endsWith("_layer")) {
+            features.add(parseFeature(node));
+
+            return;
+        }
+
+        NodeList children = node.getChildNodes();
+
+        if (children != null && children.getLength() > 0) {
+            for (int i = 0, n = children.getLength(); i < n; i++) {
+                parseFeatureInfos(children.item(i), features);
+            }
+        }
+    }
+
+
+    protected FeatureInfo parseFeature(Node node) {
+        logger.debug("GFIServiceImpl.parseFeature");
+
+        String layername = node.getNodeName();
+
+        FeatureInfo f = new FeatureInfo(layername);
+
+        NodeList children = node.getChildNodes();
+        int numChildren   = children != null ? children.getLength() : 0;
+
+        logger.debug("Feature '" + layername + "' has " + numChildren + " nodes.");
+
+        for (int i = 0; i < numChildren; i++) {
+            Node  tmp       = children.item(i);
+            String nodeName = tmp.getNodeName();
+
+            logger.debug("   node name: '" + nodeName + "'");
+
+            if (nodeName.equals("gml:name")) {
+                logger.debug("NAME node has child: " + tmp.getFirstChild().getNodeValue());
+                f.setLayername(tmp.getFirstChild().getNodeValue());
+            }
+            else if (nodeName.endsWith("_feature")) {
+                parseFeatureAttributes(tmp, f);
+            }
+        }
+
+        return f;
+    }
+
+
+    protected void parseFeatureAttributes(Node node, FeatureInfo f) {
+        logger.debug("GFIServiceImpl.parseFeatureAttributes");
+
+        NodeList children = node.getChildNodes();
+        int numChildren   = children != null ? children.getLength() : 0;
+
+        logger.debug("Has " + numChildren + " attributes.");
+
+        for (int i = 0; i < numChildren; i++) {
+            Node   tmp  = children.item(i);
+            String name = tmp.getNodeName();
+
+            logger.debug("  tmp attribute name: '" + name + "'");
+
+            if (name.equals("gml:boundedBy")) {
+                // TODO
+            }
+            else {
+                Node child = tmp.getFirstChild();
+                if (child != null) {
+                    f.addAttr(name, child.getNodeValue());
+                }
+            }
+        }
+    }
 }
 // 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/shared/model/FeatureInfo.java	Fri Nov 18 11:39:10 2011 +0000
@@ -0,0 +1,50 @@
+package de.intevation.flys.client.shared.model;
+
+import java.io.Serializable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FeatureInfo implements Serializable {
+
+    protected String layername;
+
+    protected Map<String, String> attrs;
+
+
+    public FeatureInfo() {
+    }
+
+
+    public FeatureInfo(String layername) {
+        this.layername = layername;
+        this.attrs     = new HashMap<String, String>();
+    }
+
+
+    public void setLayername(String layername) {
+        this.layername = layername;
+    }
+
+
+    public String getLayername() {
+        return layername;
+    }
+
+
+    public void addAttr(String key, String value) {
+        if (key != null && key.length() > 0) {
+            attrs.put(key, value);
+        }
+    }
+
+
+    public Map<String, String> getAttrs() {
+        return attrs;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/webapp/FLYS.css	Thu Nov 17 16:24:09 2011 +0000
+++ b/flys-client/src/main/webapp/FLYS.css	Fri Nov 18 11:39:10 2011 +0000
@@ -128,3 +128,7 @@
     font-style: normal;
     padding-left: 10px;
 }
+
+.featureinfo-row {
+    border-bottom: 1px solid black;
+}

http://dive4elements.wald.intevation.org