001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/sdeapi/Transaction.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 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: 9342 $ $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 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 }