view gnv-artifacts/src/main/java/de/intevation/gnv/utils/ShapeFileWriter.java @ 1030:c07d9f9a738c

Removed bugs that existed in the caching mechanism (issue264, issue268). gnv-artifacts/trunk@1067 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 06 May 2010 08:32:56 +0000
parents 2cea76f1112e
children f953c9a559d8
line wrap: on
line source
package de.intevation.gnv.utils;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureStore;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.geobackend.base.ResultDescriptor;

/**
 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
 */
public final class ShapeFileWriter
{
    private static Logger log = Logger.getLogger(
        ShapeFileWriter.class);

    private static NumberFormat format = NumberFormat.getInstance();

    /**
     * Precision used to format double values.
     */
    public static final int DOUBLE_PRECISION = 3;

    static {
        format.setMaximumFractionDigits(DOUBLE_PRECISION);
    }

    private ShapeFileWriter() {
    }


    /**
     * Write multilinestrings to shapefile.
     *
     * @param shapeFile Shapefile.
     * @param parameterId The parameter id.
     * @param layer The layer.
     * @param date The date.
     * @param multiLineStrings The multilinestring.
     * @return true, if shapefile writing was successful - otherwise false.
     */
    public static boolean writeMultiLineStringsToFile(
        File                                shapeFile,
        Integer                             parameterId,
        Integer                             layer,
        Date                                date,
        List<Pair<Object, MultiLineString>> multiLineStrings
    ) {
        return writeMultiLineStringsToFile(
            shapeFile,
            parameterId,
            layer,
            date,
            multiLineStrings,
            "isolines");
    }


    /**
     * Write multilinestrings to shapefile.
     *
     * @param shapeFile Shapefile.
     * @param parameterId The parameter id.
     * @param layer The layer.
     * @param date The date.
     * @param multiLineStrings The multilinestring.
     * @param name A name.
     * @return true, if shapefile writing was successful - otherwise false.
     */
    public static boolean writeMultiLineStringsToFile(
        File                                shapeFile,
        Integer                             parameterId,
        Integer                             layer,
        Date                                date,
        List<Pair<Object, MultiLineString>> multiLineStrings,
        String                              name
    ) {
        Map<String, Serializable> params = new HashMap<String, Serializable>();

        try {
            params.put("url", shapeFile.toURI().toURL());
        }
        catch (MalformedURLException mue) {
            log.error(mue.getLocalizedMessage(), mue);
            return false;
        }

        params.put("create spatial index", Boolean.TRUE);


        if (name == null) {
            name = shapeFile.getName();
        }

        SimpleFeatureType TYPE;

        try {
            TYPE = DataUtilities.createType(
                name,
                "geom:MultiLineString:srid=4326," +
                "PARAMETER:Integer," +
                "LAYER:Integer,"     +
                "DATE:Date,"         +
                "VALUE:Double,"       +
                "DESC:String");
        }
        catch (SchemaException se) {
            log.error(se.getLocalizedMessage(), se);
            return false;
        }

        SimpleFeatureBuilder featureBuilder =
            new SimpleFeatureBuilder(TYPE);

        FeatureCollection<SimpleFeatureType, SimpleFeature> collection =
            FeatureCollections.newCollection();

        for (Pair<Object, MultiLineString> pair: multiLineStrings) {
            featureBuilder.add(pair.getB());
            featureBuilder.add(parameterId);
            featureBuilder.add(layer);
            featureBuilder.add(date);
            featureBuilder.add(pair.getA());
            featureBuilder.add(value2description(asDouble(pair.getA())));
            SimpleFeature feature = featureBuilder.buildFeature(null);
            collection.add(feature);
        }

        DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();

        Transaction transaction = null;

        boolean success = false;
        try {
            ShapefileDataStore newDataStore =
                (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);

            newDataStore.createSchema(TYPE);
            newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

            transaction = new DefaultTransaction("create");

            String typeName = newDataStore.getTypeNames()[0];

            FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
                (FeatureStore<SimpleFeatureType, SimpleFeature>)
                    newDataStore.getFeatureSource(typeName);

            featureStore.setTransaction(transaction);

            featureStore.addFeatures(collection);
            transaction.commit();
            success = true;
        }
        catch (IOException ioe) {
            log.error(ioe.getLocalizedMessage(), ioe);
        }
        finally {
            if (transaction != null) {
                if (!success) {
                    try { transaction.rollback(); }
                    catch (IOException ioe) {}
                }
                try { transaction.close(); }
                catch (IOException ioe) {}
            }
        }

        return success;
    }


    /**
     * Write multipolygon to file.
     *
     * @param shapeFile The shapefile.
     * @param parameterId The parameter id.
     * @param layer The layer.
     * @param date The date.
     * @param multiPolygons Multipolygons.
     * @return true, if shapefile writing was successful - otherwise false.
     */
    public static boolean writeMultiPolygonsToFile(
        File                       shapeFile,
        Integer                    parameterId,
        Integer                    layer,
        Date                       date,
        Map<Integer, MultiPolygon> multiPolygons
    ) {
        return writeMultiPolygonsToFile(
            shapeFile,
            parameterId,
            layer,
            date,
            multiPolygons,
            "polygons");
    }


    /**
     * Write data to shapefile.
     *
     * @param shapeFile The shapefile.
     * @param name The name.
     * @param data The data.
     * @param geometryType The geometry type.
     * @return true, if shapefile writing was successful - otherwise false.
     */
    public static boolean writeDataToFile(File shapeFile,
                                          String name,
                                          Collection<Result> data,
                                          String geometryType){

        WKTReader wktReader = new WKTReader();

        Map<String, Serializable> params = new HashMap<String, Serializable>();

        try {
            params.put("url", shapeFile.toURI().toURL());
        }
        catch (MalformedURLException mue) {
            log.error(mue.getLocalizedMessage(), mue);
            return false;
        }

        params.put("create spatial index", Boolean.TRUE);


        if (name == null) {
            name = shapeFile.getName();
        }

        SimpleFeatureType type = null;
        SimpleFeatureBuilder featureBuilder = null;
        FeatureCollection<SimpleFeatureType, SimpleFeature> collection =
            FeatureCollections.newCollection();
        int j = 0;
        for (Result result: data) {
            j++;
            try {
                Geometry g = wktReader.read(result.getString(0));
                ResultDescriptor rd = result.getResultDescriptor();
                int columns = rd.getColumnCount();
                if (type == null){
                    try {
                        String schema = "geom:"+geometryType+":srid=4326";
                        for (int i = 1; i < columns; i++){
                            schema+=","+rd.getColumnName(i)+
                                    ":"+rd.getColumnClassName(i);
                        }
                        type = DataUtilities.createType(name, schema);
                    }
                    catch (SchemaException se) {
                        log.error(se.getLocalizedMessage(), se);
                        return false;
                    }
                    featureBuilder = new SimpleFeatureBuilder(type);
                }
                featureBuilder.add(g);
                for (int i = 1; i < columns; i++){
                    featureBuilder.add(result.getObject(i));
                }
                SimpleFeature feature = featureBuilder.buildFeature(null);
                collection.add(feature);
            } catch (ParseException e) {
                log.error("cannot create geometry "+j+" for "+result.getString(0));
            } catch (java.lang.IllegalArgumentException e){
                log.error("cannot create geometry for "+result.getString(0));
            }
        }

        DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();

        Transaction transaction = null;

        boolean success = false;
        try {
            ShapefileDataStore newDataStore =
                (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);

            newDataStore.createSchema(type);
            newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

            transaction = new DefaultTransaction("create");

            String typeName = newDataStore.getTypeNames()[0];

            FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
                (FeatureStore<SimpleFeatureType, SimpleFeature>)
                    newDataStore.getFeatureSource(typeName);

            featureStore.setTransaction(transaction);

            featureStore.addFeatures(collection);
            transaction.commit();
            success = true;
        }
        catch (IOException ioe) {
            log.error(ioe.getLocalizedMessage(), ioe);
        }
        finally {
            if (transaction != null) {
                if (!success) {
                    try { transaction.rollback(); }
                    catch (IOException ioe) {}
                }
                try { transaction.close(); }
                catch (IOException ioe) {}
            }
        }

        return true;
    }


    /**
     * Write multipolygons to file.
     *
     * @param shapeFile The shapefile.
     * @param parameterId The parameter id.
     * @param layer The layer.
     * @param date The date.
     * @param multiPolygons Multipolygons.
     * @param name A name.
     * @return true, if shapefile writing was successful - otherwise false.
     */
    public static boolean writeMultiPolygonsToFile(
        File                       shapeFile,
        Integer                    parameterId,
        Integer                    layer,
        Date                       date,
        Map<Integer, MultiPolygon> multiPolygons,
        String                     name
    ) {
        Map<String, Serializable> params = new HashMap<String, Serializable>();

        try {
            params.put("url", shapeFile.toURI().toURL());
        }
        catch (MalformedURLException mue) {
            log.error(mue.getLocalizedMessage(), mue);
            return false;
        }

        params.put("create spatial index", Boolean.TRUE);


        if (name == null) {
            name = shapeFile.getName();
        }

        SimpleFeatureType TYPE;

        try {
            TYPE = DataUtilities.createType(
                name,
                "geom:MultiPolygon:srid=4326," +
                "PARAMETER:Integer," +
                "LAYER:Integer,"     +
                "DATE:Date,"         +
                "CLASS:Integer");
        }
        catch (SchemaException se) {
            log.error(se.getLocalizedMessage(), se);
            return false;
        }

        SimpleFeatureBuilder featureBuilder =
            new SimpleFeatureBuilder(TYPE);

        FeatureCollection<SimpleFeatureType, SimpleFeature> collection =
            FeatureCollections.newCollection();

        for (Map.Entry<Integer, MultiPolygon> entry:
            multiPolygons.entrySet()
        ) {
            featureBuilder.add(entry.getValue());
            featureBuilder.add(parameterId);
            featureBuilder.add(layer);
            featureBuilder.add(date);
            featureBuilder.add(entry.getKey());
            SimpleFeature feature = featureBuilder.buildFeature(null);
            collection.add(feature);
        }

        DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory();

        Transaction transaction = null;

        boolean success = false;
        try {
            ShapefileDataStore newDataStore =
                (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);

            newDataStore.createSchema(TYPE);
            newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

            transaction = new DefaultTransaction("create");

            String typeName = newDataStore.getTypeNames()[0];

            FeatureStore<SimpleFeatureType, SimpleFeature> featureStore =
                (FeatureStore<SimpleFeatureType, SimpleFeature>)
                    newDataStore.getFeatureSource(typeName);

            featureStore.setTransaction(transaction);

            featureStore.addFeatures(collection);
            transaction.commit();
            success = true;
        }
        catch (IOException ioe) {
            log.error(ioe.getLocalizedMessage(), ioe);
        }
        finally {
            if (transaction != null) {
                if (!success) {
                    try { transaction.rollback(); }
                    catch (IOException ioe) {}
                }
                try { transaction.close(); }
                catch (IOException ioe) {}
            }
        }

        return success;
    }

    /**
     * Returns an object as Double.
     *
     * @param a An object.
     * @return Object <i>a</i> as Double. If <i>a</i> is not a double and no
     * number, 0d is returned.
     */
    private static final Double asDouble(Object a) {
        if (a instanceof Double) {
            return (Double)a;
        }
        if (a instanceof Number) {
            return Double.valueOf(((Number)a).doubleValue());
        }
        return 0d;
    }

    /**
     * Turns a double value into a string representation taking account of the
     * locale.
     *
     * @param value A double value.
     * @return The double value formatted as string.
     */
    private static final String value2description(Double value) {
        return format.format(value);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org