001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/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 }