Package org.geoserver.wfs

Source Code of org.geoserver.wfs.InsertElementHandler

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wfs;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

import net.opengis.wfs.InsertElementType;
import net.opengis.wfs.InsertedFeatureType;
import net.opengis.wfs.TransactionResponseType;
import net.opengis.wfs.TransactionType;
import net.opengis.wfs.WfsFactory;

import org.eclipse.emf.ecore.EObject;
import org.geoserver.config.GeoServer;
import org.geoserver.feature.ReprojectingFeatureCollection;
import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.operation.projection.PointOutsideEnvelopeException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.identity.FeatureId;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Geometry;


/**
* Handler for the insert element
*
* @author Andrea Aime - TOPP
*
*/
public class InsertElementHandler extends AbstractTransactionElementHandler {
    /**
     * logger
     */
    static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.wfs");
    private FilterFactory filterFactory;

    public InsertElementHandler(GeoServer gs, FilterFactory filterFactory) {
        super(gs);
        this.filterFactory = filterFactory;
    }

    public void checkValidity(EObject element, Map featureTypeInfos)
        throws WFSTransactionException {
        if (!getInfo().getServiceLevel().getOps().contains( WFSInfo.Operation.TRANSACTION_INSERT)) {
            throw new WFSException("Transaction INSERT support is not enabled");
        }
    }

    @SuppressWarnings("unchecked")
    public void execute(EObject element, TransactionType request, Map featureStores,
        TransactionResponseType response, TransactionListener listener)
        throws WFSTransactionException {
        LOGGER.finer("Transasction Insert:" + element);

        InsertElementType insert = (InsertElementType) element;
        long inserted = response.getTransactionSummary().getTotalInserted().longValue();

        try {
            // group features by their schema
            HashMap /* <SimpleFeatureType,FeatureCollection> */ schema2features = new HashMap();

            for (Iterator f = insert.getFeature().iterator(); f.hasNext();) {
                SimpleFeature feature = (SimpleFeature) f.next();
                SimpleFeatureType schema = feature.getFeatureType();
                SimpleFeatureCollection collection;
                collection = (SimpleFeatureCollection) schema2features.get(schema);

                if (collection == null) {
                    collection = new DefaultFeatureCollection(null, schema);
                    schema2features.put(schema, collection);
                }

                collection.add(feature);
            }

            // JD: change from set fo list because if inserting
            // features into different feature stores, they could very well
            // get given the same id
            // JD: change from list to map so that the map can later be
            // processed and we can report the fids back in the same order
            // as they were supplied
            HashMap schema2fids = new HashMap();

            for (Iterator c = schema2features.values().iterator(); c.hasNext();) {
                SimpleFeatureCollection collection = (SimpleFeatureCollection) c.next();
                SimpleFeatureType schema = collection.getSchema();

                final QName elementName = new QName(schema.getName().getNamespaceURI(), schema.getTypeName());
                SimpleFeatureStore store;
                store = DataUtilities.simple((FeatureStore) featureStores.get(elementName));

                if (store == null) {
                    throw new WFSException("Could not locate FeatureStore for '" + elementName
                        + "'");
                }

                if (collection != null) {
                    // if we really need to, make sure we are inserting coordinates that do
                    // match the CRS area of validity
                    if(getInfo().isCiteCompliant()) {
                        checkFeatureCoordinatesRange(collection);
                    }
                   
                    // reprojection
                    final GeometryDescriptor defaultGeometry = store.getSchema().getGeometryDescriptor();
                    if(defaultGeometry != null) {
                        CoordinateReferenceSystem target = defaultGeometry.getCoordinateReferenceSystem();
                        if (target != null) {
                            collection = new ReprojectingFeatureCollection(collection, target);
                        }
                    }
                   
                    // Need to use the namespace here for the
                    // lookup, due to our weird
                    // prefixed internal typenames. see
                    // http://jira.codehaus.org/secure/ViewIssue.jspa?key=GEOS-143

                    // Once we get our datastores making features
                    // with the correct namespaces
                    // we can do something like this:
                    // FeatureTypeInfo typeInfo =
                    // catalog.getFeatureTypeInfo(schema.getTypeName(),
                    // schema.getNamespace());
                    // until then (when geos-144 is resolved) we're
                    // stuck with:
                    // QName qName = (QName) typeNames.get( i );
                    // FeatureTypeInfo typeInfo =
                    // catalog.featureType( qName.getPrefix(),
                    // qName.getLocalPart() );

                    // this is possible with the insert hack above.
                    LOGGER.finer("Use featureValidation to check contents of insert");

                    // featureValidation(
                    // typeInfo.getDataStore().getId(), schema,
                    // collection );
                    List fids = (List) schema2fids.get(schema.getTypeName());

                    if (fids == null) {
                        fids = new LinkedList();
                        schema2fids.put(schema.getTypeName(), fids);
                    }

                    //fire pre insert event
                    TransactionEvent event = new TransactionEvent(TransactionEventType.PRE_INSERT,
                            elementName, collection);
                    event.setSource( insert );
                   
                    listener.dataStoreChange( event );
                    fids.addAll(store.addFeatures(collection));
                   
                    //fire post insert event
                    //event = new TransactionEvent(TransactionEventType.POST_INSERT, elementName, collection, insert );
                    //listener.dataStoreChange( event );
                }
            }

            // report back fids, we need to keep the same order the
            // fids were reported in the original feature collection
            InsertedFeatureType insertedFeature = null;

            for (Iterator f = insert.getFeature().iterator(); f.hasNext();) {
                SimpleFeature feature = (SimpleFeature) f.next();
                SimpleFeatureType schema = feature.getFeatureType();

                // get the next fid
                LinkedList fids = (LinkedList) schema2fids.get(schema.getTypeName());
                String fid = ((FeatureId) fids.removeFirst()).getID();

                insertedFeature = WfsFactory.eINSTANCE.createInsertedFeatureType();
                insertedFeature.setHandle(insert.getHandle());
                insertedFeature.getFeatureId().add(filterFactory.featureId(fid));

                response.getInsertResults().getFeature().add(insertedFeature);
            }

            // update the insert counter
            inserted += insert.getFeature().size();
        } catch (Exception e) {
            String msg = "Error performing insert: " + e.getMessage();
            throw new WFSTransactionException(msg, e, insert.getHandle());
        }

        // update transaction summary
        response.getTransactionSummary().setTotalInserted(BigInteger.valueOf(inserted));
    }

   
    /**
     * Checks that all features coordinates are within the expected coordinate range
     * @param collection
     * @throws PointOutsideEnvelopeException
     */
    void checkFeatureCoordinatesRange(SimpleFeatureCollection collection)
            throws PointOutsideEnvelopeException {
        List types = collection.getSchema().getAttributeDescriptors();
        SimpleFeatureIterator fi = collection.features();
        try {
            while(fi.hasNext()) {
                SimpleFeature f = fi.next();
                for (int i = 0; i < types.size(); i++) {
                    if(types.get(i) instanceof GeometryDescriptor) {
                        GeometryDescriptor gat = (GeometryDescriptor) types.get(i);
                        if(gat.getCoordinateReferenceSystem() != null) {
                            Geometry geom = (Geometry) f.getAttribute(i);
                            if(geom != null)
                                JTS.checkCoordinatesRange(geom, gat.getCoordinateReferenceSystem());
                        }
                    }
                }
            }
        } finally {
            fi.close();
        }
    }

    public Class getElementClass() {
        return InsertElementType.class;
    }

    public QName[] getTypeNames(EObject element) throws WFSTransactionException {
        InsertElementType insert = (InsertElementType) element;
        List typeNames = new ArrayList();

        if (!insert.getFeature().isEmpty()) {
            for (Iterator f = insert.getFeature().iterator(); f.hasNext();) {
                SimpleFeature feature = (SimpleFeature) f.next();

                String name = feature.getFeatureType().getTypeName();
                String namespaceURI = feature.getFeatureType().getName().getNamespaceURI();

                typeNames.add(new QName(namespaceURI, name));
            }
        } else {
            LOGGER.finer("Insert was empty - does not need a FeatuerSoruce");
        }

        return (QName[]) typeNames.toArray(new QName[typeNames.size()]);
    }
}
TOP

Related Classes of org.geoserver.wfs.InsertElementHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.