    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/io/sdeapi/Transaction.java $
    002    /*----------------------------------------------------------------------------
    003     This file is part of deegree, http://deegree.org/
    004     Copyright (C) 2001-2009 by:
    005       Department of Geography, University of Bonn
    006     and
    007       lat/lon GmbH
    008
    009     This library is free software; you can redistribute it and/or modify it under
    010     the terms of the GNU Lesser General Public License as published by the Free
    011     Software Foundation; either version 2.1 of the License, or (at your option)
    012     any later version.
    013     This library is distributed in the hope that it will be useful, but WITHOUT
    014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    016     details.
    017     You should have received a copy of the GNU Lesser General Public License
    018     along with this library; if not, write to the Free Software Foundation, Inc.,
    019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    020
    021     Contact information:
    022
    023     lat/lon GmbH
    024     Aennchenstr. 19, 53177 Bonn
    025     Germany
    026     http://lat-lon.de/
    027
    028     Department of Geography, University of Bonn
    029     Prof. Dr. Klaus Greve
    030     Postfach 1147, 53001 Bonn
    031     Germany
    032     http://www.geographie.uni-bonn.de/deegree/
    033
    034     e-mail: info@deegree.org
    035    ----------------------------------------------------------------------------*/
    036    package org.deegree.io.sdeapi;
    037
    038    import java.io.ByteArrayInputStream;
    039    import java.util.ArrayList;
    040    import java.util.Date;
    041    import java.util.HashMap;
    042    import java.util.Iterator;
    043    import java.util.Vector;
    044
    045    import org.deegree.framework.log.ILogger;
    046    import org.deegree.framework.log.LoggerFactory;
    047    import org.deegree.framework.util.TimeTools;
    048    import org.deegree.model.spatialschema.Geometry;
    049
    050    import com.esri.sde.sdk.client.SeColumnDefinition;
    051    import com.esri.sde.sdk.client.SeConnection;
    052    import com.esri.sde.sdk.client.SeCoordinateReference;
    053    import com.esri.sde.sdk.client.SeDelete;
    054    import com.esri.sde.sdk.client.SeException;
    055    import com.esri.sde.sdk.client.SeExtent;
    056    import com.esri.sde.sdk.client.SeInsert;
    057    import com.esri.sde.sdk.client.SeLayer;
    058    import com.esri.sde.sdk.client.SeRow;
    059    import com.esri.sde.sdk.client.SeShape;
    060    import com.esri.sde.sdk.client.SeTable;
    061    import com.esri.sde.sdk.client.SeUpdate;
    062
    063    /**
    064     * the class offers access to the transactional behavior of the a connection to ArcSDE
    065     *
    066     * @version $Revision: 18195 $ $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    067     */
    068    public class Transaction {
    069
    070        private static ILogger LOG = LoggerFactory.getLogger( Transaction.class );
    071
    072        // Connection to SDE
    073        private SeConnection conn = null;
    074
    075        // Currently opened Layer and associated Table
    076        private SeLayer layer = null;
    077
    078        private HashMap<String, SeColumnDefinition> colDefs = null;
    079
    080        private ArrayList<SeColumnDefinition> colDefsList = null;
    081
    082        // Current Spatial Filter - a BoundingBox
    083        private SeShape spatialFilter = null;
    084
    085        /**
    086         * Creates a new SpatialQuery object.
    087         *
    088         * @param server
    089         * @param port
    090         * @param database
    091         * @param user
    092         * @param password
    093         *
    094         * @throws SeException
    095         */
    096        public Transaction( String server, int port, String database, String user, String password ) throws SeException {
    097            openConnection( server, port, database, user, password );
    098        }
    099
    100        /**
    101         * Connect to the ArcSDE server <br>
    102         * throws SeException
    103         *
    104         * @param server
    105         * @param port
    106         * @param database
    107         * @param user
    108         * @param password
    109         * @throws SeException
    110         */
    111        public void openConnection( String server, int port, String database, String user, String password )
    112                                throws SeException {
    113
    114            conn = new SeConnection( server, port, database, user, password );
    115
    116        }
    117
    118        /**
    119         * Close the current connection to the ArcSDE server <br>
    120         * throws SeException
    121         *
    122         * @throws SeException
    123         */
    124        public void closeConnection()
    125                                throws SeException {
    126            conn.close();
    127        }
    128
    129        /**
    130         * Set a SDE layer to work on and appropriate table <br>
    131         * throws SeException
    132         *
    133         * @param layername
    134         * @throws SeException
    135         */
    136        public void setLayer( String layername )
    137                                throws SeException {
    138
    139            Vector<?> layerList = conn.getLayers();
    140            String spatialCol = "";
    141
    142            for ( int i = 0; i < layerList.size(); i++ ) {
    143                SeLayer layer = (SeLayer) layerList.elementAt( i );
    144
    145                if ( layer.getQualifiedName().trim().equalsIgnoreCase( layername ) ) {
    146                    spatialCol = layer.getSpatialColumn();
    147                    break;
    148                }
    149            }
    150
    151            layer = new SeLayer( conn, layername, spatialCol );
    152            SeTable table = new SeTable( conn, layer.getQualifiedName() );
    153            SeColumnDefinition[] cols = table.describe();
    154            colDefs = new HashMap<String, SeColumnDefinition>();
    155            colDefsList = new ArrayList<SeColumnDefinition>();
    156            for ( int i = 0; i < cols.length; i++ ) {
    157                colDefs.put( cols[i].getName(), cols[i] );
    158                colDefsList.add( cols[i] );
    159            }
    160
    161        }
    162
    163        /**
    164         * Set a SpatialFilter to Query (BoundingBox) <br>
    165         * throws SeException
    166         *
    167         * @param minx
    168         * @param miny
    169         * @param maxx
    170         * @param maxy
    171         * @throws SeException
    172         */
    173        public void setSpatialFilter( double minx, double miny, double maxx, double maxy )
    174                                throws SeException {
    175
    176            spatialFilter = new SeShape( layer.getCoordRef() );
    177
    178            SeExtent extent = new SeExtent( minx, miny, maxx, maxy );
    179            spatialFilter.generateRectangle( extent );
    180
    181        }
    182
    183        /**
    184         * inserts a feature into the ArcSDE
    185         *
    186         * @param inRow
    187         *            feature/row to be inserted
    188         *
    189         * @throws SeException
    190         * @throws DeegreeSeException
    191         */
    192        public void insertFeature( HashMap<?, ?> inRow )
    193                                throws SeException, DeegreeSeException {
    194
    195            ArrayList<String> list = new ArrayList<String>();
    196            // get all fields of the row where the values are not null
    197            for ( int i = 0; i < colDefsList.size(); i++ ) {
    198                SeColumnDefinition cd = colDefsList.get( i );
    199                if ( inRow.get( cd.getName() ) != null || inRow.get( cd.getName().toUpperCase() ) != null ) {
    200                    list.add( cd.getName() );
    201                }
    202            }
    203            String[] columns = list.toArray( new String[list.size()] );
    204
    205            SeInsert insert = null;
    206            try {
    207                // create an insert object
    208                insert = new SeInsert( conn );
    209                insert.intoTable( layer.getName(), columns );
    210                insert.setWriteMode( true );
    211
    212                SeRow row = insert.getRowToSet();
    213                SeColumnDefinition[] cols = row.getColumns();
    214
    215                // get reference system
    216                SeCoordinateReference coordref = layer.getCoordRef();
    217                for ( int i = 0; i < cols.length; i++ ) {
    218                    Object o = inRow.get( cols[i].getName() );
    219                    if ( o == null ) {
    220                        o = inRow.get( cols[i].getName().toUpperCase() );
    221                    }
    222                    if ( o != null ) {
    223                        int type = cols[i].getType();
    224                        row = setValue( row, i, type, o, coordref );
    225                    }
    226                }
    227                // perform insert operation
    228                insert.execute();
    229                insert.flushBufferedWrites();
    230            } catch ( SeException e ) {
    231                throw e;
    232            } finally {
    233                // Making sure the insert stream was closed. If the stream isn't closed,
    234                // the resources used by the stream will be held/locked by the stream
    235                // until the associated connection is closed.
    236                try {
    237                    insert.close();
    238                } catch ( SeException se ) {
    239                    se.printStackTrace();
    240                }
    241            }
    242
    243        }
    244
    245        /**
    246         * fills the passed row with the also passed value considering its type
    247         *
    248         * @param row
    249         *            SDE row to insert
    250         * @param pos
    251         *            position where to set the value in the row
    252         * @param type
    253         *            value type
    254         * @param value
    255         *            value to insert
    256         */
    257        private SeRow setValue( SeRow row, int pos, int type, Object value, SeCoordinateReference crs )
    258                                throws SeException, DeegreeSeException {
    259
    260            switch ( type ) {
    261            case SeColumnDefinition.TYPE_BLOB: {
    262                if ( value == null ) {
    263                    row.setBlob( pos, null );
    264                } else {
    265                    row.setBlob( pos, (ByteArrayInputStream) value );
    266                }
    267                break;
    268            }
    269            case SeColumnDefinition.TYPE_DATE: {
    270                if ( value != null && value instanceof String ) {
    271                    value = TimeTools.createCalendar( (String) value ).getTime();
    272                }
    273                row.setDate( pos, (Date) value );
    274                break;
    275            }
    276            case SeColumnDefinition.TYPE_FLOAT64: {
    277                if ( value != null && value instanceof String ) {
    278                    value = new Double( (String) value );
    279                }
    280                row.setDouble( pos, (Double) value );
    281                break;
    282            }
    283            case SeColumnDefinition.TYPE_FLOAT32: {
    284                if ( value != null && value instanceof String ) {
    285                    value = new Float( (String) value );
    286                }
    287                row.setFloat( pos, (Float) value );
    288                break;
    289            }
    290            case SeColumnDefinition.TYPE_INT32: {
    291                if ( value != null && value instanceof String ) {
    292                    value = new Integer( (String) value );
    293                }
    294                row.setInteger( pos, (Integer) value );
    295                break;
    296            }
    297            case SeColumnDefinition.TYPE_RASTER: {
    298                row.setBlob( pos, (ByteArrayInputStream) value );
    299                break;
    300            }
    301            case SeColumnDefinition.TYPE_SHAPE: {
    302                // TODO
    303                /*
    304                 * if (value != null && value instanceof String) { // if value is a string try to
    305                 * convert it into GML try { value = GMLGeometryAdapter.wrap( (String)value ); } catch
    306                 * (Exception e) { throw new SeInvalidShapeException( "the passed value "+ "isn't a GML
    307                 * geometry\n" + e); } } if (value != null && value instanceof GMLGeometry) { // if
    308                 * value is a GML convert it into a deegree geometry try { value =
    309                 * GMLGeometryAdapter.wrap( ((GMLGeometry)value).getAsElement() ); } catch (Exception e) {
    310                 * throw new SeInvalidShapeException( "the passed value/GML "+ "can't be transformed "+ "
    311                 * to a deegree geometry\n" + e); } }
    312                 */
    313                try {
    314                    if ( value != null ) {
    315                        SeShape shp = SDEAdapter.export( (Geometry) value, crs );
    316                        row.setShape( pos, shp );
    317                    } else {
    318                        row.setShape( pos, null );
    319                    }
    320                } catch ( Exception e ) {
    321                    throw new DeegreeSeException( "the passed geometry can't  " + "be transformed to a SeShape\n" + e );
    322                }
    323                break;
    324            }
    325            case SeColumnDefinition.TYPE_INT16: {
    326                if ( value != null && value instanceof String ) {
    327                    value = new Short( (String) value );
    328                }
    329                row.setShort( pos, (Short) value );
    330                break;
    331            }
    332            case SeColumnDefinition.TYPE_STRING: {
    333                row.setString( pos, (String) value );
    334                break;
    335            }
    336            }
    337
    338            return row;
    339        }
    340
    341        /**
    342         * updates a feature of the ArcSDE
    343         *
    344         * @param inRow
    345         *            update data
    346         * @param where
    347         *            none spatial condtions to limit the targeted rows
    348         * @param extent
    349         *            spatial condtion to limit the targeted rows (not considered yet)
    350         *
    351         * @throws SeException
    352         * @throws DeegreeSeException
    353         */
    354        public void updateFeature( HashMap<?, ?> inRow, String where, Geometry extent )
    355                                throws SeException, DeegreeSeException {
    356
    357            ArrayList<String> list = new ArrayList<String>();
    358
    359            // get all fields of the row where the values are not null
    360            Iterator<?> iterator = inRow.keySet().iterator();
    361            while ( iterator.hasNext() ) {
    362                Object o = iterator.next();
    363                if ( o != null ) {
    364                    list.add( (String) o );
    365                }
    366            }
    367            String[] columns = list.toArray( new String[list.size()] );
    368
    369            // get rows to be updated
    370            // SeQuery query = new SeQuery( conn, columns, sqlCons );
    371            SeUpdate update = new SeUpdate( conn );
    372            SeTable table = new SeTable( conn, layer.getQualifiedName() );
    373            // TODO use also spatial conditions
    374            update.toTable( table.getName(), columns, where.trim() );
    375            update.setWriteMode( true );
    376
    377            SeRow row = update.getRowToSet();
    378            SeCoordinateReference coordref = layer.getCoordRef();
    379
    380            if ( row != null ) {
    381                // while ( row != null ) {
    382                for ( int i = 0; i < columns.length; i++ ) {
    383                    int type = colDefs.get( columns[i] ).getType();
    384                    row = setValue( row, i, type, inRow.get( columns[i] ), coordref );
    385                }
    386                // row = update.getRowToSet();
    387                // }
    388                update.execute();
    389            } else {
    390                LOG.logWarning( "No rows fetched/updated" );
    391            }
    392
    393            update.close();
    394
    395        }
    396
    397        /**
    398         * deletes a feature from the ArcSDE
    399         *
    400         * @param where
    401         *            none spatial condtions to limit the targeted rows
    402         * @param extent
    403         *            spatial condtion to limit the targeted rows (not considered yet)
    404         *
    405         * @throws SeException
    406         */
    407        public void deleteFeature( String where, Geometry extent )
    408                                throws SeException {
    409
    410            // TODO use also spatial conditions
    411            SeDelete delete = new SeDelete( conn );
    412            delete.fromTable( layer.getQualifiedName(), where );
    413            delete.close();
    414
    415        }
    416
    417    }