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