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 :