001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/datastore/sde/SDEUpdateHandler.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2006 by: M.O.S.S. Computer Grafik Systeme GmbH
006 Hohenbrunner Weg 13
007 D-82024 Taufkirchen
008 http://www.moss.de/
009
010 This library is free software; you can redistribute it and/or
011 modify it under the terms of the GNU Lesser General Public
012 License as published by the Free Software Foundation; either
013 version 2.1 of the License, or (at your option) any later version.
014
015 This library is distributed in the hope that it will be useful,
016 but WITHOUT ANY WARRANTY; without even the implied warranty of
017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018 Lesser General Public License for more details.
019
020 You should have received a copy of the GNU Lesser General Public
021 License along with this library; if not, write to the Free Software
022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023
024 ---------------------------------------------------------------------------*/
025 package org.deegree.io.datastore.sde;
026
027 import java.util.ArrayList;
028 import java.util.List;
029 import java.util.Map;
030
031 import org.deegree.datatypes.QualifiedName;
032 import org.deegree.framework.log.ILogger;
033 import org.deegree.framework.log.LoggerFactory;
034 import org.deegree.io.datastore.DatastoreException;
035 import org.deegree.io.datastore.schema.MappedFeatureType;
036 import org.deegree.io.datastore.schema.MappedGeometryPropertyType;
037 import org.deegree.io.datastore.schema.MappedPropertyType;
038 import org.deegree.io.datastore.schema.MappedSimplePropertyType;
039 import org.deegree.io.datastore.schema.content.MappingField;
040 import org.deegree.io.datastore.schema.content.MappingGeometryField;
041 import org.deegree.io.datastore.schema.content.SimpleContent;
042 import org.deegree.io.datastore.sql.TableAliasGenerator;
043 import org.deegree.io.sdeapi.SDEAdapter;
044 import org.deegree.io.sdeapi.SDEConnection;
045 import org.deegree.model.feature.FeatureProperty;
046 import org.deegree.model.filterencoding.Filter;
047 import org.deegree.model.spatialschema.Geometry;
048 import org.deegree.ogcbase.PropertyPath;
049
050 import com.esri.sde.sdk.client.SeColumnDefinition;
051 import com.esri.sde.sdk.client.SeException;
052 import com.esri.sde.sdk.client.SeObjectId;
053 import com.esri.sde.sdk.client.SeRow;
054 import com.esri.sde.sdk.client.SeShape;
055 import com.esri.sde.sdk.client.SeState;
056 import com.esri.sde.sdk.client.SeUpdate;
057
058 /**
059 * Handler for <code>Update</code> operations contained in <code>Transaction</code> requests.
060 *
061 * @author <a href="mailto:cpollmann@moss.de">Christoph Pollmann</a>
062 * @author last edited by: $Author: apoth $
063 *
064 * @version $Revision: 7844 $
065 */
066 public class SDEUpdateHandler extends AbstractSDERequestHandler {
067
068 private static final ILogger LOG = LoggerFactory.getLogger( SDEUpdateHandler.class );
069
070 /**
071 * Creates a new <code>UpdateHandler</code> from the given parameters.
072 *
073 * @param dsTa
074 * @param aliasGenerator
075 * @param conn
076 * @throws DatastoreException
077 */
078 public SDEUpdateHandler( SDETransaction dsTa, TableAliasGenerator aliasGenerator, SDEConnection conn ) {
079 super( dsTa.getDatastore(), aliasGenerator, conn );
080 }
081
082 /**
083 * Performs an update operation against the associated datastore.
084 *
085 * @param ft
086 * @param properties
087 * @param filter
088 * @return number of updated (root) feature instances
089 * @throws DatastoreException
090 */
091 public int performUpdate( MappedFeatureType ft, Map<PropertyPath, FeatureProperty> properties, Filter filter )
092 throws DatastoreException {
093
094 // only for statistics???
095 // FeatureId[] fids = determineAffectedFIDs( mappedFeatureType, filter );
096
097 // process properties list
098 // TODO: has to take care about properties in related tables
099 ArrayList<MappedPropertyType> list = new ArrayList<MappedPropertyType>();
100 for ( PropertyPath path : properties.keySet() ) {
101 QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
102 MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
103 if ( pt == null ) {
104 String msg = "Internal error: unknown property type " + qn;
105 LOG.logDebug( msg );
106 throw new DatastoreException( msg );
107 }
108 if ( 0 < pt.getTableRelations().length ) {
109 String msg = "Update of properties of related tables is not implemented yet " + qn;
110 LOG.logDebug( msg );
111 throw new DatastoreException( msg );
112 }
113 list.add( pt );
114 }
115 MappedPropertyType[] mappedPType = list.toArray( new MappedPropertyType[list.size()] );
116
117 // prepare update
118 SDEWhereBuilder whereBuilder = datastore.getWhereBuilder( new MappedFeatureType[] { ft }, null, filter,
119 aliasGenerator );
120 Map<String, List<MappingField>> columnsMap = buildColumnsMap( ft, mappedPType, false );
121 String[] columns = columnsMap.keySet().toArray( new String[columnsMap.size()] );
122 Map mappingFieldsMap = buildMappingFieldMap( columns, columnsMap );
123 StringBuffer whereCondition = new StringBuffer();
124 whereBuilder.appendWhereCondition( whereCondition );
125
126 try {
127 SeUpdate updater = new SeUpdate( conn.getConnection() );
128 updater.setState( conn.getState().getId(), new SeObjectId( SeState.SE_NULL_STATE_ID ),
129 SeState.SE_STATE_DIFF_NOCHECK );
130 updater.toTable( ft.getTable(), columns, whereCondition.toString() );
131 updater.setWriteMode( true );
132 SeRow row = updater.getRowToSet();
133 if ( row.hasColumns() ) {
134 SeColumnDefinition[] cd = row.getColumns();
135 for ( int k = 0; k < cd.length; k++ ) {
136 LOG.logDebug( "*** col[" + k + "] name=" + cd[k].getName() + " type=" + cd[k].getType() + "/"
137 + typeName( cd[k].getType() ) );
138 }
139 } else {
140 LOG.logDebug( "*** no column definitions!!!" );
141 }
142
143 for ( PropertyPath path : properties.keySet() ) {
144 QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
145 MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
146 if ( pt instanceof MappedSimplePropertyType ) {
147 SimpleContent content = ( (MappedSimplePropertyType) pt ).getContent();
148 if ( content instanceof MappingField ) {
149 MappingField field = (MappingField) content;
150 Integer resultPos = (Integer) mappingFieldsMap.get( field );
151 Object value = properties.get( path ).getValue();
152 SDEAdapter.setRowValue( row, resultPos.intValue(), value,
153 SDEAdapter.mapSQL2SDE( field.getType() ) );
154 }
155 } else if ( pt instanceof MappedGeometryPropertyType ) {
156 MappingGeometryField field = ( (MappedGeometryPropertyType) pt ).getMappingField();
157 Integer resultPos = (Integer) mappingFieldsMap.get( field );
158 SeShape value = (SeShape) datastore.convertDegreeToDBGeometry( (Geometry) properties.get( path ).getValue() );
159 row.setShape( resultPos.intValue(), value );
160 }
161 }
162
163 updater.execute();
164 updater.close();
165 } catch ( SeException e ) {
166 e.printStackTrace();
167 throw new DatastoreException( "update failed", e );
168 }
169
170 // return fids.length;
171 return 1; // don't know, how many rows are affected and don't want to query it only for
172 // statistics
173 }
174
175 public static String typeName( int type ) {
176 switch ( type ) {
177 case SeColumnDefinition.TYPE_BLOB:
178 return "BLOB";
179 case SeColumnDefinition.TYPE_CLOB:
180 return "CLOB";
181 case SeColumnDefinition.TYPE_DATE:
182 return "DATE";
183 case SeColumnDefinition.TYPE_FLOAT32:
184 return "FLOAT32";
185 case SeColumnDefinition.TYPE_FLOAT64:
186 return "FLOAT64";
187 case SeColumnDefinition.TYPE_INT16:
188 return "INT16";
189 case SeColumnDefinition.TYPE_INT32:
190 return "INT32";
191 case SeColumnDefinition.TYPE_INT64:
192 return "INT64";
193 case SeColumnDefinition.TYPE_NCLOB:
194 return "NCLOB";
195 case SeColumnDefinition.TYPE_NSTRING:
196 return "NSTRING";
197 case SeColumnDefinition.TYPE_RASTER:
198 return "RASTER";
199 case SeColumnDefinition.TYPE_SHAPE:
200 return "SHAPE";
201 case SeColumnDefinition.TYPE_STRING:
202 return "STRING";
203 case SeColumnDefinition.TYPE_UUID:
204 return "UUID";
205 case SeColumnDefinition.TYPE_XML:
206 return "XML";
207 default:
208 return "???";
209 }
210 }
211 }