001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/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: rbezema $
063 *
064 * @version $Revision: 12183 $
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 */
077 public SDEUpdateHandler( SDETransaction dsTa, TableAliasGenerator aliasGenerator, SDEConnection conn ) {
078 super( dsTa.getDatastore(), aliasGenerator, conn );
079 }
080
081 /**
082 * Performs an update operation against the associated datastore.
083 *
084 * @param ft
085 * @param properties
086 * @param filter
087 * @return number of updated (root) feature instances
088 * @throws DatastoreException
089 */
090 public int performUpdate( MappedFeatureType ft, Map<PropertyPath, FeatureProperty> properties, Filter filter )
091 throws DatastoreException {
092
093 // only for statistics???
094 // FeatureId[] fids = determineAffectedFIDs( mappedFeatureType, filter );
095
096 // process properties list
097 // TODO: has to take care about properties in related tables
098 ArrayList<MappedPropertyType> list = new ArrayList<MappedPropertyType>();
099 for ( PropertyPath path : properties.keySet() ) {
100 QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
101 MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
102 if ( pt == null ) {
103 String msg = "Internal error: unknown property type " + qn;
104 LOG.logDebug( msg );
105 throw new DatastoreException( msg );
106 }
107 if ( 0 < pt.getTableRelations().length ) {
108 String msg = "Update of properties of related tables is not implemented yet " + qn;
109 LOG.logDebug( msg );
110 throw new DatastoreException( msg );
111 }
112 list.add( pt );
113 }
114 MappedPropertyType[] mappedPType = list.toArray( new MappedPropertyType[list.size()] );
115
116 // prepare update
117 SDEWhereBuilder whereBuilder = datastore.getWhereBuilder( new MappedFeatureType[] { ft }, null, filter,
118 aliasGenerator );
119 Map<String, List<MappingField>> columnsMap = buildColumnsMap( ft, mappedPType, false );
120 String[] columns = columnsMap.keySet().toArray( new String[columnsMap.size()] );
121 Map<MappingField, Integer> mappingFieldsMap = buildMappingFieldMap( columns, columnsMap );
122 StringBuffer whereCondition = new StringBuffer();
123 whereBuilder.appendWhereCondition( whereCondition );
124
125 try {
126 SeUpdate updater = new SeUpdate( conn.getConnection() );
127 updater.setState( conn.getState().getId(), new SeObjectId( SeState.SE_NULL_STATE_ID ),
128 SeState.SE_STATE_DIFF_NOCHECK );
129 updater.toTable( ft.getTable(), columns, whereCondition.toString() );
130 updater.setWriteMode( true );
131 SeRow row = updater.getRowToSet();
132 if ( row.hasColumns() ) {
133 SeColumnDefinition[] cd = row.getColumns();
134 for ( int k = 0; k < cd.length; k++ ) {
135 LOG.logDebug( "*** col[" + k + "] name=" + cd[k].getName() + " type=" + cd[k].getType() + "/"
136 + typeName( cd[k].getType() ) );
137 }
138 } else {
139 LOG.logDebug( "*** no column definitions!!!" );
140 }
141
142 for ( PropertyPath path : properties.keySet() ) {
143 QualifiedName qn = path.getStep( path.getSteps() - 1 ).getPropertyName();
144 MappedPropertyType pt = (MappedPropertyType) ft.getProperty( qn );
145 if ( pt instanceof MappedSimplePropertyType ) {
146 SimpleContent content = ( (MappedSimplePropertyType) pt ).getContent();
147 if ( content instanceof MappingField ) {
148 MappingField field = (MappingField) content;
149 Integer resultPos = mappingFieldsMap.get( field );
150 Object value = properties.get( path ).getValue();
151 SDEAdapter.setRowValue( row, resultPos.intValue(), value,
152 SDEAdapter.mapSQL2SDE( field.getType() ) );
153 }
154 } else if ( pt instanceof MappedGeometryPropertyType ) {
155 MappingGeometryField field = ( (MappedGeometryPropertyType) pt ).getMappingField();
156 Integer resultPos = mappingFieldsMap.get( field );
157 SeShape value = (SeShape) datastore.convertDegreeToDBGeometry( (Geometry) properties.get( path ).getValue() );
158 row.setShape( resultPos.intValue(), value );
159 }
160 }
161
162 updater.execute();
163 updater.close();
164 } catch ( SeException e ) {
165 e.printStackTrace();
166 throw new DatastoreException( "update failed", e );
167 }
168
169 // return fids.length;
170 return 1; // don't know, how many rows are affected and don't want to query it only for
171 // statistics
172 }
173
174 /**
175 * @param type
176 * @return the String mapped from the given type
177 */
178 public static String typeName( int type ) {
179 switch ( type ) {
180 case SeColumnDefinition.TYPE_BLOB:
181 return "BLOB";
182 case SeColumnDefinition.TYPE_CLOB:
183 return "CLOB";
184 case SeColumnDefinition.TYPE_DATE:
185 return "DATE";
186 case SeColumnDefinition.TYPE_FLOAT32:
187 return "FLOAT32";
188 case SeColumnDefinition.TYPE_FLOAT64:
189 return "FLOAT64";
190 case SeColumnDefinition.TYPE_INT16:
191 return "INT16";
192 case SeColumnDefinition.TYPE_INT32:
193 return "INT32";
194 case SeColumnDefinition.TYPE_INT64:
195 return "INT64";
196 case SeColumnDefinition.TYPE_NCLOB:
197 return "NCLOB";
198 case SeColumnDefinition.TYPE_NSTRING:
199 return "NSTRING";
200 case SeColumnDefinition.TYPE_RASTER:
201 return "RASTER";
202 case SeColumnDefinition.TYPE_SHAPE:
203 return "SHAPE";
204 case SeColumnDefinition.TYPE_STRING:
205 return "STRING";
206 case SeColumnDefinition.TYPE_UUID:
207 return "UUID";
208 case SeColumnDefinition.TYPE_XML:
209 return "XML";
210 default:
211 return "???";
212 }
213 }
214 }