001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/io/oraclegeoraster/GeoRasterReader.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2006 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: 7765 $
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: 7765 $, $Date: 2007-07-16 13:05:57 +0200 (Mo, 16 Jul 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( "mapping STRUCT to a JGeoRaster object" );
157                LOG.logDebug( "identified Oracle version: ", major + "." + minor );
158                            
159                JGeoRaster jGeoRaster = null;
160                if ( major == 10 && minor == 1 ) {
161                    // synthax for Oracle 10g R1
162                    Class[] clzz = new Class[] { STRUCT.class };
163                    Method method = JGeoRaster.class.getMethod( "load", clzz );
164                    jGeoRaster = (JGeoRaster)method.invoke( null, new Object[] { struct } );
165                    jGeoRaster = JGeoRaster.load( struct );
166                } else if ( major == 10 && minor == 2 ) {
167                    // synthax for Oracle 10g R2
168                    Class[] clzz = new Class[] { STRUCT.class, Connection.class, boolean.class };
169                    Method method = JGeoRaster.class.getMethod( "load", clzz );
170                    Object[] params = new Object[] { struct, connection, false };
171                    jGeoRaster = (JGeoRaster)method.invoke( null, params );
172                } else {
173                    throw new InvalidParameterValueException("Oracle must have version 10.1 or 10.2 for using Georaster functionality" );
174                }
175                jGeoRaster.setViewerUse( true );
176                Properties props = jGeoRaster.getProperties();
177    
178                int maxWidth = Integer.parseInt( props.getProperty( "rasterInfo/dimensionSize_column" ) );
179                int maxHeight = Integer.parseInt( props.getProperty( "rasterInfo/dimensionSize_row" ) );
180    
181                JGeoRasterMeta metaObj = jGeoRaster.getMetadataObject();
182    
183                double xMin = metaObj.getX( 0, 0 );
184                double xMax = metaObj.getX( maxWidth - 1, maxHeight - 1 );
185                double sc = Math.pow( 2, level );
186                double lenX = ( xMax - xMin ) * sc;
187                double yMin = metaObj.getY( 0, 0 );
188                double yMax = metaObj.getY( maxWidth - 1, maxHeight - 1 );
189                double lenY = ( yMax - yMin ) * sc;
190    
191                int xMinCell = (int) Math.round( ( envelope.getMin().getX() - xMin ) * maxWidth / lenX );
192                int xMaxCell = (int) Math.round( ( envelope.getMax().getX() - xMin ) * maxWidth / lenX ) - 1;
193                int yMaxCell = (int) Math.round( ( envelope.getMin().getY() - yMin ) * maxHeight / lenY );
194                int yMinCell = (int) Math.round( ( envelope.getMax().getY() - yMin ) * maxHeight / lenY ) - 1;
195    
196                String bb = StringTools.concat( 100, xMinCell, " ", yMinCell, " ", xMaxCell, " ", yMaxCell );
197                LOG.logInfo( "requested box:", bb );
198    
199                LOG.logDebug( "reading georaster image, with level: " + level );
200                img = jGeoRaster.getRasterImage( connection, level, xMinCell, yMinCell, xMaxCell, yMaxCell );
201    
202                int xDiff = ( xMaxCell - xMinCell ) + 1;
203                int yDiff = ( yMaxCell - yMinCell ) + 1;
204                if ( img != null && ( img.getWidth() != xDiff || img.getHeight() != yDiff ) && xDiff > 0 && yDiff > 0 ) {
205                    // request img size != result
206                    LOG.logDebug( StringTools.concat( 100, "request img size != result; new image size: ", xDiff, "x",
207                                                      yDiff ) );
208                    BufferedImage bimg = new BufferedImage( xDiff, yDiff, BufferedImage.TYPE_INT_ARGB );
209                    Graphics2D bg = bimg.createGraphics();
210    
211                    int posX = 0;
212                    int posY = 0;
213    
214                    if ( xMinCell < 0 ) {
215                        posX = Math.abs( xMinCell );
216                    }
217                    if ( yMinCell < 0 ) {
218                        posY = Math.abs( yMinCell );
219                    }
220    
221                    bg.drawImage( (Image) img, posX, posY, null );
222                    bg.dispose();
223    
224                    img = bimg;
225                }
226    
227            } catch ( SQLException e1 ) {
228                e1.printStackTrace();
229                String s = StringTools.concat( 1000, e1.getMessage(), " ", rasterTable, "; ", rasterRDT, "; ",
230                                               geoRasterCol, "; ", identification, "; level: ", level );
231                throw new RuntimeException( s );
232            } catch ( Exception e ) {
233                e.printStackTrace();
234                throw new RuntimeException( e );
235            }
236            return img;
237        }
238    
239        /**
240         * 
241         * @param connection
242         * @param rasterRDT
243         * @param rasterTable
244         * @param geoRasterCol
245         * @param rasterID
246         * @return
247         * @throws SQLException
248         */
249        private static STRUCT readGeoRasterMetadata( Connection connection, String rasterRDT, String rasterTable,
250                                                     String geoRasterCol, int rasterID )
251                                throws SQLException {
252            LOG.logDebug( "reading georaster" );
253            PreparedStatement ps = connection.prepareStatement( "select " + geoRasterCol + " from " + rasterTable
254                                                                + " a where a." + geoRasterCol + ".rasterid = " + rasterID
255                                                                + " and a." + geoRasterCol + ".rasterdatatable = '"
256                                                                + rasterRDT.toUpperCase() + "'" );
257            ResultSet resultset = ps.executeQuery();
258            if ( !resultset.next() ) {
259                throw new SQLException( "No GeoRaster object exists at rasterid = " + rasterID + ", RDT = " + rasterRDT );
260            }
261    
262            STRUCT struct = (STRUCT) resultset.getObject( geoRasterCol.toUpperCase() );
263            resultset.close();
264            return struct;
265        }
266    
267        /**
268         * returns the rasterID of the requested GeoRaster
269         * 
270         * @param connection
271         * @param identification
272         * @param sql
273         * @return
274         * @throws SQLException
275         * @throws GeoRasterException
276         */
277        private static int readRasterID( Connection connection, String identification, String rasterTable,
278                                         String geoRasterCol )
279                                throws SQLException, GeoRasterException {
280    
281            LOG.logDebug( "reading rasterid " );
282    
283            String sql = "SELECT  a." + geoRasterCol + ".rasterid FROM " + rasterTable + " a where " + identification;
284            Statement stmt = connection.createStatement();
285            ResultSet rs = stmt.executeQuery( sql );
286            if ( !rs.next() ) {
287                throw new GeoRasterException( "Georaster with identification = " + identification + " not found!" );
288            }
289            int rasterID = rs.getInt( 1 );
290            stmt.close();
291            rs.close();
292            return rasterID;
293        }
294    
295    }
296    /***************************************************************************************************
297     * Changes to this class. What the people have been up to: $Log$ Revision 1.11 2006/07/05 12:59:09
298     * poth bug fix - raster coordinates calculation for other pyramid levels than '0'
299     * 
300     * Revision 1.10 2006/07/03 06:40:13 poth ** empty log message ***
301     * 
302     * Revision 1.9 2006/06/30 14:15:29 poth footer added
303     * 
304     * 
305     **************************************************************************************************/