001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }