    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/io/datastore/sde/SDEUpdateHandler.java $
    002    /*----------------    FILE HEADER  ------------------------------------------
    003
    004     This file is part of deegree.
    005     Copyright (C) 2006 by: M.O.S.S. Computer Grafik Systeme GmbH
    006     Hohenbrunner Weg 13
    007     D-82024 Taufkirchen
    008     http://www.moss.de/
    009
    010     This library is free software; you can redistribute it and/or
    011     modify it under the terms of the GNU Lesser General Public
    012     License as published by the Free Software Foundation; either
    013     version 2.1 of the License, or (at your option) any later version.
    014
    015     This library is distributed in the hope that it will be useful,
    016     but WITHOUT ANY WARRANTY; without even the implied warranty of
    017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    018     Lesser General Public License for more details.
    019
    020     You should have received a copy of the GNU Lesser General Public
    021     License along with this library; if not, write to the Free Software
    022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    023
    024     ---------------------------------------------------------------------------*/
    025    package org.deegree.io.datastore.sde;
    026
    027    import java.util.ArrayList;
    028    import java.util.List;
    029    import java.util.Map;
    030
    031    import org.deegree.datatypes.QualifiedName;
    032    import org.deegree.framework.log.ILogger;
    033    import org.deegree.framework.log.LoggerFactory;
    034    import org.deegree.io.datastore.DatastoreException;
    035    import org.deegree.io.datastore.schema.MappedFeatureType;
    036    import org.deegree.io.datastore.schema.MappedGeometryPropertyType;
    037    import org.deegree.io.datastore.schema.MappedPropertyType;
    038    import org.deegree.io.datastore.schema.MappedSimplePropertyType;
    039    import org.deegree.io.datastore.schema.content.MappingField;
    040    import org.deegree.io.datastore.schema.content.MappingGeometryField;
    041    import org.deegree.io.datastore.schema.content.SimpleContent;
    042    import org.deegree.io.datastore.sql.TableAliasGenerator;
    043    import org.deegree.io.sdeapi.SDEAdapter;
    044    import org.deegree.io.sdeapi.SDEConnection;
    045    import org.deegree.model.feature.FeatureProperty;
    046    import org.deegree.model.filterencoding.Filter;
    047    import org.deegree.model.spatialschema.Geometry;
    048    import org.deegree.ogcbase.PropertyPath;
    049
    050    import com.esri.sde.sdk.client.SeColumnDefinition;
    051    import com.esri.sde.sdk.client.SeException;
    052    import com.esri.sde.sdk.client.SeObjectId;
    053    import com.esri.sde.sdk.client.SeRow;
    054    import com.esri.sde.sdk.client.SeShape;
    055    import com.esri.sde.sdk.client.SeState;
    056    import com.esri.sde.sdk.client.SeUpdate;
    057
    058    /**
    059     * Handler for <code>Update</code> operations contained in <code>Transaction</code> requests.
    060     *
    061     * @author <a href="mailto:cpollmann@moss.de">Christoph Pollmann</a>
    062     * @author last edited by: $Author: rbezema $
    063     *
    064     * @version $Revision: 12183 $
    065     */
    066    public class SDEUpdateHandler extends AbstractSDERequestHandler {
    067
    068        private static final ILogger LOG = LoggerFactory.getLogger( SDEUpdateHandler.class );
    069
    070        /**
    071         * Creates a new <code>UpdateHandler</code> from the given parameters.
    072         *
    073         * @param dsTa
    074         * @param aliasGenerator
    075         * @param conn
    076         */
    077        public SDEUpdateHandler( SDETransaction dsTa, TableAliasGenerator aliasGenerator, SDEConnection conn ) {
    078            super( dsTa.getDatastore(), aliasGenerator, conn );
    079        }
    080
    081        /**
    082         * Performs an update operation against the associated datastore.
    083         *
    084         * @param ft
    085         * @param properties
    086         * @param filter
    087         * @return number of updated (root) feature instances
    088         * @throws DatastoreException
    089         */
    090        public int performUpdate( MappedFeatureType ft, Map<PropertyPath, FeatureProperty> properties, Filter filter )
    091                                throws DatastoreException {
    092
    093            // only for statistics???
    094            // FeatureId[] fids = determineAffectedFIDs( mappedFeatureType, filter );
    095
    096            // process properties list
    097            // TODO: has to take care about properties in related tables
    098            ArrayList<MappedPropertyType> list = new ArrayList<MappedPropertyType>();
    099            for ( PropertyPath path : properties.keySet() ) {
    100                QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
    101                MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
    102                if ( pt == null ) {
    103                    String msg = "Internal error: unknown property type " + qn;
    104                    LOG.logDebug( msg );
    105                    throw new DatastoreException( msg );
    106                }
    107                if ( 0 < pt.getTableRelations().length ) {
    108                    String msg = "Update of properties of related tables is not implemented yet " + qn;
    109                    LOG.logDebug( msg );
    110                    throw new DatastoreException( msg );
    111                }
    112                list.add( pt );
    113            }
    114            MappedPropertyType[] mappedPType = list.toArray( new MappedPropertyType[list.size()] );
    115
    116            // prepare update
    117            SDEWhereBuilder whereBuilder = datastore.getWhereBuilder( new MappedFeatureType[] { ft }, null, filter,
    118                                                                      aliasGenerator );
    119            Map<String, List<MappingField>> columnsMap = buildColumnsMap( ft, mappedPType, false );
    120            String[] columns = columnsMap.keySet().toArray( new String[columnsMap.size()] );
    121            Map<MappingField, Integer> mappingFieldsMap = buildMappingFieldMap( columns, columnsMap );
    122            StringBuffer whereCondition = new StringBuffer();
    123            whereBuilder.appendWhereCondition( whereCondition );
    124
    125            try {
    126                SeUpdate updater = new SeUpdate( conn.getConnection() );
    127                updater.setState( conn.getState().getId(), new SeObjectId( SeState.SE_NULL_STATE_ID ),
    128                                  SeState.SE_STATE_DIFF_NOCHECK );
    129                updater.toTable( ft.getTable(), columns, whereCondition.toString() );
    130                updater.setWriteMode( true );
    131                SeRow row = updater.getRowToSet();
    132                if ( row.hasColumns() ) {
    133                    SeColumnDefinition[] cd = row.getColumns();
    134                    for ( int k = 0; k < cd.length; k++ ) {
    135                        LOG.logDebug( "*** col[" + k + "] name=" + cd[k].getName() + " type=" + cd[k].getType() + "/"
    136                                      + typeName( cd[k].getType() ) );
    137                    }
    138                } else {
    139                    LOG.logDebug( "*** no column definitions!!!" );
    140                }
    141
    142                for ( PropertyPath path : properties.keySet() ) {
    143                    QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
    144                    MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
    145                    if ( pt instanceof MappedSimplePropertyType ) {
    146                        SimpleContent content = ( (MappedSimplePropertyType) pt ).getContent();
    147                        if ( content instanceof MappingField ) {
    148                            MappingField field = (MappingField) content;
    149                            Integer resultPos = mappingFieldsMap.get( field );
    150                            Object value = properties.get( path ).getValue();
    151                            SDEAdapter.setRowValue( row, resultPos.intValue(), value,
    152                                                    SDEAdapter.mapSQL2SDE( field.getType() ) );
    153                        }
    154                    } else if ( pt instanceof MappedGeometryPropertyType ) {
    155                        MappingGeometryField field = ( (MappedGeometryPropertyType) pt ).getMappingField();
    156                        Integer resultPos = mappingFieldsMap.get( field );
    157                        SeShape value = (SeShape) datastore.convertDegreeToDBGeometry( (Geometry) properties.get( path ).getValue() );
    158                        row.setShape( resultPos.intValue(), value );
    159                    }
    160                }
    161
    162                updater.execute();
    163                updater.close();
    164            } catch ( SeException e ) {
    165                e.printStackTrace();
    166                throw new DatastoreException( "update failed", e );
    167            }
    168
    169            // return fids.length;
    170            return 1; // don't know, how many rows are affected and don't want to query it only for
    171            // statistics
    172        }
    173
    174        /**
    175         * @param type
    176         * @return the String mapped from the given type
    177         */
    178        public static String typeName( int type ) {
    179            switch ( type ) {
    180            case SeColumnDefinition.TYPE_BLOB:
    181                return "BLOB";
    182            case SeColumnDefinition.TYPE_CLOB:
    183                return "CLOB";
    184            case SeColumnDefinition.TYPE_DATE:
    185                return "DATE";
    186            case SeColumnDefinition.TYPE_FLOAT32:
    187                return "FLOAT32";
    188            case SeColumnDefinition.TYPE_FLOAT64:
    189                return "FLOAT64";
    190            case SeColumnDefinition.TYPE_INT16:
    191                return "INT16";
    192            case SeColumnDefinition.TYPE_INT32:
    193                return "INT32";
    194            case SeColumnDefinition.TYPE_INT64:
    195                return "INT64";
    196            case SeColumnDefinition.TYPE_NCLOB:
    197                return "NCLOB";
    198            case SeColumnDefinition.TYPE_NSTRING:
    199                return "NSTRING";
    200            case SeColumnDefinition.TYPE_RASTER:
    201                return "RASTER";
    202            case SeColumnDefinition.TYPE_SHAPE:
    203                return "SHAPE";
    204            case SeColumnDefinition.TYPE_STRING:
    205                return "STRING";
    206            case SeColumnDefinition.TYPE_UUID:
    207                return "UUID";
    208            case SeColumnDefinition.TYPE_XML:
    209                return "XML";
    210            default:
    211                return "???";
    212            }
    213        }
    214    }