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 }