Java tutorial
/* * Copyright 2008-2010 Austrian Institute of Technology * * Licensed under the EUPL, Version 1.1 or - as soon they * will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * you may not use this work except in compliance with the * Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in * writing, software distributed under the Licence is * distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * See the Licence for the specific language governing * permissions and limitations under the Licence. */ package at.ait.dme.yuma.server.map; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import at.ait.dme.yuma.client.map.annotation.WGS84Coordinate; import at.ait.dme.yuma.server.map.transformation.AffineTransformation; import at.ait.dme.yuma.server.map.transformation.ControlPointManager; import at.ait.dme.yuma.server.map.transformation.TransformationException; import at.ait.dme.yuma.server.map.transformation.TransformationResult; import at.ait.dme.yuma.server.util.Config; /** * Servlet for converting KML files from geo- to map-coordinates. * * @author Rainer Simon */ @SuppressWarnings("serial") public class KMLConverterServlet extends HttpServlet { /** * Property names */ private static final String OUTLIER_THRESHOLD_PROPERTY = "map.kml.outlier.threshold"; /** * Outlier threshold in pixel */ private int outlierThreshold; @Override public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); Config config = new Config(servletConfig, getClass().getResourceAsStream("map-service.properties")); outlierThreshold = config.getIntegerProperty(OUTLIER_THRESHOLD_PROPERTY); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Params: URL of the base map into which KML shall be transformed, URL of the KML String europeanaUri = request.getParameter("europeanaUri"); String mapUrl = request.getParameter("map"); String kmlUrl = request.getParameter("kml"); if ((mapUrl != null) && (kmlUrl != null)) { // Get KML source file via HTTP GetMethod kmlRequest = new GetMethod(kmlUrl); int responseCode = new HttpClient().executeMethod(kmlRequest); if (responseCode == 200) { try { // Parse KML DOM DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document kml = builder.parse(kmlRequest.getResponseBodyAsStream()); // Instantiate Interpolator ControlPointManager cpm = new ControlPointManager(request, response, europeanaUri, mapUrl); AffineTransformation ip = new AffineTransformation(cpm.getControlPoints()); // Convert coordinates in DOM kml = convert(kml, ip); // Serialize KML result DOM and return Transformer tf = TransformerFactory.newInstance().newTransformer(); Source source = new DOMSource(kml); Result result = new StreamResult(response.getOutputStream()); tf.transform(source, result); } catch (Exception e) { response.sendError(500, e.getMessage()); return; } } else { response.sendError(500, "KML not found. (Server returned error " + responseCode + ")"); return; } response.setContentType("application/vnd.google-earth.kml+xml"); response.setCharacterEncoding("UTF-8"); response.getWriter().write("done"); } else { response.sendError(404); } } private Document convert(Document kml, AffineTransformation interpolator) { // Get all 'coordinates' nodes NodeList coordNodes = kml.getElementsByTagName("coordinates"); StringBuffer sb; String[] coords; String[] lonlat; TransformationResult ir; for (int i = 0; i < coordNodes.getLength(); i++) { // Construct result coordinate string sb = new StringBuffer(); // Original WGS84 coordinate set: 'lon,lat,alt lon,lat,alt lon,lat,alt ...' Node n = coordNodes.item(i); // Split into individual WGS84 coordinates: 'lon,lat,alt' coords = n.getTextContent().trim().split(" "); int lastX = 0; int lastY = 0; double dist = 0; for (int j = 0; j < coords.length; j++) { // Split into coordinate values lonlat = coords[j].split(","); if (lonlat.length > 1) { try { // Interpolate ir = interpolator.getXYFromKnownLatLon( new WGS84Coordinate(Double.parseDouble(lonlat[1]), Double.parseDouble(lonlat[0]))); // Threshold check: does the distance between this point and // the last one exceed the threshold? --> Outlier! Don't add dist = Math.sqrt(Math.pow((ir.xy.x - lastX), 2) + Math.pow((ir.xy.y - lastY), 2)); if ((j == 0) || (dist < outlierThreshold)) { sb.append(ir.xy.x + "," + ir.xy.y + "\n"); lastX = ir.xy.x; lastY = ir.xy.y; } } catch (TransformationException e) { // Cannot happen unless interpolator is invalid throw new RuntimeException(e); } } } // Replace node n.setTextContent(sb.toString()); } return kml; } }