001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/datastore/sde/SDEDatastore.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 org.deegree.datatypes.QualifiedName;
028    import org.deegree.framework.log.ILogger;
029    import org.deegree.framework.log.LoggerFactory;
030    import org.deegree.io.JDBCConnection;
031    import org.deegree.io.datastore.AnnotationDocument;
032    import org.deegree.io.datastore.Datastore;
033    import org.deegree.io.datastore.DatastoreConfiguration;
034    import org.deegree.io.datastore.DatastoreException;
035    import org.deegree.io.datastore.DatastoreTransaction;
036    import org.deegree.io.datastore.schema.MappedFeatureType;
037    import org.deegree.io.datastore.schema.MappedGMLSchema;
038    import org.deegree.io.datastore.sql.SQLAnnotationDocument;
039    import org.deegree.io.datastore.sql.SQLDatastoreConfiguration;
040    import org.deegree.io.datastore.sql.StatementBuffer;
041    import org.deegree.io.datastore.sql.TableAliasGenerator;
042    import org.deegree.io.sdeapi.SDEAdapter;
043    import org.deegree.io.sdeapi.SDEConnection;
044    import org.deegree.io.sdeapi.SDEConnectionPool;
045    import org.deegree.model.feature.FeatureCollection;
046    import org.deegree.model.filterencoding.Filter;
047    import org.deegree.model.spatialschema.Geometry;
048    import org.deegree.ogcwebservices.wfs.operation.Query;
049    
050    import com.esri.sde.sdk.client.SeCoordinateReference;
051    import com.esri.sde.sdk.client.SeQuery;
052    import com.esri.sde.sdk.client.SeShape;
053    
054    /**
055     * Datastore implementation for an ESRI SDE database.
056     * 
057     * @author <a href="mailto:cpollmann@moss.de">Christoph Pollmann</a>
058     * @author last edited by: $Author: mschneider $
059     * 
060     * @version $Revision: 12032 $, $Date: 2008-05-29 18:27:00 +0200 (Do, 29. Mai 2008) $
061     */
062    public class SDEDatastore extends Datastore {
063    
064        private static final ILogger LOG = LoggerFactory.getLogger( SDEDatastore.class );
065    
066        private SDEConnectionPool pool = null;
067    
068        @Override
069        public AnnotationDocument getAnnotationParser() {
070            return new SQLAnnotationDocument( this.getClass() );
071        }
072       
073        @Override
074        public void configure( DatastoreConfiguration config )
075                                throws DatastoreException {
076            super.configure( config );
077            this.pool = SDEConnectionPool.getInstance();
078        }
079    
080        @Override
081        public DatastoreConfiguration getConfiguration() {
082            return super.getConfiguration();
083        }
084    
085        @Override
086        public void bindSchema( MappedGMLSchema schema )
087                                throws DatastoreException {
088            super.bindSchema( schema );
089        }
090    
091        @Override
092        public MappedGMLSchema[] getSchemas() {
093            return super.getSchemas();
094        }
095    
096        @Override
097        public MappedFeatureType getFeatureType( QualifiedName ftName ) {
098            return super.getFeatureType( ftName );
099        }
100    
101        @Override
102        public void close()
103                                throws DatastoreException {
104            pool = null;
105        }
106    
107        @Override
108        public FeatureCollection performQuery( final Query query, final MappedFeatureType[] rootFts )
109                                throws DatastoreException {
110    
111            FeatureCollection result = null;
112            SDEConnection conn = acquireConnection();
113            SDEQueryHandler queryHandler = new SDEQueryHandler( this, new TableAliasGenerator(), conn, rootFts, query );
114            result = queryHandler.performQuery();
115            return result;
116        }
117    
118        @Override
119        public DatastoreTransaction acquireTransaction()
120                                throws DatastoreException {
121            DatastoreTransaction transactionHandler = new SDETransaction( this, new TableAliasGenerator(),
122                                                                          acquireConnection() );
123            return transactionHandler;
124        }
125    
126        /**
127         * Returns a specific <code>WhereBuilder</code> implementation for SDE.
128         * 
129         * @param rootFts
130         * @param aliases
131         * @param filter
132         * @param aliasGenerator
133         * @return a specific <code>WhereBuilder</code> implementation for SDE.
134         * @throws DatastoreException
135         */
136        public SDEWhereBuilder getWhereBuilder( MappedFeatureType[] rootFts, String[] aliases, Filter filter,
137                                                TableAliasGenerator aliasGenerator )
138                                throws DatastoreException {
139            SDEWhereBuilder wb = new SDEWhereBuilder( rootFts, aliases, filter, aliasGenerator );
140            return wb;
141        }
142    
143        /**
144         * Converts a database specific geometry <code>Object</code> from the <code>ResultSet</code> to a deegree
145         * <code>Geometry</code>.
146         * 
147         * @param value
148         * @return corresponding deegree geometry
149         * @throws DatastoreException
150         */
151        public Geometry convertDBToDegreeGeometry( Object value )
152                                throws DatastoreException {
153    
154            Geometry geometry = null;
155            if ( value != null ) {
156                try {
157                    SeCoordinateReference coordRef = ( (SeShape) value ).getCoordRef();
158                    String desc = coordRef.getProjectionDescription();
159                    LOG.logDebug( "******* coordSys=" + desc + "****" );
160                    geometry = SDEAdapter.wrap( (SeShape) value );
161                } catch ( Exception e ) {
162                    throw new DatastoreException( "Error converting SeShape to Geometry: " + e.getMessage() );
163                }
164            }
165            return geometry;
166        }
167    
168        /**
169         * Converts a deegree <code>Geometry</code> to a database specific geometry <code>Object</code>.
170         * 
171         * @param geometry
172         * @return corresponding database specific geometry object
173         * @throws DatastoreException
174         */
175        public Object convertDegreeToDBGeometry( Geometry geometry )
176                                throws DatastoreException {
177            Object value = null;
178            if ( geometry != null ) {
179                try {
180                    // TODO: SRS handling
181                    SeCoordinateReference coordRef = new SeCoordinateReference();
182                    value = SDEAdapter.export( geometry, coordRef );
183                } catch ( Exception e ) {
184                    throw new DatastoreException( "Error converting Geometry to SeShape: " + e.getMessage(), e );
185                }
186            }
187            return value;
188        }
189    
190        /**
191         * Returns the database connection requested for.
192         * 
193         * @return Connection
194         * @throws DatastoreException
195         */
196        protected SDEConnection acquireConnection()
197                                throws DatastoreException {
198            JDBCConnection jdbcConnection = ( (SQLDatastoreConfiguration) this.getConfiguration() ).getJDBCConnection();
199            SDEConnection conn = null;
200            try {
201                String url = jdbcConnection.getURL();
202                String[] tmp = url.split( ":" );
203                int instance = 5151;
204                if ( 2 == tmp.length ) {
205                    url = tmp[0];
206                    instance = Integer.parseInt( tmp[1] );
207                }
208                conn = pool.acquireConnection( url, instance, jdbcConnection.getSDEDatabase(),
209                                               jdbcConnection.getSDEVersion(), jdbcConnection.getUser(),
210                                               jdbcConnection.getPassword() );
211            } catch ( Exception e ) {
212                String msg = "Cannot acquire database connection: " + e.getMessage();
213                LOG.logInfo( msg );
214                throw new DatastoreException( msg, e );
215            }
216            return conn;
217        }
218    
219        /**
220         * Releases the connection.
221         * 
222         * @param conn
223         *            Connection to be released.
224         * @throws DatastoreException
225         */
226        protected void releaseConnection( SDEConnection conn )
227                                throws DatastoreException {
228            JDBCConnection jdbcConnection = ( (SQLDatastoreConfiguration) this.getConfiguration() ).getJDBCConnection();
229            try {
230                String url = jdbcConnection.getURL();
231                String[] tmp = url.split( ":" );
232                int instance = 5151;
233                if ( 2 == tmp.length ) {
234                    url = tmp[0];
235                    instance = Integer.parseInt( tmp[1] );
236                }
237                pool.releaseConnection( conn, url, instance, jdbcConnection.getSDEDatabase(),
238                                        jdbcConnection.getSDEVersion(), jdbcConnection.getUser() );
239            } catch ( Exception e ) {
240                String msg = "Cannot release database connection: " + e.getMessage();
241                LOG.logInfo( msg );
242                throw new DatastoreException( msg, e );
243            }
244        }
245    
246        /**
247         * Converts the <code>StatementBuffer</code> into a <code>PreparedStatement</code>, which is initialized and
248         * ready to be performed.
249         * 
250         * @param conn
251         *            connection to be used to create the <code>PreparedStatement</code>
252         * @param statementBuffer
253         * @return the <code>PreparedStatment</code>, ready to be performed
254         */
255        public SeQuery prepareStatement( SDEConnection conn, StatementBuffer statementBuffer ) {
256            LOG.logDebug( "Preparing statement: " + statementBuffer.getQueryString() );
257    
258            SeQuery query = null;
259            try {
260                query = new SeQuery( conn.getConnection() );
261                query.prepareSql( statementBuffer.getQueryString() );
262            } catch ( Exception e ) {
263                e.printStackTrace();
264            }
265    
266            // TODO
267            return query;
268        }
269    
270        @Override
271        public FeatureCollection performQuery( Query query, MappedFeatureType[] rootFts, DatastoreTransaction context )
272                                throws DatastoreException {
273            throw new DatastoreException( "method invocation for sde not applicable" );
274        }
275    
276        @Override
277        public void releaseTransaction( DatastoreTransaction ta )
278                                throws DatastoreException {
279            releaseConnection( ( (SDETransaction) ta ).getConnection() );
280        }
281    }