sascha@465: package de.intevation.gnv.utils;
sascha@465: 
sascha@465: import java.io.File;
sascha@465: import java.io.IOException;
sascha@498: import java.io.Serializable;
sascha@465: import java.net.MalformedURLException;
tim@649: import java.util.Collection;
sascha@498: import java.util.Date;
sascha@498: import java.util.HashMap;
sascha@498: import java.util.List;
sascha@498: import java.util.Map;
sascha@465: 
sascha@498: import org.apache.log4j.Logger;
sascha@498: import org.geotools.data.DataStoreFactorySpi;
sascha@465: import org.geotools.data.DataUtilities;
sascha@465: import org.geotools.data.DefaultTransaction;
sascha@498: import org.geotools.data.FeatureStore;
sascha@498: import org.geotools.data.Transaction;
sascha@465: import org.geotools.data.shapefile.ShapefileDataStore;
sascha@465: import org.geotools.data.shapefile.ShapefileDataStoreFactory;
sascha@498: import org.geotools.feature.FeatureCollection;
sascha@498: import org.geotools.feature.FeatureCollections;
sascha@498: import org.geotools.feature.SchemaException;
sascha@498: import org.geotools.feature.simple.SimpleFeatureBuilder;
sascha@498: import org.geotools.referencing.crs.DefaultGeographicCRS;
sascha@498: import org.opengis.feature.simple.SimpleFeature;
sascha@498: import org.opengis.feature.simple.SimpleFeatureType;
sascha@465: 
tim@649: import com.vividsolutions.jts.geom.Geometry;
tim@649: import com.vividsolutions.jts.geom.MultiLineString;
tim@649: import com.vividsolutions.jts.geom.MultiPolygon;
tim@649: import com.vividsolutions.jts.io.ParseException;
tim@649: import com.vividsolutions.jts.io.WKTReader;
tim@649: 
tim@649: import de.intevation.gnv.geobackend.base.Result;
tim@727: import de.intevation.gnv.geobackend.base.ResultDescriptor;
tim@649: 
sascha@465: /**
sascha@465:  * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
sascha@465:  */
sascha@465: public final class ShapeFileWriter
sascha@465: {
sascha@465:     private static Logger log = Logger.getLogger(
sascha@465:         ShapeFileWriter.class);
sascha@465: 
sascha@465:     private ShapeFileWriter() {
sascha@465:     }
sascha@465: 
sascha@465:     public static boolean writeMultiLineStringsToFile(
sascha@465:         File                                shapeFile,
sascha@498:         Integer                             parameterId,
sascha@498:         Integer                             layer,
sascha@498:         Date                                date,
sascha@465:         List<Pair<Object, MultiLineString>> multiLineStrings
sascha@465:     ) {
sascha@498:         return writeMultiLineStringsToFile(
sascha@498:             shapeFile,
sascha@498:             parameterId,
sascha@498:             layer,
sascha@498:             date,
sascha@498:             multiLineStrings, 
sascha@498:             "isolines");
sascha@465:     }
sascha@465: 
sascha@465:     public static boolean writeMultiLineStringsToFile(
sascha@465:         File                                shapeFile,
sascha@498:         Integer                             parameterId,
sascha@498:         Integer                             layer,
sascha@498:         Date                                date,
sascha@465:         List<Pair<Object, MultiLineString>> multiLineStrings,
sascha@498:         String                              name
sascha@465:     ) {
sascha@498:         Map<String, Serializable> params = new HashMap<String, Serializable>();
sascha@465: 
sascha@465:         try {
sascha@498:             params.put("url", shapeFile.toURI().toURL());
sascha@465:         }
sascha@465:         catch (MalformedURLException mue) {
sascha@465:             log.error(mue.getLocalizedMessage(), mue);
sascha@465:             return false;
sascha@465:         }
sascha@465: 
sascha@498:         params.put("create spatial index", Boolean.TRUE);
sascha@465: 
sascha@465: 
sascha@498:         if (name == null) {
sascha@498:             name = shapeFile.getName();
sascha@498:         }
sascha@465: 
sascha@498:         SimpleFeatureType TYPE;
sascha@498:         
sascha@498:         try { 
sascha@498:             TYPE = DataUtilities.createType(
sascha@498:                 name,
sascha@498:                 "geom:MultiLineString:srid=4326," +
sascha@498:                 "PARAMETER:Integer," + 
sascha@498:                 "LAYER:Integer,"     +
sascha@498:                 "DATE:Date,"         +
sascha@498:                 "VALUE:Double");
sascha@465:         }
sascha@465:         catch (SchemaException se) {
sascha@465:             log.error(se.getLocalizedMessage(), se);
sascha@498:             return false;
sascha@465:         }
sascha@498: 
sascha@498:         SimpleFeatureBuilder featureBuilder =
sascha@498:             new SimpleFeatureBuilder(TYPE);
sascha@498: 
sascha@498:         FeatureCollection<SimpleFeatureType, SimpleFeature> collection = 
sascha@498:             FeatureCollections.newCollection();
sascha@498: 
sascha@498:         for (Pair<Object, MultiLineString> pair: multiLineStrings) {
sascha@498:             featureBuilder.add(pair.getB());
sascha@498:             featureBuilder.add(parameterId);
sascha@498:             featureBuilder.add(layer);
sascha@498:             featureBuilder.add(date);
sascha@498:             featureBuilder.add(pair.getA());
sascha@498:             SimpleFeature feature = featureBuilder.buildFeature(null);
sascha@498:             collection.add(feature);
sascha@498:         }
sascha@498: 
sascha@498:         DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();
sascha@498: 
sascha@498:         Transaction transaction = null;
sascha@498: 
sascha@498:         boolean success = false;
sascha@498:         try {
sascha@498:             ShapefileDataStore newDataStore =
sascha@498:                 (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
sascha@498: 
sascha@498:             newDataStore.createSchema(TYPE);
sascha@498:             newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
sascha@498: 
sascha@498:             transaction = new DefaultTransaction("create");
sascha@498: 
sascha@498:             String typeName = newDataStore.getTypeNames()[0];
sascha@498: 
sascha@498:             FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
sascha@498:                 (FeatureStore<SimpleFeatureType, SimpleFeature>)
sascha@498:                     newDataStore.getFeatureSource(typeName);
sascha@498: 
sascha@498:             featureStore.setTransaction(transaction);
sascha@498: 
sascha@498:             featureStore.addFeatures(collection);
sascha@498:             transaction.commit();
sascha@498:             success = true;
sascha@498:         } 
sascha@465:         catch (IOException ioe) {
sascha@465:             log.error(ioe.getLocalizedMessage(), ioe);
sascha@465:         }
sascha@465:         finally {
sascha@498:             if (transaction != null) {
sascha@498:                 if (!success) {
sascha@498:                     try { transaction.rollback(); }
sascha@498:                     catch (IOException ioe) {}
sascha@498:                 }
sascha@498:                 try { transaction.close(); }
sascha@465:                 catch (IOException ioe) {}
sascha@465:             }
sascha@465:         }
sascha@465: 
sascha@465:         return success;
sascha@465:     }
sascha@465: 
sascha@465:     public static boolean writeMultiPolygonsToFile(
sascha@465:         File                       shapeFile,
sascha@498:         Integer                    parameterId,
sascha@498:         Integer                    layer,
sascha@498:         Date                       date,
sascha@465:         Map<Integer, MultiPolygon> multiPolygons
sascha@465:     ) {
sascha@498:         return writeMultiPolygonsToFile(
sascha@498:             shapeFile, 
sascha@498:             parameterId,
sascha@498:             layer,
sascha@498:             date,
sascha@498:             multiPolygons, 
sascha@498:             "polygons");
sascha@465:     }
sascha@465: 
tim@649:     
tim@655:     public static String writeDataToFile(File shapeFile,
tim@649:                                           String name,
tim@649:                                           Collection<Result> data){
tim@655:         String geomType = null;
tim@655:         
tim@649:         WKTReader wktReader = new WKTReader();
tim@649:         
tim@649:         Map<String, Serializable> params = new HashMap<String, Serializable>();
tim@649: 
tim@649:         try {
tim@649:             params.put("url", shapeFile.toURI().toURL());
tim@649:         }
tim@649:         catch (MalformedURLException mue) {
tim@649:             log.error(mue.getLocalizedMessage(), mue);
tim@655:             return null;
tim@649:         }
tim@649: 
tim@649:         params.put("create spatial index", Boolean.TRUE);
tim@649: 
tim@649: 
tim@649:         if (name == null) {
tim@649:             name = shapeFile.getName();
tim@649:         }
tim@649: 
tim@649:         SimpleFeatureType type = null;
tim@649:         SimpleFeatureBuilder featureBuilder = null;
tim@649:         FeatureCollection<SimpleFeatureType, SimpleFeature> collection = 
tim@649:             FeatureCollections.newCollection();
tim@727:         int j = 0;
tim@649:         for (Result result: data) {
tim@727:             j++;
tim@649:             try {
tim@649:                 Geometry g = wktReader.read(result.getString(0));
tim@727:                 ResultDescriptor rd = result.getResultDescriptor();
tim@727:                 int columns = rd.getColumnCount();
tim@649:                 if (type == null){
tim@649:                     try { 
tim@655:                         geomType = g.getGeometryType().toUpperCase();
tim@727:                         String schema = "geom:"+g.getGeometryType()+":srid=4326";
tim@727:                         for (int i = 1; i < columns; i++){
tim@727:                             schema+=","+rd.getColumnName(i)+
tim@727:                                     ":"+rd.getColumnClassName(i);
tim@727:                         }
tim@727:                         type = DataUtilities.createType(name, schema);
tim@649:                     }
tim@649:                     catch (SchemaException se) {
tim@649:                         log.error(se.getLocalizedMessage(), se);
tim@655:                         return null;
tim@649:                     }
tim@649:                     featureBuilder = new SimpleFeatureBuilder(type);
tim@649:                 }
tim@649:                 featureBuilder.add(g);
tim@727:                 for (int i = 1; i < columns; i++){
tim@727:                     featureBuilder.add(result.getObject(i));
tim@727:                 }
tim@649:                 SimpleFeature feature = featureBuilder.buildFeature(null);
tim@649:                 collection.add(feature);
tim@649:             } catch (ParseException e) {
tim@727:                 log.error("cannot create geometry "+j+" for "+result.getString(0));
tim@649:             } catch (java.lang.IllegalArgumentException e){
tim@649:                 log.error("cannot create geometry for "+result.getString(0));
tim@649:             }
tim@649:         }
tim@649: 
tim@649:         DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();
tim@649: 
tim@649:         Transaction transaction = null;
tim@649: 
tim@649:         boolean success = false;
tim@649:         try {
tim@649:             ShapefileDataStore newDataStore =
tim@649:                 (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
tim@649: 
tim@649:             newDataStore.createSchema(type);
tim@649:             newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
tim@649: 
tim@649:             transaction = new DefaultTransaction("create");
tim@649: 
tim@649:             String typeName = newDataStore.getTypeNames()[0];
tim@649: 
tim@649:             FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
tim@649:                 (FeatureStore<SimpleFeatureType, SimpleFeature>)
tim@649:                     newDataStore.getFeatureSource(typeName);
tim@649: 
tim@649:             featureStore.setTransaction(transaction);
tim@649: 
tim@649:             featureStore.addFeatures(collection);
tim@649:             transaction.commit();
tim@649:             success = true;
tim@649:         } 
tim@649:         catch (IOException ioe) {
tim@649:             log.error(ioe.getLocalizedMessage(), ioe);
tim@649:         }
tim@649:         finally {
tim@649:             if (transaction != null) {
tim@649:                 if (!success) {
tim@649:                     try { transaction.rollback(); }
tim@649:                     catch (IOException ioe) {}
tim@649:                 }
tim@649:                 try { transaction.close(); }
tim@649:                 catch (IOException ioe) {}
tim@649:             }
tim@649:         }
tim@649: 
tim@655:         return geomType;
tim@649:         
tim@649:     }
tim@649:     
sascha@465:     public static boolean writeMultiPolygonsToFile(
sascha@465:         File                       shapeFile,
sascha@498:         Integer                    parameterId,
sascha@498:         Integer                    layer,
sascha@498:         Date                       date,
sascha@465:         Map<Integer, MultiPolygon> multiPolygons,
sascha@498:         String                     name
sascha@465:     ) {
sascha@498:         Map<String, Serializable> params = new HashMap<String, Serializable>();
sascha@465: 
sascha@465:         try {
sascha@498:             params.put("url", shapeFile.toURI().toURL());
sascha@465:         }
sascha@465:         catch (MalformedURLException mue) {
sascha@465:             log.error(mue.getLocalizedMessage(), mue);
sascha@465:             return false;
sascha@465:         }
sascha@465: 
sascha@498:         params.put("create spatial index", Boolean.TRUE);
sascha@465: 
sascha@465: 
sascha@498:         if (name == null) {
sascha@498:             name = shapeFile.getName();
sascha@498:         }
sascha@465: 
sascha@498:         SimpleFeatureType TYPE;
sascha@498:         
sascha@498:         try { 
sascha@498:             TYPE = DataUtilities.createType(
sascha@498:                 name,
sascha@498:                 "geom:MultiPolygon:srid=4326," +
sascha@498:                 "PARAMETER:Integer," + 
sascha@498:                 "LAYER:Integer,"     +
sascha@498:                 "DATE:Date,"         +
sascha@498:                 "CLASS:Integer");
sascha@465:         }
sascha@465:         catch (SchemaException se) {
sascha@465:             log.error(se.getLocalizedMessage(), se);
sascha@498:             return false;
sascha@465:         }
sascha@498: 
sascha@498:         SimpleFeatureBuilder featureBuilder =
sascha@498:             new SimpleFeatureBuilder(TYPE);
sascha@498: 
sascha@498:         FeatureCollection<SimpleFeatureType, SimpleFeature> collection = 
sascha@498:             FeatureCollections.newCollection();
sascha@498: 
sascha@498:         for (Map.Entry<Integer, MultiPolygon> entry:
sascha@498:             multiPolygons.entrySet()
sascha@498:         ) {
sascha@498:             featureBuilder.add(entry.getValue());
sascha@498:             featureBuilder.add(parameterId);
sascha@498:             featureBuilder.add(layer);
sascha@498:             featureBuilder.add(date);
sascha@498:             featureBuilder.add(entry.getKey());
sascha@498:             SimpleFeature feature = featureBuilder.buildFeature(null);
sascha@498:             collection.add(feature);
sascha@498:         }
sascha@498: 
sascha@498:         DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();
sascha@498: 
sascha@498:         Transaction transaction = null;
sascha@498: 
sascha@498:         boolean success = false;
sascha@498:         try {
sascha@498:             ShapefileDataStore newDataStore =
sascha@498:                 (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
sascha@498: 
sascha@498:             newDataStore.createSchema(TYPE);
sascha@498:             newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
sascha@498: 
sascha@498:             transaction = new DefaultTransaction("create");
sascha@498: 
sascha@498:             String typeName = newDataStore.getTypeNames()[0];
sascha@498: 
sascha@498:             FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
sascha@498:                 (FeatureStore<SimpleFeatureType, SimpleFeature>)
sascha@498:                     newDataStore.getFeatureSource(typeName);
sascha@498: 
sascha@498:             featureStore.setTransaction(transaction);
sascha@498: 
sascha@498:             featureStore.addFeatures(collection);
sascha@498:             transaction.commit();
sascha@498:             success = true;
sascha@498:         } 
sascha@465:         catch (IOException ioe) {
sascha@465:             log.error(ioe.getLocalizedMessage(), ioe);
sascha@465:         }
sascha@465:         finally {
sascha@498:             if (transaction != null) {
sascha@498:                 if (!success) {
sascha@498:                     try { transaction.rollback(); }
sascha@498:                     catch (IOException ioe) {}
sascha@498:                 }
sascha@498:                 try { transaction.close(); }
sascha@465:                 catch (IOException ioe) {}
sascha@465:             }
sascha@465:         }
sascha@465: 
sascha@465:         return success;
sascha@465:     }
sascha@465: 
sascha@465:     private static final Double asDouble(Object a) {
sascha@498:         if (a instanceof Double) {
sascha@465:             return (Double)a;
sascha@498:         }
sascha@498:         if (a instanceof Number) {
sascha@465:             return Double.valueOf(((Number)a).doubleValue());
sascha@498:         }
sascha@465:         return 0d;
sascha@465:     }
sascha@465: }
sascha@465: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :