/*
* uDig - User Friendly Desktop Internet GIS client
* (C) MangoSystem - www.mangosystem.com
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.processingtoolbox.tools;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.store.ReprojectingFeatureCollection;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.referencing.CRS;
import org.geotools.util.logging.Logging;
import org.geotools.xml.Configuration;
import org.locationtech.udig.processingtoolbox.ToolboxPlugin;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
/**
* Format Transformer
*
* @author Minpa Lee, MangoSystem
*
* @source $URL$
*/
@SuppressWarnings("nls")
public class FormatTransformer {
final static Logger LOGGER = Logging.getLogger(FormatTransformer.class);
public enum EncodeType {
GML212(0), GML311(1), GML32(2), GEOJSON(3), KML21(4), KML22(5), CSV(6), WKT(7);
private final int value;
EncodeType(int value) {
this.value = value;
}
static final Map<Integer, EncodeType> map = new HashMap<Integer, EncodeType>();
static {
for (EncodeType type : EncodeType.values()) {
map.put(type.value, type);
}
}
public static EncodeType valueOf(int index) {
EncodeType type = map.get(Integer.valueOf(index));
if (type == null) {
return EncodeType.GML311; // default
}
return type;
}
}
private EncodeType encodeType = EncodeType.GML311;
public FormatTransformer(EncodeType encodeType) {
this.encodeType = encodeType;
}
public String getExtension() {
switch (encodeType) {
case GML212:
case GML311:
case GML32:
return ".gml";
case KML21:
case KML22:
return ".kml";
case GEOJSON:
return ".json";
case CSV:
return ".csv";
case WKT:
return ".wkt";
default:
return ".gml";
}
}
public void encode(SimpleFeatureCollection features, File outputFile) throws IOException {
switch (encodeType) {
case CSV:
encodeCSV(features, outputFile, Charset.defaultCharset(), "|");
break;
case WKT:
encodeWKT(features, outputFile, Charset.defaultCharset(), "|");
break;
case GEOJSON:
encodeGeoJSON(features, outputFile);
break;
case GML212:
case GML311:
case GML32:
encodeGML(features, outputFile);
break;
case KML21:
case KML22:
encodeKML(features, outputFile);
break;
default:
encodeGML(features, outputFile);
break;
}
}
public void encodeKML(SimpleFeatureCollection features, File outputFile) throws IOException {
SimpleFeatureCollection wgs84 = features;
CoordinateReferenceSystem sourceCRS = wgs84.getSchema().getCoordinateReferenceSystem();
try {
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
if (!CRS.equalsIgnoreMetadata(sourceCRS, targetCRS)) {
wgs84 = new ReprojectingFeatureCollection(features, targetCRS);
}
} catch (NoSuchAuthorityCodeException e) {
ToolboxPlugin.log(e.getMessage());
} catch (FactoryException e) {
ToolboxPlugin.log(e.getMessage());
}
QName qName = org.geotools.kml.KML.kml;
org.geotools.xml.Configuration config = new org.geotools.kml.KMLConfiguration();
if (encodeType == EncodeType.KML22) {
qName = org.geotools.kml.v22.KML.kml;
config = new org.geotools.kml.v22.KMLConfiguration();
}
write(config, qName, wgs84, outputFile);
}
public void encodeGML(SimpleFeatureCollection features, File outputFile) throws IOException {
QName qName;
org.geotools.xml.Configuration config;
switch (encodeType) {
case GML212:
qName = org.geotools.gml2.GML._FeatureCollection;
config = new org.geotools.gml2.GMLConfiguration();
// config = new org.geotools.wfs.v1_0.WFSConfiguration();
break;
case GML311:
qName = org.geotools.gml3.GML.FeatureCollection;
config = new org.geotools.gml3.GMLConfiguration();
// config = new org.geotools.wfs.v1_1.WFSConfiguration();
break;
case GML32:
qName = org.geotools.gml3.v3_2.GML.FeatureCollection;
config = new org.geotools.gml3.v3_2.GMLConfiguration();
// config = new org.geotools.wfs.v2_0.WFSConfiguration();
break;
default:
qName = org.geotools.gml3.GML.FeatureCollection;
config = new org.geotools.gml3.GMLConfiguration();
break;
}
write(config, qName, features, outputFile);
}
private void write(Configuration config, QName qName, SimpleFeatureCollection features,
File outputFile) throws IOException {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFile);
org.geotools.xml.Encoder encoder = new org.geotools.xml.Encoder(config);
encoder.setIndenting(true);
encoder.setIndentSize(2);
encoder.encode(features, qName, fos);
} catch (FileNotFoundException e) {
ToolboxPlugin.log(e.getMessage());
} finally {
closeQuietly(fos);
}
}
public void encodeCSV(SimpleFeatureCollection features, File outputFile, Charset charset,
String delimeter) throws IOException {
BufferedWriter writer = null;
try {
String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
FileOutputStream fos = new FileOutputStream(outputFile);
writer = new BufferedWriter(new OutputStreamWriter(fos, charset));
// write fields
SimpleFeatureType schema = features.getSchema();
StringBuffer sb = new StringBuffer();
for (AttributeDescriptor descriptor : schema.getAttributeDescriptors()) {
if (descriptor instanceof GeometryDescriptor) {
continue;
}
if (sb.length() > 0) {
sb.append(delimeter);
}
sb.append(descriptor.getLocalName());
}
sb.append(delimeter).append("xcoord").append(delimeter).append("ycoord")
.append(newLine);
writer.write(sb.toString());
// write contents
SimpleFeatureIterator featureIter = null;
try {
featureIter = features.features();
while (featureIter.hasNext()) {
SimpleFeature feature = featureIter.next();
Geometry origGeom = (Geometry) feature.getDefaultGeometry();
Coordinate coordinate = origGeom.getCentroid().getCoordinate();
sb.setLength(0);
for (Object value : feature.getAttributes()) {
if (value instanceof Geometry) {
continue;
}
if (sb.length() > 0) {
sb.append(delimeter);
}
sb.append(value == null ? "" : value.toString());
}
sb.append(delimeter).append(coordinate.x);
sb.append(delimeter).append(coordinate.y).append(newLine);
writer.write(sb.toString());
}
} finally {
featureIter.close();
}
writer.flush();
writer.close();
} catch (FileNotFoundException e) {
ToolboxPlugin.log(e.getMessage());
} finally {
closeQuietly(writer);
}
}
public void encodeWKT(SimpleFeatureCollection features, File outputFile, Charset charset,
String delimeter) throws IOException {
BufferedWriter writer = null;
try {
String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
FileOutputStream fos = new FileOutputStream(outputFile);
writer = new BufferedWriter(new OutputStreamWriter(fos, charset));
boolean isComma = delimeter.equals(",");
// write fields
SimpleFeatureType schema = features.getSchema();
StringBuffer sb = new StringBuffer();
for (AttributeDescriptor descriptor : schema.getAttributeDescriptors()) {
if (sb.length() > 0) {
sb.append(delimeter);
}
sb.append(descriptor.getLocalName());
}
writer.write(sb.append(newLine).toString());
// write contents
SimpleFeatureIterator featureIter = null;
try {
featureIter = features.features();
while (featureIter.hasNext()) {
SimpleFeature feature = featureIter.next();
Geometry origGeom = (Geometry) feature.getDefaultGeometry();
sb.setLength(0);
for (Object value : feature.getAttributes()) {
if (sb.length() > 0) {
sb.append(delimeter);
}
if (value instanceof Geometry) {
if (isComma) {
sb.append("\"").append(origGeom.toText()).append("\"");
} else {
sb.append(origGeom.toText());
}
} else {
sb.append(value == null ? "" : value.toString());
}
}
writer.write(sb.append(newLine).toString());
}
} finally {
featureIter.close();
}
writer.flush();
writer.close();
} catch (FileNotFoundException e) {
ToolboxPlugin.log(e.getMessage());
} finally {
closeQuietly(writer);
}
}
public void encodeGeoJSON(SimpleFeatureCollection features, File outputFile) throws IOException {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFile);
FeatureJSON featureJson = new FeatureJSON();
featureJson.setEncodeFeatureCollectionCRS(true);
featureJson.writeFeatureCollection(features, fos);
} catch (FileNotFoundException e) {
ToolboxPlugin.log(e.getMessage());
} finally {
closeQuietly(fos);
}
}
private void closeQuietly(Closeable io) {
try {
if (io != null) {
io.close();
}
} catch (IOException e) {
LOGGER.log(Level.FINER, e.getMessage(), e);
}
}
}