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