/** * Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * • Apache License, version 2.0 * • Apache Software License, version 1.0 * • GNU Lesser General Public License, version 3 * • Mozilla Public License, versions 1.0, 1.1 and 2.0 * • Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * As an exception to the terms of the GPL, you may copy, modify, * propagate, and distribute a work formed by combining 52°North WPS * GeoTools Modules with the Eclipse Libraries, or a work derivative of * such a combination, even if such copying, modification, propagation, or * distribution would otherwise violate the terms of the GPL. Nothing in * this exception exempts you from complying with the GPL in all respects * for all of the code used other than the Eclipse Libraries. You may * include this exception and its grant of permissions when you distribute * 52°North WPS GeoTools Modules. Inclusion of this notice with such a * distribution constitutes a grant of such permissions. If you do not wish * to grant these permissions, remove this paragraph from your * distribution. "52°North WPS GeoTools Modules" means the 52°North WPS * modules using GeoTools functionality - software licensed under version 2 * or any later version of the GPL, or a work based on such software and * licensed under the GPL. "Eclipse Libraries" means Eclipse Modeling * Framework Project and XML Schema Definition software distributed by the * Eclipse Foundation and licensed under the Eclipse Public License Version * 1.0 ("EPL"), or a work based on such software and licensed under the EPL. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. */ package org.n52.wps.io.datahandler.generator; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.math.BigDecimal; import java.util.ArrayList; import net.opengis.examples.packet.DataType; import net.opengis.examples.packet.GMLPacketDocument; import net.opengis.examples.packet.GMLPacketType; import net.opengis.examples.packet.PropertyType; import net.opengis.examples.packet.StaticFeatureType; import net.opengis.examples.packet.PropertyType.Value; import net.opengis.gml.CoordType; import net.opengis.gml.LineStringPropertyType; import net.opengis.gml.LinearRingMemberType; import net.opengis.gml.LinearRingType; import net.opengis.gml.PointPropertyType; import net.opengis.gml.PolygonType; import org.geotools.feature.FeatureIterator; import org.n52.wps.io.data.IData; import org.n52.wps.io.data.binding.complex.GTVectorDataBinding; import org.opengis.feature.simple.SimpleFeature; import org.w3c.dom.Node; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; public class SimpleGMLGenerator extends AbstractGenerator { public SimpleGMLGenerator() { super(); supportedIDataTypes.add(GTVectorDataBinding.class); } @Override public InputStream generateStream(IData data, String mimeType, String schema) throws IOException { File tempFile = null; InputStream stream = null; try { tempFile = File.createTempFile("gml", "xml"); this.finalizeFiles.add(tempFile); FileOutputStream outputStream = new FileOutputStream(tempFile); this.writeToStream(data, outputStream); outputStream.flush(); outputStream.close(); stream = new FileInputStream(tempFile); } catch (IOException e){ throw new IOException("Unable to generate GML"); } return stream; } public Node generateXML(IData coll, String schema) { return generateXMLObj(coll, schema).getDomNode(); } public void write(IData coll, Writer writer) { GMLPacketDocument doc = generateXMLObj(coll, null); try { BufferedWriter bufferedWriter = new BufferedWriter(writer); bufferedWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); doc.save(bufferedWriter); bufferedWriter.close(); } catch(IOException e) { throw new RuntimeException(e); } } private GMLPacketDocument generateXMLObj(IData coll, String schema2) { GMLPacketDocument doc = GMLPacketDocument.Factory.newInstance(); GMLPacketType packet = doc.addNewGMLPacket(); if(coll == null) { return doc; } FeatureIterator<?> iter = ((GTVectorDataBinding)coll).getPayload().features(); while(iter.hasNext()) { SimpleFeature feature = (SimpleFeature) iter.next(); StaticFeatureType staticFeature = packet.addNewPacketMember().addNewStaticFeature(); Geometry geom = (Geometry) feature.getDefaultGeometry(); String geomType = geom.getGeometryType(); if(geomType.equals("Point")) { Point point = (Point)geom; Coordinate coord = point.getCoordinate(); if (coord != null) { PointPropertyType pointType = staticFeature.addNewPointProperty(); pointType.addNewPoint().setCoord(convertToXMLCoordType(coord)); generateAttribute(feature, staticFeature); } } else if(geomType.equals("LineString")) { LineString ls = (LineString)geom; CoordType[] coords = convertToXMLCoordType(ls.getCoordinates()); if(coords != null) { ls.getCoordinates(); LineStringPropertyType lsType = staticFeature.addNewLineStringProperty(); lsType.addNewLineString().setCoordArray(coords); generateAttribute(feature, staticFeature); } } else if(geomType.equals("Polygon")) { Polygon polygon = (Polygon)geom; PolygonType xmlPolygon = staticFeature.addNewPolygonProperty().addNewPolygon(); xmlPolygon.setOuterBoundaryIs(convertToXMLLinearRing(polygon.getExteriorRing())); LinearRingMemberType innerBoundary = xmlPolygon.addNewInnerBoundaryIs(); for(int i = 0; i < polygon.getNumInteriorRing(); i++) { LinearRingType innerRing = innerBoundary.addNewLinearRing(); innerRing.setCoordArray(convertToXMLCoordType(polygon.getInteriorRingN(i).getCoordinates())); } generateAttribute(feature, staticFeature); } else if (geomType.equals("MultiPolygon")) { MultiPolygon mp = (MultiPolygon)geom; for(int i = 0; i < mp.getNumGeometries(); i++) { if(i > 0) { staticFeature = packet.addNewPacketMember().addNewStaticFeature(); } Polygon p = (Polygon) (geom.getGeometryN(i)); PolygonType pType = staticFeature.addNewPolygonProperty().addNewPolygon(); pType.setOuterBoundaryIs(convertToXMLLinearRing(p.getExteriorRing())); LinearRingMemberType innerBoundary = pType.addNewInnerBoundaryIs(); for(int j = 0; j < p.getNumInteriorRing(); j++) { LinearRingType innerRing = innerBoundary.addNewLinearRing(); innerRing.setCoordArray(convertToXMLCoordType(p.getInteriorRingN(j).getCoordinates())); } } generateAttribute(feature, staticFeature); } // THE MULTILINESTRING WILL BE DEVIDED INTO NORMAL LINESTRINGs, else if(geomType.equals("MultiLineString")) { MultiLineString mls = (MultiLineString)geom; for(int i = 0; i < mls.getNumGeometries(); i++) { if(i > 0) { staticFeature = packet.addNewPacketMember().addNewStaticFeature(); } LineString ls = (LineString) (geom.getGeometryN(i)); LineStringPropertyType lsType = staticFeature.addNewLineStringProperty(); lsType.addNewLineString().setCoordArray(convertToXMLCoordType(ls.getCoordinates())); } generateAttribute(feature, staticFeature); } // else if(geomType.equals("GeometryCollection")) { // GeometryCollection geomColl = (GeometryCollection)geom; // geomColl.get // } else if(geom.isEmpty()) { //GEOMETRY is empty, do nothing } else { throw new IllegalArgumentException("geometryType not supported: " + geomType); } } return doc; } private void generateAttribute(SimpleFeature feature, StaticFeatureType staticFeature) { if(feature.getFeatureType().getAttributeCount()>1){ PropertyType propertyType; Value value; int attributePosCounter=0; for (Object o: feature.getAttributes()) { DataType.Enum dataType; if(o instanceof Integer){ dataType = DataType.INTEGER; }else if(o instanceof String){ dataType = DataType.STRING; }else if(o instanceof Boolean){ dataType = DataType.BOOLEAN; }else if(o instanceof Long){ dataType = DataType.LONG; }else if(o instanceof Double){ dataType = DataType.DECIMAL; } else continue; //Don't create anything propertyType = staticFeature.addNewProperty(); propertyType.setPropertyName(feature.getFeatureType().getAttributeDescriptors().get(attributePosCounter).getLocalName()); value = propertyType.addNewValue(); value.setDataType(dataType); value.setStringValue(String.valueOf(o)); attributePosCounter++; } } } private LinearRingMemberType convertToXMLLinearRing(LineString ls) { LinearRingMemberType ringMember = LinearRingMemberType.Factory.newInstance(); LinearRingType ring = LinearRingType.Factory.newInstance(); CoordType[] coords = convertToXMLCoordType(ls.getCoordinates()); if(coords == null) { return null; } ring.setCoordArray(coords); ringMember.setLinearRing(ring); return ringMember; } private CoordType[] convertToXMLCoordType(Coordinate[] coords) { ArrayList<CoordType> coordsList = new ArrayList<CoordType>(); for(int i = 0; i < coords.length; i++) { CoordType tempCoord = convertToXMLCoordType(coords[i]); if(tempCoord != null) { coordsList.add(tempCoord); } } if(coordsList.isEmpty()) { return null; } CoordType[] returnCoords = new CoordType[coordsList.size()]; returnCoords = coordsList.toArray(returnCoords); return returnCoords; } private CoordType convertToXMLCoordType(Coordinate coord) { if(Double.isNaN(coord.x) || Double.isNaN(coord.y)) { return null; } CoordType xmlCoord = CoordType.Factory.newInstance(); try { xmlCoord.setX(new BigDecimal(Double.toString(coord.x))); xmlCoord.setY(new BigDecimal(Double.toString(coord.y))); } catch(NumberFormatException e) { throw new IllegalArgumentException(e); } if(!Double.isNaN(coord.z)) { xmlCoord.setZ(BigDecimal.valueOf(coord.z)); } return xmlCoord; } public void writeToStream(IData coll, OutputStream os) { OutputStreamWriter w = new OutputStreamWriter(os); write (coll, w); } }