/**
* Copyright (c) 2011 Ontology Engineering Group,
* Departamento de Inteligencia Artificial,
* Facultad de Informetica, Universidad
* Politecnica de Madrid, Spain
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package es.upm.fi.dia.oeg.map4rdf.server.servlet;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import de.micromata.opengis.kml.v_2_2_0.Document;
import de.micromata.opengis.kml.v_2_2_0.Kml;
import de.micromata.opengis.kml.v_2_2_0.LineString;
import de.micromata.opengis.kml.v_2_2_0.MultiGeometry;
import de.micromata.opengis.kml.v_2_2_0.Placemark;
import es.upm.fi.dia.oeg.map4rdf.client.util.ConfigurationUtil;
import es.upm.fi.dia.oeg.map4rdf.server.conf.multiple.MultipleConfigurations;
import es.upm.fi.dia.oeg.map4rdf.server.dao.DaoException;
import es.upm.fi.dia.oeg.map4rdf.share.Circle;
import es.upm.fi.dia.oeg.map4rdf.share.FacetConstraint;
import es.upm.fi.dia.oeg.map4rdf.share.GeoResource;
import es.upm.fi.dia.oeg.map4rdf.share.Geometry;
import es.upm.fi.dia.oeg.map4rdf.share.MultiPolygon;
import es.upm.fi.dia.oeg.map4rdf.share.Point;
import es.upm.fi.dia.oeg.map4rdf.share.PolyLine;
import es.upm.fi.dia.oeg.map4rdf.share.Polygon;
/**
* @author Alexander De Leon
*/
@Singleton
public class KmlService extends HttpServlet {
private static final long serialVersionUID = 4451922424233735357L;
private MultipleConfigurations configurations;
private static final String [] reservedParameters={ConfigurationUtil.CONFIGURATION_ID};
@Inject
public KmlService(MultipleConfigurations configurations) {
this.configurations = configurations;;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Set<FacetConstraint> constraints = getFacetConstraints(req);
String configID = getConfigurationID(req);
try {
List<GeoResource> resources = configurations.getConfiguration(configID)
.getMap4rdfDao().getGeoResources(null, constraints);
resp.setContentType("application/vnd.google-earth.kml+xml");
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"","resources.kml");
resp.setHeader(headerKey, headerValue);
writeKml(resources, resp.getOutputStream());
} catch (DaoException e) {
throw new ServletException(e);
}
}
private void writeKml(List<GeoResource> resources, ServletOutputStream outputStream) {
Kml kml = new Kml();
Document doc = kml.createAndSetDocument();
for (GeoResource resource : resources) {
Placemark placemark = doc.createAndAddPlacemark().withName(resource.getUri());
if (resource.isMultiGeometry()) {
MultiGeometry multiGeometry = new MultiGeometry();
for (Geometry geometry : resource.getGeometries()) {
multiGeometry.addToGeometry(getKmlGeometry(geometry));
}
placemark.setGeometry(multiGeometry);
} else {
placemark.setGeometry(getKmlGeometry(resource.getFirstGeometry()));
}
}
// write XML
try {
kml.marshal(outputStream);
} catch (FileNotFoundException e) {
// ignore this is applicable for outputstream
}
}
private de.micromata.opengis.kml.v_2_2_0.Geometry getKmlGeometry(Geometry geometry) {
switch (geometry.getType()) {
case POINT:
Point point = (Point) geometry;
de.micromata.opengis.kml.v_2_2_0.Point kmlPoint = new de.micromata.opengis.kml.v_2_2_0.Point();
kmlPoint.addToCoordinates(point.getX(), point.getY());
return kmlPoint;
case POLYLINE:
PolyLine polyline = (PolyLine) geometry;
LineString kmlPolyline = new LineString();
for (Point linePoint : polyline.getPoints()) {
kmlPolyline.addToCoordinates(linePoint.getX(), linePoint.getY());
}
return kmlPolyline;
case POLYGON:
Polygon polygon = (Polygon) geometry;
de.micromata.opengis.kml.v_2_2_0.LinearRing kmlPolygon = new de.micromata.opengis.kml.v_2_2_0.LinearRing();
for (Point polygonPoint : polygon.getPoints()) {
kmlPolygon.addToCoordinates(polygonPoint.getX(), polygonPoint.getY());
}
return kmlPolygon;
case CIRCLE:
Circle circle = (Circle) geometry;
de.micromata.opengis.kml.v_2_2_0.LinearRing kmlCircle= new de.micromata.opengis.kml.v_2_2_0.LinearRing();
double distanceStep=0.001;
double deegreeStep=360/((2*Math.PI*circle.getRadius())/distanceStep);
for(double degree=0;degree<360;degree+=deegreeStep){
double plusX = Math.sin(Math.toRadians(degree))*circle.getRadius();
double plusY = Math.cos(Math.toRadians(degree))*circle.getRadius();
kmlCircle.addToCoordinates(circle.getCenter().getX()+plusX, circle.getCenter().getY()+plusY);
}
return kmlCircle;
case MULTIPOLYGON:
MultiPolygon multiPolygon = (MultiPolygon) geometry;
de.micromata.opengis.kml.v_2_2_0.MultiGeometry kmlMultiPolygon = new MultiGeometry();
for(Polygon polygonM:multiPolygon.getPolygons()){
de.micromata.opengis.kml.v_2_2_0.LinearRing kmlPolygonM = new de.micromata.opengis.kml.v_2_2_0.LinearRing();
for (Point polygonPoint : polygonM.getPoints()) {
kmlPolygonM.addToCoordinates(polygonPoint.getX(), polygonPoint.getY());
}
kmlMultiPolygon.addToGeometry(kmlPolygonM);
}
return kmlMultiPolygon;
}
return null; // make compiler happy
}
private Set<FacetConstraint> getFacetConstraints(HttpServletRequest req) {
Set<FacetConstraint> constraints = new HashSet<FacetConstraint>();
Enumeration<String> paramNames = (Enumeration<String>)req.getParameterNames();
while (paramNames.hasMoreElements()) {
String facetId = paramNames.nextElement();
boolean isReservedParam = false;
for(String toTest : reservedParameters){
if(toTest.toLowerCase().trim().equals(facetId.toLowerCase().trim())){
isReservedParam=true;
break;
}
}
if(!isReservedParam){
String[] valueIds = req.getParameterValues(facetId);
for (String valueId : valueIds) {
constraints.add(new FacetConstraint(facetId, valueId));
}
}
}
if(constraints.isEmpty()){
return null;
}
return constraints;
}
private String getConfigurationID(HttpServletRequest req) throws ServletException {
String value = req.getParameter(ConfigurationUtil.CONFIGURATION_ID);
if(value == null || value.isEmpty()){
throw new ServletException("Bad parameter value of parameter key: "+ConfigurationUtil.CONFIGURATION_ID);
}
return value;
}
}