/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.io.sdeapi; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.TimeTools; import org.deegree.model.spatialschema.Geometry; import com.esri.sde.sdk.client.SeColumnDefinition; import com.esri.sde.sdk.client.SeConnection; import com.esri.sde.sdk.client.SeCoordinateReference; import com.esri.sde.sdk.client.SeDelete; import com.esri.sde.sdk.client.SeException; import com.esri.sde.sdk.client.SeExtent; import com.esri.sde.sdk.client.SeInsert; import com.esri.sde.sdk.client.SeInvalidShapeException; import com.esri.sde.sdk.client.SeLayer; import com.esri.sde.sdk.client.SeRow; import com.esri.sde.sdk.client.SeShape; import com.esri.sde.sdk.client.SeTable; import com.esri.sde.sdk.client.SeUpdate; /** * the class offers access to the transactional behavior of the a * connection to ArcSDE * * @version $Revision: 1.12 $ $Date: 2006/08/06 21:01:50 $ */ public class Transaction { private static ILogger LOG = LoggerFactory.getLogger( Transaction.class ); // Connection to SDE private SeConnection conn = null; // Currently opened Layer and associated Table private SeLayer layer = null; private HashMap colDefs = null; private ArrayList colDefsList = null; // Current Spatial Filter - a BoundingBox private SeShape spatialFilter = null; /** * Creates a new SpatialQuery object. * * @param server * @param port * @param database * @param user * @param password * * @throws SeException */ public Transaction( String server, int port, String database, String user, String password ) throws SeException { openConnection( server, port, database, user, password ); } /** * Connect to the ArcSDE server * <br>throws SeException */ public void openConnection( String server, int port, String database, String user, String password ) throws SeException { conn = new SeConnection( server, port, database, user, password ); } /** * Close the current connection to the ArcSDE server * <br>throws SeException */ public void closeConnection() throws SeException { conn.close(); } /** * Set a SDE layer to work on and appropriate table * <br>throws SeException */ public void setLayer( String layername ) throws SeException { Vector layerList = conn.getLayers(); String spatialCol = ""; for ( int i = 0; i < layerList.size(); i++ ) { SeLayer layer = (SeLayer) layerList.elementAt( i ); if ( layer.getQualifiedName().trim().equalsIgnoreCase( layername ) ) { spatialCol = layer.getSpatialColumn(); break; } } layer = new SeLayer( conn, layername, spatialCol ); SeTable table = new SeTable( conn, layer.getQualifiedName() ); SeColumnDefinition[] cols = table.describe(); colDefs = new HashMap(); colDefsList = new ArrayList(); for ( int i = 0; i < cols.length; i++ ) { colDefs.put( cols[i].getName(), cols[i] ); colDefsList.add( cols[i] ); } } /** * Set a SpatialFilter to Query (BoundingBox) * <br>throws SeException */ public void setSpatialFilter( double minx, double miny, double maxx, double maxy ) throws SeException { spatialFilter = new SeShape( layer.getCoordRef() ); SeExtent extent = new SeExtent( minx, miny, maxx, maxy ); spatialFilter.generateRectangle( extent ); } /** * inserts a feature into the ArcSDE * * @param inRow feature/row to be inserted * * @throws SeException */ public void insertFeature( HashMap inRow ) throws SeException { ArrayList list = new ArrayList(); // get all fields of the row where the values are not null for ( int i = 0; i < colDefsList.size(); i++ ) { SeColumnDefinition cd = (SeColumnDefinition) colDefsList.get( i ); if ( inRow.get( cd.getName() ) != null || inRow.get( cd.getName().toUpperCase() ) != null ) { list.add( new String( cd.getName() ) ); } } String[] columns = (String[]) list.toArray( new String[list.size()] ); SeInsert insert = null; try { // create an insert object insert = new SeInsert( conn ); insert.intoTable( layer.getName(), columns ); insert.setWriteMode( true ); SeRow row = insert.getRowToSet(); SeColumnDefinition[] cols = row.getColumns(); // get reference system SeCoordinateReference coordref = layer.getCoordRef(); for ( int i = 0; i < cols.length; i++ ) { Object o = inRow.get( cols[i].getName() ); if ( o == null ) { o = inRow.get( cols[i].getName().toUpperCase() ); } if ( o != null ) { int type = cols[i].getType(); row = setValue( row, i, type, o, coordref ); } } // perform insert operation insert.execute(); insert.flushBufferedWrites(); } catch ( SeException e ) { throw e; } finally { // Making sure the insert stream was closed. If the stream isn't closed, // the resources used by the stream will be held/locked by the stream // until the associated connection is closed. try { insert.close(); } catch ( SeException se ) { se.printStackTrace(); } } } /** * fills the passed row with the also passed value considering its type * * @param row SDE row to insert * @param pos position where to set the value in the row * @param type value type * @param value value to insert */ private SeRow setValue( SeRow row, int pos, int type, Object value, SeCoordinateReference crs ) throws SeException { switch ( type ) { case SeColumnDefinition.TYPE_BLOB: { if ( value == null ) { row.setBlob( pos, null ); } else { row.setBlob( pos, (ByteArrayInputStream) value ); } break; } case SeColumnDefinition.TYPE_DATE: { if ( value != null && value instanceof String ) { value = TimeTools.createCalendar( (String) value ).getTime(); } row.setDate( pos, (Date) value ); break; } case SeColumnDefinition.TYPE_DOUBLE: { if ( value != null && value instanceof String ) { value = new Double( (String) value ); } row.setDouble( pos, (Double) value ); break; } case SeColumnDefinition.TYPE_FLOAT: { if ( value != null && value instanceof String ) { value = new Float( (String) value ); } row.setFloat( pos, (Float) value ); break; } case SeColumnDefinition.TYPE_INTEGER: { if ( value != null && value instanceof String ) { value = new Integer( (String) value ); } row.setInteger( pos, (Integer) value ); break; } case SeColumnDefinition.TYPE_RASTER: { row.setBlob( pos, (ByteArrayInputStream) value ); break; } case SeColumnDefinition.TYPE_SHAPE: { //TODO /* if (value != null && value instanceof String) { // if value is a string try to convert it into GML try { value = GMLGeometryAdapter.wrap( (String)value ); } catch (Exception e) { throw new SeInvalidShapeException( "the passed value "+ "isn't a GML geometry\n" + e); } } if (value != null && value instanceof GMLGeometry) { // if value is a GML convert it into a deegree geometry try { value = GMLGeometryAdapter.wrap( ((GMLGeometry)value).getAsElement() ); } catch (Exception e) { throw new SeInvalidShapeException( "the passed value/GML "+ "can't be transformed "+ " to a deegree geometry\n" + e); } } */ try { if ( value != null ) { SeShape shp = SDEAdapter.export( (Geometry) value, crs ); row.setShape( pos, shp ); } else { row.setShape( pos, null ); } } catch ( Exception e ) { throw new SeInvalidShapeException( "the passed geometry can't " + "be transformed to a SeShape\n" + e ); } break; } case SeColumnDefinition.TYPE_SMALLINT: { if ( value != null && value instanceof String ) { value = new Short( (String) value ); } row.setShort( pos, (Short) value ); break; } case SeColumnDefinition.TYPE_STRING: { row.setString( pos, (String) value ); break; } } return row; } /** * updates a feature of the ArcSDE * * @param inRow update data * @param where none spatial condtions to limit the targeted rows * @param extent spatial condtion to limit the targeted rows (not considered yet) * * @throws SeException */ public void updateFeature( HashMap inRow, String where, Geometry extent ) throws SeException { ArrayList list = new ArrayList(); // get all fields of the row where the values are not null Iterator iterator = inRow.keySet().iterator(); while ( iterator.hasNext() ) { Object o = iterator.next(); if ( o != null ) { list.add( o ); } } String[] columns = (String[]) list.toArray( new String[list.size()] ); // get rows to be updated //SeQuery query = new SeQuery( conn, columns, sqlCons ); SeUpdate update = new SeUpdate( conn ); SeTable table = new SeTable( conn, layer.getQualifiedName() ); // TODO use also spatial conditions update.toTable( table.getName(), columns, where.trim() ); update.setWriteMode( true ); SeRow row = update.getRowToSet(); SeCoordinateReference coordref = layer.getCoordRef(); if ( row != null ) { //while ( row != null ) { for ( int i = 0; i < columns.length; i++ ) { int type = ( (SeColumnDefinition) colDefs.get( columns[i] ) ).getType(); row = setValue( row, i, type, inRow.get( columns[i] ), coordref ); } // row = update.getRowToSet(); // } update.execute(); } else { LOG.logWarning( "No rows fetched/updated" ); } update.close(); } /** * deletes a feature from the ArcSDE * * @param where none spatial condtions to limit the targeted rows * @param extent spatial condtion to limit the targeted rows (not considered yet) * * @throws SeException */ public void deleteFeature( String where, Geometry extent ) throws SeException { //TODO use also spatial conditions SeDelete delete = new SeDelete( conn ); delete.fromTable( layer.getQualifiedName(), where ); delete.close(); } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: Transaction.java,v $ Revision 1.12 2006/08/06 21:01:50 poth deprecated method calls removed / Logger added Revision 1.11 2006/07/12 14:46:19 poth comment footer added ********************************************************************** */