ingo@1400: package de.intevation.flys.client.server;
ingo@1400:
ingo@1400: import java.io.InputStream;
ingo@1400: import java.io.IOException;
ingo@1400: import java.net.URL;
ingo@1400: import java.net.URLConnection;
ingo@1402: import java.util.ArrayList;
ingo@1400: import java.util.List;
ingo@1400:
ingo@1402: import org.w3c.dom.Document;
ingo@1402: import org.w3c.dom.Node;
ingo@1402: import org.w3c.dom.NodeList;
ingo@1402:
ingo@1400: import org.apache.log4j.Logger;
ingo@1400:
ingo@1400: import com.google.gwt.user.server.rpc.RemoteServiceServlet;
ingo@1400:
ingo@1402: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@1400:
ingo@1400: import de.intevation.flys.client.shared.exceptions.ServerException;
ingo@1400: import de.intevation.flys.client.shared.model.AttributedTheme;
ingo@1402: import de.intevation.flys.client.shared.model.FeatureInfo;
ingo@1400: import de.intevation.flys.client.shared.model.Theme;
ingo@1400:
ingo@1400: import de.intevation.flys.client.client.services.GFIService;
ingo@1400:
ingo@1400:
ingo@1400: /**
ingo@1400: * @author Ingo Weinzierl
ingo@1400: */
ingo@1400: public class GFIServiceImpl
ingo@1400: extends RemoteServiceServlet
ingo@1400: implements GFIService
ingo@1400: {
ingo@1400: public static final String ERR_NO_VALID_GFI_URL =
ingo@1400: "error_no_valid_gfi_url";
ingo@1400:
ingo@1400: public static final String ERR_GFI_REQUEST_FAILED =
ingo@1400: "error_gfi_req_failed";
ingo@1400:
ingo@1400: public static final String ERR_PARSING_RESPONSE_FAILED =
ingo@1400: "error_gfi_parsing_failed";
ingo@1400:
ingo@1400:
ingo@1400: private static final Logger logger =
ingo@1400: Logger.getLogger(GFIServiceImpl.class);
ingo@1400:
ingo@1400:
ingo@1400: /**
ingo@1400: * @param themes
ingo@1400: * @param format
ingo@1400: * @param bbox
ingo@1400: * @param height
ingo@1400: * @param width
ingo@1400: * @param x
ingo@1400: * @param y
ingo@1400: *
ingo@1400: * @return
ingo@1400: */
ingo@1402: public List query(
ingo@1400: List themes,
ingo@1400: String format,
ingo@1400: String bbox,
ingo@1400: String projection,
ingo@1400: int height,
ingo@1400: int width,
ingo@1400: int x,
ingo@1400: int y
ingo@1400: ) throws ServerException
ingo@1400: {
ingo@1400: logger.info("GFIServiceImpl.query");
ingo@1400:
ingo@1400: String path = createGetFeautureInfoURL(
ingo@1400: themes, format, bbox, projection, height, width, x, y);
ingo@1402:
ingo@1400: logger.debug("URL=" + path);
ingo@1400:
ingo@1400: try {
ingo@1400: URL url = new URL(path);
ingo@1400:
ingo@1400: URLConnection conn = url.openConnection();
ingo@1400: conn.connect();
ingo@1400:
ingo@1400: InputStream is = conn.getInputStream();
ingo@1400:
ingo@1402: return parseResponse(is);
ingo@1400:
ingo@1400: }
ingo@1400: catch (IOException ioe) {
ingo@1400: logger.warn(ioe, ioe);
ingo@1400: }
ingo@1400:
ingo@1400: throw new ServerException(ERR_GFI_REQUEST_FAILED);
ingo@1400: }
ingo@1400:
ingo@1400:
ingo@1400: /**
ingo@1400: * @param map
ingo@1400: * @param themes
ingo@1400: * @param format
ingo@1400: * @param x
ingo@1400: * @param y
ingo@1400: *
ingo@1400: * @return
ingo@1400: */
ingo@1400: protected String createGetFeautureInfoURL(
ingo@1400: List themes,
ingo@1400: String infoFormat,
ingo@1400: String bbox,
ingo@1400: String projection,
ingo@1400: int height,
ingo@1400: int width,
ingo@1400: int x,
ingo@1400: int y
ingo@1400: ) throws ServerException
ingo@1400: {
ingo@1400: String url = getUrl(themes);
ingo@1400:
ingo@1400: if (url == null || url.length() == 0) {
ingo@1400: throw new ServerException(ERR_NO_VALID_GFI_URL);
ingo@1400: }
ingo@1400:
ingo@1400: String layers = createLayersString(themes);
ingo@1400:
ingo@1400: StringBuilder sb = new StringBuilder();
ingo@1400: sb.append(url);
ingo@1400:
ingo@1400: if (url.indexOf("?") < 0) {
ingo@1400: sb.append("?SERVICE=WMS");
ingo@1400: }
ingo@1400: else {
ingo@1400: sb.append("&SERVICE=WMS");
ingo@1400: }
ingo@1400:
ingo@1400: sb.append("&VERSION=1.1.1");
ingo@1400: sb.append("&REQUEST=GetFeatureInfo");
ingo@1400: sb.append("&LAYERS=" + layers);
ingo@1400: sb.append("&QUERY_LAYERS=" + layers);
ingo@1400: sb.append("&BBOX=" + bbox);
ingo@1400: sb.append("&HEIGHT=" + height);
ingo@1400: sb.append("&WIDTH=" + width);
ingo@1400: sb.append("&FORMAT=image/png");
ingo@1400: sb.append("&INFO_FORMAT=" + infoFormat);
ingo@1400: sb.append("&SRS=" + projection);
ingo@1400: sb.append("&X=" + String.valueOf(x));
ingo@1400: sb.append("&Y=" + String.valueOf(y));
ingo@1400:
ingo@1400: return sb.toString();
ingo@1400: }
ingo@1400:
ingo@1400:
ingo@1400: protected String getUrl(List themes) {
ingo@1400: for (Theme t: themes) {
ingo@1400: AttributedTheme attr = (AttributedTheme) t;
ingo@1400:
ingo@1400: if (attr.getAttrAsBoolean("queryable")) {
ingo@1400: return attr.getAttr("url");
ingo@1400: }
ingo@1400: }
ingo@1400:
ingo@1400: return null;
ingo@1400: }
ingo@1400:
ingo@1400:
ingo@1400: protected String createLayersString(List themes) {
ingo@1400: StringBuilder sb = new StringBuilder();
ingo@1400: boolean first = true;
ingo@1400:
ingo@1400: for (Theme theme: themes) {
ingo@1400: AttributedTheme layer = (AttributedTheme) theme;
ingo@1400: if (layer.getAttrAsBoolean("queryable")) {
ingo@2448: if (!first) {
ingo@2448: sb.append(",");
ingo@2448: }
ingo@2448:
ingo@1400: sb.append(layer.getAttr("layers"));
ingo@1400: first = false;
ingo@1400: }
ingo@1400: }
ingo@1400:
ingo@1400: return sb.toString();
ingo@1400: }
ingo@1402:
ingo@1402:
ingo@1402: protected List parseResponse(InputStream is) {
ingo@1402: logger.debug("GFIServiceImpl.parseResponse");
ingo@1402:
ingo@1402: Document response = XMLUtils.parseDocument(is);
ingo@1402:
ingo@1402: List features = new ArrayList();
ingo@1402:
ingo@1402: parseFeatureInfos(response, features);
ingo@1402:
ingo@1402: return features;
ingo@1402: }
ingo@1402:
ingo@1402:
ingo@1402: protected void parseFeatureInfos(Node node, List features) {
ingo@1402: logger.debug("GFIServiceImpl.parseFeatureInfos");
ingo@1402:
ingo@1402: String name = node.getNodeName();
ingo@1402:
ingo@1402: if (name.endsWith("_layer")) {
ingo@1402: features.add(parseFeature(node));
ingo@1402:
ingo@1402: return;
ingo@1402: }
ingo@1402:
ingo@1402: NodeList children = node.getChildNodes();
ingo@1402:
ingo@1402: if (children != null && children.getLength() > 0) {
ingo@1402: for (int i = 0, n = children.getLength(); i < n; i++) {
ingo@1402: parseFeatureInfos(children.item(i), features);
ingo@1402: }
ingo@1402: }
ingo@1402: }
ingo@1402:
ingo@1402:
ingo@1402: protected FeatureInfo parseFeature(Node node) {
ingo@1402: logger.debug("GFIServiceImpl.parseFeature");
ingo@1402:
ingo@1402: String layername = node.getNodeName();
ingo@1402:
ingo@1402: FeatureInfo f = new FeatureInfo(layername);
ingo@1402:
ingo@1402: NodeList children = node.getChildNodes();
ingo@1402: int numChildren = children != null ? children.getLength() : 0;
ingo@1402:
ingo@1402: logger.debug("Feature '" + layername + "' has " + numChildren + " nodes.");
ingo@1402:
ingo@1402: for (int i = 0; i < numChildren; i++) {
ingo@1402: Node tmp = children.item(i);
ingo@1402: String nodeName = tmp.getNodeName();
ingo@1402:
ingo@1402: logger.debug(" node name: '" + nodeName + "'");
ingo@1402:
ingo@1402: if (nodeName.equals("gml:name")) {
ingo@1402: logger.debug("NAME node has child: " + tmp.getFirstChild().getNodeValue());
ingo@1402: f.setLayername(tmp.getFirstChild().getNodeValue());
ingo@1402: }
ingo@1402: else if (nodeName.endsWith("_feature")) {
ingo@1402: parseFeatureAttributes(tmp, f);
ingo@1402: }
ingo@1402: }
ingo@1402:
ingo@1402: return f;
ingo@1402: }
ingo@1402:
ingo@1402:
ingo@1402: protected void parseFeatureAttributes(Node node, FeatureInfo f) {
ingo@1402: logger.debug("GFIServiceImpl.parseFeatureAttributes");
ingo@1402:
ingo@1402: NodeList children = node.getChildNodes();
ingo@1402: int numChildren = children != null ? children.getLength() : 0;
ingo@1402:
ingo@1402: logger.debug("Has " + numChildren + " attributes.");
ingo@1402:
ingo@1402: for (int i = 0; i < numChildren; i++) {
ingo@1402: Node tmp = children.item(i);
ingo@1402: String name = tmp.getNodeName();
ingo@1402:
ingo@1402: logger.debug(" tmp attribute name: '" + name + "'");
ingo@1402:
ingo@1402: if (name.equals("gml:boundedBy")) {
ingo@1402: // TODO
ingo@1402: }
ingo@1402: else {
ingo@1402: Node child = tmp.getFirstChild();
ingo@1402: if (child != null) {
ingo@1402: f.addAttr(name, child.getNodeValue());
ingo@1402: }
ingo@1402: }
ingo@1402: }
ingo@1402: }
ingo@1400: }
ingo@1400: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :