001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/oraclegeoraster/GeoRasterReader.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53177 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.io.oraclegeoraster;
045    
046    import java.awt.Graphics2D;
047    import java.awt.Image;
048    import java.awt.image.BufferedImage;
049    import java.awt.image.RenderedImage;
050    import java.io.IOException;
051    import java.lang.reflect.Method;
052    import java.sql.Connection;
053    import java.sql.PreparedStatement;
054    import java.sql.ResultSet;
055    import java.sql.SQLException;
056    import java.sql.Statement;
057    import java.util.Properties;
058    
059    import oracle.spatial.georaster.GeoRasterException;
060    import oracle.spatial.georaster.JGeoRaster;
061    import oracle.spatial.georaster.JGeoRasterMeta;
062    import oracle.sql.STRUCT;
063    
064    import org.deegree.framework.log.ILogger;
065    import org.deegree.framework.log.LoggerFactory;
066    import org.deegree.framework.util.StringTools;
067    import org.deegree.io.DBConnectionPool;
068    import org.deegree.io.JDBCConnection;
069    import org.deegree.model.spatialschema.Envelope;
070    import org.deegree.ogcwebservices.InvalidParameterValueException;
071    
072    /**
073     * 
074     * 
075     * 
076     * @version $Revision: 9342 $
077     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
078     * @author last edited by: $Author: apoth $
079     * 
080     * @version 1.0. $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
081     * 
082     * @since 2.0
083     */
084    public class GeoRasterReader {
085    
086        private static final ILogger LOG = LoggerFactory.getLogger( GeoRasterReader.class );
087    
088        /**
089         * 
090         * @param grDesc
091         * @param envelope
092         *            requested envelope
093         * @param level
094         *            requested level (resolution)
095         * @return
096         * @throws SQLException
097         * @throws IOException
098         * @throws GeoRasterException
099         * @throws Exception
100         */
101        public static RenderedImage exportRaster( GeoRasterDescription grDesc, Envelope envelope )
102                                throws SQLException, IOException, GeoRasterException, Exception {
103    
104            DBConnectionPool pool = DBConnectionPool.getInstance();
105            JDBCConnection jdbc = grDesc.getJdbcConnection();
106            Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), jdbc.getPassword() );
107    
108            RenderedImage ri = exportRaster( con, envelope, grDesc.getRdtTable(), grDesc.getTable(), grDesc.getColumn(),
109                                             grDesc.getIdentification(), grDesc.getLevel() );
110    
111            /*
112             * System.out.println( grDesc.getTable() ); System.out.println( grDesc.getLevel() );
113             * System.out.println(ri.getWidth() ); System.out.println(ri.getHeight() );
114             */
115    
116            pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), jdbc.getPassword() );
117    
118            return ri;
119        }
120    
121        /**
122         * 
123         * @param connection
124         *            connnection to Oracle database
125         * @param envelope
126         *            requested area
127         * @param rasterRDT
128         *            name of the RDT-table
129         * @param rasterTable
130         *            name of the table containing a georaster col
131         * @param geoRasterCol
132         *            name of the geoRaster column
133         * @param identification
134         *            SQL where clause that identifies the raster of interest
135         * @param level
136         *            requested resolution level
137         * @return
138         * @throws SQLException
139         * @throws IOException
140         * @throws GeoRasterException
141         * @throws Exception
142         */
143        public static RenderedImage exportRaster( Connection connection, Envelope envelope, String rasterRDT,
144                                                  String rasterTable, String geoRasterCol, String identification, int level )
145                                throws Exception {
146            RenderedImage img = null;
147            try {
148    
149                int rasterID = readRasterID( connection, identification, rasterTable, geoRasterCol );
150    
151                STRUCT struct = readGeoRasterMetadata( connection, rasterRDT, rasterTable, geoRasterCol, rasterID );
152    
153                int major = connection.getMetaData().getDriverMajorVersion();
154                int minor = connection.getMetaData().getDriverMinorVersion();
155    
156                LOG.logDebug( "Envelope: ", envelope );
157                LOG.logDebug( "mapping STRUCT to a JGeoRaster object" );
158                LOG.logDebug( "identified Oracle version: ", major + "." + minor );
159    
160                JGeoRaster jGeoRaster = null;
161                if ( major == 10 && minor == 1 ) {
162                    // synthax for Oracle 10g R1
163                    Class[] clzz = new Class[] { STRUCT.class };
164                    Method method = JGeoRaster.class.getMethod( "load", clzz );
165                    jGeoRaster = (JGeoRaster) method.invoke( null, new Object[] { struct } );
166                    jGeoRaster = JGeoRaster.load( struct );
167                } else if ( major == 10 && minor == 2 ) {
168                    // synthax for Oracle 10g R2
169                    Class[] clzz = new Class[] { STRUCT.class, Connection.class, boolean.class };
170                    Method method = JGeoRaster.class.getMethod( "load", clzz );
171                    Object[] params = new Object[] { struct, connection, false };
172                    jGeoRaster = (JGeoRaster) method.invoke( null, params );
173                } else {
174                    throw new InvalidParameterValueException(
175                                                              "Oracle must have version 10.1 or 10.2 for using Georaster functionality" );
176                }
177                jGeoRaster.setViewerUse( true );
178                Properties props = jGeoRaster.getProperties();
179    
180                int maxWidth = Integer.parseInt( props.getProperty( "rasterInfo/dimensionSize_column" ) );
181                int maxHeight = Integer.parseInt( props.getProperty( "rasterInfo/dimensionSize_row" ) );
182    
183                JGeoRasterMeta metaObj = jGeoRaster.getMetadataObject();
184    
185                double xMin = metaObj.getX( 0, 0 );
186                double xMax = metaObj.getX( maxWidth - 1, maxHeight - 1 );
187                double sc = Math.pow( 2, level );
188                double lenX = ( xMax - xMin ) * sc;
189                double yMin = metaObj.getY( 0, 0 );
190                double yMax = metaObj.getY( maxWidth - 1, maxHeight - 1 );
191                double lenY = ( yMax - yMin ) * sc;
192    
193                int xMinCell = (int) Math.round( ( envelope.getMin().getX() - xMin ) * maxWidth / lenX );
194                int xMaxCell = (int) Math.round( ( envelope.getMax().getX() - xMin ) * maxWidth / lenX ) - 1;
195                int yMaxCell = (int) Math.round( ( envelope.getMin().getY() - yMin ) * maxHeight / lenY );
196                int yMinCell = (int) Math.round( ( envelope.getMax().getY() - yMin ) * maxHeight / lenY ) - 1;
197    
198                String bb = StringTools.concat( 100, xMinCell, " ", yMinCell, " ", xMaxCell, " ", yMaxCell );
199                LOG.logInfo( "requested box:", bb );
200    
201                LOG.logDebug( "reading georaster image, with level: " + level );
202                img = jGeoRaster.getRasterImage( connection, level, xMinCell, yMinCell, xMaxCell, yMaxCell );
203    
204                int xDiff = ( xMaxCell - xMinCell ) + 1;
205                int yDiff = ( yMaxCell - yMinCell ) + 1;
206                if ( img != null && ( img.getWidth() != xDiff || img.getHeight() != yDiff ) && xDiff > 0 && yDiff > 0 ) {
207                    // request img size != result
208                    LOG.logDebug( StringTools.concat( 100, "request img size != result; new image size: ", xDiff, "x",
209                                                      yDiff ) );
210                    BufferedImage bimg = new BufferedImage( xDiff, yDiff, BufferedImage.TYPE_INT_ARGB );
211                    Graphics2D bg = bimg.createGraphics();
212    
213                    int posX = 0;
214                    int posY = 0;
215    
216                    if ( xMinCell < 0 ) {
217                        posX = Math.abs( xMinCell );
218                    }
219                    if ( yMinCell < 0 ) {
220                        posY = Math.abs( yMinCell );
221                    }
222    
223                    bg.drawImage( (Image) img, posX, posY, null );
224                    bg.dispose();
225    
226                    img = bimg;
227                }
228    
229            } catch ( SQLException e1 ) {
230                e1.printStackTrace();
231                String s = StringTools.concat( 1000, e1.getMessage(), " ", rasterTable, "; ", rasterRDT, "; ",
232                                               geoRasterCol, "; ", identification, "; level: ", level );
233                throw new RuntimeException( s );
234            } catch ( Exception e ) {
235                e.printStackTrace();
236                throw new RuntimeException( e );
237            }
238            return img;
239        }
240    
241        /**
242         * 
243         * @param connection
244         * @param rasterRDT
245         * @param rasterTable
246         * @param geoRasterCol
247         * @param rasterID
248         * @return
249         * @throws SQLException
250         */
251        private static STRUCT readGeoRasterMetadata( Connection connection, String rasterRDT, String rasterTable,
252                                                     String geoRasterCol, int rasterID )
253                                throws SQLException {
254            LOG.logDebug( "reading georaster" );
255            PreparedStatement ps = connection.prepareStatement( "select " + geoRasterCol + " from " + rasterTable
256                                                                + " a where a." + geoRasterCol + ".rasterid = " + rasterID
257                                                                + " and a." + geoRasterCol + ".rasterdatatable = '"
258                                                                + rasterRDT.toUpperCase() + "'" );
259            ResultSet resultset = ps.executeQuery();
260            if ( !resultset.next() ) {
261                throw new SQLException( "No GeoRaster object exists at rasterid = " + rasterID + ", RDT = " + rasterRDT );
262            }
263    
264            STRUCT struct = (STRUCT) resultset.getObject( geoRasterCol.toUpperCase() );
265            resultset.close();
266            return struct;
267        }
268    
269        /**
270         * returns the rasterID of the requested GeoRaster
271         * 
272         * @param connection
273         * @param identification
274         * @param sql
275         * @return
276         * @throws SQLException
277         * @throws GeoRasterException
278         */
279        private static int readRasterID( Connection connection, String identification, String rasterTable,
280                                         String geoRasterCol )
281                                throws SQLException, GeoRasterException {
282    
283            LOG.logDebug( "reading rasterid " );
284    
285            String sql = "SELECT  a." + geoRasterCol.toUpperCase() + ".rasterid FROM " + rasterTable.toUpperCase()
286                         + " a where " + identification;
287            LOG.logDebug( sql );
288            Statement stmt = connection.createStatement();
289            ResultSet rs = stmt.executeQuery( sql );
290            if ( !rs.next() ) {
291                throw new GeoRasterException( "Georaster with identification = " + identification + " not found!" );
292            }
293            int rasterID = rs.getInt( 1 );
294            stmt.close();
295            rs.close();
296            return rasterID;
297        }
298    
299    }