⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 updateelementhandler.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
字号:
/* 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 net.opengis.wfs.AllSomeType;
import net.opengis.wfs.PropertyType;
import net.opengis.wfs.TransactionResponseType;
import net.opengis.wfs.TransactionType;
import net.opengis.wfs.UpdateElementType;
import org.eclipse.emf.ecore.EObject;
import org.geoserver.feature.ReprojectingFeatureCollection;
import org.geotools.data.FeatureLocking;
import org.geotools.data.FeatureStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.AttributeType;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureType;
import org.geotools.feature.type.GeometricAttributeType;
import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.referencing.operation.projection.PointOutsideEnvelopeException;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.Id;
import org.opengis.filter.expression.PropertyName;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.vfny.geoserver.global.FeatureTypeInfo;

import com.vividsolutions.jts.geom.Geometry;

import java.io.IOException;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.Logger;
import javax.xml.namespace.QName;


/**
 * Processes standard update elements
 *
 * @author Andrea Aime - TOPP
 *
 */
public class UpdateElementHandler implements TransactionElementHandler {
    /**
     * logger
     */
    static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.wfs");
    private WFS wfs;

    public UpdateElementHandler(WFS wfs) {
        this.wfs = wfs;
    }

    public void checkValidity(EObject element, Map typeInfos)
        throws WFSTransactionException {
        // check inserts are enabled
        if ((wfs.getServiceLevel() & WFS.SERVICE_UPDATE) == 0) {
            throw new WFSException("Transaction Update support is not enabled");
        }

        FilterFactory ff = CommonFactoryFinder.getFilterFactory( null );
        
        // check that all required properties have a specified value
        UpdateElementType update = (UpdateElementType) element;

        try {
            FeatureTypeInfo meta = (FeatureTypeInfo) typeInfos.values().iterator().next();
            FeatureType featureType = meta.getFeatureType();

            for (Iterator prop = update.getProperty().iterator(); prop.hasNext();) {
                PropertyType property = (PropertyType) prop.next();

                //check that valus that are non-nillable exist
                if (property.getValue() == null) {
                    String propertyName = property.getName().getLocalPart();
                    AttributeType attributeType = featureType.getAttributeType(propertyName);

                    if ((attributeType != null) && (attributeType.getMinOccurs() > 0)) {
                        String msg = "Property '" + attributeType.getLocalName()
                            + "' is mandatory but no value specified.";
                        throw new WFSException(msg, "MissingParameterValue");
                    }
                }
                
                //check that property names are actually valid
                QName name = property.getName();
                PropertyName propertyName = null;
                
                if ( name.getPrefix() != null && !"".equals( name.getPrefix() )) {
                    propertyName = ff.property( name.getPrefix() + ":" + name.getLocalPart() );
                }
                else {
                    propertyName = ff.property( name.getLocalPart() ); 
                }
                
                if ( propertyName.evaluate( featureType ) == null ) {
                    String msg = "No such property: " + property.getName();
                    throw new WFSException( msg );
                }
            }
        } catch (IOException e) {
            throw new WFSTransactionException("Could not locate feature type information for "
                + update.getTypeName(), e, update.getHandle());
        }
    }

    public void execute(EObject element, TransactionType request, Map featureStores,
        TransactionResponseType response, TransactionListener listener)
        throws WFSTransactionException {
        UpdateElementType update = (UpdateElementType) element;
        QName elementName = update.getTypeName();
        String handle = update.getHandle();
        long updated = response.getTransactionSummary().getTotalUpdated().longValue();

        FeatureStore store = (FeatureStore) featureStores.get(elementName);

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

        LOGGER.finer("Transaction Update:" + element);

        try {
            Filter filter = (Filter) update.getFilter();
            
            
            // make sure all geometric elements in the filter have a crs, and that the filter
            // is reprojected to store's native crs as well
            CoordinateReferenceSystem declaredCRS = WFSReprojectionUtil.getDeclaredCrs(
                    store.getSchema(), request.getVersion());
            filter = WFSReprojectionUtil.normalizeFilterCRS(filter, store.getSchema(), declaredCRS);


            AttributeType[] types = new AttributeType[update.getProperty().size()];
            Object[] values = new Object[update.getProperty().size()];

            for (int j = 0; j < update.getProperty().size(); j++) {
                PropertyType property = (PropertyType) update.getProperty().get(j);
                types[j] = store.getSchema().getAttributeType(property.getName().getLocalPart());
                values[j] = property.getValue();
                
                // if geometry, it may be necessary to reproject it to the native CRS before
                // update
                if (values[j] instanceof Geometry ) {
                    Geometry geometry = (Geometry) values[j];
                    
                    // get the source crs, check the geometry itself first. If not set, assume
                    // the default one
                    CoordinateReferenceSystem source = null;
                    if ( geometry.getUserData() instanceof CoordinateReferenceSystem ) {
                        source = (CoordinateReferenceSystem) geometry.getUserData();
                    } else {
                        geometry.setUserData(declaredCRS);
                        source = declaredCRS;
                    }
                    
                    // see if the geometry has a CRS other than the default one
                    CoordinateReferenceSystem target = null;
                    if (types[j] instanceof GeometricAttributeType) {
                        target = ((GeometricAttributeType)types[j]).getCoordinateSystem();
                    }
                    
                    if(wfs.getCiteConformanceHacks())
                        JTS.checkCoordinatesRange(geometry, source != null ? source : target);
                    
                    //if we have a source and target and they are not equal, do 
                    // the reprojection, otherwise just update the value as is
                    if ( source != null && target != null && !CRS.equalsIgnoreMetadata(source, target)) {
                        try {
                            //TODO: this code should be shared with the code
                            // from ReprojectingFeatureCollection --JD
                            MathTransform tx = CRS.findMathTransform(source, target);
                            GeometryCoordinateSequenceTransformer gtx = 
                                new GeometryCoordinateSequenceTransformer();
                            gtx.setMathTransform(tx);
                            
                            values[j] = gtx.transform(geometry);    
                        }
                        catch( Exception e ) {
                            String msg = "Failed to reproject geometry:" + e.getLocalizedMessage(); 
                            throw new WFSTransactionException( msg, e );
                        }
                    }
                    
                }
            }

            // Pass through data to collect fids and damaged
            // region
            // for validation
            //
            Set fids = new HashSet();
            LOGGER.finer("Preprocess to remember modification as a set of fids");
            
            FeatureCollection features = store.getFeatures(filter);
            listener.dataStoreChange(new TransactionEvent(TransactionEventType.PRE_UPDATE, features));

            Iterator preprocess = features.iterator();

            try {
                while (preprocess.hasNext()) {
                    Feature feature = (Feature) preprocess.next();
                    fids.add(feature.getID());
                }
            } catch (NoSuchElementException e) {
                throw new WFSException("Could not aquire FeatureIDs", e);
            } finally {
                features.close(preprocess);
            }

            try {
                if (types.length == 1) {
                    store.modifyFeatures(types[0], values[0], filter);
                } else {
                    store.modifyFeatures(types, values, filter);
                }
            } finally {
                // make sure we unlock
                if ((request.getLockId() != null) && store instanceof FeatureLocking
                        && (request.getReleaseAction() == AllSomeType.SOME_LITERAL)) {
                    FeatureLocking locking = (FeatureLocking) store;
                    locking.unLockFeatures(filter);
                }
            }

            // Post process - gather the same features after the update, and  
            if (!fids.isEmpty()) {
                LOGGER.finer("Post process update for boundary update and featureValidation");

                Set featureIds = new HashSet();

                FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
                for (Iterator f = fids.iterator(); f.hasNext();) {
                    featureIds.add(ff.featureId((String) f.next()));
                }

                Id modified = ff.id(featureIds);

                FeatureCollection changed = store.getFeatures(modified);
                listener.dataStoreChange(new TransactionEvent(TransactionEventType.POST_UPDATE,
                        changed));
            }

            // update the update counter
            updated += fids.size();
        } catch (IOException ioException) {
            // JD: changing from throwing service exception to
            // adding action that failed
            throw new WFSTransactionException(ioException, null, handle);
        } catch(PointOutsideEnvelopeException poe) {
            throw new WFSTransactionException(poe, null, handle);
        }

        // update transaction summary
        response.getTransactionSummary().setTotalUpdated(BigInteger.valueOf(updated));
    }

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

    public QName[] getTypeNames(EObject element) throws WFSTransactionException {
        return new QName[] { ((UpdateElementType) element).getTypeName() };
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -