svn - r34313 - in trunk/modules/plugin/arcsde/datastore/src: main/java/org/geotools/arcsde main/java/org/geotools/arcsde/data main/java/org/geotools/arcsde/filter main/java/org/geotools/arcsde/gce main/java/org/geotools/arcsde/raster main/java/org/geotools/arcsde/raster/gce main/java/org/geotools/arcsde/raster/info main/java/org/geotools/arcsde/raster/io main/java/org/geotools/arcsde/raster/jai main/java/org/geotools/arcsde/util main/resources/org/geotools/arcsde test/java/org/geotools/arcsde test/java/org/geotools/arcsde/data test/java/org/geotools/arcsde/gce test/java/org/geotools/arcsde/raster test/java/org/geotools/arcsde/raster/gce test/java/org/geotools/arcsde/raster/info test/java/org/geotools/arcsde/raster/io

1 message Options
Embed this post
Permalink
svn_geotools

svn - r34313 - in trunk/modules/plugin/arcsde/datastore/src: main/java/org/geotools/arcsde main/java/org/geotools/arcsde/data main/java/org/geotools/arcsde/filter main/java/org/geotools/arcsde/gce main/java/org/geotools/arcsde/raster main/java/org/geotools/arcsde/raster/gce main/java/org/geotools/arcsde/raster/info main/java/org/geotools/arcsde/raster/io main/java/org/geotools/arcsde/raster/jai main/java/org/geotools/arcsde/util main/resources/org/geotools/arcsde test/java/org/geotools/arcsde test/java/org/geotools/arcsde/data test/java/org/geotools/arcsde/gce test/java/org/geotools/arcsde/raster test/java/org/geotools/arcsde/raster/gce test/java/org/geotools/arcsde/raster/info test/java/org/geotools/arcsde/raster/io

Reply Threaded More More options
Print post
Permalink
Author: groldan
Date: 2009-11-03 11:03:24 -0500 (Tue, 03 Nov 2009)
New Revision: 34313

Added:
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/CompressionType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/GatherCoverageMetadataCommand.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterleaveType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterpolationType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/PyramidLevelInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterBandInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterCellType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterDatasetInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterQueryInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterUtils.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/BitmaskToNoDataConverter.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/DefaultTiledRasterReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/RasterReaderFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReaderFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TiledRasterReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledImageInputStream.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAIOnlineTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/RasterTestData.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/info/
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/info/RasterInfoTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/info/RasterUtilsTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/io/
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/io/BitmaskToNoDataConverterTest.java
Removed:
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEImageReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDERasterFormat.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDETiledImageInputStream.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/BitmaskToNoDataConverter.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/CompressionType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/DefaultTiledRasterReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/GatherCoverageMetadataCommand.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterleaveType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterpolationType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/NativeTileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PromotingTileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PyramidLevelInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterBandInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterCellType.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterDatasetInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInputStream.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterQueryInfo.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterReaderFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterUtils.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReaderFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TiledRasterReader.java
   trunk/modules/plugin/arcsde/datastore/src/main/resources/org/geotools/arcsde/gce/
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAIOnlineTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/BitmaskToNoDataConverterTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterInfoTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterTestData.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterUtilsTest.java
Modified:
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEDataStore.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEQuery.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureCollection.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureWriter.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/SeToJTSGeometryFactory.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/TransactionFeatureWriter.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/filter/FilterToSQLSDE.java
   trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/util/ArcSDEUtils.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEDataStoreFactoryTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactoryTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreNonSpatialTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEJavaApiTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ClobTestData.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/FIDReaderTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/SDEJavaApiJoinTest.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestFeatureListener.java
   trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestProgressListener.java
Log:
GEOT-2616, package reorganization

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactory.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactory.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -64,8 +64,10 @@
  * </p>
  *
  * @author Gabriel Roldan (OpenGeo)
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/ArcSDEJNDIDataStoreFactory.java $
  * @version $Id$
  * @since 2.5.7
  */

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -22,7 +22,7 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.geotools.arcsde.gce.ArcSDERasterFormat;
+import org.geotools.arcsde.raster.gce.ArcSDERasterFormat;
 import org.geotools.coverage.grid.io.GridFormatFactorySpi;
 import org.geotools.util.logging.Logging;
 

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEDataStore.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEDataStore.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEDataStore.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -64,6 +64,7 @@
 import org.geotools.feature.SchemaException;
 import org.geotools.geometry.jts.LiteCoordinateSequenceFactory;
 import org.geotools.util.logging.Logging;
+import org.hsqldb.Session;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.AttributeDescriptor;
@@ -378,7 +379,7 @@
         // this is the one which's gonna close the connection when done
         final ArcSDEAttributeReader attReader;
         attReader = new ArcSDEAttributeReader(sdeQuery, geometryFactory, session);
-        
+
         FeatureReader<SimpleFeatureType, SimpleFeature> reader;
         try {
             reader = new ArcSDEFeatureReader(attReader);

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEQuery.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEQuery.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEQuery.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -52,6 +52,7 @@
 import org.geotools.filter.visitor.SimplifyingFilterVisitor;
 import org.geotools.filter.visitor.SimplifyingFilterVisitor.FIDValidator;
 import org.geotools.util.logging.Logging;
+import org.hsqldb.Session;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.AttributeDescriptor;
 import org.opengis.feature.type.GeometryDescriptor;
@@ -69,7 +70,6 @@
 import com.esri.sde.sdk.client.SeQueryInfo;
 import com.esri.sde.sdk.client.SeSqlConstruct;
 import com.esri.sde.sdk.client.SeTable;
-import com.esri.sde.sdk.geom.GeometryFactory;
 import com.vividsolutions.jts.geom.Envelope;
 
 /**
@@ -881,8 +881,10 @@
      * DOCUMENT ME!
      *
      * @author $author$
- *
- * @source $URL$
+     *
+     * @source $URL:
+     *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java
+     *         /org/geotools/arcsde/data/ArcSDEQuery.java $
      * @version $Revision: 1.9 $
      */
     public static class FilterSet {

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureCollection.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureCollection.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureCollection.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -26,6 +26,7 @@
 import org.geotools.feature.FeatureCollection;
 import org.geotools.geometry.jts.ReferencedEnvelope;
 import org.geotools.util.logging.Logging;
+import org.hsqldb.Session;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.GeometryDescriptor;

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureWriter.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureWriter.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSdeFeatureWriter.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -40,10 +40,10 @@
 import org.geotools.data.jdbc.MutableFIDFeature;
 import org.geotools.factory.CommonFactoryFinder;
 import org.geotools.feature.simple.SimpleFeatureBuilder;
-import org.geotools.feature.type.Types;
 import org.geotools.geometry.jts.ReferencedEnvelope;
 import org.geotools.util.Converters;
 import org.geotools.util.logging.Logging;
+import org.hsqldb.Session;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.AttributeDescriptor;
@@ -365,10 +365,10 @@
      * @see FeatureWriter#write()
      */
     public void write() throws IOException {
-        
-        //make the feature validate against its schema before inserting/updating
+
+        // make the feature validate against its schema before inserting/updating
         feature.validate();
-        
+
         if (isNewlyCreated(feature)) {
             Number newId;
             try {

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/SeToJTSGeometryFactory.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/SeToJTSGeometryFactory.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/SeToJTSGeometryFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -19,8 +19,10 @@
  * creates JTS geometries directly by calling {@link SeRow#getGeometry(GeometryFactory, int)},
  * instead of fetching an {@link SeShape} through {@link SeRow#getShape(int)} and then converting it
  * to a JTS geometry. This is work in progress and _experimental_, though.
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/data/SeToJTSGeometryFactory.java $
  */
 public class SeToJTSGeometryFactory implements GeometryFactory {
 
@@ -73,7 +75,7 @@
     }
 
     public void partOffsets(int[] partOffsets) {
-        //System.out.println(Arrays.toString(partOffsets));
+        // System.out.println(Arrays.toString(partOffsets));
     }
 
     /**

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/TransactionFeatureWriter.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/TransactionFeatureWriter.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/data/TransactionFeatureWriter.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -26,6 +26,7 @@
 import org.geotools.data.FeatureWriter;
 import org.geotools.data.Transaction;
 import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.hsqldb.Session;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.filter.Filter;

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/filter/FilterToSQLSDE.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/filter/FilterToSQLSDE.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/filter/FilterToSQLSDE.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -228,12 +228,12 @@
         String fidField = layerFidFieldName;
 
         try {
-            String sql = buildFilter(fids, fidField+" IN(", ")", ",", 1000, " OR ");
+            String sql = buildFilter(fids, fidField + " IN(", ")", ",", 1000, " OR ");
 
             if (LOGGER.isLoggable(Level.FINER)) {
                 LOGGER.finer("added fid filter: " + sql);
             }
-
+
             this.out.write(sql);
         } catch (Exception ex) {
             throw new RuntimeException(ex.getMessage(), ex);
@@ -242,43 +242,37 @@
     }
 
     // return a string
-    private String buildFilter(long[] fids, String prefix, String suffix, String separator, int groupSize, String groupSeparator)
-    {
+    private String buildFilter(long[] fids, String prefix, String suffix, String separator,
+            int groupSize, String groupSeparator) {
         final int count = fids.length;
         final int groups = count / groupSize;
         final int remainder = count % groupSize;
         final StringBuilder sql = new StringBuilder();
-        for (int i=0; i<groups; i++)
-        {
-            if ( i > 0 )
-            {
+        for (int i = 0; i < groups; i++) {
+            if (i > 0) {
                 sql.append(groupSeparator);
             }
             sql.append(prefix);
-            addSubList(sql, fids, i*groupSize, (i+1)*groupSize, separator);
+            addSubList(sql, fids, i * groupSize, (i + 1) * groupSize, separator);
             sql.append(suffix);
         }
-        if ( remainder > 0 )
-        {
-            if ( groups > 0 )
-            {
+        if (remainder > 0) {
+            if (groups > 0) {
                 sql.append(groupSeparator);
-            }
+            }
             sql.append(prefix);
-            addSubList(sql, fids, count-remainder, count, separator);
+            addSubList(sql, fids, count - remainder, count, separator);
             sql.append(suffix);
         }
         return sql.toString();
     }
-
-    private void addSubList(StringBuilder sql, long[] fids, int start, int end, String separator)
-    {
-        for (int i=start; i<end; i++)
-        {
+
+    private void addSubList(StringBuilder sql, long[] fids, int start, int end, String separator) {
+        for (int i = start; i < end; i++) {
             sql.append(fids[i]);
             sql.append(separator);
         }
-        sql.setLength(sql.length()-separator.length());
+        sql.setLength(sql.length() - separator.length());
     }
 
     /**

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,686 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
-import java.awt.image.renderable.ParameterBlock;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-import javax.imageio.ImageTypeSpecifier;
-import javax.media.jai.ImageLayout;
-import javax.media.jai.InterpolationNearest;
-import javax.media.jai.JAI;
-import javax.media.jai.ParameterBlockJAI;
-import javax.media.jai.operator.FormatDescriptor;
-import javax.media.jai.operator.MosaicDescriptor;
-
-import org.geotools.coverage.CoverageFactoryFinder;
-import org.geotools.coverage.GridSampleDimension;
-import org.geotools.coverage.TypeMap;
-import org.geotools.coverage.grid.GeneralGridEnvelope;
-import org.geotools.coverage.grid.GridCoverage2D;
-import org.geotools.coverage.grid.GridEnvelope2D;
-import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.data.DataSourceException;
-import org.geotools.data.DefaultServiceInfo;
-import org.geotools.data.ServiceInfo;
-import org.geotools.factory.Hints;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.util.logging.Logging;
-import org.opengis.coverage.ColorInterpretation;
-import org.opengis.coverage.grid.Format;
-import org.opengis.coverage.grid.GridCoverageReader;
-import org.opengis.parameter.GeneralParameterValue;
-
-/**
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java $
- */
-@SuppressWarnings( { "deprecation", "nls" })
-final class ArcSDEGridCoverage2DReaderJAI extends AbstractGridCoverage2DReader {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    /**
-     * @see LoggingHelper#log(RenderedImage, Long, String)
-     */
-    private static final boolean DEBUG_TO_DISK = Boolean
-            .getBoolean("org.geotools.arcsde.gce.debug");
-
-    private final ArcSDERasterFormat parent;
-
-    private final RasterDatasetInfo rasterInfo;
-
-    private DefaultServiceInfo serviceInfo;
-
-    private RasterReaderFactory rasterReaderFactory;
-
-    public ArcSDEGridCoverage2DReaderJAI(final ArcSDERasterFormat parent,
-            final RasterReaderFactory rasterReaderFactory, final RasterDatasetInfo rasterInfo,
-            final Hints hints) throws IOException {
-        // check it's a supported format
-        {
-            final int bitsPerSample = rasterInfo.getBand(0, 0).getCellType().getBitsPerSample();
-            if (rasterInfo.getNumBands() > 1 && (bitsPerSample == 1 || bitsPerSample == 4)) {
-                throw new IllegalArgumentException(bitsPerSample
-                        + "-bit rasters with more than one band are not supported");
-            }
-        }
-        this.parent = parent;
-        this.rasterReaderFactory = rasterReaderFactory;
-        this.rasterInfo = rasterInfo;
-
-        super.hints = hints;
-        super.coverageFactory = CoverageFactoryFinder.getGridCoverageFactory(this.hints);
-        super.crs = rasterInfo.getCoverageCrs();
-        super.originalEnvelope = rasterInfo.getOriginalEnvelope();
-
-        GeneralGridEnvelope gridRange = rasterInfo.getOriginalGridRange();
-        super.originalGridRange = new GridEnvelope2D(gridRange.toRectangle());
-
-        super.coverageName = rasterInfo.getRasterTable();
-        final int numLevels = rasterInfo.getNumPyramidLevels(0);
-
-        // level 0 is not an overview, but the raster itself
-        super.numOverviews = numLevels - 1;
-
-        // ///
-        //
-        // setting the higher resolution avalaible for this coverage
-        //
-        // ///
-        highestRes = super.getResolution(originalEnvelope, (Rectangle) originalGridRange, crs);
-        // //
-        //
-        // get information for the successive images
-        //
-        // //
-        // REVISIT may the different rasters in the raster dataset have different pyramid levels? I
-        // guess so
-        if (numOverviews > 0) {
-            overViewResolutions = new double[numOverviews][2];
-            for (int pyramidLevel = 1; pyramidLevel <= numOverviews; pyramidLevel++) {
-                Rectangle levelGridRange = rasterInfo.getGridRange(0, pyramidLevel);
-                GeneralEnvelope levelEnvelope = rasterInfo.getGridEnvelope(0, pyramidLevel);
-                overViewResolutions[pyramidLevel - 1] = super.getResolution(levelEnvelope,
-                        levelGridRange, crs);
-            }
-        } else {
-            overViewResolutions = null;
-        }
-    }
-
-    /**
-     * @see GridCoverageReader#getFormat()
-     */
-    public Format getFormat() {
-        return parent;
-    }
-
-    @Override
-    public ServiceInfo getInfo() {
-        if (serviceInfo == null) {
-            serviceInfo = new DefaultServiceInfo();
-            serviceInfo.setTitle(rasterInfo.getRasterTable());
-            serviceInfo.setDescription(rasterInfo.toString());
-            Set<String> keywords = new HashSet<String>();
-            keywords.add("ArcSDE");
-            serviceInfo.setKeywords(keywords);
-        }
-        return serviceInfo;
-    }
-
-    /**
-     * @see GridCoverageReader#read(GeneralParameterValue[])
-     */
-    public GridCoverage2D read(GeneralParameterValue[] params) throws IOException {
-
-        final GeneralEnvelope requestedEnvelope;
-        final Rectangle requestedDim;
-        final OverviewPolicy overviewPolicy;
-        {
-            final ReadParameters opParams = RasterUtils.parseReadParams(getOriginalEnvelope(),
-                    params);
-            overviewPolicy = opParams.overviewPolicy;
-            requestedEnvelope = opParams.requestedEnvelope;
-            requestedDim = opParams.dim;
-        }
-
-        /*
-         * For each raster in the raster dataset, obtain the tiles, pixel range, and resulting
-         * envelope
-         */
-        final List<RasterQueryInfo> queries;
-        queries = findMatchingRasters(requestedEnvelope, requestedDim, overviewPolicy);
-        if (queries.isEmpty()) {
-            /*
-             * none of the rasters match the requested envelope. This may happen by the tiled nature
-             * of the raster dataset
-             */
-            return createFakeCoverage(requestedEnvelope, requestedDim);
-        }
-
-        final GeneralEnvelope resultEnvelope = getResultEnvelope(queries);
-
-        final LoggingHelper log = new LoggingHelper();
-        log.appendLoggingGeometries(LoggingHelper.REQ_ENV, requestedEnvelope);
-        log.appendLoggingGeometries(LoggingHelper.RES_ENV, resultEnvelope);
-
-        /*
-         * Once we collected the matching rasters and their image subsets, find out where in the
-         * overall resulting mosaic they fit. If the rasters does not share the spatial resolution,
-         * the QueryInfo.resultDimension and QueryInfo.mosaicLocation width or height won't match
-         */
-        final Rectangle mosaicGeometry;
-        mosaicGeometry = RasterUtils.setMosaicLocations(rasterInfo, resultEnvelope, queries);
-
-        /*
-         * Gather the rendered images for each of the rasters that match the requested envelope
-         */
-        final TiledRasterReader rasterReader = rasterReaderFactory.create(rasterInfo);
-
-        try {
-            readAllTiledRasters(queries, rasterReader, log);
-        } finally {
-            // rasterReader.dispose();
-        }
-
-        log.log(LoggingHelper.REQ_ENV);
-        log.log(LoggingHelper.RES_ENV);
-        log.log(LoggingHelper.MOSAIC_ENV);
-        log.log(LoggingHelper.MOSAIC_EXPECTED);
-
-        final RenderedImage coverageRaster = createMosaic(queries, mosaicGeometry, log);
-        assert mosaicGeometry.getWidth() == coverageRaster.getWidth();
-        assert mosaicGeometry.getHeight() == coverageRaster.getHeight();
-
-        /*
-         * BUILDING COVERAGE
-         */
-        GridSampleDimension[] bands = getSampleDimensions(coverageRaster);
-
-        GridCoverage2D resultCoverage = coverageFactory.create(coverageName, coverageRaster,
-                resultEnvelope, bands, null, null);
-
-        return resultCoverage;
-    }
-
-    private GridSampleDimension[] getSampleDimensions(final RenderedImage coverageRaster)
-            throws IOException {
-
-        GridSampleDimension[] bands = rasterInfo.getGridSampleDimensions();
-
-        // may the image have been promoted? build the correct band info then
-        final int imageBands = coverageRaster.getSampleModel().getNumBands();
-        if (bands.length == 1 && imageBands > 1) {
-            LOGGER.fine(coverageName + " was promoted from 1 to "
-                    + coverageRaster.getSampleModel().getNumBands()
-                    + " bands, returning an appropriate set of GridSampleDimension");
-            // stolen from super.createCoverage:
-            final ColorModel cm = coverageRaster.getColorModel();
-            bands = new GridSampleDimension[imageBands];
-
-            // setting bands names.
-            for (int i = 0; i < imageBands; i++) {
-                final ColorInterpretation colorInterpretation;
-                colorInterpretation = TypeMap.getColorInterpretation(cm, i);
-                if (colorInterpretation == null) {
-                    throw new IOException("Unrecognized sample dimension type");
-                }
-                bands[i] = new GridSampleDimension(colorInterpretation.name()).geophysics(true);
-            }
-        }
-
-        return bands;
-    }
-
-    private void readAllTiledRasters(final List<RasterQueryInfo> queries,
-            final TiledRasterReader rasterReader, final LoggingHelper log) throws IOException {
-
-        for (RasterQueryInfo queryInfo : queries) {
-
-            final Long rasterId = queryInfo.getRasterId();
-
-            final RenderedImage rasterImage;
-
-            try {
-                final int pyramidLevel = queryInfo.getPyramidLevel();
-                final Rectangle matchingTiles = queryInfo.getMatchingTiles();
-                // final Point imageLocation = queryInfo.getTiledImageSize().getLocation();
-                rasterImage = rasterReader.read(rasterId, pyramidLevel, matchingTiles);
-            } catch (IOException e) {
-                LOGGER.log(Level.SEVERE, "Fetching data for " + queryInfo.toString(), e);
-                throw e;
-            }
-
-            queryInfo.setResultImage(rasterImage);
-
-            {
-                LOGGER.finer(queryInfo.toString());
-                log.appendLoggingGeometries(LoggingHelper.MOSAIC_EXPECTED, queryInfo
-                        .getMosaicLocation());
-                log
-                        .appendLoggingGeometries(LoggingHelper.MOSAIC_ENV, queryInfo
-                                .getResultEnvelope());
-
-                final Rectangle tiledImageSize = queryInfo.getTiledImageSize();
-                int width = rasterImage.getWidth();
-                int height = rasterImage.getHeight();
-                if (tiledImageSize.width != width || tiledImageSize.height != height) {
-                    throw new IllegalStateException(
-                            "Read image is not of the expected size. Image=" + width + "x" + height
-                                    + ", expected: " + tiledImageSize.width + "x"
-                                    + tiledImageSize.height);
-                }
-                // if (tiledImageSize.x != rasterImage.getMinX()
-                // || tiledImageSize.y != rasterImage.getMinY()) {
-                // throw new IllegalStateException("Read image is not at the expected location "
-                // + tiledImageSize.x + "," + tiledImageSize.y + ": "
-                // + rasterImage.getMinX() + "," + rasterImage.getMinY());
-                // }
-            }
-        }
-    }
-
-    /**
-     * Called when the requested envelope do overlap the coverage envelope but none of the rasters
-     * in the dataset do
-     *
-     * @param requestedEnvelope
-     * @param requestedDim
-     * @return
-     */
-    private GridCoverage2D createFakeCoverage(GeneralEnvelope requestedEnvelope,
-            Rectangle requestedDim) {
-
-        ImageTypeSpecifier its = rasterInfo.getRenderedImageSpec(0);
-        SampleModel sampleModel = its.getSampleModel(requestedDim.width, requestedDim.height);
-        ColorModel colorModel = its.getColorModel();
-
-        WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
-        BufferedImage image = new BufferedImage(colorModel, raster, false, null);
-        return coverageFactory.create(coverageName, image, requestedEnvelope);
-    }
-
-    private List<RasterQueryInfo> findMatchingRasters(final GeneralEnvelope requestedEnvelope,
-            final Rectangle requestedDim, final OverviewPolicy overviewPolicy) {
-
-        final List<RasterQueryInfo> matchingQueries;
-        matchingQueries = RasterUtils.findMatchingRasters(rasterInfo, requestedEnvelope,
-                requestedDim, overviewPolicy);
-
-        if (matchingQueries.isEmpty()) {
-            return matchingQueries;
-        }
-
-        for (RasterQueryInfo match : matchingQueries) {
-            RasterUtils.fitRequestToRaster(requestedEnvelope, rasterInfo, match);
-        }
-        return matchingQueries;
-    }
-
-    private GeneralEnvelope getResultEnvelope(final List<RasterQueryInfo> queryInfos) {
-
-        GeneralEnvelope finalEnvelope = null;
-
-        for (RasterQueryInfo rasterQueryInfo : queryInfos) {
-            // gather resulting envelope
-            if (finalEnvelope == null) {
-                finalEnvelope = new GeneralEnvelope(rasterQueryInfo.getResultEnvelope());
-            } else {
-                finalEnvelope.add(rasterQueryInfo.getResultEnvelope());
-            }
-        }
-        if (finalEnvelope == null) {
-            throw new IllegalStateException("Restult envelope is null, this shouldn't happen!! "
-                    + "we checked the request overlaps the coverage envelope before!");
-        }
-        return finalEnvelope;
-    }
-
-    /**
-     * For each raster: crop->scale->translate->add to mosaic
-     *
-     * @param queries
-     * @param mosaicGeometry
-     * @return
-     * @throws IOException
-     */
-    private RenderedImage createMosaic(final List<RasterQueryInfo> queries,
-            final Rectangle mosaicGeometry, final LoggingHelper log) throws IOException {
-
-        List<RenderedImage> transformed = new ArrayList<RenderedImage>(queries.size());
-
-        /*
-         * Do we need to expand to RGB color space and then create a new colormapped image with the
-         * whole mosaic?
-         */
-        boolean expandThenContractCM = queries.size() > 1 && rasterInfo.isColorMapped();
-        if (expandThenContractCM) {
-            LOGGER.info("Creating mosaic out of " + queries.size()
-                    + " colormapped rasters. The mosaic tiles will be expanded to "
-                    + "\nRGB space and the resulting mosaic reduced to a new IndexColorModel");
-        }
-
-        for (RasterQueryInfo query : queries) {
-            RenderedImage image = query.getResultImage();
-            log.log(image, query.getRasterId(), "01_original");
-
-            image = cropToRequiredDimension(image, query.getTiledImageSize(), query
-                    .getResultDimensionInsideTiledImage());
-            log.log(image, query.getRasterId(), "02_crop");
-
-            final Rectangle mosaicLocation = query.getMosaicLocation();
-            // scale
-            Float scaleX = Float.valueOf((float) (mosaicLocation.getWidth() / image.getWidth()));
-            Float scaleY = Float.valueOf((float) (mosaicLocation.getHeight() / image.getHeight()));
-            Float translateX = Float.valueOf(0);
-            Float translateY = Float.valueOf(0);
-            // image.getData();
-            if (!(Float.valueOf(1.0F).equals(scaleX) && Float.valueOf(1.0F).equals(scaleY))) {
-                ParameterBlock pb = new ParameterBlock();
-                pb.addSource(image);
-                pb.add(scaleX);
-                pb.add(scaleY);
-                pb.add(translateX);
-                pb.add(translateY);
-                pb.add(new InterpolationNearest());
-
-                if (queries.size() > 0) {
-                    try {
-                        LOGGER.info("Forcing loading data for mosaic as per GEOT-");
-                        // image.getData();
-                    } catch (RuntimeException e) {
-                        throw new DataSourceException("Error fetching arcsde raster", e);
-                    }
-                }
-
-                image = JAI.create("scale", pb);
-                log.log(image, query.getRasterId(), "03_scale");
-
-                int width = image.getWidth();
-                int height = image.getHeight();
-
-                assert mosaicLocation.width == width;
-                assert mosaicLocation.height == height;
-            }
-            if (image.getMinX() != mosaicLocation.x || image.getMinY() != mosaicLocation.y) {
-                // translate
-                ParameterBlock pb = new ParameterBlock();
-                pb.addSource(image);
-                pb.add(Float.valueOf(mosaicLocation.x - image.getMinX()));
-                pb.add(Float.valueOf(mosaicLocation.y - image.getMinY()));
-                pb.add(null);
-
-                image = JAI.create("translate", pb);
-                log.log(image, query.getRasterId(), "04_translate");
-
-                assert image.getMinX() == mosaicLocation.x : image.getMinX() + " != "
-                        + mosaicLocation.x;
-                assert image.getMinY() == mosaicLocation.y : image.getMinY() + " != "
-                        + mosaicLocation.y;
-                assert image.getWidth() == mosaicLocation.width : image.getWidth() + " != "
-                        + mosaicLocation.width;
-                assert image.getHeight() == mosaicLocation.height : image.getHeight() + " != "
-                        + mosaicLocation.height;
-            }
-            if (expandThenContractCM) {
-                if (LOGGER.isLoggable(Level.FINER)) {
-                    LOGGER.finer("Creating color expanded version of tile for raster #"
-                            + query.getRasterId());
-                }
-
-                /*
-                 * reformat the image as a 4 band rgba backed by byte data
-                 */
-                image = FormatDescriptor.create(image, Integer.valueOf(DataBuffer.TYPE_BYTE), null);
-
-                log.log(image, query.getRasterId(), "04_1_colorExpanded");
-            }
-
-            transformed.add(image);
-        }
-
-        final RenderedImage mosaic;
-        if (queries.size() == 1) {
-            /*
-             * This is besides a very slight perf improvement needed because the JAI mosaic
-             * operation truncates floating point raster values to 0 and 1. REVISIT: If there's no
-             * workaround for that we should prevent raster catalogs made of floating point rasters
-             * and throw an exception as we could not really support that.
-             */
-            mosaic = transformed.get(0);
-        } else {
-            /*
-             * adapted from RasterLayerResponse.java in the imagemosaic module
-             */
-            ParameterBlockJAI mosaicParams = new ParameterBlockJAI("Mosaic");
-
-            // TODO: set background values to raster's no-data
-            // mosaicParams.setParameter("backgroundValues",backgroundValues);
-
-            mosaicParams.setParameter("mosaicType", MosaicDescriptor.MOSAIC_TYPE_OVERLAY);
-
-            final ImageLayout layout = new ImageLayout(mosaicGeometry.x, mosaicGeometry.y,
-                    mosaicGeometry.width, mosaicGeometry.height);
-            layout.setTileWidth(mosaicGeometry.width);
-            layout.setTileHeight(mosaicGeometry.height);
-            final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
-            // hints.put(JAI.KEY_SERIALIZE_DEEP_COPY, Boolean.TRUE);
-
-            for (RenderedImage img : transformed) {
-                mosaicParams.addSource(img);
-                log.appendLoggingGeometries(LoggingHelper.MOSAIC_RESULT, img);
-            }
-            log.log(LoggingHelper.MOSAIC_RESULT);
-
-            LOGGER.fine("Creating mosaic out of " + queries.size() + " raster tiles");
-            mosaic = JAI.create("Mosaic", mosaicParams, hints);
-
-            log.log(mosaic, 0L, "05_mosaic_result");
-        }
-        return mosaic;
-    }
-
-    /**
-     * Crops the image representing a full tile set to the required dimension and returns it, but
-     * keeps minx and miny being zero.
-     *
-     * @param fullTilesRaster
-     * @param tiledImageGridRagne
-     * @param cropTo
-     * @return
-     */
-    private RenderedImage cropToRequiredDimension(final RenderedImage fullTilesRaster,
-            final Rectangle tiledImageGridRagne, final Rectangle cropTo) {
-
-        // int minX = fullTilesRaster.getMinX();
-        // int minY = fullTilesRaster.getMinY();
-        // int width = fullTilesRaster.getWidth();
-        // int height = fullTilesRaster.getHeight();
-
-        int minX = tiledImageGridRagne.x;
-        int minY = tiledImageGridRagne.y;
-        int width = tiledImageGridRagne.width;
-        int height = tiledImageGridRagne.height;
-
-        Rectangle origDim = new Rectangle(minX, minY, width, height);
-        if (!origDim.contains(cropTo)) {
-            throw new IllegalArgumentException("Original image (" + origDim
-                    + ") does not contain desired dimension (" + cropTo + ")");
-        } else if (origDim.equals(cropTo)) {
-            if (LOGGER.isLoggable(Level.FINER)) {
-                LOGGER.finer("No need to crop image, full tiled dimension and target one "
-                        + "do match: original: " + width + "x" + height + ", target: "
-                        + cropTo.width + "x" + cropTo.height);
-            }
-            return fullTilesRaster;
-        }
-
-        ParameterBlock cropParams = new ParameterBlock();
-
-        cropParams.addSource(fullTilesRaster);// Source
-        cropParams.add(Float.valueOf(cropTo.x - tiledImageGridRagne.x)); // x origin for each band
-        cropParams.add(Float.valueOf(cropTo.y - tiledImageGridRagne.y)); // y origin for each band
-        cropParams.add(Float.valueOf(cropTo.width));// width for each band
-        cropParams.add(Float.valueOf(cropTo.height));// height for each band
-
-        final RenderingHints hints = null;
-        RenderedImage image = JAI.create("Crop", cropParams, hints);
-
-        assert cropTo.x - tiledImageGridRagne.x == image.getMinX();
-        assert cropTo.y - tiledImageGridRagne.y == image.getMinY();
-        assert cropTo.width == image.getWidth();
-        assert cropTo.height == image.getHeight();
-
-        // assert cropTo.x == image.getMinX();
-        // assert cropTo.y == image.getMinY();
-        // assert cropTo.width == image.getWidth();
-        // assert cropTo.height == image.getHeight();
-        return image;
-    }
-
-    static class ReadParameters {
-        GeneralEnvelope requestedEnvelope;
-
-        Rectangle dim;
-
-        OverviewPolicy overviewPolicy;
-    }
-
-    /**
-     * A simple helper class to guard and easy logging the mosaic geometries in both geographical
-     * and pixel ranges
-     */
-    private static class LoggingHelper {
-
-        private static final File debugDir = new File(System.getProperty("user.home")
-                + File.separator + "arcsde_test");
-
-        static {
-            if (DEBUG_TO_DISK) {
-                debugDir.mkdir();
-            }
-        }
-
-        public Level GEOM_LEVEL = Level.FINER;
-
-        public static String REQ_ENV = "Requested envelope";
-
-        public static String RES_ENV = "Resulting envelope";
-
-        public static String MOSAIC_ENV = "Resulting mosaiced envelopes";
-
-        public static String MOSAIC_EXPECTED = "Expected mosaic layout (in pixels)";
-
-        public static String MOSAIC_RESULT = "Resulting image mosaic layout (in pixels)";
-
-        private Map<String, StringBuilder> geoms = null;
-
-        LoggingHelper() {
-            // not much to to
-        }
-
-        private StringBuilder getGeom(String geomName) {
-            if (geoms == null) {
-                geoms = new HashMap<String, StringBuilder>();
-            }
-            StringBuilder sb = geoms.get(geomName);
-            if (sb == null) {
-                sb = new StringBuilder("MULTIPOLYGON(\n");
-                geoms.put(geomName, sb);
-            }
-            return sb;
-        }
-
-        public void appendLoggingGeometries(String geomName, RenderedImage img) {
-            if (LOGGER.isLoggable(GEOM_LEVEL)) {
-                appendLoggingGeometries(geomName, new Rectangle(img.getMinX(), img.getMinY(), img
-                        .getWidth(), img.getHeight()));
-            }
-        }
-
-        public void appendLoggingGeometries(String geomName, Rectangle env) {
-            if (LOGGER.isLoggable(GEOM_LEVEL)) {
-                appendLoggingGeometries(geomName, new GeneralEnvelope(env));
-            }
-        }
-
-        public void appendLoggingGeometries(String geomName, GeneralEnvelope env) {
-            if (LOGGER.isLoggable(GEOM_LEVEL)) {
-                StringBuilder sb = getGeom(geomName);
-                sb.append("  ((" + env.getMinimum(0) + " " + env.getMinimum(1) + ", "
-                        + env.getMaximum(0) + " " + env.getMinimum(1) + ", " + env.getMaximum(0)
-                        + " " + env.getMaximum(1) + ", " + env.getMinimum(0) + " "
-                        + env.getMaximum(1) + ", " + env.getMinimum(0) + " " + env.getMinimum(1)
-                        + ")),");
-            }
-        }
-
-        public void log(String geomName) {
-            if (LOGGER.isLoggable(GEOM_LEVEL)) {
-                StringBuilder sb = getGeom(geomName);
-                sb.setLength(sb.length() - 1);
-                sb.append("\n)");
-                LOGGER.log(GEOM_LEVEL, geomName + ":\n" + sb.toString());
-            }
-        }
-
-        public void log(RenderedImage image, Long rasterId, String fileName) {
-            if (DEBUG_TO_DISK) {
-                LOGGER.warning("BEWARE THE DEBUG FLAG IS TURNED ON! "
-                        + "IF IN PRODUCTION THIS IS A SEVERE MISTAKE!!!");
-                // ImageIO.write(FormatDescriptor.create(image,
-                // Integer.valueOf(DataBuffer.TYPE_BYTE),
-                // null), "TIFF", new File(debugDir, rasterId.longValue() + fileName + ".tiff"));
-
-                try {
-                    ImageIO.write(image, "TIFF", new File(debugDir, rasterId.longValue() + fileName
-                            + ".tiff"));
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-
-        }
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEImageReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEImageReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEImageReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,189 +0,0 @@
-package org.geotools.arcsde.gce;
-
-import java.awt.Point;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.IndexColorModel;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-
-import javax.imageio.ImageReadParam;
-import javax.imageio.ImageReader;
-import javax.imageio.ImageTypeSpecifier;
-import javax.imageio.metadata.IIOMetadata;
-import javax.imageio.spi.ImageReaderSpi;
-import javax.media.jai.PlanarImage;
-
-import org.geotools.arcsde.gce.TileReader.TileInfo;
-
-import com.sun.media.imageioimpl.common.SimpleRenderedImage;
-
-public class ArcSDEImageReader extends ImageReader {
-
-    private TileReader tileReader;
-
-    private ImageTypeSpecifier typeSpec;
-
-    protected ArcSDEImageReader(final ImageReaderSpi originatingProvider,
-            final ImageTypeSpecifier typeSpec) {
-        super(originatingProvider);
-        this.typeSpec = typeSpec;
-    }
-
-    @Override
-    public int getWidth(int imageIndex) throws IOException {
-        int w = tileReader.getTilesWide() * tileReader.getTileWidth();
-        return w;
-    }
-
-    @Override
-    public int getHeight(int imageIndex) throws IOException {
-        int h = tileReader.getTilesHigh() * tileReader.getTileHeight();
-        return h;
-    }
-
-    @Override
-    public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
-        return null;
-    }
-
-    @Override
-    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
-        return Collections.singleton(typeSpec).iterator();
-    }
-
-    @Override
-    public int getNumImages(boolean allowSearch) throws IOException {
-        return 1;
-    }
-
-    @Override
-    public IIOMetadata getStreamMetadata() throws IOException {
-        return null;
-    }
-
-    @Override
-    public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param)
-            throws IOException {
-        // return read(imageIndex, param);
-
-        RenderedImage image = new ArcSDETiledRenderedImage(tileReader, typeSpec);
-
-        // BufferedImage bufferedImage = PlanarImage.wrapRenderedImage(image).getAsBufferedImage();
-        // return bufferedImage;
-        return image;
-    }
-
-    @Override
-    public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
-        if (param == null) {
-            param = getDefaultReadParam();
-        }
-
-        RenderedImage rendered = readAsRenderedImage(imageIndex, param);
-
-        BufferedImage bufferedImage = PlanarImage.wrapRenderedImage(rendered).getAsBufferedImage();
-
-        return bufferedImage;
-    }
-
-    @Override
-    public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
-        this.tileReader = (TileReader) input;
-    }
-
-    @SuppressWarnings("unchecked")
-    private static class ArcSDETiledRenderedImage extends SimpleRenderedImage {
-
-        private TileReader tileReader;
-
-        public ArcSDETiledRenderedImage(TileReader tileReader, ImageTypeSpecifier typeSpec) {
-            System.err.println(tileReader);
-            this.tileReader = tileReader;
-            super.colorModel = typeSpec.getColorModel();
-            super.sampleModel = typeSpec.getSampleModel();
-            super.height = tileReader.getTilesHigh() * tileReader.getTileHeight();
-            super.width = tileReader.getTilesWide() * tileReader.getTileWidth();
-            super.minX = 0;
-            super.minY = 0;
-            super.tileGridXOffset = 0;
-            super.tileGridYOffset = 0;
-            super.tileHeight = tileReader.getTileHeight();
-            super.tileWidth = tileReader.getTileWidth();
-        }
-
-        private WritableRaster[][] tileCache = null;
-
-        /**
-         * @see java.awt.image.RenderedImage#getTile(int, int)
-         */
-        public Raster getTile(final int tileX, final int tileY) {
-            //System.err.printf("getTile(%d, %d)\n", tileX, tileY);
-            if (tileCache == null) {
-                tileCache = new WritableRaster[tileReader.getTilesWide()][tileReader.getTilesHigh()];
-            }
-
-            WritableRaster currentTile = tileCache[tileX][tileY];
-            if (currentTile == null) {
-                final int tilesWide = tileReader.getTilesWide();
-                final int tilesHigh = tileReader.getTilesHigh();
-
-                for (int ty = 0; ty < tilesHigh; ty++) {
-                    for (int tx = 0; tx < tilesWide; tx++) {
-
-                        currentTile = tileCache[tx][ty];
-
-                        if (currentTile == null) {
-                            int x = tileXToX(tx);
-                            int y = tileYToY(ty);
-                            //System.err.println("fetching tile " + tx + "," + ty);
-                            currentTile = fetchTile(x, y);
-                            tileCache[tx][ty] = currentTile;
-                        }
-                        if (tx == tileX && ty == tileY) {
-                            return currentTile;
-                        }
-                    }
-                }
-            }
-            //currentTile = tileCache[tileX][tileY];
-            return currentTile;
-        }
-
-        private WritableRaster fetchTile(final int xOrigin, final int yOrigin) {
-            final int numBands = sampleModel.getNumBands();
-
-            final SampleModel tileSampleModel = super.sampleModel.createCompatibleSampleModel(
-                    tileWidth, tileHeight);
-
-            DataBuffer dataBuffer = sampleModel.createDataBuffer();
-            for (int bandN = 0; bandN < numBands; bandN++) {
-                TileInfo tileInfo;
-                try {
-                    tileInfo = tileReader.next();
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
-
-                byte[] rawBandData = tileInfo.getTileData();
-
-                final int numPixels = tileWidth * tileHeight;
-                for (int pixelN = 0; pixelN < numPixels; pixelN++) {
-                    int val = rawBandData[2 * pixelN + 1] & 0xFF;
-                    dataBuffer.setElem(bandN, pixelN, val);
-                }
-            }
-            
-            WritableRaster currentTile;
-            currentTile = Raster.createWritableRaster(tileSampleModel, dataBuffer, new Point(xOrigin, yOrigin));
-            return currentTile;
-        }
-
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDERasterFormat.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDERasterFormat.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDERasterFormat.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,437 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.geotools.arcsde.jndi.SharedSessionPool;
-import org.geotools.arcsde.session.ArcSDEConnectionConfig;
-import org.geotools.arcsde.session.ISession;
-import org.geotools.arcsde.session.ISessionPool;
-import org.geotools.arcsde.session.SessionPoolFactory;
-import org.geotools.arcsde.session.UnavailableConnectionException;
-import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
-import org.geotools.coverage.grid.io.AbstractGridFormat;
-import org.geotools.coverage.grid.io.imageio.GeoToolsWriteParams;
-import org.geotools.data.DataSourceException;
-import org.geotools.factory.GeoTools;
-import org.geotools.factory.Hints;
-import org.geotools.parameter.DefaultParameterDescriptorGroup;
-import org.geotools.parameter.ParameterGroup;
-import org.geotools.util.logging.Logging;
-import org.opengis.coverage.grid.Format;
-import org.opengis.coverage.grid.GridCoverageWriter;
-import org.opengis.parameter.GeneralParameterDescriptor;
-
-/**
- * An implementation of the ArcSDE Raster Format. Based on the ArcGrid module.
- *
- * @author Saul Farber (saul.farber)
- * @author jeichar
- * @author Simone Giannecchini (simboss)
- * @author Gabriel Roldan (OpenGeo)
- * @source $URL:
- *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/arcsde/datastore/src/main/java
- *         /org/geotools/arcsde/gce/ArcSDERasterFormat.java $
- */
-@SuppressWarnings( { "nls", "deprecation" })
-public final class ArcSDERasterFormat extends AbstractGridFormat implements Format {
-
-    protected static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    /**
-     * Cache of raster metadata objects, where the keys are the URL's representing the full
-     * connection properties to a given ArcSDE raster, and the value the
-     * {@link ArcSDERasterGridCoverage2DReader}'s externalized state, so it is not needed to gather
-     * the raster properties each time.
-     */
-    private final Map<String, RasterDatasetInfo> rasterInfos = new WeakHashMap<String, RasterDatasetInfo>();
-
-    private final Map<String, ArcSDEConnectionConfig> connectionConfigs = new WeakHashMap<String, ArcSDEConnectionConfig>();
-
-    private static final ArcSDERasterFormat instance = new ArcSDERasterFormat();
-
-    private boolean statisticsMandatory = true;
-
-    /**
-     * Creates an instance and sets the metadata.
-     */
-    private ArcSDERasterFormat() {
-        setInfo();
-    }
-
-    public static ArcSDERasterFormat getInstance() {
-        return instance;
-    }
-
-    /**
-     * Sets the metadata information.
-     */
-    private void setInfo() {
-        Map<String, String> info = new HashMap<String, String>();
-
-        info.put("name", "ArcSDE Raster");
-        info.put("description", "ArcSDE Raster Format");
-        info.put("vendor", "Geotools");
-        info.put("docURL", "");
-        info.put("version", GeoTools.getVersion().toString());
-        mInfo = info;
-
-        readParameters = new ParameterGroup(new DefaultParameterDescriptorGroup(mInfo,
-                new GeneralParameterDescriptor[] { READ_GRIDGEOMETRY2D, OVERVIEW_POLICY }));
-    }
-
-    /**
-     * @param source
-     *            either a {@link String} or {@link File} instance representing the connection URL
-     * @see AbstractGridFormat#getReader(Object source)
-     */
-    @Override
-    public AbstractGridCoverage2DReader getReader(Object source) {
-        return getReader(source, null);
-    }
-
-    /**
-     * @param source
-     *            either a {@link String} or {@link File} instance representing the connection URL
-     * @see AbstractGridFormat#getReader(Object, Hints)
-     */
-    @Override
-    public AbstractGridCoverage2DReader getReader(final Object source, final Hints hints) {
-        try {
-            if (source == null) {
-                throw new DataSourceException("No source set to read this coverage.");
-            }
-
-            // this will be our connection string
-            final String coverageUrl = parseCoverageUrl(source);
-
-            final ArcSDEConnectionConfig connectionConfig = getConnectionConfig(coverageUrl);
-
-            final ISessionPool sessionPool = setupConnectionPool(connectionConfig);
-
-            final RasterDatasetInfo rasterInfo = getRasterInfo(coverageUrl, sessionPool);
-
-            final RasterReaderFactory rasterReaderFactory = new RasterReaderFactory(sessionPool);
-
-            return new ArcSDEGridCoverage2DReaderJAI(this, rasterReaderFactory, rasterInfo, hints);
-        } catch (IOException dse) {
-            LOGGER
-                    .log(Level.SEVERE, "Unable to creata ArcSDERasterReader for " + source + ".",
-                            dse);
-            throw new RuntimeException(dse);
-        }
-    }
-
-    private RasterDatasetInfo getRasterInfo(final String coverageUrl, ISessionPool connectionPool)
-            throws IOException {
-
-        RasterDatasetInfo rasterInfo = rasterInfos.get(coverageUrl);
-        if (rasterInfo == null) {
-            synchronized (rasterInfos) {
-                rasterInfo = rasterInfos.get(coverageUrl);
-                if (rasterInfo == null) {
-                    ISession scon;
-                    try {
-                        scon = connectionPool.getSession(false);
-                    } catch (UnavailableConnectionException e) {
-                        throw new RuntimeException(e);
-                    }
-                    try {
-                        final String rasterTable;
-                        {
-                            String sdeUrl = coverageUrl;
-                            if (sdeUrl.indexOf(";") != -1) {
-                                /*
-                                 * We're not using any extra param anymore. Yet, be cautious cause a
-                                 * client may still be using urls with some old extra param, so just
-                                 * strip it
-                                 */
-                                sdeUrl = sdeUrl.substring(0, sdeUrl.indexOf(";"));
-                            }
-                            rasterTable = sdeUrl.substring(sdeUrl.indexOf("#") + 1);
-                            if (LOGGER.isLoggable(Level.FINE)) {
-                                LOGGER.fine("Building ArcSDEGridCoverageReader2D for "
-                                        + rasterTable);
-                            }
-                        }
-
-                        GatherCoverageMetadataCommand command = new GatherCoverageMetadataCommand(
-                                rasterTable, statisticsMandatory);
-                        rasterInfo = scon.issue(command);
-                        rasterInfos.put(coverageUrl, rasterInfo);
-                    } finally {
-                        scon.dispose();
-                    }
-                }
-            }
-        }
-        return rasterInfo;
-    }
-
-    private ArcSDEConnectionConfig getConnectionConfig(final String coverageUrl) {
-        ArcSDEConnectionConfig sdeConfig;
-        sdeConfig = connectionConfigs.get(coverageUrl);
-        if (sdeConfig == null) {
-            synchronized (connectionConfigs) {
-                sdeConfig = connectionConfigs.get(coverageUrl);
-                if (sdeConfig == null) {
-                    sdeConfig = sdeURLToConnectionConfig(new StringBuffer(coverageUrl));
-                    connectionConfigs.put(coverageUrl, sdeConfig);
-                }
-            }
-        }
-        return sdeConfig;
-    }
-
-    /**
-     * @see AbstractGridFormat#getWriter(Object)
-     */
-    @Override
-    public GridCoverageWriter getWriter(Object destination) {
-        // return new ArcGridWriter(destination);
-        return null;
-    }
-
-    /**
-     * @param source
-     *            either a {@link String} or {@link File} instance representing the connection URL
-     * @see AbstractGridFormat#accepts(Object input)
-     */
-    @Override
-    public boolean accepts(Object input) {
-        StringBuffer url;
-        if (input instanceof File) {
-            url = new StringBuffer(((File) input).getPath());
-        } else if (input instanceof String) {
-            url = new StringBuffer((String) input);
-        } else {
-            return false;
-        }
-        try {
-            sdeURLToConnectionConfig(url);
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * @see Format#getName()
-     */
-    @Override
-    public String getName() {
-        return this.mInfo.get("name");
-    }
-
-    /**
-     * @see Format#getDescription()
-     */
-    @Override
-    public String getDescription() {
-        return this.mInfo.get("description");
-    }
-
-    /**
-     * @see Format#getVendor()
-     */
-    @Override
-    public String getVendor() {
-        return this.mInfo.get("vendor");
-    }
-
-    /**
-     * @see Format#getDocURL()
-     */
-    @Override
-    public String getDocURL() {
-        return this.mInfo.get("docURL");
-    }
-
-    /**
-     * @see Format#getVersion()
-     */
-    @Override
-    public String getVersion() {
-        return this.mInfo.get("version");
-    }
-
-    /**
-     * Retrieves the default instance for the {@link ArcSDERasterFormat} of the
-     * {@link GeoToolsWriteParams} to control the writing process.
-     *
-     * @return a default instance for the {@link ArcSDERasterFormat} of the
-     *         {@link GeoToolsWriteParams} to control the writing process.
-     * @see AbstractGridFormat#getDefaultImageIOWriteParameters()
-     */
-    @Override
-    public GeoToolsWriteParams getDefaultImageIOWriteParameters() {
-        throw new UnsupportedOperationException("ArcSDE Rasters are read only for now.");
-    }
-
-    // ////////////////
-
-    /**
-     * @param input
-     *            either a {@link String} or a {@link File} instance representing the connection URL
-     *            to a given coverage
-     * @return the connection URL as a string
-     */
-    private String parseCoverageUrl(Object input) {
-        String coverageUrl;
-        if (input instanceof String) {
-            coverageUrl = (String) input;
-            if (LOGGER.isLoggable(Level.FINE)) {
-                LOGGER.fine("connecting to ArcSDE Raster: " + coverageUrl);
-            }
-        } else if (input instanceof File) {
-            coverageUrl = ((File) input).getPath();
-            if (LOGGER.isLoggable(Level.FINE)) {
-                LOGGER.fine("connectiong via file-hack to ArcSDE Raster: " + coverageUrl);
-            }
-        } else {
-            throw new IllegalArgumentException("Unsupported input type: " + input.getClass());
-        }
-        return coverageUrl;
-    }
-
-    /**
-     * Checks the input provided to this {@link ArcSDERasterGridCoverage2DReader} and sets all the
-     * other objects and flags accordingly.
-     *
-     * @param sdeUrl
-     *            a url representing the connection parameters to an arcsde server instance provied
-     *            to this {@link ArcSDERasterGridCoverage2DReader}.
-     * @throws IOException
-     */
-    private ISessionPool setupConnectionPool(ArcSDEConnectionConfig sdeConfig) throws IOException {
-
-        if (LOGGER.isLoggable(Level.FINE)) {
-            LOGGER.fine("Getting ArcSDE connection pool for " + sdeConfig);
-        }
-
-        ISessionPool sessionPool;
-        sessionPool = SharedSessionPool.getInstance(sdeConfig, SessionPoolFactory.getInstance());
-
-        return sessionPool;
-    }
-
-    /**
-     * @param sdeUrl
-     *            - A StringBuffer containing a string of form
-     *            'sde://user:pass@sdehost:[port]/[dbname]
-     * @return a ConnectionConfig object representing these parameters
-     */
-    public static ArcSDEConnectionConfig sdeURLToConnectionConfig(StringBuffer sdeUrl) {
-        // annoyingly, geoserver currently stores the user-entered SDE string as
-        // a File, and passes us the
-        // File object. The File object strips the 'sde://user...' into a
-        // 'sde:/user..'. So we need to check
-        // for both forms of the url.
-        String sdeHost, sdeUser, sdePass, sdeDBName;
-        int sdePort;
-        if (sdeUrl.indexOf("sde:/") == -1) {
-            throw new IllegalArgumentException(
-                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName -- Got "
-                            + sdeUrl);
-        }
-        if (sdeUrl.indexOf("sde://") == -1) {
-            sdeUrl.delete(0, 5);
-        } else {
-            sdeUrl.delete(0, 6);
-        }
-
-        int idx = sdeUrl.indexOf(":");
-        if (idx == -1) {
-            throw new IllegalArgumentException(
-                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
-        }
-        sdeUser = sdeUrl.substring(0, idx);
-        sdeUrl.delete(0, idx);
-
-        idx = sdeUrl.indexOf("@");
-        if (idx == -1) {
-            throw new IllegalArgumentException(
-                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
-        }
-        sdePass = sdeUrl.substring(1, idx);
-        sdeUrl.delete(0, idx);
-
-        idx = sdeUrl.indexOf(":");
-        if (idx == -1) {
-            // there's no "port" specification. Assume 5151;
-            sdePort = 5151;
-
-            idx = sdeUrl.indexOf("/");
-            if (idx == -1) {
-                throw new IllegalArgumentException(
-                        "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
-            }
-            sdeHost = sdeUrl.substring(1, idx).toString();
-            sdeUrl.delete(0, idx);
-        } else {
-            sdeHost = sdeUrl.substring(1, idx).toString();
-            sdeUrl.delete(0, idx);
-
-            idx = sdeUrl.indexOf("/");
-            if (idx == -1) {
-                throw new IllegalArgumentException(
-                        "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
-            }
-            sdePort = Integer.parseInt(sdeUrl.substring(1, idx).toString());
-            sdeUrl.delete(0, idx);
-        }
-
-        idx = sdeUrl.indexOf("#");
-        if (idx == -1) {
-            throw new IllegalArgumentException(
-                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
-        }
-        sdeDBName = sdeUrl.substring(1, idx).toString();
-        sdeUrl.delete(0, idx);
-
-        Map<String, String> params = new HashMap<String, String>();
-        params.put(ArcSDEConnectionConfig.SERVER_NAME_PARAM_NAME, sdeHost);
-        params.put(ArcSDEConnectionConfig.PORT_NUMBER_PARAM_NAME, String.valueOf(sdePort));
-        params.put(ArcSDEConnectionConfig.INSTANCE_NAME_PARAM_NAME, sdeDBName);
-        params.put(ArcSDEConnectionConfig.USER_NAME_PARAM_NAME, sdeUser);
-        params.put(ArcSDEConnectionConfig.PASSWORD_PARAM_NAME, sdePass);
-        params.put(ArcSDEConnectionConfig.MIN_CONNECTIONS_PARAM_NAME, "1");
-        params.put(ArcSDEConnectionConfig.MAX_CONNECTIONS_PARAM_NAME, "20");
-        params.put(ArcSDEConnectionConfig.CONNECTION_TIMEOUT_PARAM_NAME, "-1");// do not wait
-
-        ArcSDEConnectionConfig config = ArcSDEConnectionConfig.fromMap(params);
-        return config;
-    }
-
-    /**
-     * Used by test code to indicate wether to fail when a raster lacks statistics, since we can't
-     * create statistics with the ArcSDE Java API
-     *
-     * @param statisticsMandatory
-     */
-    void setStatisticsMandatory(final boolean statisticsMandatory) {
-        this.statisticsMandatory = statisticsMandatory;
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDETiledImageInputStream.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDETiledImageInputStream.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDETiledImageInputStream.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,139 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.io.IOException;
-
-import javax.imageio.stream.ImageInputStream;
-import javax.imageio.stream.ImageInputStreamImpl;
-
-import org.geotools.arcsde.gce.TileReader.TileInfo;
-
-/**
- * An {@link ImageInputStream} that reads ArcSDE raster tiles in a band interleaved order.
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/ArcSDETiledImageInputStream.java $
- */
-final class ArcSDETiledImageInputStream extends ImageInputStreamImpl implements ImageInputStream {
-
-    private final TileReader tileReader;
-
-    private final int tileDataLength;
-
-    private byte[] currTileData;
-
-    private int currTileDataIndex;
-
-    private int currTileIndex = -1;
-
-    private final int length;
-
-    public ArcSDETiledImageInputStream(final TileReader tileReader) {
-        super();
-        this.tileReader = tileReader;
-        final int bytesPerTile = tileReader.getBytesPerTile();
-        this.tileDataLength = bytesPerTile;
-        this.currTileData = new byte[bytesPerTile];
-        // force load at the first read invocation
-        this.currTileDataIndex = tileDataLength;
-
-        final int tilesWide = tileReader.getTilesWide();
-        final int tilesHigh = tileReader.getTilesHigh();
-        final int numberOfBands = tileReader.getNumberOfBands();
-
-        length = bytesPerTile * tilesWide * tilesHigh * numberOfBands;
-    }
-
-    /**
-     * Returns the computed lenght of the stream based on the tile dimensions, number of tiles,
-     * number of bands, and bits per sample
-     */
-    @Override
-    public long length() {
-        return length;
-    }
-
-    @Override
-    public int read() throws IOException {
-        final byte[] data = getTileData();
-        if (data == null) {
-            close();
-            return -1;
-        }
-        byte b = data[currTileDataIndex];
-        ++currTileDataIndex;
-        ++streamPos;
-        return b;
-    }
-
-    @Override
-    public int read(byte[] buff, int off, int len) throws IOException {
-        final byte[] data = getTileData();
-        if (data == null) {
-            close();
-            return -1;
-        }
-        final int available = data.length - currTileDataIndex;
-        final int count = Math.min(available, len);
-        System.arraycopy(data, currTileDataIndex, buff, off, count);
-        currTileDataIndex += count;
-        streamPos += count;
-        return count;
-    }
-
-    /**
-     * Fetches a tile from the {@code tileReader} if necessary and returns the current tile data.
-     * <p>
-     * It is needed to fetch a new tile if {@link #currTileDataIndex} indicates all the current tile
-     * data has been already read. If so, {@code currTileDataIndex} is reset to 0. The {@code read}
-     * operations are responsible of incrementing {@code currTileDataIndex} depending on how many
-     * bytes have been consumed from the tile data returned by this method.
-     * </p>
-     *
-     * @return {@code null} if there's no more tiles to fetch, the current tile data otherwise
-     * @throws IOException
-     */
-    private byte[] getTileData() throws IOException {
-        if (currTileDataIndex == tileDataLength) {
-            if (!tileReader.hasNext()) {
-                return null;
-            }
-
-            currTileDataIndex = 0;
-            ++currTileIndex;
-            TileInfo tile = tileReader.next();
-            currTileData = tile.getTileData();
-
-            if (!tileReader.hasNext()) {
-                tileReader.dispose();
-            }
-        }
-        return currTileData;
-    }
-
-    @Override
-    public void close() throws IOException {
-        tileReader.dispose();
-        super.close();
-    }
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/BitmaskToNoDataConverter.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/BitmaskToNoDataConverter.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/BitmaskToNoDataConverter.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,234 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-
-import java.awt.Dimension;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A helper class to set nodata values directly onto the arcsde tile's returned {@code byte[]}
- *
- * @author Gabriel Roldan
- * @since 2.5.6
- * @version $Id$
- *
- */
-class BitmaskToNoDataConverter {
-
-    public static final BitmaskToNoDataConverter NO_ACTION_CONVERTER = new BitmaskToNoDataConverter(
-            0, 0, null) {
-
-        @Override
-        public void setNoData(Long bandId, byte[] tileData, byte[] bitMaskData) {
-            // no action
-        }
-
-        @Override
-        public void setAll(Long bandId, byte[] tileData) {
-            // no action
-        }
-
-        @Override
-        public void setNoData(Long bandId, int sampleN, byte[] tileData) {
-            // no action
-        }
-
-    };
-
-    protected final int pixelsPerTile;
-
-    protected final Map<Long, byte[]> byBandIdNoDataValues;
-
-    protected final int bitsPerSample;
-
-    /**
-     *
-     * @param pixelsPerTile
-     * @param bitsPerSample
-     * @param byBandIdNoDataValues
-     */
-    private BitmaskToNoDataConverter(final int pixelsPerTile, final int bitsPerSample,
-            final Map<Long, byte[]> byBandIdNoDataValues) {
-
-        this.pixelsPerTile = pixelsPerTile;
-        this.bitsPerSample = bitsPerSample;
-        this.byBandIdNoDataValues = byBandIdNoDataValues;
-
-    }
-
-    /**
-     * Creates a "nodata setter" for the given raster determined by the raster dataset and the
-     * raster index inside the dataset
-     *
-     * @param rasterInfo
-     * @param rasterIndex
-     * @return
-     */
-    public static BitmaskToNoDataConverter getInstance(final RasterDatasetInfo rasterInfo,
-            final long rasterId) {
-
-        final int rasterIndex = rasterInfo.getRasterIndex(rasterId);
-        final int numBands = rasterInfo.getNumBands();
-        final RasterCellType targetType = rasterInfo.getTargetCellType(rasterIndex);
-
-        Map<Long, byte[]> byBandIdNoDataValues = new HashMap<Long, byte[]>();
-
-        Dimension tileDimension = rasterInfo.getTileDimension(rasterIndex);
-        final int samplesPerTile = tileDimension.width * tileDimension.height;
-
-        for (int bandN = 0; bandN < numBands; bandN++) {
-            long bandId = rasterInfo.getBand(rasterIndex, bandN).getBandId();
-            Number noDataValue = rasterInfo.getNoDataValue(rasterIndex, bandN);
-            byte[] noDataValueBytes = toBytes(noDataValue, targetType);
-            byBandIdNoDataValues.put(Long.valueOf(bandId), noDataValueBytes);
-        }
-
-        final int bitsPerSample = targetType.getBitsPerSample();
-        BitmaskToNoDataConverter noDataSetter;
-        if (targetType == TYPE_8BIT_U) {
-            noDataSetter = new Unsigned8bitConverter(samplesPerTile, bitsPerSample,
-                    byBandIdNoDataValues);
-        } else {
-            noDataSetter = new BitmaskToNoDataConverter(samplesPerTile, bitsPerSample,
-                    byBandIdNoDataValues);
-        }
-
-        return noDataSetter;
-    }
-
-    static byte[] toBytes(final Number noDataValue, final RasterCellType targetType) {
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        DataOutputStream writer = new DataOutputStream(out);
-
-        try {
-            switch (targetType) {
-            case TYPE_16BIT_S:
-                writer.writeShort(noDataValue.intValue());
-                break;
-            case TYPE_16BIT_U:
-                writer.writeShort(noDataValue.intValue());
-                break;
-            case TYPE_32BIT_REAL:
-                writer.writeFloat(noDataValue.floatValue());
-                break;
-            case TYPE_32BIT_S:
-                writer.writeInt(noDataValue.intValue());
-                break;
-            case TYPE_32BIT_U:
-                writer.writeInt(noDataValue.intValue());
-                break;
-            case TYPE_64BIT_REAL:
-                writer.writeDouble(noDataValue.doubleValue());
-                break;
-            case TYPE_8BIT_S:
-                writer.writeByte(noDataValue.byteValue());
-                break;
-            case TYPE_8BIT_U:
-                writer.writeByte(noDataValue.intValue());
-                break;
-            default:
-                throw new UnsupportedOperationException(
-                        "No no-data converter exists for sample type " + targetType);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Can't happen!", e);
-        }
-
-        byte[] no_data_bytes = out.toByteArray();
-        return no_data_bytes;
-    }
-
-    /**
-     * Returns whether the sample N in the bitmask byte array is marked as a no-data pixel
-     */
-    public final boolean isNoData(int sampleN, byte[] bitmaskData) {
-        boolean isNoData = ((bitmaskData[sampleN / 8] >> (7 - (sampleN % 8))) & 0x01) == 0x00;
-        return isNoData;
-    }
-
-    /**
-     * Sets all the samples of {@code tileData} marked as no-data pixel in {@code bitmaskData} to
-     * the no-data value for band {@code bandId}
-     */
-    public void setNoData(final Long bandId, final byte[] tileData, final byte[] bitmaskData) {
-        for (int sampleN = 0; sampleN < pixelsPerTile; sampleN++) {
-            if (isNoData(sampleN, bitmaskData)) {
-                setNoData(bandId, sampleN, tileData);
-            }
-        }
-    }
-
-    /**
-     * Sets all the samples in {@code tileData} to the no-data value for the band {@code bandId}
-     * <p>
-     * Default implementation is to call {@link #setNoData(Long, int, byte[])} as many times as
-     * number of samples in a tile. Subclasses may override to optimize.
-     * </p>
-     */
-    public void setAll(final Long bandId, final byte[] tileData) {
-        for (int sampleN = 0; sampleN < pixelsPerTile; sampleN++) {
-            setNoData(bandId, sampleN, tileData);
-        }
-    }
-
-    /**
-     * Sets the sample N for the band {@code bandId} on {@code tileData} to the no-data value
-     */
-    public void setNoData(final Long bandId, final int sampleN, final byte[] tileData) {
-        byte[] noData = byBandIdNoDataValues.get(bandId);
-        int pixArrayOffset = (sampleN * bitsPerSample) / 8;
-        System.arraycopy(noData, 0, tileData, pixArrayOffset, noData.length);
-    }
-
-    /**
-     * A subclass that provides some optimization for the case where the target cell type is
-     * {@link RasterCellType#TYPE_8BIT_U}
-     */
-    static final class Unsigned8bitConverter extends BitmaskToNoDataConverter {
-
-        public Unsigned8bitConverter(final int samplesPerTile, final int bitsPerSample,
-                final Map<Long, byte[]> byBandIdNoDataValues) {
-            super(samplesPerTile, bitsPerSample, byBandIdNoDataValues);
-        }
-
-        /**
-         * Overrides to use the faster {@link Arrays#fill(byte[], byte)} method rather than calling
-         * {@link #setNoData(Long, int, byte[])} {@code samplesPerTile} times
-         */
-        @Override
-        public void setAll(Long bandId, byte[] tileData) {
-            byte noDataValue = byBandIdNoDataValues.get(bandId)[0];
-            Arrays.fill(tileData, noDataValue);
-        }
-
-        @Override
-        public void setNoData(Long bandId, int sampleN, byte[] tileData) {
-            byte noDataValue = byBandIdNoDataValues.get(bandId)[0];
-            tileData[sampleN] = noDataValue;
-        }
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/CompressionType.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/CompressionType.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/CompressionType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,61 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.util.NoSuchElementException;
-
-import com.esri.sde.sdk.client.SeRaster;
-
-/**
- * An enumeration that mirrors the different possible raster compression types in Arcsde (ie,
- * {@code SeRaster#SE_COMPRESSION_*})
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-enum CompressionType {
-    COMPRESSION_JP2, COMPRESSION_JPEG, COMPRESSION_LZ77, COMPRESSION_NONE;
-    static {
-        COMPRESSION_JP2.setSdeTypeId(SeRaster.SE_COMPRESSION_JP2);
-        COMPRESSION_JPEG.setSdeTypeId(SeRaster.SE_COMPRESSION_JPEG);
-        COMPRESSION_LZ77.setSdeTypeId(SeRaster.SE_COMPRESSION_LZ77);
-        COMPRESSION_NONE.setSdeTypeId(SeRaster.SE_COMPRESSION_NONE);
-    }
-
-    private int typeId;
-
-    private void setSdeTypeId(int typeId) {
-        this.typeId = typeId;
-    }
-
-    public int getSeCompressionType() {
-        return this.typeId;
-    }
-
-    public static CompressionType valueOf(final int seCompressionType) {
-        for (CompressionType type : CompressionType.values()) {
-            if (type.getSeCompressionType() == seCompressionType) {
-                return type;
-            }
-        }
-        throw new NoSuchElementException("Compression type " + seCompressionType
-                + " does not exist");
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/DefaultTiledRasterReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/DefaultTiledRasterReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/DefaultTiledRasterReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,224 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.image.ColorModel;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.renderable.ParameterBlock;
-import java.io.IOException;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageReadParam;
-import javax.imageio.ImageReader;
-import javax.imageio.ImageTypeSpecifier;
-import javax.imageio.spi.ImageReaderSpi;
-import javax.imageio.stream.ImageInputStream;
-import javax.media.jai.ImageLayout;
-import javax.media.jai.JAI;
-
-import org.geotools.arcsde.session.ISessionPool;
-import org.geotools.util.logging.Logging;
-
-import com.esri.sde.sdk.client.SeQuery;
-
-/**
- * The default implementation for {@link TiledRasterReader}.
- * <p>
- * This implementation holds a connection and an open {@link SeQuery query} until the reader is
- * exhausted or {@link #dispose()} is called.
- * </p>
- *
- * @author Gabriel Roldan
- * @version $Id$
- * @since 2.5.7
- */
-class DefaultTiledRasterReader implements TiledRasterReader {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private RasterDatasetInfo rasterInfo;
-
-    private final ISessionPool sessionPool;
-
-    /**
-     * Creates an {@link DefaultTiledRasterReader} that uses the given connection to fetch raster
-     * data for the given {@link RasterDatasetInfo rasterInfo}.
-     * <p>
-     * </p>
-     *
-     * @param sessionPool
-     *            where to grab sessions from to query the rasters described by {@code rasterInfo}
-     * @param rasterInfo
-     * @throws IOException
-     */
-    public DefaultTiledRasterReader(final ISessionPool sessionPool,
-            final RasterDatasetInfo rasterInfo) throws IOException {
-        this.sessionPool = sessionPool;
-        this.rasterInfo = rasterInfo;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TiledRasterReader#read
-     */
-    public RenderedImage read(final long rasterId, final int pyramidLevel, final Rectangle tileRange)
-            throws IOException {
-        final RenderedImage rasterImage;
-
-        rasterImage = getRasterMatchingTileRange(rasterId, pyramidLevel, tileRange);
-
-        return rasterImage;
-    }
-
-    private RenderedImage getRasterMatchingTileRange(final long rasterId, int pyramidLevel,
-            final Rectangle matchingTiles) throws IOException {
-
-        final TileReader tileReader;
-        tileReader = TileReaderFactory.getInstance(sessionPool, rasterInfo, rasterId, pyramidLevel,
-                matchingTiles);
-
-        // covers an area of full tiles
-        final RenderedImage fullTilesRaster;
-
-        /*
-         * Create the tiled raster covering the full area of the matching tiles
-         */
-
-        fullTilesRaster = createTiledRaster(tileReader, matchingTiles, rasterId);
-
-        return fullTilesRaster;
-    }
-
-    /**
-     * @param tileReader
-     * @param matchingTiles
-     * @param rasterId
-     * @return
-     * @throws IOException
-     */
-    private RenderedImage createTiledRaster(final TileReader tileReader,
-            final Rectangle matchingTiles, final long rasterId) throws IOException {
-        // Prepare temporary colorModel and sample model, needed to build the final
-        // ArcSDEPyramidLevel level;
-        final Dimension tiledImageSize;
-        final ColorModel colorModel;
-        final SampleModel sampleModel;
-        {
-            final int tiledImageWidth = tileReader.getTilesWide() * tileReader.getTileWidth();
-            final int tiledImageHeight = tileReader.getTilesHigh() * tileReader.getTileHeight();
-            tiledImageSize = new Dimension(tiledImageWidth, tiledImageHeight);
-
-            final ImageTypeSpecifier fullImageSpec = rasterInfo.getRenderedImageSpec(rasterId);
-            colorModel = fullImageSpec.getColorModel();
-            sampleModel = fullImageSpec.getSampleModel(tiledImageWidth, tiledImageHeight);
-        }
-
-        final int tileWidth = tileReader.getTileWidth();
-        final int tileHeight = tileReader.getTileHeight();
-
-        // building the final image layout
-        final ImageLayout imageLayout;
-        {
-            // the value for the resulting image.getMinX() and image.getMinY() reflecting its
-            // position in the whole image at the pyramid level
-            int minX = (matchingTiles.x * tileWidth);
-            int minY = (matchingTiles.y * tileHeight);
-
-            int width = tiledImageSize.width;
-            int height = tiledImageSize.height;
-
-            int tileGridXOffset = minX;
-            int tileGridYOffset = minY;
-
-            // imageLayout = new ImageLayout(minX, minY, width, height, tileGridXOffset,
-            // tileGridYOffset, tileWidth, tileHeight, sampleModel, colorModel);
-            imageLayout = new ImageLayout(0, 0, width, height, 0, 0, tileWidth, tileHeight,
-                    sampleModel, colorModel);
-        }
-
-        // Finally, build the image input stream
-        final ImageInputStream raw;
-        final ImageReader readerInstance;
-        {
-            final long[] imageOffsets = new long[] { 0 };
-            final Dimension[] imageDimensions = new Dimension[] { tiledImageSize };
-
-            final ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
-//
-//            final ImageInputStream tiledImageInputStream;
-//            tiledImageInputStream = new ArcSDETiledImageInputStream(tileReader);
-//            raw = new RawImageInputStream(tiledImageInputStream, its, imageOffsets, imageDimensions);
-//            ImageReaderSpi imageIOSPI = new RawImageReaderSpi();
-//            readerInstance = imageIOSPI.createReaderInstance();
-
-            // final InputStream is = new RasterInputStream(tileReader);
-            // final ImageInputStream tiledImageInputStream;
-            // tiledImageInputStream = ImageIO.createImageInputStream(is);
-            //
-            // raw = new RawImageInputStream(tiledImageInputStream, its, imageOffsets,
-            // imageDimensions);
-            // ImageReaderSpi imageIOSPI = new RawImageReaderSpi();
-            // readerInstance = imageIOSPI.createReaderInstance();
-
-        
-            ArcSDEImageReader reader = new ArcSDEImageReader((ImageReaderSpi)null, its);
-            reader.setInput(tileReader, true, true);
-            
-            RenderedImage image = reader.readAsRenderedImage(0, null);
-            //image.getData();
-            return image;
-        }
-
-        // First operator: read the image
-//        final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout);
-//
-//        ParameterBlock pb = new ParameterBlock();
-//        pb.add(raw);// Input
-//        /*
-//         * image index, always 0 since we're already fetching the required pyramid level
-//         */
-//        pb.add(Integer.valueOf(0)); // Image index
-//        pb.add(Boolean.FALSE); // Read metadata
-//        pb.add(Boolean.FALSE);// Read thumbnails
-//        pb.add(Boolean.FALSE);// Verify input
-//        pb.add(null);// Listeners
-//        pb.add(null);// Locale
-//        final ImageReadParam rParam = new ImageReadParam();
-//        pb.add(rParam);// ReadParam
-//        pb.add(readerInstance);// Reader
-//
-//        RenderedImage image = JAI.create("ImageRead", pb, hints);
-//        // image.getData();
-//        // // translate
-//        // int minX = (matchingTiles.x * tileWidth);
-//        // int minY = (matchingTiles.y * tileHeight);
-//        // pb = new ParameterBlock();
-//        // pb.addSource(image);
-//        // pb.add(Float.valueOf(minX));
-//        // pb.add(Float.valueOf(minY));
-//        // pb.add(null);
-//        //
-//        // image = JAI.create("translate", pb);
-//
-//        return image;
-        
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/GatherCoverageMetadataCommand.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/GatherCoverageMetadataCommand.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/GatherCoverageMetadataCommand.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,521 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.geom.Point2D;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferUShort;
-import java.awt.image.IndexColorModel;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.geotools.arcsde.ArcSdeException;
-import org.geotools.arcsde.session.Command;
-import org.geotools.arcsde.session.ISession;
-import org.geotools.arcsde.util.ArcSDEUtils;
-import org.geotools.data.DataSourceException;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.referencing.crs.DefaultEngineeringCRS;
-import org.geotools.util.logging.Logging;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import com.esri.sde.sdk.client.SDEPoint;
-import com.esri.sde.sdk.client.SeColumnDefinition;
-import com.esri.sde.sdk.client.SeConnection;
-import com.esri.sde.sdk.client.SeCoordinateReference;
-import com.esri.sde.sdk.client.SeException;
-import com.esri.sde.sdk.client.SeExtent;
-import com.esri.sde.sdk.client.SeQuery;
-import com.esri.sde.sdk.client.SeRaster;
-import com.esri.sde.sdk.client.SeRasterAttr;
-import com.esri.sde.sdk.client.SeRasterBand;
-import com.esri.sde.sdk.client.SeRasterColumn;
-import com.esri.sde.sdk.client.SeRow;
-import com.esri.sde.sdk.client.SeSqlConstruct;
-import com.esri.sde.sdk.client.SeTable;
-
-/**
- * Session command to gather information for an ArcSDE Raster, such as dimensions, spatial extent,
- * number of pyramid levels, etc; into a {@link RasterDatasetInfo}
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.8
- * @source $UR$
- */
-public class GatherCoverageMetadataCommand extends Command<RasterDatasetInfo> {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private final boolean statisticsMandatory;
-
-    private final String rasterTableName;
-
-    public GatherCoverageMetadataCommand(final String rasterTableName,
-            final boolean statisticsMandatory) {
-        this.rasterTableName = rasterTableName;
-        this.statisticsMandatory = statisticsMandatory;
-    }
-
-    /**
-     * @throws IOException
-     *             if an exception occurs accessing the raster metadata
-     * @throws SeException
-     * @throws IllegalArgumentException
-     *             if the raster has no CRS, contains no raster attributes, has no pyramids, no
-     *             bands or no statistics
-     */
-    @Override
-    public RasterDatasetInfo execute(ISession session, SeConnection connection) throws SeException,
-            IOException {
-        LOGGER.fine("Gathering raster dataset metadata for " + rasterTableName);
-        final String[] rasterColumns = getRasterColumns(connection, rasterTableName);
-        final List<RasterInfo> rastersLayoutInfo = new ArrayList<RasterInfo>();
-        {
-            final List<SeRasterAttr> rasterAttributes;
-            rasterAttributes = getSeRasterAttr(connection, rasterTableName, rasterColumns);
-
-            if (rasterAttributes.size() == 0) {
-                throw new IllegalArgumentException("Table " + rasterTableName
-                        + " contains no raster datasets");
-            }
-
-            final CoordinateReferenceSystem coverageCrs;
-
-            /*
-             * by bandId map of colormaps. The dataset may be composed of more than one raster so we
-             * gather all the colormaps once and held them here by rasterband id
-             */
-            final Map<Long, IndexColorModel> rastersColorMaps;
-            {
-                final SeRasterColumn rasterColumn;
-                final SeRasterBand sampleBand;
-                final long rasterColumnId;
-                final int bitsPerSample;
-                try {
-                    SeRasterAttr ratt = rasterAttributes.get(0);
-                    rasterColumn = new SeRasterColumn(connection, ratt.getRasterColumnId());
-                    rasterColumnId = rasterColumn.getID().longValue();
-                    sampleBand = ratt.getBands()[0];
-                    bitsPerSample = RasterCellType.valueOf(ratt.getPixelType()).getBitsPerSample();
-                } catch (SeException e) {
-                    throw new ArcSdeException(e);
-                }
-                final SeCoordinateReference seCoordRef = rasterColumn.getCoordRef();
-                if (seCoordRef == null) {
-                    throw new IllegalArgumentException(rasterTableName
-                            + " has no coordinate reference system set");
-                }
-                LOGGER.finer("Looking CRS for raster column " + rasterTableName);
-                coverageCrs = ArcSDEUtils.findCompatibleCRS(seCoordRef);
-                if (DefaultEngineeringCRS.CARTESIAN_2D == coverageCrs) {
-                    LOGGER.warning("Raster " + rasterTableName
-                            + " has not CRS set, using DefaultEngineeringCRS.CARTESIAN_2D");
-                }
-                if (sampleBand.hasColorMap()) {
-                    rastersColorMaps = loadColorMaps(rasterColumnId, bitsPerSample, connection);
-                } else {
-                    rastersColorMaps = Collections.emptyMap();
-                }
-
-            }
-            try {
-                for (SeRasterAttr rAtt : rasterAttributes) {
-                    LOGGER.fine("Gathering raster metadata for " + rasterTableName + " raster "
-                            + rAtt.getRasterId().longValue());
-
-                    if (rAtt.getMaxLevel() == 0) {
-                        throw new IllegalArgumentException(
-                                "Raster cotains no pyramid levels, we don't support non pyramid rasters");
-                    }
-                    if (rAtt.getNumBands() == 0) {
-                        throw new IllegalArgumentException("Raster "
-                                + rAtt.getRasterId().longValue() + " in " + rasterTableName
-                                + " contains no raster attribtues");
-                    }
-                    if (this.statisticsMandatory && !rAtt.getBandInfo(1).hasStats()) {
-                        throw new IllegalArgumentException(rasterTableName
-                                + " has no statistics generated (or not all it's rasters have). "
-                                + "Please use sderaster -o stats to create them before use");
-                    }
-
-                    RasterInfo rasterInfo = new RasterInfo(rAtt, coverageCrs);
-                    rastersLayoutInfo.add(rasterInfo);
-
-                    final GeneralEnvelope originalEnvelope;
-                    originalEnvelope = calculateOriginalEnvelope(rAtt, coverageCrs);
-                    rasterInfo.setOriginalEnvelope(originalEnvelope);
-                    final List<RasterBandInfo> bands;
-                    bands = setUpBandInfo(connection, rAtt, rastersColorMaps);
-                    rasterInfo.setBands(bands);
-                    if (LOGGER.isLoggable(Level.FINER)) {
-                        LOGGER.finer("Gathered metadata for " + rasterTableName + "#"
-                                + rAtt.getRasterId().longValue() + ":\n" + rasterInfo.toString());
-                    }
-                }
-            } catch (SeException e) {
-                throw new ArcSdeException("Gathering raster dataset information", e);
-            }
-        }
-
-        RasterDatasetInfo rasterInfo = new RasterDatasetInfo();
-        rasterInfo.setRasterTable(rasterTableName);
-        rasterInfo.setRasterColumns(rasterColumns);
-        rasterInfo.setPyramidInfo(rastersLayoutInfo);
-
-        return rasterInfo;
-    }
-
-    private String[] getRasterColumns(final SeConnection scon, final String rasterTable)
-            throws IOException, SeException {
-
-        String[] rasterColumns;
-        SeTable sTable = new SeTable(scon, rasterTable);
-        SeColumnDefinition[] cols;
-        try {
-            cols = sTable.describe();
-        } catch (SeException e) {
-            throw new ArcSdeException("Exception fetching the list of columns for table "
-                    + rasterTable, e);
-        }
-        List<String> fetchColumns = new ArrayList<String>(cols.length / 2);
-        for (int i = 0; i < cols.length; i++) {
-            if (cols[i].getType() == SeColumnDefinition.TYPE_RASTER)
-                fetchColumns.add(cols[i].getName());
-        }
-        if (fetchColumns.size() == 0) {
-            throw new DataSourceException("Couldn't find any TYPE_RASTER columns in ArcSDE table "
-                    + rasterTable);
-        }
-
-        rasterColumns = fetchColumns.toArray(new String[fetchColumns.size()]);
-        return rasterColumns;
-    }
-
-    private GeneralEnvelope calculateOriginalEnvelope(final SeRasterAttr rasterAttributes,
-            CoordinateReferenceSystem coverageCrs) throws IOException {
-        SeExtent sdeExtent;
-        try {
-            sdeExtent = rasterAttributes.getExtent();
-        } catch (SeException e) {
-            throw new ArcSdeException("Exception getting the raster extent", e);
-        }
-        GeneralEnvelope originalEnvelope = new GeneralEnvelope(coverageCrs);
-        originalEnvelope.setRange(0, sdeExtent.getMinX(), sdeExtent.getMaxX());
-        originalEnvelope.setRange(1, sdeExtent.getMinY(), sdeExtent.getMaxY());
-        return originalEnvelope;
-    }
-
-    private List<SeRasterAttr> getSeRasterAttr(SeConnection scon, String rasterTable,
-            String[] rasterColumns) throws IOException {
-
-        LOGGER.fine("Gathering raster attributes for " + rasterTable);
-        SeRasterAttr rasterAttributes;
-        LinkedList<SeRasterAttr> rasterAttList = new LinkedList<SeRasterAttr>();
-        SeQuery query = null;
-        try {
-            query = new SeQuery(scon, rasterColumns, new SeSqlConstruct(rasterTable));
-            query.prepareQuery();
-            query.execute();
-
-            SeRow row = query.fetch();
-            while (row != null) {
-                rasterAttributes = row.getRaster(0);
-                rasterAttList.addFirst(rasterAttributes);
-                row = query.fetch();
-            }
-        } catch (SeException se) {
-            throw new ArcSdeException("Error fetching raster attributes for " + rasterTable, se);
-        } finally {
-            if (query != null) {
-                try {
-                    query.close();
-                } catch (SeException e) {
-                    throw new ArcSdeException(e);
-                }
-            }
-        }
-        LOGGER.fine("Found " + rasterAttList.size() + " raster attributes for " + rasterTable);
-        return rasterAttList;
-    }
-
-    /**
-     *
-     * @param band
-     * @param scon
-     * @return
-     * @throws ArcSdeException
-     */
-    private Map<Long, IndexColorModel> loadColorMaps(final long rasterColumnId,
-            final int bitsPerSample, SeConnection scon) throws IOException {
-        LOGGER.fine("Reading colormap for raster column " + rasterColumnId);
-
-        final String auxTableName = getAuxTableName(rasterColumnId, scon);
-        LOGGER.fine("Quering auxiliary table " + auxTableName + " for color map data");
-
-        Map<Long, IndexColorModel> colorMaps = new HashMap<Long, IndexColorModel>();
-        SeQuery query = null;
-        try {
-            SeSqlConstruct sqlConstruct = new SeSqlConstruct();
-            sqlConstruct.setTables(new String[] { auxTableName });
-            String whereClause = "TYPE = 3";
-            sqlConstruct.setWhere(whereClause);
-
-            query = new SeQuery(scon, new String[] { "RASTERBAND_ID", "OBJECT" }, sqlConstruct);
-            query.prepareQuery();
-            query.execute();
-
-            long bandId;
-            ByteArrayInputStream colorMapIS;
-            DataBuffer colorMapData;
-            IndexColorModel colorModel;
-
-            SeRow row = query.fetch();
-            while (row != null) {
-                bandId = ((Number) row.getObject(0)).longValue();
-                colorMapIS = row.getBlob(1);
-
-                colorMapData = readColorMap(colorMapIS);
-                colorModel = RasterUtils.sdeColorMapToJavaColorModel(colorMapData, bitsPerSample);
-
-                colorMaps.put(Long.valueOf(bandId), colorModel);
-
-                row = query.fetch();
-            }
-        } catch (SeException e) {
-            throw new ArcSdeException("Error fetching colormap data for column " + rasterColumnId
-                    + " from table " + auxTableName, e);
-        } finally {
-            if (query != null) {
-                try {
-                    query.close();
-                } catch (SeException e) {
-                    LOGGER.log(Level.INFO, "ignoring exception when closing query to "
-                            + "fetch colormap data", e);
-                }
-            }
-        }
-        LOGGER.fine("Read color map data for " + colorMaps.size() + " rasters");
-        return colorMaps;
-    }
-
-    private DataBuffer readColorMap(final ByteArrayInputStream colorMapIS) throws IOException {
-
-        final DataInputStream dataIn = new DataInputStream(colorMapIS);
-        // discard unneeded data
-        dataIn.readInt();
-
-        final int colorSpaceType = dataIn.readInt();
-        final int numBanks;
-        if (colorSpaceType == SeRaster.SE_COLORMAP_RGB) {
-            numBanks = 3;
-        } else if (colorSpaceType == SeRaster.SE_COLORMAP_RGBA) {
-            numBanks = 4;
-        } else {
-            throw new IllegalStateException("Got unknown colormap type: " + colorSpaceType);
-        }
-        LOGGER.finest("Colormap has " + numBanks + " color components");
-
-        final int buffType = dataIn.readInt();
-        final int numElems = dataIn.readInt();
-        LOGGER.finest("ColorMap length: " + numElems);
-
-        final DataBuffer buff;
-        if (buffType == SeRaster.SE_COLORMAP_DATA_BYTE) {
-            LOGGER.finest("Creating Byte data buffer for " + numBanks + " banks and " + numElems
-                    + " elements per bank");
-            buff = new DataBufferByte(numElems, numBanks);
-            for (int elem = 0; elem < numElems; elem++) {
-                for (int bank = 0; bank < numBanks; bank++) {
-                    int val = dataIn.readUnsignedByte();
-                    buff.setElem(bank, elem, val);
-                }
-            }
-        } else if (buffType == SeRaster.SE_COLORMAP_DATA_SHORT) {
-            LOGGER.finest("Creating Short data buffer for " + numBanks + " banks and " + numElems
-                    + " elements per bank");
-            buff = new DataBufferUShort(numElems, numBanks);
-            for (int elem = 0; elem < numElems; elem++) {
-                for (int bank = 0; bank < numBanks; bank++) {
-                    int val = dataIn.readUnsignedShort();
-                    buff.setElem(bank, elem, val);
-                }
-            }
-        } else {
-            throw new IllegalStateException("Unknown databuffer type from colormap header: "
-                    + buffType + " expected one of TYPE_BYTE, TYPE_SHORT");
-        }
-
-        assert dataIn.read() == -1 : "color map data should have been exausted";
-        return buff;
-    }
-
-    private String getAuxTableName(long rasterColumnId, SeConnection scon) throws IOException {
-
-        final String owner;
-        SeQuery query = null;
-        try {
-            final String dbaName = scon.getSdeDbaName();
-            String rastersColumnsTable = dbaName + ".SDE_RASTER_COLUMNS";
-
-            SeSqlConstruct sqlCons = new SeSqlConstruct(rastersColumnsTable);
-            sqlCons.setWhere("RASTERCOLUMN_ID = " + rasterColumnId);
-
-            try {
-                query = new SeQuery(scon, new String[] { "OWNER" }, sqlCons);
-                query.prepareQuery();
-            } catch (SeException e) {
-                // sde 9.3 calls it raster_columns, not sde_raster_columns...
-                rastersColumnsTable = dbaName + ".RASTER_COLUMNS";
-                sqlCons = new SeSqlConstruct(rastersColumnsTable);
-                sqlCons.setWhere("RASTERCOLUMN_ID = " + rasterColumnId);
-                query = new SeQuery(scon, new String[] { "OWNER" }, sqlCons);
-                query.prepareQuery();
-            }
-            query.execute();
-
-            SeRow row = query.fetch();
-            if (row == null) {
-                throw new IllegalArgumentException("No raster column registered with id "
-                        + rasterColumnId);
-            }
-            owner = row.getString(0);
-            query.close();
-        } catch (SeException e) {
-            throw new ArcSdeException("Error getting auxiliary table for raster column "
-                    + rasterColumnId, e);
-        } finally {
-            if (query != null) {
-                try {
-                    query.close();
-                } catch (SeException e) {
-                    LOGGER.log(Level.INFO, "ignoring exception when closing query to "
-                            + "fetch colormap data", e);
-                }
-            }
-        }
-
-        final String auxTableName = owner + ".SDE_AUX_" + rasterColumnId;
-
-        return auxTableName;
-    }
-
-    private List<RasterBandInfo> setUpBandInfo(SeConnection scon, SeRasterAttr rasterAttributes,
-            Map<Long, IndexColorModel> rastersColorMaps) throws IOException {
-        final int numBands;
-        final SeRasterBand[] seBands;
-        final RasterCellType cellType;
-        try {
-            numBands = rasterAttributes.getNumBands();
-            seBands = rasterAttributes.getBands();
-            cellType = RasterCellType.valueOf(rasterAttributes.getPixelType());
-        } catch (SeException e) {
-            throw new ArcSdeException(e);
-        }
-
-        List<RasterBandInfo> detachedBandInfo = new ArrayList<RasterBandInfo>(numBands);
-
-        RasterBandInfo bandInfo;
-        SeRasterBand band;
-        for (int bandN = 0; bandN < numBands; bandN++) {
-            band = seBands[bandN];
-            bandInfo = new RasterBandInfo();
-            final int bitsPerSample = cellType.getBitsPerSample();
-            setBandInfo(numBands, bandInfo, band, scon, bitsPerSample, rastersColorMaps);
-            detachedBandInfo.add(bandInfo);
-        }
-        return detachedBandInfo;
-    }
-
-    /**
-     *
-     * @param numBands
-     * @param bandInfo
-     * @param band
-     * @param scon
-     * @param bitsPerSample
-     *            only used if the band is colormapped to create the IndexColorModel
-     * @throws IOException
-     */
-    private void setBandInfo(final int numBands, final RasterBandInfo bandInfo,
-            final SeRasterBand band, final SeConnection scon, int bitsPerSample,
-            final Map<Long, IndexColorModel> colorMaps) throws IOException {
-
-        bandInfo.bandId = band.getId().longValue();
-        bandInfo.bandNumber = band.getBandNumber();
-        bandInfo.bandName = "Band " + bandInfo.bandNumber;
-
-        final boolean hasColorMap = band.hasColorMap();
-        if (hasColorMap) {
-            IndexColorModel colorMap = colorMaps.get(Long.valueOf(bandInfo.bandId));
-            LOGGER.finest("Setting band's color map: " + colorMap);
-            bandInfo.nativeColorMap = colorMap;
-            bandInfo.colorMap = RasterUtils.ensureNoDataPixelIsAvailable(colorMap);
-        } else {
-            bandInfo.nativeColorMap = null;
-        }
-
-        bandInfo.compressionType = CompressionType.valueOf(band.getCompressionType());
-        bandInfo.cellType = RasterCellType.valueOf(band.getPixelType());
-        bandInfo.interleaveType = InterleaveType.valueOf(band.getInterleave());
-        bandInfo.interpolationType = InterpolationType.valueOf(band.getInterpolation());
-        bandInfo.hasStats = band.hasStats();
-        if (bandInfo.hasStats) {
-            try {
-                bandInfo.statsMin = band.getStatsMin();
-                bandInfo.statsMax = band.getStatsMax();
-                bandInfo.statsMean = band.getStatsMean();
-                bandInfo.statsStdDev = band.getStatsStdDev();
-            } catch (SeException e) {
-                throw new ArcSdeException(e);
-            }
-            // double noDataValue = 0;
-            // bandInfo.noDataValue = noDataValue;
-        } else {
-            bandInfo.statsMin = java.lang.Double.NaN;
-            bandInfo.statsMax = java.lang.Double.NaN;
-            bandInfo.statsMean = java.lang.Double.NaN;
-            bandInfo.statsStdDev = java.lang.Double.NaN;
-        }
-        if (bandInfo.getColorMap() != null) {
-            bandInfo.noDataValue = RasterUtils.determineNoDataValue(bandInfo.getColorMap());
-        } else {
-            double statsMin = bandInfo.getStatsMin();
-            double statsMax = bandInfo.getStatsMax();
-            RasterCellType nativeCellType = bandInfo.getCellType();
-            bandInfo.noDataValue = RasterUtils.determineNoDataValue(numBands, statsMin, statsMax,
-                    nativeCellType);
-        }
-        SDEPoint tOrigin;
-        try {
-            tOrigin = band.getTileOrigin();
-        } catch (SeException e) {
-            throw new ArcSdeException(e);
-        }
-        bandInfo.tileOrigin = new Point2D.Double(tOrigin.getX(), tOrigin.getY());
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterleaveType.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterleaveType.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterleaveType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,64 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.util.NoSuchElementException;
-
-import com.esri.sde.sdk.client.SeRaster;
-
-/**
- * An enumeration that mirrors the different possible band interleave types in Arcsde (ie, {@code
- * SeRaster#SE_RASTER_INTERLEAVE_*})
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-enum InterleaveType {
-    INTERLEAVE_BIL, INTERLEAVE_BIL_91, INTERLEAVE_BIP, INTERLEAVE_BIP_91, INTERLEAVE_BSQ, INTERLEAVE_BSQ_91, INTERLEAVE_NONE;
-    static {
-        INTERLEAVE_BIL.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIL);
-        INTERLEAVE_BIL_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIL_91);
-        INTERLEAVE_BIP.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIP);
-        INTERLEAVE_BIP_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIP_91);
-        INTERLEAVE_BSQ.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BSQ);
-        INTERLEAVE_BSQ_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BSQ_91);
-        INTERLEAVE_NONE.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_NONE);
-    }
-
-    private int typeId;
-
-    private void setSdeTypeId(int typeId) {
-        this.typeId = typeId;
-    }
-
-    public int getSeRasterInterleaveType() {
-        return this.typeId;
-    }
-
-    public static InterleaveType valueOf(final int seRasterInterleaveType) {
-        for (InterleaveType type : InterleaveType.values()) {
-            if (type.getSeRasterInterleaveType() == seRasterInterleaveType) {
-                return type;
-            }
-        }
-        throw new NoSuchElementException("Raster interleave type " + seRasterInterleaveType
-                + " does not exist");
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterpolationType.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterpolationType.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterpolationType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,61 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.util.NoSuchElementException;
-
-import com.esri.sde.sdk.client.SeRaster;
-
-/**
- * An enumeration that mirrors the different possible raster interpolation types in Arcsde (ie,
- * {@code SeRaster#SE_INTERPOLATION_*})
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-enum InterpolationType {
-    INTERPOLATION_BICUBIC, INTERPOLATION_BILINEAR, INTERPOLATION_NEAREST, INTERPOLATION_NONE;
-    static {
-        INTERPOLATION_BICUBIC.setSdeTypeId(SeRaster.SE_INTERPOLATION_BICUBIC);
-        INTERPOLATION_BILINEAR.setSdeTypeId(SeRaster.SE_INTERPOLATION_BILINEAR);
-        INTERPOLATION_NEAREST.setSdeTypeId(SeRaster.SE_INTERPOLATION_NEAREST);
-        INTERPOLATION_NONE.setSdeTypeId(SeRaster.SE_INTERPOLATION_NONE);
-    }
-
-    private int typeId;
-
-    private void setSdeTypeId(int typeId) {
-        this.typeId = typeId;
-    }
-
-    public int getSeInterpolationType() {
-        return this.typeId;
-    }
-
-    public static InterpolationType valueOf(final int seInterpolationType) {
-        for (InterpolationType type : InterpolationType.values()) {
-            if (type.getSeInterpolationType() == seInterpolationType) {
-                return type;
-            }
-        }
-        throw new NoSuchElementException("Interpolation type " + seInterpolationType
-                + " does not exist");
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/NativeTileReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/NativeTileReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/NativeTileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,528 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.io.EOFException;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.geotools.arcsde.ArcSdeException;
-import org.geotools.arcsde.session.Command;
-import org.geotools.arcsde.session.ISession;
-import org.geotools.arcsde.session.ISessionPool;
-import org.geotools.arcsde.session.UnavailableConnectionException;
-import org.geotools.util.logging.Logging;
-
-import com.esri.sde.sdk.client.SeConnection;
-import com.esri.sde.sdk.client.SeException;
-import com.esri.sde.sdk.client.SeQuery;
-import com.esri.sde.sdk.client.SeRaster;
-import com.esri.sde.sdk.client.SeRasterConstraint;
-import com.esri.sde.sdk.client.SeRasterTile;
-import com.esri.sde.sdk.client.SeRow;
-import com.esri.sde.sdk.client.SeSqlConstruct;
-import com.esri.sde.sdk.client.SeStreamOp;
-
-/**
- * Offers an iterator like interface to fetch ArcSDE raster tiles.
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/NativeTileReader.java $
- */
-@SuppressWarnings( { "nls" })
-final class NativeTileReader implements TileReader {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private final RasterDatasetInfo rasterInfo;
-
-    private final long rasterId;
-
-    private final int pyramidLevel;
-
-    private final Rectangle requestedTiles;
-
-    private final ISessionPool sessionPool;
-
-    private ISession session;
-
-    private TileFetchCommand tileFetchCommand;
-
-    /**
-     * {@link SeStreamOp} held to be closed at {@link #dispose()}
-     *
-     * @see #execute()
-     */
-    private SeQuery preparedQuery;
-
-    private TileInfo nextTile;
-
-    private boolean started;
-
-    private final int bitmaskDataLength;
-
-    private final BitmaskToNoDataConverter noData;
-
-    private final int pixelsPerTile;
-
-    private final int tileDataLength;
-
-    private int bitsPerSample;
-
-    /**
-     * Command to fetch an {@link SeRasterTile tile}
-     */
-    private static class TileFetchCommand extends Command<TileInfo> {
-
-        private final SeRow row;
-
-        private final int tileDataLength;
-
-        public TileFetchCommand(final SeRow row, final int tileDataLength) {
-            this.row = row;
-            this.tileDataLength = tileDataLength;
-        }
-
-        @Override
-        public TileInfo execute(ISession session, SeConnection connection) throws SeException,
-                IOException {
-            SeRasterTile tile = row.getRasterTile();
-            final TileInfo tileInfo;
-            if (tile == null) {
-                tileInfo = null;
-            } else {
-                byte[] bitMaskData = tile.getBitMaskData();
-                int numPixelsRead = tile.getNumPixels();
-                byte[] tileData;
-                if (numPixelsRead == 0) {
-                    tileData = new byte[tileDataLength];
-                } else {
-                    tileData = tile.getPixelData();
-                }
-                long bandId = tile.getBandId().longValue();
-                int colIndex = tile.getColumnIndex();
-                int rowIndex = tile.getRowIndex();
-                tileInfo = new TileInfo(bandId, colIndex, rowIndex, numPixelsRead, tileData,
-                        bitMaskData);
-            }
-            return tileInfo;
-        }
-    }
-
-    /**
-     * @see DefaultTiledRasterReader#nextRaster()
-     */
-    private static class QueryRasterCommand extends Command<Void> {
-
-        private SeQuery preparedQuery;
-
-        private SeRow row;
-
-        private final SeRasterConstraint rasterConstraint;
-
-        private final String rasterColumn;
-
-        private final String rasterTable;
-
-        private final long rasterId;
-
-        /**
-         *
-         * @param rConstraint
-         *            indicates which bands, pyramid level and grid envelope to query
-         * @param rasterTable
-         *            indicates which raster table to query
-         * @param rasterColumn
-         *            indicates what raster column in the raster table to query
-         * @param rasterId
-         *            indicates which raster in the raster catalog to query
-         */
-        public QueryRasterCommand(final SeRasterConstraint rConstraint, final String rasterTable,
-                final String rasterColumn, final long rasterId) {
-            this.rasterConstraint = rConstraint;
-            this.rasterTable = rasterTable;
-            this.rasterColumn = rasterColumn;
-            this.rasterId = rasterId;
-        }
-
-        @Override
-        public Void execute(ISession session, SeConnection connection) throws SeException,
-                IOException {
-
-            final SeSqlConstruct sqlConstruct = new SeSqlConstruct(rasterTable);
-            /*
-             * Filter by the given raster id
-             */
-            final String rasterIdFilter = rasterColumn + " = " + rasterId;
-            sqlConstruct.setWhere(rasterIdFilter);
-
-            final String[] rasterColumns = { rasterColumn };
-            preparedQuery = new SeQuery(connection, rasterColumns, sqlConstruct);
-            preparedQuery.prepareQuery();
-            preparedQuery.execute();
-
-            this.row = preparedQuery.fetch();
-            if (row == null) {
-                return null;
-            }
-
-            preparedQuery.queryRasterTile(rasterConstraint);
-
-            return null;
-        }
-
-        public SeQuery getPreparedQuery() {
-            return preparedQuery;
-        }
-
-        public SeRow getSeRow() {
-            return row;
-        }
-    }
-
-    /**
-     * Creates a {@link TileReader} that reads tiles out of ArcSDE for the given {@code
-     * preparedQuery} and {@code SeRow} using the given {@code session}, in the native raster
-     * format.
-     * <p>
-     * As for any object that receives a {@link ISession session}, the same rule applies: this class
-     * is not responsible of {@link ISession#dispose() disposing} the session, but the calling code
-     * is.
-     * </p>
-     *
-     * @param preparedQuery
-     *            the query stream to close when done
-     * @param row
-     * @param imageDimensions
-     *            the image size, x and y are the offsets, width and height the actual width and
-     *            height, used to ignore incomming pixel data as appropriate to fit the image
-     *            dimensions
-     * @param bitsPerSample
-     * @param numberOfBands2
-     * @param requestedTiles
-     */
-    NativeTileReader(final ISessionPool sessionPool, final RasterDatasetInfo rasterInfo,
-            final long rasterId, final int pyramidLevel, final Rectangle requestedTiles,
-            final BitmaskToNoDataConverter noData) {
-        this.sessionPool = sessionPool;
-        this.rasterInfo = rasterInfo;
-        this.rasterId = rasterId;
-        this.pyramidLevel = pyramidLevel;
-        this.requestedTiles = requestedTiles;
-        this.noData = noData;
-
-        final Dimension tileSize = rasterInfo.getTileDimension(rasterId);
-
-        this.pixelsPerTile = tileSize.width * tileSize.height;
-
-        final RasterCellType nativeCellType = rasterInfo.getNativeCellType();
-        this.bitsPerSample = nativeCellType.getBitsPerSample();
-        this.tileDataLength = (int) Math
-                .ceil(((double) pixelsPerTile * (double) bitsPerSample) / 8D);
-        this.bitmaskDataLength = (int) Math.ceil(pixelsPerTile / 8D);
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getBitsPerSample()
-     */
-    public int getBitsPerSample() {
-        return bitsPerSample;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getPixelsPerTile()
-     */
-    public int getPixelsPerTile() {
-        return pixelsPerTile;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getNumberOfBands()
-     */
-    public int getNumberOfBands() {
-        return rasterInfo.getNumBands();
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getTileWidth()
-     */
-    public int getTileWidth() {
-        return rasterInfo.getTileWidth(rasterId);
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getTileHeight()
-     */
-    public int getTileHeight() {
-        return rasterInfo.getTileHeight(rasterId);
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getTilesWide()
-     */
-    public int getTilesWide() {
-        return requestedTiles.width;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getTilesHigh()
-     */
-    public int getTilesHigh() {
-        return requestedTiles.height;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#getBytesPerTile()
-     */
-    public int getBytesPerTile() {
-        return tileDataLength;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#hasNext()
-     */
-    public boolean hasNext() throws IOException {
-        if (!started) {
-            execute();
-            try {
-                nextTile = session.issue(tileFetchCommand);
-            } catch (IOException e) {
-                dispose();
-                throw e;
-            } catch (RuntimeException e) {
-                dispose();
-                throw e;
-            }
-            started = true;
-            if (nextTile == null) {
-                dispose();
-                LOGGER.fine("No tiles to fetch at all, releasing connection");
-            }
-        }
-        return nextTile != null;
-    }
-
-    /**
-     * Creates and executes the {@link SeQuery} that's used to fetch the required tiles from the
-     * specified raster, and stores (as member variables) the {@link SeRow} to fetch the tiles from
-     * and the {@link SeQuery} to be closed at the TileReader's disposal
-     *
-     * @throws IOException
-     */
-    private void execute() throws IOException {
-
-        final int rasterIndex = rasterInfo.getRasterIndex(rasterId);
-        final int tileWidth = rasterInfo.getTileWidth(rasterId);
-        final int tileHeight = rasterInfo.getTileHeight(rasterId);
-
-        /*
-         * Create the raster constraint to query the needed tiles out of the specified raster at the
-         * given pyramid level
-         */
-        final SeRasterConstraint rConstraint;
-        try {
-            final int numberOfBands;
-            numberOfBands = rasterInfo.getNumBands();
-
-            int[] bandsToQuery = new int[numberOfBands];
-            for (int bandN = 1; bandN <= numberOfBands; bandN++) {
-                bandsToQuery[bandN - 1] = bandN;
-            }
-
-            int minTileX = requestedTiles.x;
-            int minTileY = requestedTiles.y;
-            int maxTileX = minTileX + requestedTiles.width - 1;
-            int maxTileY = minTileY + requestedTiles.height - 1;
-            if (LOGGER.isLoggable(Level.FINE)) {
-                LOGGER.fine("Requesting tiles [x=" + minTileX + "-" + maxTileX + ", y=" + minTileY
-                        + "-" + maxTileY + "] from tile range [x=0-"
-                        + (rasterInfo.getNumTilesWide(rasterIndex, pyramidLevel) - 1) + ", y=0-"
-                        + (rasterInfo.getNumTilesHigh(rasterIndex, pyramidLevel) - 1) + "]");
-            }
-            // SDEPoint tileOrigin = rAttr.getTileOrigin();
-
-            if (LOGGER.isLoggable(Level.FINE)) {
-                Rectangle tiledImageSize = new Rectangle(0, 0, tileWidth * requestedTiles.width,
-                        tileHeight * requestedTiles.height);
-
-                LOGGER.fine("Tiled image size: " + tiledImageSize);
-            }
-
-            final int interleaveType = SeRaster.SE_RASTER_INTERLEAVE_BIP;
-
-            rConstraint = new SeRasterConstraint();
-            rConstraint.setBands(bandsToQuery);
-            rConstraint.setLevel(pyramidLevel);
-            rConstraint.setEnvelope(minTileX, minTileY, maxTileX, maxTileY);
-            rConstraint.setInterleave(interleaveType);
-        } catch (SeException se) {
-            throw new ArcSdeException(se);
-        }
-
-        /*
-         * Obtain the ISession this tile reader will work with until exhausted
-         */
-        try {
-            // lets share connections as we're going to do read only operations
-            final boolean transactional = false;
-            this.session = sessionPool.getSession(transactional);
-            // System.err.println("----> Using " + session + " to read raster #" + rasterId
-            // + " on Thread " + Thread.currentThread().getName() + ". Tile set: "
-            // + requestedTiles);
-            if (LOGGER.isLoggable(Level.FINER)) {
-                LOGGER.finer("Using " + session + " to read raster #" + rasterId + " on Thread "
-                        + Thread.currentThread().getName() + ". Tile set: " + requestedTiles);
-            }
-        } catch (UnavailableConnectionException e) {
-            // really bad luck..
-            throw new RuntimeException(e);
-        }
-
-        final String rasterTable = rasterInfo.getRasterTable();
-        final String rasterColumn = rasterInfo.getRasterColumns()[0];
-        final QueryRasterCommand queryCommand = new QueryRasterCommand(rConstraint, rasterTable,
-                rasterColumn, rasterId);
-
-        session.issue(queryCommand);
-
-        final SeRow row = queryCommand.getSeRow();
-
-        this.tileFetchCommand = new TileFetchCommand(row, tileDataLength);
-        this.preparedQuery = queryCommand.getPreparedQuery();
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#next()
-     */
-    public TileInfo next() throws IOException {
-        final TileInfo tile;
-        final boolean hasNext = hasNext();
-        if (hasNext) {
-            tile = nextTile();
-        } else {
-            throw new IllegalStateException("There're no more tiles to fetch");
-        }
-
-        try {
-            final byte[] bitMaskData = tile.getBitmaskData();
-
-            if (LOGGER.isLoggable(Level.FINEST)) {
-                LOGGER.finest(" >> Fetching " + tile + " - bitmask: " + bitMaskData.length);
-            }
-
-            assert bitMaskData.length == 0 ? true : bitmaskDataLength == bitMaskData.length;
-
-            final int numPixels = tile.getNumPixelsRead();
-            final byte[] rawTileData = tile.getTileData();
-
-            final Long bandId = tile.getBandId();
-
-            if (0 == numPixels) {
-                if (LOGGER.isLoggable(Level.FINER)) {
-                    LOGGER.finer("tile contains no pixel data, skipping: " + tile);
-                }
-                noData.setAll(bandId, rawTileData);
-            } else if (pixelsPerTile == numPixels) {
-
-                if (bitMaskData.length > 0) {
-                    noData.setNoData(bandId, rawTileData, bitMaskData);
-                }
-
-                if (LOGGER.isLoggable(Level.FINEST)) {
-                    LOGGER.finest("returning " + numPixels + " pixels data packaged into "
-                            + tileDataLength + " bytes for tile [" + tile.getColumnIndex() + ","
-                            + tile.getRowIndex() + "]");
-                }
-            } else {
-                throw new IllegalStateException("Expected pixels per tile == " + pixelsPerTile
-                        + " but got " + numPixels + ": " + tile);
-            }
-
-            // return new TileInfo(bandId, bitMaskData, numPixels);
-            return tile;
-
-        } catch (RuntimeException e) {
-            dispose();
-            throw e;
-        }
-    }
-
-    private TileInfo nextTile() throws IOException {
-        if (nextTile == null) {
-            dispose();
-            throw new EOFException("No more tiles to read");
-        }
-        TileInfo curr = nextTile;
-
-        try {
-            nextTile = session.issue(tileFetchCommand);
-        } catch (IOException e) {
-            dispose();
-            throw e;
-        } catch (RuntimeException e) {
-            dispose();
-            throw e;
-        }
-        if (nextTile == null) {
-            dispose();
-            LOGGER.finer("There're no more tiles to fetch");
-        }
-
-        return curr;
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#dispose()
-     */
-    public void dispose() {
-        if (session != null) {
-            // System.err.println("TileReader disposing " + session + " on Thread "
-            // + Thread.currentThread().getName());
-            if (LOGGER.isLoggable(Level.FINER)) {
-                LOGGER.finer("TileReader disposing " + session + " on Thread "
-                        + Thread.currentThread().getName());
-            }
-            try {
-                session.close(this.preparedQuery);
-            } catch (Exception e) {
-                LOGGER.log(Level.WARNING, "Closing tile reader's prepared Query", e);
-            }
-            session.dispose();
-            session = null;
-        }
-    }
-
-    /**
-     * Disposes as to make sure the {@link ISession session} is returned to the pool even if a
-     * failing or non careful client left this object hanging around
-     *
-     * @see #dispose()
-     * @see java.lang.Object#finalize()
-     */
-    @Override
-    protected void finalize() {
-        dispose();
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PromotingTileReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PromotingTileReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PromotingTileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,206 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_1BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.geotools.util.logging.Logging;
-
-import com.esri.sde.sdk.client.SeRasterTile;
-
-/**
- * A {@link TileReader} decorator
- *
- * @author Gabriel Roldan
- * @version $Id$
- * @since 2.5.6
- */
-final class PromotingTileReader implements TileReader {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private final TileReader nativeReader;
-
-    private final RasterCellType targetType;
-
-    private final SampleDepthPromoter promoter;
-
-    private final BitmaskToNoDataConverter noData;
-
-    public PromotingTileReader(final TileReader nativeTileReader, final RasterCellType sourceType,
-            final RasterCellType targetType, final BitmaskToNoDataConverter noData) {
-
-        this.nativeReader = nativeTileReader;
-        this.targetType = targetType;
-        this.noData = noData;
-        this.promoter = SampleDepthPromoter.createFor(sourceType, targetType);
-        LOGGER.fine("Using sample depth promoting tile reader, from " + sourceType + " to "
-                + targetType);
-    }
-
-    public int getBitsPerSample() {
-        return targetType.getBitsPerSample();
-    }
-
-    public int getBytesPerTile() {
-        double pixelsPerTile = getPixelsPerTile();
-        double bitsPerSample = getBitsPerSample();
-        int bytesPerTile = (int) Math.floor((pixelsPerTile * bitsPerSample) / 8D);
-        return bytesPerTile;
-    }
-
-    public int getNumberOfBands() {
-        return nativeReader.getNumberOfBands();
-    }
-
-    public int getPixelsPerTile() {
-        return nativeReader.getPixelsPerTile();
-    }
-
-    public int getTileHeight() {
-        return nativeReader.getTileHeight();
-    }
-
-    public int getTileWidth() {
-        return nativeReader.getTileWidth();
-    }
-
-    public int getTilesHigh() {
-        return nativeReader.getTilesHigh();
-    }
-
-    public int getTilesWide() {
-        return nativeReader.getTilesWide();
-    }
-
-    public boolean hasNext() throws IOException {
-        return nativeReader.hasNext();
-    }
-
-    public TileInfo next() throws IOException {
-        final TileInfo tileInfo = nativeReader.next();
-        final byte[] nativeTileData = tileInfo.getTileData();
-        final byte[] tileData = new byte[getBytesPerTile()];
-        try {
-            final byte[] bitmaskData = tileInfo.getBitmaskData();
-            final boolean hasNoDataPixels = bitmaskData.length > 0;
-            final Long bandId = tileInfo.getBandId();
-
-            final int numPixelsRead = tileInfo.getNumPixelsRead();
-            if (numPixelsRead == 0) {
-                noData.setAll(bandId, tileData);
-            } else {
-                final int numSamples = getPixelsPerTile();
-                assert numPixelsRead == numSamples;
-
-                for (int sampleN = 0; sampleN < numSamples; sampleN++) {
-                    if (hasNoDataPixels && noData.isNoData(sampleN, bitmaskData)) {
-                        noData.setNoData(bandId, sampleN, tileData);
-                    } else {
-                        promoter.promote(sampleN, nativeTileData, tileData);
-                    }
-                }
-            }
-
-        } catch (RuntimeException e) {
-            dispose();
-            throw e;
-        }
-
-        TileInfo promotedTileInfo = new TileInfo(tileInfo.getBandId(), tileInfo.getColumnIndex(),
-                tileInfo.getRowIndex(), tileInfo.getNumPixelsRead(), tileData, tileInfo
-                        .getBitmaskData());
-        return promotedTileInfo;
-    }
-
-    /**
-     *
-     * @author Gabriel Roldan
-     */
-    private static abstract class SampleDepthPromoter {
-
-        public abstract void promote(int sampleN, byte[] nativeTileData, byte[] tileData);
-
-        public static SampleDepthPromoter createFor(final RasterCellType source,
-                final RasterCellType target) {
-
-            if (source == TYPE_1BIT && target == RasterCellType.TYPE_8BIT_U) {
-                return new OneBitToUchar();
-            } else if (source == TYPE_8BIT_U && target == TYPE_16BIT_U) {
-                return new UcharToUshort();
-            } else if (source == TYPE_16BIT_S && target == TYPE_32BIT_S) {
-                return new ShortToInt();
-            }
-
-            UnsupportedOperationException exception = new UnsupportedOperationException(
-                    "Promoting from " + source + " to " + target + " not yet implemented");
-            LOGGER.log(Level.WARNING, "Can't promote", exception);
-            throw exception;
-        }
-    }
-
-    private static final class UcharToUshort extends SampleDepthPromoter {
-
-        @Override
-        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
-            int pixArrayOffset = 2 * sampleN;
-            tileData[pixArrayOffset] = 0;
-            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 0) & 0xFF);
-        }
-    }
-
-    private static final class OneBitToUchar extends SampleDepthPromoter {
-
-        @Override
-        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
-            int pixArrayOffset = sampleN / 8;
-            int bit = sampleN % 8;
-            int _byte = nativeTileData[pixArrayOffset];
-            byte ucharvalue = (byte) ((_byte >> (7 - bit)) & 0x01);
-            tileData[sampleN] = ucharvalue;
-        }
-    }
-
-    private static final class ShortToInt extends SampleDepthPromoter {
-
-        @Override
-        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
-            int pixArrayOffset = 4 * sampleN;
-
-            tileData[pixArrayOffset] = 0;
-            tileData[pixArrayOffset + 1] = 0;
-            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 8) & 0xFF);
-            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 0) & 0xFF);
-        }
-    }
-
-    /**
-     * @see org.geotools.arcsde.gce.TileReader#dispose()
-     */
-    public void dispose() {
-        this.nativeReader.dispose();
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PyramidLevelInfo.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PyramidLevelInfo.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PyramidLevelInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,178 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.geom.Point2D;
-
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-/**
- * Represents one level in an ArcSDE pyramid. Holds information about a given pyramid level, like
- * resolution, x/y offsets, number of tiles high/wide, total pixel size and total envelope covered
- * by this level.
- *
- * @author sfarber
- *
- */
-final class PyramidLevelInfo {
-    private int pyramidLevel, xTiles, yTiles;
-
-    Point2D extentOffset;
-
-    Point imageOffset;
-
-    private double xRes, yRes;
-
-    private ReferencedEnvelope envelope;
-
-    public Dimension size;
-
-    /**
-     *
-     * @param level
-     *            the level index
-     * @param extent
-     *            the geographical extent the level covers
-     * @param imgOffset
-     *            the offset of the image at this level
-     * @param extOffset
-     *            the offset of the image extent at this level
-     * @param numTilesWide
-     * @param numTilesHigh
-     * @param levelSize
-     *            the size of the actual image inside the tiled pixel range
-     */
-    PyramidLevelInfo(int level, ReferencedEnvelope extent, Point imgOffset, Point2D extOffset,
-            int numTilesWide, int numTilesHigh, Dimension levelSize) {
-        this.pyramidLevel = level;
-        this.xRes = extent.getWidth() / levelSize.width;
-        this.yRes = extent.getHeight() / levelSize.height;
-        this.envelope = extent;
-        this.imageOffset = imgOffset;
-        this.extentOffset = extOffset;
-        this.xTiles = numTilesWide;
-        this.yTiles = numTilesHigh;
-        this.size = levelSize;
-    }
-
-    /**
-     * @return Which level in the pyramid this object represents
-     */
-    public int getLevel() {
-        return pyramidLevel;
-    }
-
-    /**
-     * @return The X and Y resolution in units/pixel for pixels at this level
-     */
-    public double getXRes() {
-        return xRes;
-    }
-
-    /**
-     * @return The X and Y resolution in units/pixel for pixels at this level
-     */
-    public double getYRes() {
-        return yRes;
-    }
-
-    /**
-     * @return DOCUMENT ME!!!
-     */
-    public int getXOffset() {
-        return imageOffset.x;
-    }
-
-    /**
-     * @return DOCUMENT ME!!!
-     */
-    public int getYOffset() {
-        return imageOffset.y;
-    }
-
-    /**
-     * @return The total number of tiles covering the width of this level
-     */
-    public int getNumTilesWide() {
-        return xTiles;
-    }
-
-    /**
-     * @return The total number of tiles covering the height of this level
-     */
-    public int getNumTilesHigh() {
-        return yTiles;
-    }
-
-    /**
-     * The envelope covering the image grid range inside fully tiled image at this pyramid level
-     *
-     * @return The geographical area covered by the {@link #getImageRange() grid range} of the
-     *         raster at this pyramid level
-     */
-    public ReferencedEnvelope getImageEnvelope() {
-        final double deltaX = extentOffset.getX();
-        final double deltaY = extentOffset.getY();
-        double minx = this.envelope.getMinX() - deltaX;
-        double miny = this.envelope.getMinY() - deltaY;
-        double maxx = minx + this.envelope.getWidth();
-        double maxy = miny + this.envelope.getHeight();
-
-        CoordinateReferenceSystem crs = this.envelope.getCoordinateReferenceSystem();
-        ReferencedEnvelope imageExtent = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
-
-        return imageExtent;
-    }
-
-    /**
-     * @return The total number of pixels in the image at this level as whole tiles
-     */
-    public Dimension getSize() {
-        return size;
-    }
-
-    /**
-     * The rectangle covering the actual raster data inside the tiled space
-     *
-     * @return
-     */
-    public Rectangle getImageRange() {
-        final int offsetX = getXOffset();
-        final int offsetY = getYOffset();
-
-        /*
-         * get the range of actual data pixels in this pyramid level in pixel space, offset and
-         * trailing no data pixels to fill up the tile space do not count
-         */
-        final Rectangle levelRange = new Rectangle(offsetX, offsetY, size.width, size.height);
-        return levelRange;
-    }
-
-    @Override
-    public String toString() {
-        return "[level: " + pyramidLevel + " size: " + size.width + "x" + size.height + "  xRes: "
-                + xRes + "  yRes: " + yRes + "  xOffset: " + getXOffset() + "  yOffset: "
-                + getYOffset() + "  extent: " + envelope.getMinX() + "," + envelope.getMinY() + " "
-                + envelope.getMaxX() + "," + envelope.getMaxY() + "  tilesWide: " + xTiles
-                + "  tilesHigh: " + yTiles + "]";
-    }
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterBandInfo.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterBandInfo.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterBandInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,175 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.geom.Point2D;
-import java.awt.geom.Point2D.Double;
-import java.awt.image.IndexColorModel;
-
-/**
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-final class RasterBandInfo {
-
-    long bandId;
-
-    String bandName;
-
-    int bandNumber;
-
-    /**
-     * the color map as it is on the database, except that we always create a color map with alpha
-     * channel regardless of whether the native on has alpha or not, to account for the no-data
-     * pixel to be a transparent one where appropriate
-     */
-    IndexColorModel nativeColorMap;
-
-    /**
-     * The color map as it is going to be used by this library. May differ from the native one
-     * either in the number of elements (when the native color map is not full and it has no
-     * transparent pixel to be used as no-data value), or in the pixel depth (when the native
-     * colormap is full, has no no-data pixel, and hence it needs to be promoted to a higher
-     * transfer type to make room for a no-data index)
-     */
-    IndexColorModel colorMap;
-
-    /**
-     * The band's no-data value.
-     */
-    Number noDataValue;
-
-    CompressionType compressionType;
-
-    RasterCellType cellType;
-
-    InterleaveType interleaveType;
-
-    InterpolationType interpolationType;
-
-    boolean hasStats;
-
-    Point2D.Double tileOrigin;
-
-    double statsMin;
-
-    double statsMax;
-
-    double statsMean;
-
-    double statsStdDev;
-
-    public RasterBandInfo() {
-        // do nothing
-    }
-
-    /**
-     * @return the ArcSDE identifier for the band
-     */
-    public long getBandId() {
-        return bandId;
-    }
-
-    public String getBandName() {
-        return bandName;
-    }
-
-    public int getBandNumber() {
-        return bandNumber;
-    }
-
-    public boolean isColorMapped() {
-        return nativeColorMap != null;
-    }
-
-    public CompressionType getCompressionType() {
-        return compressionType;
-    }
-
-    public RasterCellType getCellType() {
-        return cellType;
-    }
-
-    public InterleaveType getInterleaveType() {
-        return interleaveType;
-    }
-
-    public InterpolationType getInterpolationType() {
-        return interpolationType;
-    }
-
-    public boolean isHasStats() {
-        return hasStats;
-    }
-
-    public Double getTileOrigin() {
-        return tileOrigin;
-    }
-
-    public IndexColorModel getNativeColorMap() {
-        return nativeColorMap;
-    }
-
-    public IndexColorModel getColorMap() {
-        return colorMap;
-    }
-
-    public double getStatsMin() {
-        return statsMin;
-    }
-
-    public double getStatsMax() {
-        return statsMax;
-    }
-
-    public double getStatsMean() {
-        return statsMean;
-    }
-
-    public double getStatsStdDev() {
-        return statsStdDev;
-    }
-
-    public Number getNoDataValue() {
-        return noDataValue;
-    }
-
-    @SuppressWarnings("nls")
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(getBandName());
-        sb.append("[ id:").append(getBandId());
-        sb.append(", type:").append(getCellType());
-        sb.append(", samples: nodata=").append(getNoDataValue()).append(" min=").append(
-                getStatsMin()).append(" max=").append(getStatsMax()).append(" mean=").append(
-                getStatsMean()).append(" stddev=").append(getStatsStdDev());
-        /*
-         * sb.append(", tile origin: ").append((int) getTileOrigin().x).append(",").append( (int)
-         * getTileOrigin().y);
-         */
-        sb.append(", compression:").append(getCompressionType());
-        sb.append(", interpolation:").append(getInterpolationType());
-        sb.append(", Color Map: ").append(isColorMapped() ? "YES" : "NO");
-        return sb.toString();
-    }
-
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterCellType.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterCellType.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterCellType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,119 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.image.DataBuffer;
-import java.util.NoSuchElementException;
-
-import org.geotools.util.NumberRange;
-
-import com.esri.sde.sdk.client.SeRaster;
-
-/**
- * An enumeration that mirrors the different possible cell resolutions in Arcsde (ie, {@code
- * SeRaster#SE_PIXEL_TYPE_*})
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-enum RasterCellType {
-    TYPE_16BIT_S(16, DataBuffer.TYPE_SHORT, true, NumberRange.create(Short.MIN_VALUE,
-            Short.MAX_VALUE)), //
-    TYPE_16BIT_U(16, DataBuffer.TYPE_USHORT, false, NumberRange.create((int) 0, (int) 65535)), //
-    TYPE_1BIT(1, DataBuffer.TYPE_BYTE, false, NumberRange.create((byte) 0, (byte) 1)), //
-    TYPE_32BIT_REAL(32, DataBuffer.TYPE_FLOAT, true, NumberRange.create(Float.MIN_VALUE,
-            Float.MAX_VALUE)), //
-    TYPE_32BIT_S(32, DataBuffer.TYPE_INT, true, NumberRange.create(Integer.MIN_VALUE,
-            Integer.MAX_VALUE)), //
-    TYPE_32BIT_U(32, DataBuffer.TYPE_INT, false, NumberRange.create(0L, (long) Math.pow(2, 32) - 1)), //
-    TYPE_4BIT(4, DataBuffer.TYPE_BYTE, false, NumberRange.create((byte) 0,
-            (byte) Math.pow(2, 4) - 1)), //
-    TYPE_64BIT_REAL(64, DataBuffer.TYPE_DOUBLE, true, NumberRange.create(Double.MIN_VALUE,
-            Double.MAX_VALUE)), //
-    TYPE_8BIT_S(8, DataBuffer.TYPE_BYTE, true, NumberRange.create(Byte.MIN_VALUE, Byte.MAX_VALUE)), //
-    TYPE_8BIT_U(8, DataBuffer.TYPE_BYTE, false, NumberRange.create((int) 0, (int) 255));
-    static {
-        // Setting the se_pixel_type in a static initializer to avoid having them linked to the fake
-        // values in the dummy api
-        TYPE_16BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_16BIT_S);
-        TYPE_16BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_16BIT_U);
-        TYPE_1BIT.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_1BIT);
-        TYPE_32BIT_REAL.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_REAL);
-        TYPE_32BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_S);
-        TYPE_32BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_U);
-        TYPE_4BIT.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_4BIT);
-        TYPE_64BIT_REAL.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_64BIT_REAL);
-        TYPE_8BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_8BIT_S);
-        TYPE_8BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_8BIT_U);
-    }
-
-    private int typeId;
-
-    private final int bitsPerSample;
-
-    private final int dataBufferType;
-
-    private final boolean signed;
-
-    private final NumberRange<?> sampleValueRange;
-
-    private RasterCellType(final int bitsPerSample, final int dataBufferType, final boolean signed,
-            final NumberRange<?> sampleValueRange) {
-        this.bitsPerSample = bitsPerSample;
-        this.dataBufferType = dataBufferType;
-        this.signed = signed;
-        this.sampleValueRange = sampleValueRange;
-    }
-
-    private void setSdeTypeId(int typeId) {
-        this.typeId = typeId;
-    }
-
-    public int getSeRasterPixelType() {
-        return this.typeId;
-    }
-
-    public int getBitsPerSample() {
-        return bitsPerSample;
-    }
-
-    public int getDataBufferType() {
-        return dataBufferType;
-    }
-
-    public boolean isSigned() {
-        return signed;
-    }
-
-    public static RasterCellType valueOf(final int seRasterPixelType) {
-        for (RasterCellType type : RasterCellType.values()) {
-            if (type.getSeRasterPixelType() == seRasterPixelType) {
-                return type;
-            }
-        }
-        throw new NoSuchElementException("Raster pixel type " + seRasterPixelType
-                + " does not exist");
-    }
-
-    public NumberRange<?> getSampleValueRange() {
-        return sampleValueRange;
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterDatasetInfo.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterDatasetInfo.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterDatasetInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,503 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.image.IndexColorModel;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.imageio.ImageTypeSpecifier;
-
-import org.geotools.coverage.Category;
-import org.geotools.coverage.GridSampleDimension;
-import org.geotools.coverage.grid.GeneralGridEnvelope;
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.referencing.CRS;
-import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
-import org.geotools.referencing.operation.transform.LinearTransform1D;
-import org.geotools.resources.i18n.Vocabulary;
-import org.geotools.resources.i18n.VocabularyKeys;
-import org.geotools.util.NumberRange;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.datum.PixelInCell;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.NoninvertibleTransformException;
-import org.opengis.referencing.operation.TransformException;
-
-/**
- * Wraps metadata information for a raster dataset, whether it is composed of a single raster, or
- * it's raster catalog, and provides some conveinent methods to get to the raster metadata of it's
- * rasters and pyramid levels.
- * <p>
- * This is the single entry point to the metadata of a raster dataset. The associated classes
- * {@link RasterInfo} and {@link PyramidLevelInfo} are to be considered private to this class.
- * </p>
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/RasterDatasetInfo.java $
- */
-@SuppressWarnings( { "nls" })
-final class RasterDatasetInfo {
-
-    /** TRasterDatasetInfo the raster table we're pulling images from in this reader * */
-    private String rasterTable = null;
-
-    /**
-     * raster column names on this raster. If there's more than one raster column (is this
-     * possible?) then we just use the first one.
-     */
-    private String[] rasterColumns;
-
-    /** Array holding information on each level of the pyramid in this raster. * */
-    private List<RasterInfo> subRasterInfo;
-
-    /**
-     * The original (ie, pyramid level zero) envelope for the whole raster dataset
-     */
-    private GeneralEnvelope originalEnvelope;
-
-    private GeneralGridEnvelope originalGridRange;
-
-    private List<GridSampleDimension> gridSampleDimensions;
-
-    private final Map<Integer, ImageTypeSpecifier> renderedImageSpec = new HashMap<Integer, ImageTypeSpecifier>();
-
-    /**
-     * @param rasterTable
-     *            the rasterTable to set
-     */
-    void setRasterTable(String rasterTable) {
-        this.rasterTable = rasterTable;
-    }
-
-    /**
-     * @return the raster table name
-     */
-    public String getRasterTable() {
-        return rasterTable;
-    }
-
-    /**
-     * @param rasterColumns
-     *            the rasterColumns to set
-     */
-    void setRasterColumns(String[] rasterColumns) {
-        this.rasterColumns = rasterColumns;
-    }
-
-    /**
-     * @return the raster column names
-     */
-    public String[] getRasterColumns() {
-        return rasterColumns;
-    }
-
-    /**
-     * @param pyramidInfo
-     *            the pyramidInfo to set
-     */
-    void setPyramidInfo(List<RasterInfo> pyramidInfo) {
-        this.subRasterInfo = pyramidInfo;
-    }
-
-    public GridSampleDimension[] getGridSampleDimensions() {
-        if (gridSampleDimensions == null) {
-            synchronized (this) {
-                if (gridSampleDimensions == null) {
-                    gridSampleDimensions = buildSampleDimensions();
-                }
-            }
-        }
-        return gridSampleDimensions.toArray(new GridSampleDimension[getNumBands()]);
-    }
-
-    @SuppressWarnings("unchecked")
-    private List<GridSampleDimension> buildSampleDimensions() {
-
-        final int numBands = getNumBands();
-        List<GridSampleDimension> dimensions = new ArrayList<GridSampleDimension>(numBands);
-
-        final Color transparent = new Color(0, 0, 0, 0);
-
-        List<RasterBandInfo> bands = subRasterInfo.get(0).getBands();
-
-        for (RasterBandInfo band : bands) {
-            final int bandNumber = band.getBandNumber();
-            // use native cell type, in case no-data value has been computed to account for
-            // sample depth promotion, we want to category to keep being the native range for
-            // the values category
-            final RasterCellType targetCellType = getNativeCellType();
-            String bandName = band.getBandName();
-
-            final double statsMin = band.getStatsMin();
-            final double statsMax = band.getStatsMax();
-
-            NumberRange<?> sampleValueRange;
-            if (Double.isNaN(statsMin) || Double.isNaN(statsMax)) {
-                sampleValueRange = targetCellType.getSampleValueRange();
-            } else {
-                sampleValueRange = NumberRange.create(statsMin, statsMax);
-                Class elementClass = targetCellType.getSampleValueRange().getElementClass();
-                sampleValueRange = sampleValueRange.castTo(elementClass);
-            }
-
-            final Color[] colorRange = null;
-
-            final boolean geophysics = isGeoPhysics();
-
-            Category valuesCat = new Category("values", colorRange, sampleValueRange,
-                    LinearTransform1D.IDENTITY).geophysics(geophysics);
-
-            Category[] categories;
-            if (geophysics) {
-                double noDataValue = band.getNoDataValue().doubleValue();
-                // same as Category.NODATA but for the actual nodata value instead of hardcoded to
-                // zero
-                Category nodataCat = new Category(Vocabulary
-                        .formatInternational(VocabularyKeys.NODATA), transparent, noDataValue);
-                categories = new Category[] { valuesCat, nodataCat };
-            } else {
-                // do not build a nodata category. A nodata value that doesn't overlap the value
-                // range couldn't be determined
-                categories = new Category[] { valuesCat };
-            }
-            /*
-             * if (band.isHasStats()) { //can't do this, get an exception telling categories
-             * overlap.. so no real way to express the statistics, uh? Category catMin = new
-             * Category("Min", null, band.getStatsMin()).geophysics(true); Category catMax = new
-             * Category("Max", null, band.getStatsMin()).geophysics(true); Category catMean = new
-             * Category("Mean", null, band.getStatsMin()).geophysics(true); Category catStdDev = new
-             * Category("StdDev", null, band.getStatsMin()) .geophysics(true); categories = new
-             * Category[] { valuesCat, nodataCat, catMin, catMax, catMean, catStdDev }; } else {
-             * categories = new Category[] { valuesCat, nodataCat }; }
-             */
-
-            // .geophysics(false) because our sample model always corresponds to the packed view
-            // (whether it matches the underlying sample depth or we're promoting in order to make
-            // room for the nodata value).
-            GridSampleDimension sampleDim = new GridSampleDimension(bandName, categories, null)
-                    .geophysics(false);
-
-            dimensions.add(sampleDim);
-        }
-        return dimensions;
-    }
-
-    private boolean isGeoPhysics() {
-        if (isColorMapped()) {
-            return false;
-        }
-        return RasterUtils.isGeoPhysics(getNumBands(), getNativeCellType());
-    }
-
-    public int getNumBands() {
-        return subRasterInfo.get(0).getNumBands();
-    }
-
-    public int getImageWidth() {
-        final GeneralGridEnvelope originalGridRange = getOriginalGridRange();
-        final int width = originalGridRange.getSpan(0);
-        return width;
-    }
-
-    public int getImageHeight() {
-        final GeneralGridEnvelope originalGridRange = getOriginalGridRange();
-        final int height = originalGridRange.getSpan(1);
-        return height;
-    }
-
-    /**
-     * @return the coverageCrs
-     */
-    public CoordinateReferenceSystem getCoverageCrs() {
-        return subRasterInfo.get(0).getCoordinateReferenceSystem();
-    }
-
-    /**
-     * @return the originalGridRange for the whole raster dataset, based on the first raster in the
-     *         raster dataset
-     */
-    public GeneralGridEnvelope getOriginalGridRange() {
-        if (originalGridRange == null) {
-            final MathTransform modelToRaster;
-            try {
-                final MathTransform rasterToModel = getRasterToModel();
-                modelToRaster = rasterToModel.inverse();
-            } catch (NoninvertibleTransformException e) {
-                throw new IllegalStateException("Can't create transform from model to raster");
-            }
-
-            int minx = Integer.MAX_VALUE;
-            int miny = Integer.MAX_VALUE;
-            int maxx = Integer.MIN_VALUE;
-            int maxy = Integer.MIN_VALUE;
-
-            final int rasterCount = getNumRasters();
-            for (int rasterN = 0; rasterN < rasterCount; rasterN++) {
-                final GeneralEnvelope rasterEnvelope = getGridEnvelope(rasterN, 0);
-                GeneralEnvelope rasterGridRangeInDataSet;
-                try {
-                    rasterGridRangeInDataSet = CRS.transform(modelToRaster, rasterEnvelope);
-                } catch (NoninvertibleTransformException e) {
-                    throw new IllegalArgumentException(e);
-                } catch (TransformException e) {
-                    throw new IllegalArgumentException(e);
-                }
-
-                minx = Math.min(minx, (int) Math.floor(rasterGridRangeInDataSet.getMinimum(0)));
-                miny = Math.min(miny, (int) Math.floor(rasterGridRangeInDataSet.getMinimum(1)));
-                maxx = Math.max(maxx, (int) Math.ceil(rasterGridRangeInDataSet.getMaximum(0)));
-                maxy = Math.max(maxy, (int) Math.ceil(rasterGridRangeInDataSet.getMaximum(1)));
-            }
-            int width = maxx - minx;
-            int height = maxy - miny;
-            Rectangle range = new Rectangle(0, 0, width, height);
-            originalGridRange = new GeneralGridEnvelope(range, 2);
-        }
-        return originalGridRange;
-    }
-
-    public MathTransform getRasterToModel() {
-
-        GeneralEnvelope firstRasterEnvelope = getGridEnvelope(0, 0);
-        Rectangle firstRasterGridRange = getGridRange(0, 0);
-        GeneralGridEnvelope gridRange = new GeneralGridEnvelope(firstRasterGridRange, 2);
-
-        // create a raster to model transform, from this tile pixel space to the tile's geographic
-        // extent
-        GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(gridRange, firstRasterEnvelope);
-        geMapper.setPixelAnchor(PixelInCell.CELL_CORNER);
-
-        final MathTransform rasterToModel = geMapper.createTransform();
-        return rasterToModel;
-    }
-
-    /**
-     * @return the originalEnvelope
-     */
-    public GeneralEnvelope getOriginalEnvelope() {
-        if (originalEnvelope == null) {
-            GeneralEnvelope env = null;
-            for (RasterInfo raster : subRasterInfo) {
-                GeneralEnvelope rasterEnvelope = raster.getOriginalEnvelope();
-                if (env == null) {
-                    env = new GeneralEnvelope(rasterEnvelope);
-                } else {
-                    env.add(rasterEnvelope);
-                }
-            }
-            originalEnvelope = env;
-        }
-        return originalEnvelope;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("ArcSDE Raster: " + getRasterTable());
-        sb.append(", Raster columns: ").append(Arrays.asList(getRasterColumns()));
-        sb.append(", Num bands: ").append(getNumBands());
-        sb.append(", Dimension: ").append(getImageWidth()).append("x").append(getImageHeight());
-        sb.append(", Pixel type: ").append(getNativeCellType());
-        sb.append(", Has Color Map: ").append(isColorMapped());
-        for (int rasterIndex = 0; rasterIndex < getNumRasters(); rasterIndex++) {
-            RasterInfo raster = getRasterInfo(rasterIndex);
-            sb.append("\n ");
-            sb.append(raster.toString());
-        }
-        return sb.toString();
-    }
-
-    public int getNumRasters() {
-        return subRasterInfo.size();
-    }
-
-    public RasterBandInfo getBand(final int rasterIndex, final int bandIndex) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getBand(bandIndex);
-    }
-
-    public int getNumPyramidLevels(final int rasterIndex) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getNumLevels();
-    }
-
-    public GeneralEnvelope getGridEnvelope(final int rasterIndex, final int pyramidLevel) {
-        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
-        return new GeneralEnvelope(level.getImageEnvelope());
-    }
-
-    public Rectangle getGridRange(final int rasterIndex, final int pyramidLevel) {
-        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
-        Rectangle levelRange = level.getImageRange();
-        return levelRange;
-    }
-
-    public int getNumTilesWide(int rasterIndex, int pyramidLevel) {
-        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
-        return level.getNumTilesWide();
-    }
-
-    public int getNumTilesHigh(int rasterIndex, int pyramidLevel) {
-        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
-        return level.getNumTilesHigh();
-    }
-
-    public int getTileWidth(final long rasterId) {
-        return getTileDimension(rasterId).width;
-    }
-
-    public int getTileHeight(final long rasterId) {
-        return getTileDimension(rasterId).height;
-    }
-
-    public Dimension getTileDimension(final long rasterId) {
-        final int rasterIndex = getRasterIndex(rasterId);
-        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getTileDimension();
-    }
-
-    public Dimension getTileDimension(int rasterIndex) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getTileDimension();
-    }
-
-    private PyramidLevelInfo getLevel(int rasterIndex, int pyramidLevel) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        PyramidLevelInfo level = rasterInfo.getPyramidLevel(pyramidLevel);
-        return level;
-    }
-
-    private RasterInfo getRasterInfo(int rasterIndex) {
-        RasterInfo rasterInfo = subRasterInfo.get(rasterIndex);
-        return rasterInfo;
-    }
-
-    public ImageTypeSpecifier getRenderedImageSpec(final long rasterId) {
-        final int rasterIndex = getRasterIndex(rasterId);
-        return getRenderedImageSpec(rasterIndex);
-    }
-
-    public ImageTypeSpecifier getRenderedImageSpec(final int rasterIndex) {
-        if (!this.renderedImageSpec.containsKey(Integer.valueOf(rasterIndex))) {
-            synchronized (this) {
-                if (!this.renderedImageSpec.containsKey(Integer.valueOf(rasterIndex))) {
-                    ImageTypeSpecifier imageTypeSpecifier;
-                    imageTypeSpecifier = RasterUtils
-                            .createFullImageTypeSpecifier(this, rasterIndex);
-                    renderedImageSpec.put(Integer.valueOf(rasterIndex), imageTypeSpecifier);
-                }
-            }
-        }
-        return this.renderedImageSpec.get(Integer.valueOf(rasterIndex));
-    }
-
-    public IndexColorModel getColorMap(final int rasterIndex) {
-        final RasterBandInfo bandOne = getBand(rasterIndex, 0);
-        return bandOne.getColorMap();
-    }
-
-    boolean isColorMapped() {
-        RasterInfo rasterInfo = getRasterInfo(0);
-        return rasterInfo.isColorMapped();
-    }
-
-    public RasterCellType getNativeCellType() {
-        RasterInfo rasterInfo = getRasterInfo(0);
-        return rasterInfo.getNativeCellType();
-    }
-
-    public RasterCellType getTargetCellType(final int rasterIndex) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getTargetCellType();
-    }
-
-    public RasterCellType getTargetCellType(final long rasterId) {
-        final int rasterIndex = getRasterIndex(rasterId);
-        return getTargetCellType(rasterIndex);
-    }
-
-    public Long getRasterId(final int rasterIndex) {
-        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        return rasterInfo.getRasterId();
-    }
-
-    public int getOptimalPyramidLevel(final int rasterIndex, final OverviewPolicy policy,
-            final GeneralEnvelope requestedEnvelope, final Rectangle requestedDim) {
-
-        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-
-        double[] requestedRes = new double[2];
-        double reqSpanX = requestedEnvelope.getSpan(0);
-        double reqSpanY = requestedEnvelope.getSpan(1);
-        requestedRes[0] = reqSpanX / requestedDim.getWidth();
-        requestedRes[1] = reqSpanY / requestedDim.getHeight();
-
-        return rasterInfo.getOptimalPyramidLevel(policy, requestedRes);
-    }
-
-    public int getRasterIndex(Long rasterId) {
-        int index = -1;
-        for (RasterInfo p : subRasterInfo) {
-            index++;
-            if (rasterId.equals(p.getRasterId())) {
-                return index;
-            }
-        }
-        throw new IllegalArgumentException("rasterId: " + rasterId);
-    }
-
-    public double[] getResolution(int rasterN, int pyramidLevel) {
-        RasterInfo rasterInfo = getRasterInfo(rasterN);
-        double[] resolution = rasterInfo.getResolution(pyramidLevel);
-        return resolution;
-    }
-
-    public Point getTileOffset(final int rasterIndex, final int pyramidLevel) {
-        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
-        PyramidLevelInfo level = rasterInfo.getPyramidLevel(pyramidLevel);
-        return new Point(level.getXOffset(), level.getYOffset());
-    }
-
-    public Number getNoDataValue(final int rasterIndex, final int bandIndex) {
-        RasterBandInfo band = getBand(rasterIndex, bandIndex);
-        Number noDataValue = band.getNoDataValue();
-        return noDataValue;
-    }
-
-    /**
-     * @param rasterIndex
-     *            the raster for which bands to return the no data values
-     * @return the list of no data values, one per band for the raster at index {@code rasterIndex}
-     */
-    public List<Number> getNoDataValues(final int rasterIndex) {
-        return getRasterInfo(rasterIndex).getNoDataValues();
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInfo.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInfo.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,405 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.data.DataSourceException;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.referencing.CRS;
-import org.opengis.referencing.FactoryException;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import com.esri.sde.sdk.client.SDEPoint;
-import com.esri.sde.sdk.client.SeException;
-import com.esri.sde.sdk.client.SeExtent;
-import com.esri.sde.sdk.client.SeRasterAttr;
-
-/**
- * A RasterInfo gathers the metadata for a single raster in a raster dataset
- * <p>
- * Basically, it wraps the SeRasterAttr object and implements some convenience methods for doing
- * calculations with it.
- * </p>
- *
- * @author Saul Farber
- * @author Gabriel Roldan
- */
-final class RasterInfo {
-
-    /**
-     * Orders pyramid levels by their level index
-     */
-    private static final Comparator<PyramidLevelInfo> levelComparator = new Comparator<PyramidLevelInfo>() {
-        public int compare(PyramidLevelInfo p0, PyramidLevelInfo p1) {
-            return (p0.getLevel() - p1.getLevel());
-        }
-    };
-
-    ArrayList<PyramidLevelInfo> pyramidList;
-
-    private int tileWidth;
-
-    private int tileHeight;
-
-    private GeneralEnvelope originalEnvelope;
-
-    private ArrayList<RasterBandInfo> bands;
-
-    private CoordinateReferenceSystem crs;
-
-    private Long rasterId;
-
-    /**
-     * Creates an in-memory representation of an ArcSDE Raster Pyramid. Basically it wraps the
-     * supplide SeRasterAttr object and implements some convenience logic for extracting
-     * information/ doing calculations with it.
-     *
-     * @param rasterAttributes
-     *            the SeRasterAttr object for the raster of interest.
-     * @param crs
-     * @throws DataSourceException
-     */
-    public RasterInfo(final SeRasterAttr rasterAttributes, final CoordinateReferenceSystem crs)
-            throws DataSourceException {
-        this.crs = crs;
-        try {
-            this.rasterId = Long.valueOf(rasterAttributes.getRasterId().longValue());
-            // levels goes from 0 to N, maxLevel is the zero-based max index of levels
-            final int numLevels = rasterAttributes.getMaxLevel() + 1;
-
-            pyramidList = new ArrayList<PyramidLevelInfo>(numLevels);
-
-            tileWidth = rasterAttributes.getTileWidth();
-            tileHeight = rasterAttributes.getTileHeight();
-
-            for (int level = 0; level < numLevels; level++) {
-                if (level == 1 && rasterAttributes.skipLevelOne()) {
-                    continue;
-                }
-
-                /*
-                 * this extent corresponds to the actual image size inside the tiled grid. That is,
-                 * to getImageWidth/Height by level. The dimensions of this extent are correct, but
-                 * it needs to be shifted by SeRasterAttr.getExtentOffsetByLevel(level) the same way
-                 * the grid envelope does by SeRasterAttr.getImageOffsetByLevel(level)
-                 */
-                final SeExtent slExtent = rasterAttributes.getExtentByLevel(level);
-
-                final int levelWidth = rasterAttributes.getImageWidthByLevel(level);
-                final int levelHeight = rasterAttributes.getImageHeightByLevel(level);
-
-                Dimension levelImageSize = new Dimension(levelWidth, levelHeight);
-
-                Point imgOffset = new Point();
-                // extent offset equals imgOffset * pixel resolution (ie, if resx == 2 and offsetX =
-                // 10, extent offset x == 20)
-                Point2D extOffset = new Point2D.Double();
-                {
-                    SDEPoint imageOffset = rasterAttributes.getImageOffsetByLevel(level);
-                    int xOffset = (int) (imageOffset == null ? 0 : imageOffset.getX());
-                    int yOffset = (int) (imageOffset == null ? 0 : imageOffset.getY());
-                    imgOffset.setLocation(xOffset, yOffset);
-
-                    SDEPoint extentOffset = rasterAttributes.getExtentOffsetByLevel(level);
-                    double xOffsetExtent = extentOffset == null ? 0D : extentOffset.getX();
-                    double yOffsetExtent = extentOffset == null ? 0D : extentOffset.getY();
-                    extOffset.setLocation(xOffsetExtent, yOffsetExtent);
-                }
-
-                final int numTilesWide = rasterAttributes.getTilesPerRowByLevel(level);
-                final int numTileHigh = rasterAttributes.getTilesPerColByLevel(level);
-
-                ReferencedEnvelope levelExtent = new ReferencedEnvelope(slExtent.getMinX(),
-                        slExtent.getMaxX(), slExtent.getMinY(), slExtent.getMaxY(), crs);
-
-                addPyramidLevel(level, levelExtent, imgOffset, extOffset, numTilesWide,
-                        numTileHigh, levelImageSize);
-            }
-
-        } catch (SeException se) {
-            throw new DataSourceException(se);
-        }
-    }
-
-    public Long getRasterId() {
-        return rasterId;
-    }
-
-    public int getTileWidth() {
-        return tileWidth;
-    }
-
-    public int getTileHeight() {
-        return tileHeight;
-    }
-
-    /**
-     * Don't use this constructor. It only exists for unit testing purposes.
-     *
-     * @param tileWidth
-     *            DON'T USE
-     * @param tileHeight
-     *            DON'T USE
-     */
-    public RasterInfo(int tileWidth, int tileHeight) {
-        this.tileWidth = tileWidth;
-        this.tileHeight = tileHeight;
-        pyramidList = new ArrayList<PyramidLevelInfo>(4);
-    }
-
-    public Dimension getTileDimension() {
-        return new Dimension(tileWidth, tileHeight);
-    }
-
-    public PyramidLevelInfo getPyramidLevel(int level) {
-        return pyramidList.get(level);
-    }
-
-    public int getNumLevels() {
-        return pyramidList.size();
-    }
-
-    /**
-     * @param pyramidLevel
-     * @return resx, resy, scalefactor
-     */
-    double[] getResolution(final int pyramidLevel) {
-        final double highestRes = getPyramidLevel(0).getXRes();
-        PyramidLevelInfo level = getPyramidLevel(pyramidLevel);
-        double[] resolution = new double[3];
-        resolution[0] = level.getXRes();
-        resolution[1] = level.getYRes();
-        resolution[2] = level.getXRes() / highestRes;
-        return resolution;
-    }
-
-    /**
-     * <p>
-     * NOTE: logic stolen and adapted from {@code AbstractGridCoverage2DReader#getOverviewImage()}
-     * </p>
-     *
-     * @param policy
-     * @return
-     */
-    public int getOptimalPyramidLevel(final OverviewPolicy policy, final double[] requestedRes) {
-
-        int pyramidLevelChoice = 0;
-
-        // sort resolutions from smallest pixels (higher res) to biggest pixels (higher res)
-        // keeping a reference to the original image choice
-        final double[] highestRes = getResolution(0);
-
-        // Now search for the best matching resolution.
-        // Check also for the "perfect match"... unlikely in practice unless someone
-        // tunes the clients to request exactly the resolution embedded in
-        // the overviews, something a perf sensitive person might do in fact
-
-        // the requested resolutions
-        final double reqx = requestedRes[0];
-        final double reqy = requestedRes[1];
-
-        // requested scale factor for least reduced axis
-        final double requestedScaleFactorX = reqx / highestRes[0];
-        final double requestedScaleFactorY = reqy / highestRes[1];
-        final int leastReduceAxis = requestedScaleFactorX <= requestedScaleFactorY ? 0 : 1;
-        final double requestedScaleFactor = leastReduceAxis == 0 ? requestedScaleFactorX
-                : requestedScaleFactorY;
-
-        final int numLevels = getNumLevels();
-
-        // no pyramiding or are we looking for a resolution even higher than the native one?
-        if (0 == numLevels || requestedScaleFactor <= 1) {
-            pyramidLevelChoice = 0;
-        } else {
-            // are we looking for a resolution even lower than the smallest overview?
-            final double[] min = getResolution(numLevels - 1);
-            if (requestedScaleFactor >= min[2]) {
-                pyramidLevelChoice = numLevels - 1;
-            } else {
-                // Ok, so we know the overview is between min and max, skip the first
-                // and search for an overview with a resolution lower than the one requested,
-                // that one and the one from the previous step will bound the searched resolution
-                double[] prev = highestRes;
-                for (int levelN = 1; levelN < numLevels; levelN++) {
-                    final double[] curr = getResolution(levelN);
-                    // perfect match check
-                    if (curr[2] == requestedScaleFactor) {
-                        pyramidLevelChoice = levelN;
-                    } else {
-                        /*
-                         * middle check. The first part of the condition should be sufficient, but
-                         * there are cases where the x resolution is satisfied by the lowest
-                         * resolution, the y by the one before the lowest (so the aspect ratio of
-                         * the request is different than the one of the overviews), and we would end
-                         * up going out of the loop since not even the lowest can "top" the request
-                         * for one axis
-                         */
-                        if (curr[2] > requestedScaleFactor || levelN == numLevels - 1) {
-                            if (policy == OverviewPolicy.QUALITY) {
-                                pyramidLevelChoice = levelN - 1;
-                            } else if (policy == OverviewPolicy.SPEED) {
-                                return levelN;
-                            } else if (requestedScaleFactor - prev[2] < curr[2]
-                                    - requestedScaleFactor) {
-                                pyramidLevelChoice = levelN - 1;
-                            } else {
-                                pyramidLevelChoice = levelN;
-                            }
-                            break;
-                        }
-                        prev = curr;
-                    }
-                }
-            }
-        }
-        // fallback
-        return pyramidLevelChoice;
-    }
-
-    /**
-     * Don't use this method. It's only public for unit testing purposes.
-     *
-     * @param level
-     *            the zero-based level index for the new level
-     * @param extent
-     *            the geographical extent the level covers, may need to be offsetted by {@code
-     *            extOffset}
-     * @param imgOffset
-     *            the offset on the X and Y axes of the actual image inside the tile space for this
-     *            level
-     * @param extOffset
-     *            the offset on the X and Y axes of the actual image inside the tile space for this
-     *            level
-     * @param numTilesWide
-     *            the number of tiles that make up the level on the X axis
-     * @param numTilesHigh
-     *            the number of tiles that make up the level on the Y axis
-     * @param imageSize
-     *            the size of the actual image in pixels
-     */
-    void addPyramidLevel(int level, ReferencedEnvelope extent, Point imgOffset, Point2D extOffset,
-            int numTilesWide, int numTilesHigh, Dimension imageSize) {
-
-        PyramidLevelInfo pyramidLevel;
-        pyramidLevel = new PyramidLevelInfo(level, extent, imgOffset, extOffset, numTilesWide,
-                numTilesHigh, imageSize);
-
-        pyramidList.add(pyramidLevel);
-
-        Collections.sort(pyramidList, levelComparator);
-    }
-
-    void setOriginalEnvelope(GeneralEnvelope originalEnvelope) {
-        this.originalEnvelope = originalEnvelope;
-    }
-
-    public GeneralEnvelope getOriginalEnvelope() {
-        return originalEnvelope;
-    }
-
-    void setBands(List<RasterBandInfo> bands) {
-        this.bands = new ArrayList<RasterBandInfo>(bands);
-    }
-
-    public List<RasterBandInfo> getBands() {
-        return new ArrayList<RasterBandInfo>(bands);
-    }
-
-    public int getNumBands() {
-        return bands.size();
-    }
-
-    public RasterBandInfo getBand(final int index) {
-        return bands.get(index);
-    }
-
-    public CoordinateReferenceSystem getCoordinateReferenceSystem() {
-        return crs;
-    }
-
-    public RasterCellType getTargetCellType() {
-//        if (isColorMapped()) {
-//            // color map is already promoted if needed
-//            return getNativeCellType();
-//        }
-        List<Number> noDataValues = getNoDataValues();
-        RasterCellType nativeCellType = getNativeCellType();
-        RasterCellType targetCellType = RasterUtils.determineTargetCellType(nativeCellType,
-                noDataValues);
-        return targetCellType;
-    }
-
-    public boolean isColorMapped() {
-        return getBand(0).isColorMapped();
-    }
-
-    public RasterCellType getNativeCellType() {
-        return getBand(0).getCellType();
-    }
-
-    public List<Number> getNoDataValues() {
-        final List<Number> noDataValues = new ArrayList<Number>();
-        for (RasterBandInfo band : getBands()) {
-            Number noDataValue = band.getNoDataValue();
-            noDataValues.add(noDataValue);
-        }
-        return noDataValues;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
-        sb.append("[Id: ").append(getRasterId());
-        String srs = null;
-        try {
-            srs = CRS.lookupIdentifier(getCoordinateReferenceSystem(), false);
-        } catch (FactoryException e) {
-            e.printStackTrace();
-        }
-        sb.append(", bands: ").append(getNumBands());
-        sb.append(", levels: ").append(getNumLevels());
-        sb.append(", tile size: ").append(getTileWidth()).append("x").append(getTileHeight());
-        sb.append(", crs: ").append(srs == null ? getCoordinateReferenceSystem().toWKT() : srs);
-        GeneralEnvelope env = getOriginalEnvelope();
-        sb.append(", Envelope: ").append(env.getMinimum(0)).append(",").append(env.getMinimum(1))
-                .append(" ").append(env.getMaximum(0)).append(",").append(env.getMaximum(1));
-
-        sb.append("]\n Bands[");
-        for (RasterBandInfo band : getBands()) {
-            sb.append("\n\t");
-            sb.append(band.toString());
-        }
-        sb.append("\n ]");
-        sb.append("\n Pyramid[");
-        for (int l = 0; l < getNumLevels(); l++) {
-            sb.append("\n\t").append(getPyramidLevel(l).toString());
-        }
-        sb.append("\n ]");
-        return sb.toString();
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInputStream.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInputStream.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInputStream.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,175 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.imageio.stream.ImageInputStream;
-
-import org.geotools.arcsde.gce.TileReader.TileInfo;
-
-/**
- * An {@link ImageInputStream} that reads ArcSDE raster tiles in a band interleaved order.
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/ArcSDETiledImageInputStream.java $
- */
-final class RasterInputStream extends InputStream {
-
-    private final TileReader tileReader;
-
-    private final int tileDataLength;
-
-    private byte[] currTileData;
-
-    private int currTileDataIndex;
-
-    private final int length;
-
-    private long streamPos;
-
-    ByteArrayInputStream in;
-    byte[] buf;
-
-    public RasterInputStream(final TileReader tileReader) {
-        super();
-        this.tileReader = tileReader;
-        final int bytesPerTile = tileReader.getBytesPerTile();
-        this.tileDataLength = bytesPerTile;
-        this.currTileData = new byte[bytesPerTile];
-        // force load at the first read invocation
-        this.currTileDataIndex = tileDataLength;
-
-        final int tilesWide = tileReader.getTilesWide();
-        final int tilesHigh = tileReader.getTilesHigh();
-        final int numberOfBands = tileReader.getNumberOfBands();
-
-        length = bytesPerTile * tilesWide * tilesHigh * numberOfBands;
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            while (tileReader.hasNext()) {
-                TileInfo next = tileReader.next();
-                out.write(next.getTileData());
-            }
-            out.flush();
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-
-        buf = out.toByteArray();
-        this.in = new ByteArrayInputStream(buf);
-
-        if (length != buf.length) {
-            throw new IllegalStateException(length + " != " + buf.length);
-        }
-    }
-
-    @Override
-    public int read() throws IOException {
-        return in.read();
-        // final byte[] data = getTileData();
-        // if (data == null) {
-        // return -1;
-        // }
-        // byte b = data[currTileDataIndex];
-        // ++currTileDataIndex;
-        // return b;
-    }
-
-    @Override
-    public int read(byte[] buff, int off, int len) throws IOException {
-        return in.read(buff, off, len);
-        // // System.err.println("read " + len + ", pos = " + streamPos + ", length = " + length);
-        // final byte[] data = getTileData();
-        // if (data == null) {
-        // return -1;
-        // }
-        // final int available = data.length - currTileDataIndex;
-        // final int count = Math.min(available, len);
-        // System.arraycopy(data, currTileDataIndex, buff, off, count);
-        // currTileDataIndex += count;
-        // streamPos += count;
-        // if (streamPos == length) {
-        // close();
-        // }
-        // return count;
-    }
-
-    /**
-     * Fetches a tile from the {@code tileReader} if necessary and returns the current tile data.
-     * <p>
-     * It is needed to fetch a new tile if {@link #currTileDataIndex} indicates all the current tile
-     * data has been already read. If so, {@code currTileDataIndex} is reset to 0. The {@code read}
-     * operations are responsible of incrementing {@code currTileDataIndex} depending on how many
-     * bytes have been consumed from the tile data returned by this method.
-     * </p>
-     *
-     * @return {@code null} if there's no more tiles to fetch, the current tile data otherwise
-     * @throws IOException
-     */
-    private byte[] getTileData() throws IOException {
-        if (currTileDataIndex == tileDataLength) {
-            if (!tileReader.hasNext()) {
-                return null;
-            }
-
-            currTileDataIndex = 0;
-            TileInfo tileInfo = tileReader.next();
-            currTileData = tileInfo.getTileData();
-        }
-        return currTileData;
-    }
-
-    @Override
-    public void close() throws IOException {
-        tileReader.dispose();
-    }
-
-    @Override
-    public int available() throws IOException {
-        return in.available();
-        // return tileDataLength - currTileDataIndex;
-    }
-
-    @Override
-    public synchronized void mark(int readlimit) {
-        in.mark(readlimit);
-        // System.err.println("mark at " + readlimit);
-    }
-
-    @Override
-    public boolean markSupported() {
-        return in.markSupported();
-        // return false;
-    }
-
-    @Override
-    public long skip(long n) throws IOException {
-        return in.skip(n);
-        // return super.skip(n);
-    }
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterQueryInfo.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterQueryInfo.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterQueryInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,216 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Rectangle;
-import java.awt.image.RenderedImage;
-import java.util.logging.Logger;
-
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.util.logging.Logging;
-
-/**
- * Captures information about a query for a single raster in a raster dataset.
- *
- * @author Gabriel Roldan
- * @version $Id$
- * @since 2.5.6
- * @see RasterUtils#findMatchingRasters
- * @see RasterUtils#fitRequestToRaster
- */
-final class RasterQueryInfo {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private GeneralEnvelope requestedEnvelope;
-
-    private Rectangle requestedDim;
-
-    private int pyramidLevel;
-
-    /**
-     * The two-dimensional range of tile indices whose envelope intersect the requested extent. Will
-     * have negative width and height if none of the tiles do.
-     */
-    private Rectangle matchingTiles;
-
-    private GeneralEnvelope resultEnvelope;
-
-    private Rectangle resultDimension;
-
-    private Long rasterId;
-
-    private Rectangle mosaicLocation;
-
-    private RenderedImage resultImage;
-
-    private Rectangle tiledImageSize;
-
-    private double[] resolution;
-
-    private int rasterIndex;
-
-    /**
-     * The full tile range for the matching pyramid level
-     */
-    private Rectangle levelTileRange;
-
-    public RasterQueryInfo() {
-        setResultDimensionInsideTiledImage(new Rectangle(0, 0, 0, 0));
-        setMatchingTiles(new Rectangle(0, 0, 0, 0));
-        setResultEnvelope(null);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder s = new StringBuilder("[Raster query info:");
-        s.append("\n\tRaster ID            : ").append(getRasterId());
-        s.append("\n\tPyramid level        : ").append(getPyramidLevel());
-        s.append("\n\tResolution           : ").append(
-                getResolution()[0] + "," + getResolution()[1]);
-        s.append("\n\tRequested envelope   : ").append(getRequestedEnvelope());
-        s.append("\n\tRequested dimension  : ").append(getRequestedDim());
-        Rectangle mt = getMatchingTiles();
-        Rectangle ltr = getLevelTileRange();
-        String matching = "x=" + mt.x + "-" + (mt.x + mt.width - 1) + ", y=" + mt.y + "-"
-                + (mt.y + mt.height - 1);
-        String level = "x=" + ltr.x + "-" + (ltr.width - 1) + ", y=" + ltr.y + "-"
-                + (ltr.height - 1);
-        s.append("\n\tMatching tiles       : ").append(matching).append(" out of ").append(level);
-        s.append("\n\tTiled image size     : ").append(getTiledImageSize());
-        s.append("\n\tResult dimension     : ").append(getResultDimensionInsideTiledImage());
-        s.append("\n\tMosaiced dimension   : ").append(getMosaicLocation());
-        s.append("\n\tResult envelope      : ").append(getResultEnvelope());
-        s.append("\n]");
-        return s.toString();
-    }
-
-    /**
-     * @return the rasterId (as in SeRaster.getId()) for the raster in the raster dataset this query
-     *         works upon
-     */
-    public Long getRasterId() {
-        return rasterId;
-    }
-
-    public GeneralEnvelope getRequestedEnvelope() {
-        return requestedEnvelope;
-    }
-
-    public Rectangle getRequestedDim() {
-        return requestedDim;
-    }
-
-    public int getPyramidLevel() {
-        return pyramidLevel;
-    }
-
-    public Rectangle getMatchingTiles() {
-        return matchingTiles;
-    }
-
-    public GeneralEnvelope getResultEnvelope() {
-        return resultEnvelope;
-    }
-
-    public Rectangle getResultDimensionInsideTiledImage() {
-        return resultDimension;
-    }
-
-    void setRasterId(Long rasterId) {
-        this.rasterId = rasterId;
-    }
-
-    void setPyramidLevel(int pyramidLevel) {
-        this.pyramidLevel = pyramidLevel;
-    }
-
-    void setRequestedEnvelope(GeneralEnvelope requestedEnvelope) {
-        this.requestedEnvelope = requestedEnvelope;
-    }
-
-    void setRequestedDim(Rectangle requestedDim) {
-        this.requestedDim = requestedDim;
-    }
-
-    void setResultEnvelope(GeneralEnvelope resultEnvelope) {
-        this.resultEnvelope = resultEnvelope;
-    }
-
-    void setMatchingTiles(Rectangle matchingTiles) {
-        this.matchingTiles = matchingTiles;
-    }
-
-    void setResultDimensionInsideTiledImage(Rectangle resultDimension) {
-        this.resultDimension = resultDimension;
-    }
-
-    void setMosaicLocation(Rectangle rasterMosaicLocation) {
-        this.mosaicLocation = rasterMosaicLocation;
-    }
-
-    public Rectangle getMosaicLocation() {
-        return mosaicLocation;
-    }
-
-    public void setResultImage(RenderedImage rasterImage) {
-        this.resultImage = rasterImage;
-        if (rasterImage.getWidth() != tiledImageSize.width
-                || rasterImage.getHeight() != tiledImageSize.height) {
-            LOGGER.warning("Result image and expected dimensions don't match: image="
-                    + resultImage.getWidth() + "x" + resultImage.getHeight() + ", expected="
-                    + tiledImageSize.width + "x" + tiledImageSize.height);
-        }
-    }
-
-    public RenderedImage getResultImage() {
-        return resultImage;
-    }
-
-    void setTiledImageSize(Rectangle tiledImageSize) {
-        this.tiledImageSize = tiledImageSize;
-    }
-
-    public Rectangle getTiledImageSize() {
-        return tiledImageSize;
-    }
-
-    void setResolution(double[] resolution) {
-        this.resolution = resolution;
-    }
-
-    public double[] getResolution() {
-        return resolution == null ? new double[] { -1, -1 } : resolution;
-    }
-
-    void setRasterIndex(int rasterN) {
-        this.rasterIndex = rasterN;
-    }
-
-    public int getRasterIndex() {
-        return rasterIndex;
-    }
-
-    void setLevelTileRange(Rectangle levelTileRange) {
-        this.levelTileRange = levelTileRange;
-    }
-
-    public Rectangle getLevelTileRange() {
-        return levelTileRange;
-    }
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterReaderFactory.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterReaderFactory.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterReaderFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,56 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- */
-package org.geotools.arcsde.gce;
-
-import java.io.IOException;
-
-import org.geotools.arcsde.session.ISessionPool;
-
-/**
- *
- * @author Gabriel Roldan
- *
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/RasterReaderFactory.java $
- * @version $Id$
- * @since 2.5.7
- */
-public class RasterReaderFactory {
-
-    private final ISessionPool sessionPool;
-
-    public RasterReaderFactory(final ISessionPool connectionPool) {
-        this.sessionPool = connectionPool;
-    }
-
-    /**
-     * Creates a {@link TiledRasterReader} that's able to read one or more raster for the given
-     * {@link RasterDatasetInfo}, depending on if {@code rasterInfo} represents a single raster or a
-     * raster catalog.
-     *
-     * @param rasterInfo
-     * @return
-     * @throws IOException
-     */
-    public TiledRasterReader create(final RasterDatasetInfo rasterInfo) throws IOException {
-        TiledRasterReader rasterReader = new DefaultTiledRasterReader(sessionPool, rasterInfo);
-
-        return rasterReader;
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterUtils.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterUtils.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterUtils.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,998 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_1BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_4BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_64BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Transparency;
-import java.awt.color.ColorSpace;
-import java.awt.image.BandedSampleModel;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.IndexColorModel;
-import java.awt.image.SampleModel;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageTypeSpecifier;
-
-import org.geotools.coverage.GridSampleDimension;
-import org.geotools.coverage.grid.GeneralGridEnvelope;
-import org.geotools.coverage.grid.GridGeometry2D;
-import org.geotools.coverage.grid.io.AbstractGridFormat;
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.referencing.CRS;
-import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
-import org.geotools.resources.image.ColorUtilities;
-import org.geotools.resources.image.ComponentColorModelJAI;
-import org.geotools.util.NumberRange;
-import org.geotools.util.logging.Logging;
-import org.opengis.geometry.Envelope;
-import org.opengis.parameter.GeneralParameterValue;
-import org.opengis.parameter.ParameterNotFoundException;
-import org.opengis.parameter.ParameterValue;
-import org.opengis.referencing.FactoryException;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.datum.PixelInCell;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.NoninvertibleTransformException;
-import org.opengis.referencing.operation.TransformException;
-
-import com.sun.imageio.plugins.common.BogusColorSpace;
-
-/**
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL$
- */
-@SuppressWarnings( { "nls" })
-class RasterUtils {
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private RasterUtils() {
-        // do nothing
-    }
-
-    public static ReferencedEnvelope toReferencedEnvelope(GeneralEnvelope envelope) {
-        double minx = envelope.getMinimum(0);
-        double maxx = envelope.getMaximum(0);
-        double miny = envelope.getMinimum(1);
-        double maxy = envelope.getMaximum(1);
-        CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
-
-        ReferencedEnvelope refEnv = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
-        return refEnv;
-    }
-
-    public static ReferencedEnvelope toNativeCrs(final GeneralEnvelope requestedEnvelope,
-            final CoordinateReferenceSystem nativeCRS) throws IllegalArgumentException {
-
-        ReferencedEnvelope reqEnv = toReferencedEnvelope(requestedEnvelope);
-
-        if (!CRS.equalsIgnoreMetadata(nativeCRS, reqEnv.getCoordinateReferenceSystem())) {
-            // we're being reprojected. We'll need to reproject reqEnv into
-            // our native coordsys
-            try {
-                // ReferencedEnvelope origReqEnv = reqEnv;
-                reqEnv = reqEnv.transform(nativeCRS, true);
-            } catch (FactoryException fe) {
-                // unable to reproject?
-                throw new IllegalArgumentException("Unable to find a reprojection from requested "
-                        + "coordsys to native coordsys for this request", fe);
-            } catch (TransformException te) {
-                throw new IllegalArgumentException("Unable to perform reprojection from requested "
-                        + "coordsys to native coordsys for this request", te);
-            }
-        }
-        return reqEnv;
-    }
-
-    public static MathTransform createRasterToModel(final Rectangle levelGridRange,
-            final GeneralEnvelope levelEnvelope) {
-        // create a raster to model transform, from this tile pixel space to the tile's geographic
-        // extent
-        GeneralGridEnvelope gridRange = new GeneralGridEnvelope(levelGridRange, 2);
-        GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(gridRange, levelEnvelope);
-        geMapper.setPixelAnchor(PixelInCell.CELL_CORNER);
-
-        final MathTransform rasterToModel = geMapper.createTransform();
-        return rasterToModel;
-    }
-
-    private static Rectangle getResultDimensionForTileRange(final Rectangle tiledImageGridRange,
-            final Rectangle matchingLevelRange) {
-
-        int minx = Math.max(tiledImageGridRange.x, matchingLevelRange.x);
-        int miny = Math.max(tiledImageGridRange.y, matchingLevelRange.y);
-        int maxx = (int) Math.min(tiledImageGridRange.getMaxX(), matchingLevelRange.getMaxX());
-        int maxy = (int) Math.min(tiledImageGridRange.getMaxY(), matchingLevelRange.getMaxY());
-
-        return new Rectangle(minx, miny, maxx - minx, maxy - miny);
-    }
-
-    /**
-     * Returns the rectangle specifying the matching tiles for a given pyramid level and rectangle
-     * specifying the overlapping area to request in the level's pixel space.
-     *
-     * @param pixelRange
-     * @param tilesHigh
-     * @param tilesWide
-     * @param tileSize
-     * @param numTilesHigh
-     * @param numTilesWide
-     *
-     * @param pixelRange
-     * @param level
-     *
-     * @return a rectangle holding the coordinates in tile space that fully covers the requested
-     *         pixel range for the given pyramid level, or a negative area rectangle
-     */
-    private static Rectangle findMatchingTiles(final Dimension tileSize, int numTilesWide,
-            int numTilesHigh, final Rectangle pixelRange) {
-
-        final int minPixelX = pixelRange.x;
-        final int minPixelY = pixelRange.y;
-
-        // TODO: WARNING, we're not considering the possible x/y offsets on the level range for the
-        // given pyramid level here!
-
-        int minTileX = (int) Math.floor(minPixelX / tileSize.getWidth());
-        int minTileY = (int) Math.floor(minPixelY / tileSize.getHeight());
-
-        int numTilesX = (int) Math.ceil(pixelRange.getWidth() / tileSize.getWidth());
-        int numTilesY = (int) Math.ceil(pixelRange.getHeight() / tileSize.getHeight());
-
-        int maxTiledX = (minTileX + numTilesX) * tileSize.width;
-        int maxTiledY = (minTileY + numTilesY) * tileSize.height;
-
-        if (maxTiledX < pixelRange.getMaxX() && (minTileX + numTilesX) < numTilesWide) {
-            numTilesX++;
-        }
-
-        if (maxTiledY < pixelRange.getMaxY() && (minTileY + numTilesY) < numTilesHigh) {
-            numTilesY++;
-        }
-
-        Rectangle matchingTiles = new Rectangle(minTileX, minTileY, numTilesX, numTilesY);
-        return matchingTiles;
-    }
-
-    private static Rectangle getTargetGridRange(final MathTransform modelToRaster,
-            final Envelope requestedEnvelope) {
-        Rectangle levelOverlappingPixels;
-        int levelMinPixelX;
-        int levelMaxPixelX;
-        int levelMinPixelY;
-        int levelMaxPixelY;
-        {
-            // use a model to raster transform to find out which pixel range at the specified level
-            // better match the requested extent
-            GeneralEnvelope requestedPixels;
-            try {
-                requestedPixels = CRS.transform(modelToRaster, requestedEnvelope);
-            } catch (NoninvertibleTransformException e) {
-                throw new IllegalArgumentException(e);
-            } catch (TransformException e) {
-                throw new IllegalArgumentException(e);
-            }
-
-            levelMinPixelX = (int) Math.floor(requestedPixels.getMinimum(0));
-            levelMaxPixelX = (int) Math.floor(requestedPixels.getMaximum(0));
-
-            levelMinPixelY = (int) Math.ceil(requestedPixels.getMinimum(1));
-            levelMaxPixelY = (int) Math.ceil(requestedPixels.getMaximum(1));
-
-            final int width = levelMaxPixelX - levelMinPixelX;
-            final int height = levelMaxPixelY - levelMinPixelY;
-            levelOverlappingPixels = new Rectangle(levelMinPixelX, levelMinPixelY, width, height);
-        }
-        return levelOverlappingPixels;
-    }
-
-    /**
-     * Creates an IndexColorModel out of a DataBuffer obtained from an ArcSDE's raster color map.
-     *
-     * @param colorMapData
-     * @return
-     */
-    public static IndexColorModel sdeColorMapToJavaColorModel(final DataBuffer colorMapData,
-            final int bitsPerSample) {
-        if (colorMapData == null) {
-            throw new NullPointerException("colorMapData");
-        }
-
-        if (colorMapData.getNumBanks() < 3 || colorMapData.getNumBanks() > 4) {
-            throw new IllegalArgumentException("colorMapData shall have 3 or 4 banks: "
-                    + colorMapData.getNumBanks());
-        }
-
-        if (bitsPerSample != 8 && bitsPerSample != 16) {
-            throw new IllegalAccessError("bits per sample shall be either 8 or 16. Got "
-                    + bitsPerSample);
-        }
-
-        final int numBanks = colorMapData.getNumBanks();
-        final int mapSize = colorMapData.getSize();
-
-        byte[] r = new byte[mapSize];
-        byte[] g = new byte[mapSize];
-        byte[] b = new byte[mapSize];
-        byte[] a = new byte[mapSize];
-
-        for (int i = 0; i < mapSize; i++) {
-            r[i] = (byte) (colorMapData.getElem(0, i) & 0xFF);
-            g[i] = (byte) (colorMapData.getElem(1, i) & 0xFF);
-            b[i] = (byte) (colorMapData.getElem(2, i) & 0xFF);
-            a[i] = (byte) ((numBanks == 3 ? 255 : colorMapData.getElem(3, i)) & 0xFF);
-        }
-
-        IndexColorModel colorModel = new IndexColorModel(bitsPerSample, mapSize, r, g, b, a);
-
-        return colorModel;
-    }
-
-    public static ImageTypeSpecifier createFullImageTypeSpecifier(
-            final RasterDatasetInfo rasterInfo, final int rasterIndex) {
-
-        final int numberOfBands = rasterInfo.getNumBands();
-        final RasterCellType nativePixelType = rasterInfo.getNativeCellType();
-        final RasterCellType pixelType = rasterInfo.getTargetCellType(rasterIndex);
-
-        // Prepare temporary colorModel and sample model, needed to build the final
-        // ArcSDEPyramidLevel level;
-        int sampleImageWidth = 1;// rasterInfo.getImageWidth();
-        int sampleImageHeight = 1;// rasterInfo.getImageHeight();
-
-        final ImageTypeSpecifier its;
-        // treat special cases...
-        final int bitsPerSample = pixelType.getBitsPerSample();
-        final int dataType = pixelType.getDataBufferType();
-        final boolean hasColorMap = rasterInfo.isColorMapped();
-
-        if (hasColorMap) {
-            // special case, a single band colormapped image
-            IndexColorModel colorMap = rasterInfo.getColorMap(rasterIndex);
-            its = createColorMappedImageSpec(colorMap, sampleImageWidth, sampleImageHeight);
-
-        } else if (nativePixelType == TYPE_1BIT && numberOfBands == 1) {
-            byte noDataValue = rasterInfo.getNoDataValue(rasterIndex, 0).byteValue();
-            // special case, a single band 1-bit
-            its = createOneBitColorMappedImageSpec(sampleImageWidth, sampleImageHeight, noDataValue);
-
-        } else if (nativePixelType == TYPE_4BIT && numberOfBands == 1) {
-            byte noDataValue = rasterInfo.getNoDataValue(rasterIndex, 0).byteValue();
-            // special case, a single band 4-bit
-            its = createFourBitColorMappedImageSpec(sampleImageWidth, sampleImageHeight,
-                    noDataValue);
-        } else if (numberOfBands == 1) {
-            // special case, a single band grayscale image, no matter the pixel depth
-            its = createGrayscaleImageSpec(sampleImageWidth, sampleImageHeight, dataType,
-                    bitsPerSample);
-
-        } else if (numberOfBands == 3 && pixelType == TYPE_8BIT_U) {
-            // special case, an optimizable RGB image
-            its = createRGBImageSpec(sampleImageWidth, sampleImageHeight, dataType);
-
-        } else if (numberOfBands == 4 && pixelType == TYPE_8BIT_U) {
-            // special case, an optimizable RGBA image
-            its = createRGBAImageSpec(sampleImageWidth, sampleImageHeight, dataType);
-
-        } else {
-            /*
-             * not an special case, go for a more generic sample model, potentially slower than the
-             * special case ones, but that'll work anyway
-             */
-
-            final ColorModel colorModel;
-            final SampleModel sampleModel;
-            {
-                final ColorSpace colorSpace;
-                colorSpace = new BogusColorSpace(numberOfBands);
-                int[] numBits = new int[numberOfBands];
-                for (int i = 0; i < numberOfBands; i++) {
-                    numBits[i] = bitsPerSample;
-                }
-                colorModel = new ComponentColorModelJAI(colorSpace, numBits, false, false,
-                        Transparency.OPAQUE, dataType);
-            }
-            {
-                int[] bankIndices = new int[numberOfBands];
-                int[] bandOffsets = new int[numberOfBands];
-                // int bandOffset = (tileWidth * tileHeight * pixelType.getBitsPerSample()) / 8;
-                for (int i = 0; i < numberOfBands; i++) {
-                    bankIndices[i] = i;
-                    bandOffsets[i] = 0;// (i * bandOffset);
-                }
-                sampleModel = new BandedSampleModel(dataType, sampleImageWidth, sampleImageHeight,
-                        sampleImageWidth, bankIndices, bandOffsets);
-            }
-            its = new ImageTypeSpecifier(colorModel, sampleModel);
-        }
-
-        return its;
-    }
-
-    private static ImageTypeSpecifier createFourBitColorMappedImageSpec(int sampleImageWidth,
-            int sampleImageHeight, byte noDataValue) {
-
-        int maxValue = (int) TYPE_4BIT.getSampleValueRange().getMaximum();
-
-        int mapSize = noDataValue > maxValue ? noDataValue : maxValue + 1;
-
-        int[] cmap = new int[mapSize];
-        ColorUtilities.expand(new Color[] { Color.BLACK, Color.WHITE }, cmap, 0, maxValue);
-
-        for (int i = maxValue; i < mapSize; i++) {
-            cmap[i] = ColorUtilities.getIntFromColor(0, 0, 0, 0);
-        }
-
-        int transparentPixel = noDataValue;
-        IndexColorModel colorModel = new IndexColorModel(8, mapSize, cmap, 0, true,
-                transparentPixel, DataBuffer.TYPE_BYTE);
-
-        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
-                sampleImageHeight);
-        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createOneBitColorMappedImageSpec(int sampleImageWidth,
-            int sampleImageHeight, byte noDataValue) {
-
-        assert noDataValue == 2;
-
-        final int FALSE = ColorUtilities.getIntFromColor(255, 255, 255, 255);
-        final int TRUE = ColorUtilities.getIntFromColor(255, 0, 0, 255);
-        final int NODATA = ColorUtilities.getIntFromColor(0, 255, 0, 255);
-
-        final int mapSize = 3;
-        int[] cmap = new int[mapSize];
-        cmap[0] = FALSE;
-        cmap[1] = TRUE;
-        cmap[2] = NODATA;
-
-        int transparentPixel = noDataValue;
-        IndexColorModel colorModel = new IndexColorModel(8, mapSize, cmap, 0, false,
-                transparentPixel, DataBuffer.TYPE_BYTE);
-
-        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
-                sampleImageHeight);
-        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createRGBAImageSpec(int sampleImageWidth,
-            int sampleImageHeight, final int dataType) {
-
-        final ImageTypeSpecifier its;
-
-        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
-        boolean hasAlpha = true;
-        boolean isAlphaPremultiplied = false;
-        int transparency = Transparency.TRANSLUCENT;
-        int transferType = dataType;
-
-        int[] nBits = { 8, 8, 8, 8 };
-        ColorModel colorModel = new ComponentColorModelJAI(colorSpace, nBits, hasAlpha,
-                isAlphaPremultiplied, transparency, transferType);
-
-        /*
-         * Do not use colorModel.createCompatibleSampleModel cause it creates a
-         * PixelInterleavedSampleModel and we need a BandedSampleModel so it matches how the data
-         * comes out of ArcSDE
-         */
-        SampleModel sampleModel = new BandedSampleModel(dataType, sampleImageWidth,
-                sampleImageHeight, 4);
-
-        its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createRGBImageSpec(int sampleImageWidth,
-            int sampleImageHeight, final int dataType) {
-
-        final ImageTypeSpecifier its;
-        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
-        boolean hasAlpha = false;
-        boolean isAlphaPremultiplied = false;
-        int transparency = Transparency.OPAQUE;
-        int transferType = dataType;
-        ColorModel colorModel = new ComponentColorModel(colorSpace, new int[] { 8, 8, 8 },
-                hasAlpha, isAlphaPremultiplied, transparency, transferType);
-
-        SampleModel sampleModel = new BandedSampleModel(dataType, sampleImageWidth,
-                sampleImageHeight, 3);
-
-        its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createGrayscaleImageSpec(int sampleImageWidth,
-            int sampleImageHeight, final int dataType, int bitsPerPixel) {
-        final ImageTypeSpecifier its;
-        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
-        boolean hasAlpha = false;
-        boolean isAlphaPremultiplied = false;
-        int transparency = Transparency.OPAQUE;
-        int transferType = dataType;
-        int[] nbits = { bitsPerPixel };
-        ColorModel colorModel = new ComponentColorModelJAI(colorSpace, nbits, hasAlpha,
-                isAlphaPremultiplied, transparency, transferType);
-
-        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
-                sampleImageHeight);
-        its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createOneBitImageSpec(final RasterDatasetInfo rasterInfo,
-            final int numberOfBands, int sampleImageWidth, int sampleImageHeight,
-            final int bitsPerSample, final int dataType) {
-        final ColorModel colorModel;
-        final SampleModel sampleModel;
-        if (numberOfBands != 1) {
-            throw new IllegalArgumentException(bitsPerSample
-                    + "-Bit rasters are only supported for one band");
-        }
-        int[] argb = new int[(int) Math.pow(2, bitsPerSample)];
-        ColorUtilities.expand(new Color[] { Color.WHITE, Color.BLACK }, argb, 0, argb.length);
-        GridSampleDimension gridSampleDimension = rasterInfo.getGridSampleDimensions()[0];
-        colorModel = gridSampleDimension.getColorModel(0, numberOfBands, dataType);
-        sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth, sampleImageHeight);
-
-        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-    }
-
-    private static ImageTypeSpecifier createColorMappedImageSpec(final IndexColorModel colorModel,
-            int sampleImageWidth, int sampleImageHeight) {
-
-        final SampleModel sampleModel;
-        final ImageTypeSpecifier its;
-        LOGGER.fine("Found single-band colormapped raster, using its index color model");
-        sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth, sampleImageHeight);
-        its = new ImageTypeSpecifier(colorModel, sampleModel);
-        return its;
-
-    }
-
-    public static ArcSDEGridCoverage2DReaderJAI.ReadParameters parseReadParams(
-            final GeneralEnvelope coverageEnvelope, final GeneralParameterValue[] params)
-            throws IllegalArgumentException {
-        if (params == null) {
-            throw new IllegalArgumentException("No GeneralParameterValue given to read operation");
-        }
-
-        GeneralEnvelope reqEnvelope = null;
-        Rectangle dim = null;
-        OverviewPolicy overviewPolicy = null;
-
-        // /////////////////////////////////////////////////////////////////////
-        //
-        // Checking params
-        //
-        // /////////////////////////////////////////////////////////////////////
-        for (int i = 0; i < params.length; i++) {
-            final ParameterValue<?> param = (ParameterValue<?>) params[i];
-            final String name = param.getDescriptor().getName().getCode();
-            if (name.equals(AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString())) {
-                final GridGeometry2D gg = (GridGeometry2D) param.getValue();
-                reqEnvelope = new GeneralEnvelope((Envelope) gg.getEnvelope2D());
-
-                CoordinateReferenceSystem nativeCrs = coverageEnvelope
-                        .getCoordinateReferenceSystem();
-                CoordinateReferenceSystem requestCrs = reqEnvelope.getCoordinateReferenceSystem();
-                if (!CRS.equalsIgnoreMetadata(nativeCrs, requestCrs)) {
-                    LOGGER.info("Request CRS and native CRS differ, "
-                            + "reprojecting request envelope to native CRS");
-                    ReferencedEnvelope nativeCrsEnv;
-                    nativeCrsEnv = toNativeCrs(reqEnvelope, nativeCrs);
-                    reqEnvelope = new GeneralEnvelope(nativeCrsEnv);
-                }
-
-                dim = gg.getGridRange2D().getBounds();
-                continue;
-            }
-            if (name.equals(AbstractGridFormat.OVERVIEW_POLICY.getName().toString())) {
-                overviewPolicy = (OverviewPolicy) param.getValue();
-                continue;
-            }
-        }
-
-        if (dim == null && reqEnvelope == null) {
-            throw new ParameterNotFoundException("Parameter is mandatory and shall provide "
-                    + "the extent and dimension to request", AbstractGridFormat.READ_GRIDGEOMETRY2D
-                    .getName().toString());
-        }
-
-        if (!reqEnvelope.intersects(coverageEnvelope, true)) {
-            throw new IllegalArgumentException(
-                    "The requested extend does not overlap the coverage extent: "
-                            + coverageEnvelope);
-        }
-
-        if (dim.width <= 0 || dim.height <= 0) {
-            throw new IllegalArgumentException("The requested coverage dimension can't be null: "
-                    + dim);
-        }
-
-        if (overviewPolicy == null) {
-            LOGGER.finer("No overview policy requested, defaulting to QUALITY");
-            overviewPolicy = OverviewPolicy.QUALITY;
-        }
-        LOGGER.fine("Overview policy is " + overviewPolicy);
-
-        LOGGER.info("Reading raster for " + dim.getWidth() + "x" + dim.getHeight()
-                + " requested dim and " + reqEnvelope.getMinimum(0) + ","
-                + reqEnvelope.getMaximum(0) + " - " + reqEnvelope.getMinimum(1)
-                + reqEnvelope.getMaximum(1) + " requested extent");
-
-        ArcSDEGridCoverage2DReaderJAI.ReadParameters parsedParams = new ArcSDEGridCoverage2DReaderJAI.ReadParameters();
-        parsedParams.requestedEnvelope = reqEnvelope;
-        parsedParams.dim = dim;
-        parsedParams.overviewPolicy = overviewPolicy;
-        return parsedParams;
-    }
-
-    /**
-     * Given a collection of {@link RasterQueryInfo} instances holding information about how a
-     * request fits for each individual raster composing a catalog, figure out where their resulting
-     * images fit into the overall mosaic that's gonna be the result of the request.
-     *
-     * @param rasterInfo
-     * @param resultEnvelope
-     * @param results
-     * @return
-     */
-    public static Rectangle setMosaicLocations(final RasterDatasetInfo rasterInfo,
-            final GeneralEnvelope resultEnvelope, final List<RasterQueryInfo> results) {
-        final Rectangle mosaicDimension;
-        final MathTransform modelToRaster;
-        final MathTransform rasterToModel;
-        {
-            /*
-             * Of all the rasters that match the requested envelope, chose the one with the lowest
-             * resolution as the base to compute the final mosaic layout, so we avoid JAI upsamples,
-             * which are buggy and produce repeated patterns over the x axis instead of just scaling
-             * up the image.
-             */
-            RasterQueryInfo dimensionChoice = findLowestResolution(results);
-            Long rasterId = dimensionChoice.getRasterId();
-            int pyramidLevel = dimensionChoice.getPyramidLevel();
-            int rasterIndex = rasterInfo.getRasterIndex(rasterId);
-            Rectangle levelRange = rasterInfo.getGridRange(rasterIndex, pyramidLevel);
-            GeneralEnvelope levelEnvelope = rasterInfo.getGridEnvelope(rasterIndex, pyramidLevel);
-            rasterToModel = createRasterToModel(levelRange, levelEnvelope);
-            try {
-                modelToRaster = rasterToModel.inverse();
-            } catch (NoninvertibleTransformException e) {
-                throw new RuntimeException(e);
-            }
-            mosaicDimension = getTargetGridRange(modelToRaster, resultEnvelope);
-        }
-
-        for (RasterQueryInfo rasterResultInfo : results) {
-            final GeneralEnvelope rasterResultEnvelope = rasterResultInfo.getResultEnvelope();
-
-            final Rectangle targetRasterGridRange;
-            targetRasterGridRange = getTargetGridRange(modelToRaster, rasterResultEnvelope);
-
-            rasterResultInfo.setMosaicLocation(targetRasterGridRange);
-        }
-
-        return mosaicDimension;
-    }
-
-    private static RasterQueryInfo findLowestResolution(List<RasterQueryInfo> results) {
-        double[] prev = { Double.MIN_VALUE, Double.MIN_VALUE };
-        RasterQueryInfo lowestResQuery = null;
-
-        double[] curr;
-        for (RasterQueryInfo query : results) {
-            curr = query.getResolution();
-            if (curr[0] > prev[0]) {
-                prev = curr;
-                lowestResQuery = query;
-            }
-        }
-        return lowestResQuery;
-    }
-
-    /**
-     * Find out the raster ids and their pyramid levels in the raster dataset for the rasters whose
-     * envelope overlaps the requested one
-     *
-     * @param rasterInfo
-     * @param requestedEnvelope
-     * @param requestedDim
-     * @param overviewPolicy
-     * @return
-     */
-    public static List<RasterQueryInfo> findMatchingRasters(final RasterDatasetInfo rasterInfo,
-            final GeneralEnvelope requestedEnvelope, final Rectangle requestedDim,
-            final OverviewPolicy overviewPolicy) {
-
-        final int numRasters = rasterInfo.getNumRasters();
-        List<RasterQueryInfo> matchingRasters = new ArrayList<RasterQueryInfo>(numRasters);
-
-        int optimalPyramidLevel;
-        GeneralEnvelope gridEnvelope;
-        for (int rasterN = 0; rasterN < numRasters; rasterN++) {
-            optimalPyramidLevel = rasterInfo.getOptimalPyramidLevel(rasterN, overviewPolicy,
-                    requestedEnvelope, requestedDim);
-            gridEnvelope = rasterInfo.getGridEnvelope(rasterN, optimalPyramidLevel);
-            final boolean edgesInclusive = true;
-            if (requestedEnvelope.intersects(gridEnvelope, edgesInclusive)) {
-                RasterQueryInfo match = new RasterQueryInfo();
-                match.setRequestedEnvelope(requestedEnvelope);
-                match.setRequestedDim(requestedDim);
-
-                match.setRasterId(rasterInfo.getRasterId(rasterN));
-                match.setRasterIndex(rasterN);
-                match.setPyramidLevel(optimalPyramidLevel);
-                match.setResolution(rasterInfo.getResolution(rasterN, optimalPyramidLevel));
-                matchingRasters.add(match);
-            }
-        }
-        return matchingRasters;
-    }
-
-    public static void fitRequestToRaster(final GeneralEnvelope requestedEnvelope,
-            final RasterDatasetInfo rasterInfo, final RasterQueryInfo query) {
-
-        final int rasterIndex = query.getRasterIndex();
-        final int pyramidLevel = query.getPyramidLevel();
-        final Rectangle rasterGridRange = rasterInfo.getGridRange(rasterIndex, pyramidLevel);
-        final GeneralEnvelope rasterEnvelope = rasterInfo
-                .getGridEnvelope(rasterIndex, pyramidLevel);
-
-        double delta = requestedEnvelope.getMinimum(0) - rasterEnvelope.getMinimum(0);
-        double resX = rasterInfo.getResolution(rasterIndex, pyramidLevel)[0];
-        int xMinPixel = (int) Math.floor(delta / resX);
-
-        delta = requestedEnvelope.getMaximum(0) - rasterEnvelope.getMinimum(0);
-        int xMaxPixel = (int) Math.ceil(delta / resX);
-
-        delta = rasterEnvelope.getMaximum(1) - requestedEnvelope.getMaximum(1);
-        double resY = rasterInfo.getResolution(rasterIndex, pyramidLevel)[1];
-        // Distance in pixels from the top of the whole pyramid image to the top
-        // of our AOI.
-        // If we're off the top, this number will be negative.
-        int yMinPixel = (int) Math.floor(delta / resY);
-
-        delta = rasterEnvelope.getMaximum(1) - requestedEnvelope.getMinimum(1);
-        int yMaxPixel = (int) Math.ceil(delta / resY);
-
-        xMinPixel = Math.max(xMinPixel, rasterGridRange.x);
-        yMinPixel = Math.max(yMinPixel, rasterGridRange.y);
-        xMaxPixel = Math.min(xMaxPixel, rasterGridRange.x + rasterGridRange.width);
-        yMaxPixel = Math.min(yMaxPixel, rasterGridRange.y + rasterGridRange.height);
-
-        final int widthPixel = xMaxPixel - xMinPixel;
-        final int heightPixel = yMaxPixel - yMinPixel;
-
-        final double xMinGeo = rasterEnvelope.getMinimum(0) + resX * xMinPixel;
-        final double yMinGeo = rasterEnvelope.getMaximum(1) - resY * (yMinPixel + heightPixel);
-        final double widthGeo = resX * widthPixel;
-        final double heightGeo = resY * heightPixel;
-
-        final Rectangle resultGridRange;
-        final GeneralEnvelope resultEnvelope;
-
-        resultEnvelope = new GeneralEnvelope(new double[] { xMinGeo, yMinGeo }, new double[] {
-                xMinGeo + widthGeo, yMinGeo + heightGeo });
-        resultEnvelope.setCoordinateReferenceSystem(rasterEnvelope.getCoordinateReferenceSystem());
-
-        resultGridRange = new Rectangle(xMinPixel, yMinPixel, widthPixel, heightPixel);
-
-        final Rectangle matchingTiles;
-        final Rectangle levelTileRange;
-        final Rectangle tiledImageGridRange;
-        {
-            final Dimension tileSize = rasterInfo.getTileDimension(rasterIndex);
-            final int numTilesWide = rasterInfo.getNumTilesWide(rasterIndex, pyramidLevel);
-            final int numTilesHigh = rasterInfo.getNumTilesHigh(rasterIndex, pyramidLevel);
-            final Point tileOffset = rasterInfo.getTileOffset(rasterIndex, pyramidLevel);
-            levelTileRange = new Rectangle(0, 0, numTilesWide, numTilesHigh);
-            matchingTiles = findMatchingTiles(tileSize, numTilesWide, numTilesHigh, resultGridRange);
-
-            int tiledImageMinX = (matchingTiles.x * tileSize.width);
-            int tiledImageMinY = (matchingTiles.y * tileSize.height);
-
-            int tiledWidth = (matchingTiles.width * tileSize.width);
-            int tiledHeight = (matchingTiles.height * tileSize.height);
-
-            tiledImageGridRange = new Rectangle(tiledImageMinX, tiledImageMinY, tiledWidth,
-                    tiledHeight);
-        }
-
-        /*
-         * What is the grid range inside the whole level grid range that fits into the matching
-         * tiles
-         */
-        Rectangle resultDimensionInsideTiledImage;
-        resultDimensionInsideTiledImage = getResultDimensionForTileRange(tiledImageGridRange,
-                resultGridRange);
-
-        query.setResultEnvelope(resultEnvelope);
-        query.setResultDimensionInsideTiledImage(resultDimensionInsideTiledImage);
-        query.setTiledImageSize(tiledImageGridRange);
-        query.setLevelTileRange(levelTileRange);
-        query.setMatchingTiles(matchingTiles);
-    }
-
-    /**
-     * Returns a color model based on {@code colorMap} that's guaranteed to have at least one
-     * transparent pixel whose index can be used as no-data value for colormapped rasters, even if
-     * the returned IndexColorModel needs to be of a higher sample depth (ie, 16 instead of 8 bit)
-     * to satisfy that.
-     *
-     * @param colorMap
-     *            the raster's native color map the returned one will be based on
-     * @return the same {@code colorMap} if it has a transparent pixel, another, possibly of a
-     *         higher depth one if not, containing all the colors from {@code colorMap} and a newly
-     *         allocated cell for the transparent pixel if necessary
-     */
-    public static IndexColorModel ensureNoDataPixelIsAvailable(final IndexColorModel colorMap) {
-        int transparentPixel = colorMap.getTransparentPixel();
-        if (transparentPixel > -1) {
-            return colorMap;
-        }
-
-        final int transferType = colorMap.getTransferType();
-        final int mapSize = colorMap.getMapSize();
-        final int maxSize = 65536;// true for either transfer type
-
-        if (mapSize == maxSize) {
-            LOGGER.fine("There's no room for a new transparent pixel, "
-                    + "returning the original colorMap as is");
-            return colorMap;
-        }
-
-        /*
-         * The original map size is lower than the maximum allowed by a UShort color map, so expand
-         * the colormap by one and make that new entry transparent
-         */
-        final int newMapSize = mapSize + 1;
-        final int[] argb = new int[newMapSize];
-        colorMap.getRGBs(argb);
-
-        // set the last entry as transparent
-        argb[newMapSize - 1] = ColorUtilities.getIntFromColor(0, 0, 0, 0);
-
-        IndexColorModel targetColorModel;
-        final int significantBits;
-        final int newTransferType;
-
-        {
-            if (DataBuffer.TYPE_BYTE == transferType && newMapSize <= 256) {
-                /*
-                 * REVISIT: check if this needs to be promoted depending on whether I decide to
-                 * treat 1 and 4 bit images as indexed with 1 and 4 significant bits respectively
-                 */
-                significantBits = colorMap.getPixelSize();
-                newTransferType = DataBuffer.TYPE_BYTE;
-            } else {
-                // it's either being promoted or was already 16-bit
-                significantBits = 16;
-                newTransferType = DataBuffer.TYPE_USHORT;
-            }
-        }
-
-        final int transparentPixelIndex = newMapSize - 1;
-        final boolean hasalpha = true;
-        final int startIndex = 0;
-
-        targetColorModel = new IndexColorModel(significantBits, newMapSize, argb, startIndex,
-                hasalpha, transparentPixelIndex, newTransferType);
-
-        return targetColorModel;
-    }
-
-    /**
-     * For a color-mapped raster, the no-data value is set to the
-     * {@link IndexColorModel#getTransparentPixel() transparent pixel}
-     *
-     * @param colorMap
-     * @return the index in the colorMap that's the transparent pixel as is to be used as no-data
-     *         value
-     */
-    public static Number determineNoDataValue(IndexColorModel colorMap) {
-        int noDataPixel = colorMap.getTransparentPixel();
-        if (-1 == noDataPixel) {
-            // there were no room for a transparent pixel, find out the closest match
-            noDataPixel = ColorUtilities.getTransparentPixel(colorMap);
-        }
-        return Integer.valueOf(noDataPixel);
-    }
-
-    /**
-     * @param numBands
-     *            number of bands in the raster dataset for the band whose nodata value is to be
-     *            determined. Might be useful to treat special cases where some assumptions are made
-     *            depending on the cell type and number of bands
-     * @param statsMin
-     *            the minimum sample value for the band as reported by the band's statistics, or
-     *            {@code NaN}
-     * @param statsMax
-     *            the maximum sample value for the band as reported by the band's statistics, or
-     *            {@code NaN}
-     * @param nativeCellType
-     *            the band's native cell type
-     * @return
-     */
-    public static Number determineNoDataValue(final int numBands, final double statsMin,
-            final double statsMax, final RasterCellType nativeCellType) {
-
-        final Number nodata;
-
-        if (nativeCellType == TYPE_32BIT_REAL) {
-            LOGGER.fine("no data value is Float.NaN");
-            return Float.valueOf(Float.NaN);
-        } else if (nativeCellType == TYPE_64BIT_REAL) {
-            LOGGER.fine("no data value is Double.NaN");
-            return Double.valueOf(Double.NaN);
-        } else if (nativeCellType == TYPE_1BIT) {
-            LOGGER.fine("1BIT images no-data value is set to 2,"
-                    + " regardless of the raster statistics");
-            return Double.valueOf(2);
-        } else if (nativeCellType == TYPE_4BIT) {
-            LOGGER.fine("4BIT images no-data value is set to 16,"
-                    + " regardless of the raster statistics");
-            return Double.valueOf(16);
-        } else if (!isGeoPhysics(numBands, nativeCellType)) {
-            LOGGER.fine("3 or 4 band, 8 bit unsigned image, assumed to be "
-                    + "RGB or RGBA respectively and nodata value hardcoded to 255");
-            return (Number) nativeCellType.getSampleValueRange().getMaxValue();
-        }
-
-        final NumberRange<?> sampleValueRange = nativeCellType.getSampleValueRange();
-
-        final double minimumSample = sampleValueRange.getMinimum(true);
-        final double maximumSample = sampleValueRange.getMaximum(true);
-
-        double lower;
-        double greater;
-        if (Double.isNaN(statsMin) || Double.isNaN(statsMax)) {
-            lower = Math.ceil(minimumSample - 1);
-            greater = Math.floor(maximumSample + 1);
-        } else {
-            lower = Math.ceil(statsMin - 1);
-            greater = Math.floor(statsMax + 1);
-        }
-
-        final boolean isUnsigned = minimumSample == 0;
-
-        if (sampleValueRange.contains((Number) Double.valueOf(lower))) {
-            // lower is ok
-            nodata = lower;
-        } else if (sampleValueRange.contains((Number) Double.valueOf(greater))) {
-            // upper is ok
-            nodata = greater;
-        } else if (isUnsigned) {
-            // need to set no-data to the higher value, floor is zero
-            nodata = greater;
-            // if (cellType == TYPE_1BIT || cellType == TYPE_4BIT) {
-            // nodata = greater;
-            // } else {
-            // // best guess without promoting. We don't actually want to promote a raster that is
-            // // non
-            // // colormapped and either has no statistics or it's range is full to preserve the
-            // // cases
-            // // were it may affect badly the visualization (for example, a 3 band 8bit raster
-            // // promoted to 3 band 16bit is gonna look almost black
-            // nodata = maximumSample;
-            // }
-        } else {
-            // no-data as the lower value is ok, floor is non zero (the celltype is signed)
-            nodata = lower;
-        }
-
-        return nodata;
-    }
-
-    public static boolean isGeoPhysics(final int numBands, final RasterCellType nativeCellType) {
-        boolean geophysics = true;
-        if (nativeCellType == TYPE_8BIT_U && (numBands == 3 || numBands == 4)) {
-            geophysics = false;
-        }
-        return geophysics;
-    }
-
-    public static RasterCellType determineTargetCellType(final RasterCellType nativeCellType,
-            final List<Number> noDataValues) {
-
-        if (TYPE_32BIT_REAL == nativeCellType || TYPE_64BIT_REAL == nativeCellType) {
-            // no data value is NaN, so no need to promote. For other types NaN is not available
-            for (Number nodata : noDataValues) {
-                if (!Double.isNaN(nodata.doubleValue())) {
-                    throw new IllegalArgumentException("no data values for float and "
-                            + "double cell types shall be NaN: " + nodata);
-                }
-            }
-            return nativeCellType;
-        }
-
-        // find a cell type that's deep enough for all the bands in the given raster
-        double noDataMin = Double.POSITIVE_INFINITY, noDataMax = Double.NEGATIVE_INFINITY;
-        {
-            for (Number noData : noDataValues) {
-                noDataMin = Math.min(noDataMin, noData.doubleValue());
-                noDataMax = Math.max(noDataMax, noData.doubleValue());
-            }
-        }
-        final NumberRange<Double> sampleValueRange;
-        sampleValueRange = nativeCellType.getSampleValueRange().castTo(Double.class);
-
-        final RasterCellType targetCellType;
-
-        if (sampleValueRange.contains((Number) Double.valueOf(noDataMin))
-                && sampleValueRange.contains((Number) Double.valueOf(noDataMax))) {
-            /*
-             * The native cell type can hold the no-data values for all bands in the raster
-             */
-            targetCellType = nativeCellType;
-        } else {
-            targetCellType = promote(nativeCellType);
-        }
-        return targetCellType;
-    }
-
-    private static RasterCellType promote(final RasterCellType nativeCellType) {
-        switch (nativeCellType) {
-        case TYPE_1BIT:
-        case TYPE_4BIT:
-            return TYPE_8BIT_U;
-        case TYPE_8BIT_U:
-            return TYPE_16BIT_U;
-        case TYPE_8BIT_S:
-            return TYPE_16BIT_S;
-        case TYPE_16BIT_U:
-            return TYPE_32BIT_U;
-        case TYPE_16BIT_S:
-            return TYPE_32BIT_S;
-        case TYPE_32BIT_S:
-        case TYPE_32BIT_REAL:
-        case TYPE_32BIT_U:
-            return TYPE_64BIT_REAL;
-        default:
-            throw new IllegalArgumentException(
-                    "Can't promote a raster of type 64-bit-real, there's "
-                            + "no higher pixel depth than that!");
-        }
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,150 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.io.IOException;
-
-/**
- * Offers an iterator like interface to read ArcSDE raster tiles into a {@code byte[]}
- *
- * @author Gabriel Roldan (OpenGeo)
- * @since 2.5.4
- * @version $Id$
- * @source $URL:
- *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
- *         /geotools/arcsde/gce/TileReader.java $
- */
-interface TileReader {
-
-    public class TileInfo {
-        private final long bandId;
-
-        private final byte[] bitmaskData;
-
-        private final int numPixelsRead;
-
-        private final byte[] tileDta;
-
-        private final int columnIndex;
-
-        private final int rowIndex;
-
-        public TileInfo(long bandId, int colIndex, int rowIndex, int numPixelsRead,
-                byte[] tileData, byte[] bitMaskData) {
-            this.bandId = bandId;
-            this.columnIndex = colIndex;
-            this.rowIndex = rowIndex;
-            this.numPixelsRead = numPixelsRead;
-            this.tileDta = tileData;
-            this.bitmaskData = bitMaskData;
-        }
-
-        public Long getBandId() {
-            return bandId;
-        }
-
-        public byte[] getBitmaskData() {
-            return bitmaskData;
-        }
-
-        public int getNumPixelsRead() {
-            return numPixelsRead;
-        }
-
-        public byte[] getTileData() {
-            return tileDta;
-        }
-
-        public int getColumnIndex() {
-            return columnIndex;
-        }
-
-        public int getRowIndex() {
-            return rowIndex;
-        }
-    }
-
-    /**
-     * @return number of bits per sample
-     */
-    public abstract int getBitsPerSample();
-
-    /**
-     * @return number of samples per tile
-     */
-    public abstract int getPixelsPerTile();
-
-    /**
-     * @return numbre of bands being fetched
-     */
-    public abstract int getNumberOfBands();
-
-    /**
-     * @return number of pixels per tile over the X axis
-     */
-    public abstract int getTileWidth();
-
-    /**
-     * @return number of pixels per tile over the Y axis
-     */
-    public abstract int getTileHeight();
-
-    /**
-     * @return number of tiles being fetched over the X axis
-     */
-    public abstract int getTilesWide();
-
-    /**
-     * @return number of tiles being fetched over the Y axis
-     */
-    public abstract int getTilesHigh();
-
-    /**
-     * @return number of bytes in the raw pixel content of a tile, not taking into account any
-     *         trailing bitmask data.
-     */
-    public abstract int getBytesPerTile();
-
-    /**
-     * @return whether there are more tiles to fetch
-     * @throws IOException
-     */
-    public abstract boolean hasNext() throws IOException;
-
-    /**
-     * Fetches a tile and fills {@code tileData} with its raw pixel data packaged as bytes according
-     * to the number of bits per sample
-     *
-     * @param tileData
-     *            a possibly {@code null} array where to store the next tile data. If {@code null} a
-     *            new byte[] of length {@link #getBytesPerTile()} will be allocated and filled up
-     *            with the raw tile pixel data.
-     * @return the bitmask data, or an empty array if the tile is full
-     * @throws IOException
-     * @throws {@link IllegalArgumentException} if tileData is not null and its size is less than
-     *         {@link #getBytesPerTile()}
-     */
-    public abstract TileInfo next() throws IOException;
-
-    /**
-     * Disposes any resource being held by this TileReader, making the TileReader unusable and the
-     * behaviour of {@link #hasNext()} and {@link #next} unpredictable
-     */
-    public abstract void dispose();
-
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReaderFactory.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReaderFactory.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReaderFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,52 +0,0 @@
-package org.geotools.arcsde.gce;
-
-import java.awt.Rectangle;
-
-import org.geotools.arcsde.session.ISessionPool;
-
-public class TileReaderFactory {
-
-    /**
-     *
-     * @param preparedQuery
-     * @param row
-     * @param nativeType
-     * @param targetType
-     * @param noDataValues
-     * @param numberOfBands
-     * @param requestedTiles
-     * @param tileSize
-     * @return
-     */
-    public static TileReader getInstance(final ISessionPool sessionPool,
-            final RasterDatasetInfo rasterInfo, final long rasterId, final int pyramidLevel,
-            final Rectangle requestedTiles) {
-
-        final TileReader tileReader;
-
-        final RasterCellType nativeType = rasterInfo.getNativeCellType();
-        final RasterCellType targetType = rasterInfo.getTargetCellType(rasterId);
-
-        final BitmaskToNoDataConverter noData;
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, rasterId);
-
-        if (targetType == nativeType) {
-
-            TileReader nativeTileReader = new NativeTileReader(sessionPool, rasterInfo, rasterId,
-                    pyramidLevel, requestedTiles, noData);
-
-            tileReader = nativeTileReader;
-
-        } else {
-            // need to promote native to target sample depth
-            TileReader nativeTileReader;
-            nativeTileReader = new NativeTileReader(sessionPool, rasterInfo, rasterId,
-                    pyramidLevel, requestedTiles, BitmaskToNoDataConverter.NO_ACTION_CONVERTER);
-
-            TileReader promotingTileReader = new PromotingTileReader(nativeTileReader, nativeType,
-                    targetType, noData);
-            tileReader = promotingTileReader;
-        }
-        return tileReader;
-    }
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TiledRasterReader.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TiledRasterReader.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TiledRasterReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,93 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Rectangle;
-import java.awt.image.RenderedImage;
-import java.io.IOException;
-
-/**
- * An Iterator like interface to read ArcSDE rasters for a given ArcSDE raster dataset (whether it
- * is a single raster or a raster catalog).
- * <p>
- * Sample usage: <code>
- * <pre>
- * RasterReaderFactory readerFactory = ....
- * RasterDatasetInfo raserInfo = ...
- * ArcSDERasterReader reader = readerFactory.create(rasterInfo);
- * try{
- *      Long nextRasterId;
- *      while((nextRasterId = reader.nextRaster()) != null){
- *          if(amIInterestedInThisRaster(nextRasterId)){
- *              int pyramidLevel = ...
- *              Rectangle tileRange = ...
- *              RenderedImage raster = reader.read(pyramidLevel, tileRange);
- *          }
- *      }
- * }finally{
- *      reader.dispose();
- * }
- * </pre>
- * </code>
- * </p>
- * <p>
- * So one has to call {@code nextRaster()} to get the id of the raster immediately available to be
- * read through {@link #read()}. This is so because there might be more than one raster on a raster
- * dataset and the order they are fetched from the ArcSDE server is non deterministic, and once you
- * opened a stream to a raster you can't open another one and then read the former.
- * </p>
- *
- * @author Gabriel Roldan
- * @version $Id$
- * @since 2.5.7
- */
-interface TiledRasterReader {
-
-    /**
-     * Disposes any resource being held by this reader, whether it's a connection to the ArcSDE
-     * server, opened streams, etc.
-     */
-    // void dispose();
-
-    /**
-     * Advances to the next available raster in the raster dataset this reader works upon and
-     * returns it's {@link SeRasterAttr#getRasterId() raster id}.
-     *
-     * @return the ID for the raster ready to be read from the queried raster column in the raster
-     *         dataset, or {@code null} if there are no more rasters to be read.
-     * @throws IOException
-     *             for any problem occurred retrieving the next {@link SeRasterAttr} in the request
-     */
-    // Long nextRaster() throws IOException;
-
-    /**
-     * Reads the image subset determined by the given pyramid level and tile range for the currently
-     * available raster attribute in the requested raster column for the given raster dataset.
-     *
-     * @param pyramidLevel
-     *            the pyramid level to read
-     * @param tileRange
-     *            the range of tiles to read at the given pyramid level. The boundaries of the tile
-     *            range are inclusive and starts at {@code 0,0} for the upper left most tile.
-     * @return the rendered image determined by the requested pyramid level and tile range
-     * @throws IOException
-     *             for any exception occurred while reading the image
-     */
-    RenderedImage read(final long rasterId, final int pyramidLevel, final Rectangle tileRange)
-            throws IOException;
-
-}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java (from rev 34312, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,812 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.gce;
+
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.awt.image.renderable.ParameterBlock;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageTypeSpecifier;
+import javax.media.jai.ImageLayout;
+import javax.media.jai.InterpolationNearest;
+import javax.media.jai.JAI;
+import javax.media.jai.ParameterBlockJAI;
+import javax.media.jai.operator.FormatDescriptor;
+import javax.media.jai.operator.MosaicDescriptor;
+
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.raster.info.RasterQueryInfo;
+import org.geotools.arcsde.raster.info.RasterUtils;
+import org.geotools.arcsde.raster.io.RasterReaderFactory;
+import org.geotools.arcsde.raster.io.TiledRasterReader;
+import org.geotools.coverage.CoverageFactoryFinder;
+import org.geotools.coverage.GridSampleDimension;
+import org.geotools.coverage.TypeMap;
+import org.geotools.coverage.grid.GeneralGridEnvelope;
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.coverage.grid.GridEnvelope2D;
+import org.geotools.coverage.grid.GridGeometry2D;
+import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
+import org.geotools.coverage.grid.io.AbstractGridFormat;
+import org.geotools.coverage.grid.io.OverviewPolicy;
+import org.geotools.data.DataSourceException;
+import org.geotools.data.DefaultServiceInfo;
+import org.geotools.data.ServiceInfo;
+import org.geotools.factory.Hints;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.referencing.CRS;
+import org.geotools.util.logging.Logging;
+import org.opengis.coverage.ColorInterpretation;
+import org.opengis.coverage.grid.Format;
+import org.opengis.coverage.grid.GridCoverageReader;
+import org.opengis.geometry.Envelope;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.parameter.ParameterValue;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.TransformException;
+
+/**
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAI.java $
+ */
+@SuppressWarnings( { "deprecation", "nls" })
+public final class ArcSDEGridCoverage2DReaderJAI extends AbstractGridCoverage2DReader {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    /**
+     * @see LoggingHelper#log(RenderedImage, Long, String)
+     */
+    private static final boolean DEBUG_TO_DISK = Boolean
+            .getBoolean("org.geotools.arcsde.gce.debug");
+
+    private final ArcSDERasterFormat parent;
+
+    private final RasterDatasetInfo rasterInfo;
+
+    private DefaultServiceInfo serviceInfo;
+
+    private RasterReaderFactory rasterReaderFactory;
+
+    public ArcSDEGridCoverage2DReaderJAI(final ArcSDERasterFormat parent,
+            final RasterReaderFactory rasterReaderFactory, final RasterDatasetInfo rasterInfo,
+            final Hints hints) throws IOException {
+        // check it's a supported format
+        {
+            final int bitsPerSample = rasterInfo.getBand(0, 0).getCellType().getBitsPerSample();
+            if (rasterInfo.getNumBands() > 1 && (bitsPerSample == 1 || bitsPerSample == 4)) {
+                throw new IllegalArgumentException(bitsPerSample
+                        + "-bit rasters with more than one band are not supported");
+            }
+        }
+        this.parent = parent;
+        this.rasterReaderFactory = rasterReaderFactory;
+        this.rasterInfo = rasterInfo;
+
+        super.hints = hints;
+        super.coverageFactory = CoverageFactoryFinder.getGridCoverageFactory(this.hints);
+        super.crs = rasterInfo.getCoverageCrs();
+        super.originalEnvelope = rasterInfo.getOriginalEnvelope();
+
+        GeneralGridEnvelope gridRange = rasterInfo.getOriginalGridRange();
+        super.originalGridRange = new GridEnvelope2D(gridRange.toRectangle());
+
+        super.coverageName = rasterInfo.getRasterTable();
+        final int numLevels = rasterInfo.getNumPyramidLevels(0);
+
+        // level 0 is not an overview, but the raster itself
+        super.numOverviews = numLevels - 1;
+
+        // ///
+        //
+        // setting the higher resolution avalaible for this coverage
+        //
+        // ///
+        highestRes = super.getResolution(originalEnvelope, (Rectangle) originalGridRange, crs);
+        // //
+        //
+        // get information for the successive images
+        //
+        // //
+        // REVISIT may the different rasters in the raster dataset have different pyramid levels? I
+        // guess so
+        if (numOverviews > 0) {
+            overViewResolutions = new double[numOverviews][2];
+            for (int pyramidLevel = 1; pyramidLevel <= numOverviews; pyramidLevel++) {
+                Rectangle levelGridRange = rasterInfo.getGridRange(0, pyramidLevel);
+                GeneralEnvelope levelEnvelope = rasterInfo.getGridEnvelope(0, pyramidLevel);
+                overViewResolutions[pyramidLevel - 1] = super.getResolution(levelEnvelope,
+                        levelGridRange, crs);
+            }
+        } else {
+            overViewResolutions = null;
+        }
+    }
+
+    /**
+     * @see GridCoverageReader#getFormat()
+     */
+    public Format getFormat() {
+        return parent;
+    }
+
+    @Override
+    public ServiceInfo getInfo() {
+        if (serviceInfo == null) {
+            serviceInfo = new DefaultServiceInfo();
+            serviceInfo.setTitle(rasterInfo.getRasterTable());
+            serviceInfo.setDescription(rasterInfo.toString());
+            Set<String> keywords = new HashSet<String>();
+            keywords.add("ArcSDE");
+            serviceInfo.setKeywords(keywords);
+        }
+        return serviceInfo;
+    }
+
+    /**
+     * @see GridCoverageReader#read(GeneralParameterValue[])
+     */
+    public GridCoverage2D read(GeneralParameterValue[] params) throws IOException {
+
+        final GeneralEnvelope requestedEnvelope;
+        final Rectangle requestedDim;
+        final OverviewPolicy overviewPolicy;
+        {
+            final ReadParameters opParams = parseReadParams(getOriginalEnvelope(), params);
+            overviewPolicy = opParams.overviewPolicy;
+            requestedEnvelope = opParams.requestedEnvelope;
+            requestedDim = opParams.dim;
+        }
+
+        /*
+         * For each raster in the raster dataset, obtain the tiles, pixel range, and resulting
+         * envelope
+         */
+        final List<RasterQueryInfo> queries;
+        queries = findMatchingRasters(requestedEnvelope, requestedDim, overviewPolicy);
+        if (queries.isEmpty()) {
+            /*
+             * none of the rasters match the requested envelope. This may happen by the tiled nature
+             * of the raster dataset
+             */
+            return createFakeCoverage(requestedEnvelope, requestedDim);
+        }
+
+        final GeneralEnvelope resultEnvelope = getResultEnvelope(queries);
+
+        final LoggingHelper log = new LoggingHelper();
+        log.appendLoggingGeometries(LoggingHelper.REQ_ENV, requestedEnvelope);
+        log.appendLoggingGeometries(LoggingHelper.RES_ENV, resultEnvelope);
+
+        /*
+         * Once we collected the matching rasters and their image subsets, find out where in the
+         * overall resulting mosaic they fit. If the rasters does not share the spatial resolution,
+         * the QueryInfo.resultDimension and QueryInfo.mosaicLocation width or height won't match
+         */
+        final Rectangle mosaicGeometry;
+        mosaicGeometry = RasterUtils.setMosaicLocations(rasterInfo, resultEnvelope, queries);
+
+        /*
+         * Gather the rendered images for each of the rasters that match the requested envelope
+         */
+        final TiledRasterReader rasterReader = rasterReaderFactory.create(rasterInfo);
+
+        try {
+            readAllTiledRasters(queries, rasterReader, log);
+        } finally {
+            // rasterReader.dispose();
+        }
+
+        log.log(LoggingHelper.REQ_ENV);
+        log.log(LoggingHelper.RES_ENV);
+        log.log(LoggingHelper.MOSAIC_ENV);
+        log.log(LoggingHelper.MOSAIC_EXPECTED);
+
+        final RenderedImage coverageRaster = createMosaic(queries, mosaicGeometry, log);
+        assert mosaicGeometry.getWidth() == coverageRaster.getWidth();
+        assert mosaicGeometry.getHeight() == coverageRaster.getHeight();
+
+        /*
+         * BUILDING COVERAGE
+         */
+        GridSampleDimension[] bands = getSampleDimensions(coverageRaster);
+
+        GridCoverage2D resultCoverage = coverageFactory.create(coverageName, coverageRaster,
+                resultEnvelope, bands, null, null);
+
+        return resultCoverage;
+    }
+
+    private GridSampleDimension[] getSampleDimensions(final RenderedImage coverageRaster)
+            throws IOException {
+
+        GridSampleDimension[] bands = rasterInfo.getGridSampleDimensions();
+
+        // may the image have been promoted? build the correct band info then
+        final int imageBands = coverageRaster.getSampleModel().getNumBands();
+        if (bands.length == 1 && imageBands > 1) {
+            LOGGER.fine(coverageName + " was promoted from 1 to "
+                    + coverageRaster.getSampleModel().getNumBands()
+                    + " bands, returning an appropriate set of GridSampleDimension");
+            // stolen from super.createCoverage:
+            final ColorModel cm = coverageRaster.getColorModel();
+            bands = new GridSampleDimension[imageBands];
+
+            // setting bands names.
+            for (int i = 0; i < imageBands; i++) {
+                final ColorInterpretation colorInterpretation;
+                colorInterpretation = TypeMap.getColorInterpretation(cm, i);
+                if (colorInterpretation == null) {
+                    throw new IOException("Unrecognized sample dimension type");
+                }
+                bands[i] = new GridSampleDimension(colorInterpretation.name()).geophysics(true);
+            }
+        }
+
+        return bands;
+    }
+
+    private void readAllTiledRasters(final List<RasterQueryInfo> queries,
+            final TiledRasterReader rasterReader, final LoggingHelper log) throws IOException {
+
+        for (RasterQueryInfo queryInfo : queries) {
+
+            final Long rasterId = queryInfo.getRasterId();
+
+            final RenderedImage rasterImage;
+
+            try {
+                final int pyramidLevel = queryInfo.getPyramidLevel();
+                final Rectangle matchingTiles = queryInfo.getMatchingTiles();
+                // final Point imageLocation = queryInfo.getTiledImageSize().getLocation();
+                rasterImage = rasterReader.read(rasterId, pyramidLevel, matchingTiles);
+            } catch (IOException e) {
+                LOGGER.log(Level.SEVERE, "Fetching data for " + queryInfo.toString(), e);
+                throw e;
+            }
+
+            queryInfo.setResultImage(rasterImage);
+
+            {
+                LOGGER.finer(queryInfo.toString());
+                log.appendLoggingGeometries(LoggingHelper.MOSAIC_EXPECTED, queryInfo
+                        .getMosaicLocation());
+                log
+                        .appendLoggingGeometries(LoggingHelper.MOSAIC_ENV, queryInfo
+                                .getResultEnvelope());
+
+                final Rectangle tiledImageSize = queryInfo.getTiledImageSize();
+                int width = rasterImage.getWidth();
+                int height = rasterImage.getHeight();
+                if (tiledImageSize.width != width || tiledImageSize.height != height) {
+                    throw new IllegalStateException(
+                            "Read image is not of the expected size. Image=" + width + "x" + height
+                                    + ", expected: " + tiledImageSize.width + "x"
+                                    + tiledImageSize.height);
+                }
+                // if (tiledImageSize.x != rasterImage.getMinX()
+                // || tiledImageSize.y != rasterImage.getMinY()) {
+                // throw new IllegalStateException("Read image is not at the expected location "
+                // + tiledImageSize.x + "," + tiledImageSize.y + ": "
+                // + rasterImage.getMinX() + "," + rasterImage.getMinY());
+                // }
+            }
+        }
+    }
+
+    /**
+     * Called when the requested envelope do overlap the coverage envelope but none of the rasters
+     * in the dataset do
+     *
+     * @param requestedEnvelope
+     * @param requestedDim
+     * @return
+     */
+    private GridCoverage2D createFakeCoverage(GeneralEnvelope requestedEnvelope,
+            Rectangle requestedDim) {
+
+        ImageTypeSpecifier its = rasterInfo.getRenderedImageSpec(0);
+        SampleModel sampleModel = its.getSampleModel(requestedDim.width, requestedDim.height);
+        ColorModel colorModel = its.getColorModel();
+
+        WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
+        BufferedImage image = new BufferedImage(colorModel, raster, false, null);
+        return coverageFactory.create(coverageName, image, requestedEnvelope);
+    }
+
+    private List<RasterQueryInfo> findMatchingRasters(final GeneralEnvelope requestedEnvelope,
+            final Rectangle requestedDim, final OverviewPolicy overviewPolicy) {
+
+        final List<RasterQueryInfo> matchingQueries;
+        matchingQueries = RasterUtils.findMatchingRasters(rasterInfo, requestedEnvelope,
+                requestedDim, overviewPolicy);
+
+        if (matchingQueries.isEmpty()) {
+            return matchingQueries;
+        }
+
+        for (RasterQueryInfo match : matchingQueries) {
+            RasterUtils.fitRequestToRaster(requestedEnvelope, rasterInfo, match);
+        }
+        return matchingQueries;
+    }
+
+    private GeneralEnvelope getResultEnvelope(final List<RasterQueryInfo> queryInfos) {
+
+        GeneralEnvelope finalEnvelope = null;
+
+        for (RasterQueryInfo rasterQueryInfo : queryInfos) {
+            // gather resulting envelope
+            if (finalEnvelope == null) {
+                finalEnvelope = new GeneralEnvelope(rasterQueryInfo.getResultEnvelope());
+            } else {
+                finalEnvelope.add(rasterQueryInfo.getResultEnvelope());
+            }
+        }
+        if (finalEnvelope == null) {
+            throw new IllegalStateException("Restult envelope is null, this shouldn't happen!! "
+                    + "we checked the request overlaps the coverage envelope before!");
+        }
+        return finalEnvelope;
+    }
+
+    /**
+     * For each raster: crop->scale->translate->add to mosaic
+     *
+     * @param queries
+     * @param mosaicGeometry
+     * @return
+     * @throws IOException
+     */
+    private RenderedImage createMosaic(final List<RasterQueryInfo> queries,
+            final Rectangle mosaicGeometry, final LoggingHelper log) throws IOException {
+
+        List<RenderedImage> transformed = new ArrayList<RenderedImage>(queries.size());
+
+        /*
+         * Do we need to expand to RGB color space and then create a new colormapped image with the
+         * whole mosaic?
+         */
+        boolean expandThenContractCM = queries.size() > 1 && rasterInfo.isColorMapped();
+        if (expandThenContractCM) {
+            LOGGER.info("Creating mosaic out of " + queries.size()
+                    + " colormapped rasters. The mosaic tiles will be expanded to "
+                    + "\nRGB space and the resulting mosaic reduced to a new IndexColorModel");
+        }
+
+        for (RasterQueryInfo query : queries) {
+            RenderedImage image = query.getResultImage();
+            log.log(image, query.getRasterId(), "01_original");
+
+            image = cropToRequiredDimension(image, query.getTiledImageSize(), query
+                    .getResultDimensionInsideTiledImage());
+            log.log(image, query.getRasterId(), "02_crop");
+
+            final Rectangle mosaicLocation = query.getMosaicLocation();
+            // scale
+            Float scaleX = Float.valueOf((float) (mosaicLocation.getWidth() / image.getWidth()));
+            Float scaleY = Float.valueOf((float) (mosaicLocation.getHeight() / image.getHeight()));
+            Float translateX = Float.valueOf(0);
+            Float translateY = Float.valueOf(0);
+            // image.getData();
+            if (!(Float.valueOf(1.0F).equals(scaleX) && Float.valueOf(1.0F).equals(scaleY))) {
+                ParameterBlock pb = new ParameterBlock();
+                pb.addSource(image);
+                pb.add(scaleX);
+                pb.add(scaleY);
+                pb.add(translateX);
+                pb.add(translateY);
+                pb.add(new InterpolationNearest());
+
+                if (queries.size() > 0) {
+                    try {
+                        LOGGER.info("Forcing loading data for mosaic as per GEOT-");
+                        // image.getData();
+                    } catch (RuntimeException e) {
+                        throw new DataSourceException("Error fetching arcsde raster", e);
+                    }
+                }
+
+                image = JAI.create("scale", pb);
+                log.log(image, query.getRasterId(), "03_scale");
+
+                int width = image.getWidth();
+                int height = image.getHeight();
+
+                assert mosaicLocation.width == width;
+                assert mosaicLocation.height == height;
+            }
+            if (image.getMinX() != mosaicLocation.x || image.getMinY() != mosaicLocation.y) {
+                // translate
+                ParameterBlock pb = new ParameterBlock();
+                pb.addSource(image);
+                pb.add(Float.valueOf(mosaicLocation.x - image.getMinX()));
+                pb.add(Float.valueOf(mosaicLocation.y - image.getMinY()));
+                pb.add(null);
+
+                image = JAI.create("translate", pb);
+                log.log(image, query.getRasterId(), "04_translate");
+
+                assert image.getMinX() == mosaicLocation.x : image.getMinX() + " != "
+                        + mosaicLocation.x;
+                assert image.getMinY() == mosaicLocation.y : image.getMinY() + " != "
+                        + mosaicLocation.y;
+                assert image.getWidth() == mosaicLocation.width : image.getWidth() + " != "
+                        + mosaicLocation.width;
+                assert image.getHeight() == mosaicLocation.height : image.getHeight() + " != "
+                        + mosaicLocation.height;
+            }
+            if (expandThenContractCM) {
+                if (LOGGER.isLoggable(Level.FINER)) {
+                    LOGGER.finer("Creating color expanded version of tile for raster #"
+                            + query.getRasterId());
+                }
+
+                /*
+                 * reformat the image as a 4 band rgba backed by byte data
+                 */
+                image = FormatDescriptor.create(image, Integer.valueOf(DataBuffer.TYPE_BYTE), null);
+
+                log.log(image, query.getRasterId(), "04_1_colorExpanded");
+            }
+
+            transformed.add(image);
+        }
+
+        final RenderedImage mosaic;
+        if (queries.size() == 1) {
+            /*
+             * This is besides a very slight perf improvement needed because the JAI mosaic
+             * operation truncates floating point raster values to 0 and 1. REVISIT: If there's no
+             * workaround for that we should prevent raster catalogs made of floating point rasters
+             * and throw an exception as we could not really support that.
+             */
+            mosaic = transformed.get(0);
+        } else {
+            /*
+             * adapted from RasterLayerResponse.java in the imagemosaic module
+             */
+            ParameterBlockJAI mosaicParams = new ParameterBlockJAI("Mosaic");
+
+            // TODO: set background values to raster's no-data
+            // mosaicParams.setParameter("backgroundValues",backgroundValues);
+
+            mosaicParams.setParameter("mosaicType", MosaicDescriptor.MOSAIC_TYPE_OVERLAY);
+
+            final ImageLayout layout = new ImageLayout(mosaicGeometry.x, mosaicGeometry.y,
+                    mosaicGeometry.width, mosaicGeometry.height);
+            layout.setTileWidth(mosaicGeometry.width);
+            layout.setTileHeight(mosaicGeometry.height);
+            final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
+            // hints.put(JAI.KEY_SERIALIZE_DEEP_COPY, Boolean.TRUE);
+
+            for (RenderedImage img : transformed) {
+                mosaicParams.addSource(img);
+                log.appendLoggingGeometries(LoggingHelper.MOSAIC_RESULT, img);
+            }
+            log.log(LoggingHelper.MOSAIC_RESULT);
+
+            LOGGER.fine("Creating mosaic out of " + queries.size() + " raster tiles");
+            mosaic = JAI.create("Mosaic", mosaicParams, hints);
+
+            log.log(mosaic, 0L, "05_mosaic_result");
+        }
+        return mosaic;
+    }
+
+    /**
+     * Crops the image representing a full tile set to the required dimension and returns it, but
+     * keeps minx and miny being zero.
+     *
+     * @param fullTilesRaster
+     * @param tiledImageGridRagne
+     * @param cropTo
+     * @return
+     */
+    private RenderedImage cropToRequiredDimension(final RenderedImage fullTilesRaster,
+            final Rectangle tiledImageGridRagne, final Rectangle cropTo) {
+
+        // int minX = fullTilesRaster.getMinX();
+        // int minY = fullTilesRaster.getMinY();
+        // int width = fullTilesRaster.getWidth();
+        // int height = fullTilesRaster.getHeight();
+
+        int minX = tiledImageGridRagne.x;
+        int minY = tiledImageGridRagne.y;
+        int width = tiledImageGridRagne.width;
+        int height = tiledImageGridRagne.height;
+
+        Rectangle origDim = new Rectangle(minX, minY, width, height);
+        if (!origDim.contains(cropTo)) {
+            throw new IllegalArgumentException("Original image (" + origDim
+                    + ") does not contain desired dimension (" + cropTo + ")");
+        } else if (origDim.equals(cropTo)) {
+            if (LOGGER.isLoggable(Level.FINER)) {
+                LOGGER.finer("No need to crop image, full tiled dimension and target one "
+                        + "do match: original: " + width + "x" + height + ", target: "
+                        + cropTo.width + "x" + cropTo.height);
+            }
+            return fullTilesRaster;
+        }
+
+        ParameterBlock cropParams = new ParameterBlock();
+
+        cropParams.addSource(fullTilesRaster);// Source
+        cropParams.add(Float.valueOf(cropTo.x - tiledImageGridRagne.x)); // x origin for each band
+        cropParams.add(Float.valueOf(cropTo.y - tiledImageGridRagne.y)); // y origin for each band
+        cropParams.add(Float.valueOf(cropTo.width));// width for each band
+        cropParams.add(Float.valueOf(cropTo.height));// height for each band
+
+        final RenderingHints hints = null;
+        RenderedImage image = JAI.create("Crop", cropParams, hints);
+
+        assert cropTo.x - tiledImageGridRagne.x == image.getMinX();
+        assert cropTo.y - tiledImageGridRagne.y == image.getMinY();
+        assert cropTo.width == image.getWidth();
+        assert cropTo.height == image.getHeight();
+
+        // assert cropTo.x == image.getMinX();
+        // assert cropTo.y == image.getMinY();
+        // assert cropTo.width == image.getWidth();
+        // assert cropTo.height == image.getHeight();
+        return image;
+    }
+
+    static class ReadParameters {
+        GeneralEnvelope requestedEnvelope;
+
+        Rectangle dim;
+
+        OverviewPolicy overviewPolicy;
+    }
+
+    private static ArcSDEGridCoverage2DReaderJAI.ReadParameters parseReadParams(
+            final GeneralEnvelope coverageEnvelope, final GeneralParameterValue[] params)
+            throws IllegalArgumentException {
+        if (params == null) {
+            throw new IllegalArgumentException("No GeneralParameterValue given to read operation");
+        }
+
+        GeneralEnvelope reqEnvelope = null;
+        Rectangle dim = null;
+        OverviewPolicy overviewPolicy = null;
+
+        // /////////////////////////////////////////////////////////////////////
+        //
+        // Checking params
+        //
+        // /////////////////////////////////////////////////////////////////////
+        for (int i = 0; i < params.length; i++) {
+            final ParameterValue<?> param = (ParameterValue<?>) params[i];
+            final String name = param.getDescriptor().getName().getCode();
+            if (name.equals(AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString())) {
+                final GridGeometry2D gg = (GridGeometry2D) param.getValue();
+                reqEnvelope = new GeneralEnvelope((Envelope) gg.getEnvelope2D());
+
+                CoordinateReferenceSystem nativeCrs = coverageEnvelope
+                        .getCoordinateReferenceSystem();
+                CoordinateReferenceSystem requestCrs = reqEnvelope.getCoordinateReferenceSystem();
+                if (!CRS.equalsIgnoreMetadata(nativeCrs, requestCrs)) {
+                    LOGGER.info("Request CRS and native CRS differ, "
+                            + "reprojecting request envelope to native CRS");
+                    ReferencedEnvelope nativeCrsEnv;
+                    nativeCrsEnv = toNativeCrs(reqEnvelope, nativeCrs);
+                    reqEnvelope = new GeneralEnvelope(nativeCrsEnv);
+                }
+
+                dim = gg.getGridRange2D().getBounds();
+                continue;
+            }
+            if (name.equals(AbstractGridFormat.OVERVIEW_POLICY.getName().toString())) {
+                overviewPolicy = (OverviewPolicy) param.getValue();
+                continue;
+            }
+        }
+
+        if (dim == null && reqEnvelope == null) {
+            throw new ParameterNotFoundException("Parameter is mandatory and shall provide "
+                    + "the extent and dimension to request", AbstractGridFormat.READ_GRIDGEOMETRY2D
+                    .getName().toString());
+        }
+
+        if (!reqEnvelope.intersects(coverageEnvelope, true)) {
+            throw new IllegalArgumentException(
+                    "The requested extend does not overlap the coverage extent: "
+                            + coverageEnvelope);
+        }
+
+        if (dim.width <= 0 || dim.height <= 0) {
+            throw new IllegalArgumentException("The requested coverage dimension can't be null: "
+                    + dim);
+        }
+
+        if (overviewPolicy == null) {
+            LOGGER.finer("No overview policy requested, defaulting to QUALITY");
+            overviewPolicy = OverviewPolicy.QUALITY;
+        }
+        LOGGER.fine("Overview policy is " + overviewPolicy);
+
+        LOGGER.info("Reading raster for " + dim.getWidth() + "x" + dim.getHeight()
+                + " requested dim and " + reqEnvelope.getMinimum(0) + ","
+                + reqEnvelope.getMaximum(0) + " - " + reqEnvelope.getMinimum(1)
+                + reqEnvelope.getMaximum(1) + " requested extent");
+
+        ArcSDEGridCoverage2DReaderJAI.ReadParameters parsedParams = new ArcSDEGridCoverage2DReaderJAI.ReadParameters();
+        parsedParams.requestedEnvelope = reqEnvelope;
+        parsedParams.dim = dim;
+        parsedParams.overviewPolicy = overviewPolicy;
+        return parsedParams;
+    }
+
+    private static ReferencedEnvelope toNativeCrs(final GeneralEnvelope requestedEnvelope,
+            final CoordinateReferenceSystem nativeCRS) throws IllegalArgumentException {
+
+        ReferencedEnvelope reqEnv = toReferencedEnvelope(requestedEnvelope);
+
+        if (!CRS.equalsIgnoreMetadata(nativeCRS, reqEnv.getCoordinateReferenceSystem())) {
+            // we're being reprojected. We'll need to reproject reqEnv into
+            // our native coordsys
+            try {
+                // ReferencedEnvelope origReqEnv = reqEnv;
+                reqEnv = reqEnv.transform(nativeCRS, true);
+            } catch (FactoryException fe) {
+                // unable to reproject?
+                throw new IllegalArgumentException("Unable to find a reprojection from requested "
+                        + "coordsys to native coordsys for this request", fe);
+            } catch (TransformException te) {
+                throw new IllegalArgumentException("Unable to perform reprojection from requested "
+                        + "coordsys to native coordsys for this request", te);
+            }
+        }
+        return reqEnv;
+    }
+
+    private static ReferencedEnvelope toReferencedEnvelope(GeneralEnvelope envelope) {
+        double minx = envelope.getMinimum(0);
+        double maxx = envelope.getMaximum(0);
+        double miny = envelope.getMinimum(1);
+        double maxy = envelope.getMaximum(1);
+        CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
+
+        ReferencedEnvelope refEnv = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
+        return refEnv;
+    }
+
+    /**
+     * A simple helper class to guard and easy logging the mosaic geometries in both geographical
+     * and pixel ranges
+     */
+    private static class LoggingHelper {
+
+        private static final File debugDir = new File(System.getProperty("user.home")
+                + File.separator + "arcsde_test");
+
+        static {
+            if (DEBUG_TO_DISK) {
+                debugDir.mkdir();
+            }
+        }
+
+        public Level GEOM_LEVEL = Level.FINER;
+
+        public static String REQ_ENV = "Requested envelope";
+
+        public static String RES_ENV = "Resulting envelope";
+
+        public static String MOSAIC_ENV = "Resulting mosaiced envelopes";
+
+        public static String MOSAIC_EXPECTED = "Expected mosaic layout (in pixels)";
+
+        public static String MOSAIC_RESULT = "Resulting image mosaic layout (in pixels)";
+
+        private Map<String, StringBuilder> geoms = null;
+
+        LoggingHelper() {
+            // not much to to
+        }
+
+        private StringBuilder getGeom(String geomName) {
+            if (geoms == null) {
+                geoms = new HashMap<String, StringBuilder>();
+            }
+            StringBuilder sb = geoms.get(geomName);
+            if (sb == null) {
+                sb = new StringBuilder("MULTIPOLYGON(\n");
+                geoms.put(geomName, sb);
+            }
+            return sb;
+        }
+
+        public void appendLoggingGeometries(String geomName, RenderedImage img) {
+            if (LOGGER.isLoggable(GEOM_LEVEL)) {
+                appendLoggingGeometries(geomName, new Rectangle(img.getMinX(), img.getMinY(), img
+                        .getWidth(), img.getHeight()));
+            }
+        }
+
+        public void appendLoggingGeometries(String geomName, Rectangle env) {
+            if (LOGGER.isLoggable(GEOM_LEVEL)) {
+                appendLoggingGeometries(geomName, new GeneralEnvelope(env));
+            }
+        }
+
+        public void appendLoggingGeometries(String geomName, GeneralEnvelope env) {
+            if (LOGGER.isLoggable(GEOM_LEVEL)) {
+                StringBuilder sb = getGeom(geomName);
+                sb.append("  ((" + env.getMinimum(0) + " " + env.getMinimum(1) + ", "
+                        + env.getMaximum(0) + " " + env.getMinimum(1) + ", " + env.getMaximum(0)
+                        + " " + env.getMaximum(1) + ", " + env.getMinimum(0) + " "
+                        + env.getMaximum(1) + ", " + env.getMinimum(0) + " " + env.getMinimum(1)
+                        + ")),");
+            }
+        }
+
+        public void log(String geomName) {
+            if (LOGGER.isLoggable(GEOM_LEVEL)) {
+                StringBuilder sb = getGeom(geomName);
+                sb.setLength(sb.length() - 1);
+                sb.append("\n)");
+                LOGGER.log(GEOM_LEVEL, geomName + ":\n" + sb.toString());
+            }
+        }
+
+        public void log(RenderedImage image, Long rasterId, String fileName) {
+            if (DEBUG_TO_DISK) {
+                LOGGER.warning("BEWARE THE DEBUG FLAG IS TURNED ON! "
+                        + "IF IN PRODUCTION THIS IS A SEVERE MISTAKE!!!");
+                // ImageIO.write(FormatDescriptor.create(image,
+                // Integer.valueOf(DataBuffer.TYPE_BYTE),
+                // null), "TIFF", new File(debugDir, rasterId.longValue() + fileName + ".tiff"));
+
+                try {
+                    ImageIO.write(image, "TIFF", new File(debugDir, rasterId.longValue() + fileName
+                            + ".tiff"));
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+
+        }
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDERasterFormat.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,440 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.gce;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.geotools.arcsde.jndi.SharedSessionPool;
+import org.geotools.arcsde.raster.info.GatherCoverageMetadataCommand;
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.raster.io.RasterReaderFactory;
+import org.geotools.arcsde.session.ArcSDEConnectionConfig;
+import org.geotools.arcsde.session.ISession;
+import org.geotools.arcsde.session.ISessionPool;
+import org.geotools.arcsde.session.SessionPoolFactory;
+import org.geotools.arcsde.session.UnavailableConnectionException;
+import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
+import org.geotools.coverage.grid.io.AbstractGridFormat;
+import org.geotools.coverage.grid.io.imageio.GeoToolsWriteParams;
+import org.geotools.data.DataSourceException;
+import org.geotools.factory.GeoTools;
+import org.geotools.factory.Hints;
+import org.geotools.parameter.DefaultParameterDescriptorGroup;
+import org.geotools.parameter.ParameterGroup;
+import org.geotools.util.logging.Logging;
+import org.opengis.coverage.grid.Format;
+import org.opengis.coverage.grid.GridCoverageWriter;
+import org.opengis.parameter.GeneralParameterDescriptor;
+
+/**
+ * An implementation of the ArcSDE Raster Format. Based on the ArcGrid module.
+ *
+ * @author Saul Farber (saul.farber)
+ * @author jeichar
+ * @author Simone Giannecchini (simboss)
+ * @author Gabriel Roldan (OpenGeo)
+ * @source $URL:
+ *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/arcsde/datastore/src/main/java
+ *         /org/geotools/arcsde/gce/ArcSDERasterFormat.java $
+ */
+@SuppressWarnings( { "nls", "deprecation" })
+public final class ArcSDERasterFormat extends AbstractGridFormat implements Format {
+
+    protected static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    /**
+     * Cache of raster metadata objects, where the keys are the URL's representing the full
+     * connection properties to a given ArcSDE raster, and the value the
+     * {@link ArcSDERasterGridCoverage2DReader}'s externalized state, so it is not needed to gather
+     * the raster properties each time.
+     */
+    private final Map<String, RasterDatasetInfo> rasterInfos = new WeakHashMap<String, RasterDatasetInfo>();
+
+    private final Map<String, ArcSDEConnectionConfig> connectionConfigs = new WeakHashMap<String, ArcSDEConnectionConfig>();
+
+    private static final ArcSDERasterFormat instance = new ArcSDERasterFormat();
+
+    private boolean statisticsMandatory = true;
+
+    /**
+     * Creates an instance and sets the metadata.
+     */
+    private ArcSDERasterFormat() {
+        setInfo();
+    }
+
+    public static ArcSDERasterFormat getInstance() {
+        return instance;
+    }
+
+    /**
+     * Sets the metadata information.
+     */
+    private void setInfo() {
+        Map<String, String> info = new HashMap<String, String>();
+
+        info.put("name", "ArcSDE Raster");
+        info.put("description", "ArcSDE Raster Format");
+        info.put("vendor", "Geotools");
+        info.put("docURL", "");
+        info.put("version", GeoTools.getVersion().toString());
+        mInfo = info;
+
+        readParameters = new ParameterGroup(new DefaultParameterDescriptorGroup(mInfo,
+                new GeneralParameterDescriptor[] { READ_GRIDGEOMETRY2D, OVERVIEW_POLICY }));
+    }
+
+    /**
+     * @param source
+     *            either a {@link String} or {@link File} instance representing the connection URL
+     * @see AbstractGridFormat#getReader(Object source)
+     */
+    @Override
+    public AbstractGridCoverage2DReader getReader(Object source) {
+        return getReader(source, null);
+    }
+
+    /**
+     * @param source
+     *            either a {@link String} or {@link File} instance representing the connection URL
+     * @see AbstractGridFormat#getReader(Object, Hints)
+     */
+    @Override
+    public AbstractGridCoverage2DReader getReader(final Object source, final Hints hints) {
+        try {
+            if (source == null) {
+                throw new DataSourceException("No source set to read this coverage.");
+            }
+
+            // this will be our connection string
+            final String coverageUrl = parseCoverageUrl(source);
+
+            final ArcSDEConnectionConfig connectionConfig = getConnectionConfig(coverageUrl);
+
+            final ISessionPool sessionPool = setupConnectionPool(connectionConfig);
+
+            final RasterDatasetInfo rasterInfo = getRasterInfo(coverageUrl, sessionPool);
+
+            final RasterReaderFactory rasterReaderFactory = new RasterReaderFactory(sessionPool);
+
+            return new ArcSDEGridCoverage2DReaderJAI(this, rasterReaderFactory, rasterInfo, hints);
+        } catch (IOException dse) {
+            LOGGER
+                    .log(Level.SEVERE, "Unable to creata ArcSDERasterReader for " + source + ".",
+                            dse);
+            throw new RuntimeException(dse);
+        }
+    }
+
+    private RasterDatasetInfo getRasterInfo(final String coverageUrl, ISessionPool connectionPool)
+            throws IOException {
+
+        RasterDatasetInfo rasterInfo = rasterInfos.get(coverageUrl);
+        if (rasterInfo == null) {
+            synchronized (rasterInfos) {
+                rasterInfo = rasterInfos.get(coverageUrl);
+                if (rasterInfo == null) {
+                    ISession scon;
+                    try {
+                        scon = connectionPool.getSession(false);
+                    } catch (UnavailableConnectionException e) {
+                        throw new RuntimeException(e);
+                    }
+                    try {
+                        final String rasterTable;
+                        {
+                            String sdeUrl = coverageUrl;
+                            if (sdeUrl.indexOf(";") != -1) {
+                                /*
+                                 * We're not using any extra param anymore. Yet, be cautious cause a
+                                 * client may still be using urls with some old extra param, so just
+                                 * strip it
+                                 */
+                                sdeUrl = sdeUrl.substring(0, sdeUrl.indexOf(";"));
+                            }
+                            rasterTable = sdeUrl.substring(sdeUrl.indexOf("#") + 1);
+                            if (LOGGER.isLoggable(Level.FINE)) {
+                                LOGGER.fine("Building ArcSDEGridCoverageReader2D for "
+                                        + rasterTable);
+                            }
+                        }
+
+                        GatherCoverageMetadataCommand command = new GatherCoverageMetadataCommand(
+                                rasterTable, statisticsMandatory);
+                        rasterInfo = scon.issue(command);
+                        rasterInfos.put(coverageUrl, rasterInfo);
+                    } finally {
+                        scon.dispose();
+                    }
+                }
+            }
+        }
+        return rasterInfo;
+    }
+
+    private ArcSDEConnectionConfig getConnectionConfig(final String coverageUrl) {
+        ArcSDEConnectionConfig sdeConfig;
+        sdeConfig = connectionConfigs.get(coverageUrl);
+        if (sdeConfig == null) {
+            synchronized (connectionConfigs) {
+                sdeConfig = connectionConfigs.get(coverageUrl);
+                if (sdeConfig == null) {
+                    sdeConfig = sdeURLToConnectionConfig(new StringBuffer(coverageUrl));
+                    connectionConfigs.put(coverageUrl, sdeConfig);
+                }
+            }
+        }
+        return sdeConfig;
+    }
+
+    /**
+     * @see AbstractGridFormat#getWriter(Object)
+     */
+    @Override
+    public GridCoverageWriter getWriter(Object destination) {
+        // return new ArcGridWriter(destination);
+        return null;
+    }
+
+    /**
+     * @param source
+     *            either a {@link String} or {@link File} instance representing the connection URL
+     * @see AbstractGridFormat#accepts(Object input)
+     */
+    @Override
+    public boolean accepts(Object input) {
+        StringBuffer url;
+        if (input instanceof File) {
+            url = new StringBuffer(((File) input).getPath());
+        } else if (input instanceof String) {
+            url = new StringBuffer((String) input);
+        } else {
+            return false;
+        }
+        try {
+            sdeURLToConnectionConfig(url);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * @see Format#getName()
+     */
+    @Override
+    public String getName() {
+        return this.mInfo.get("name");
+    }
+
+    /**
+     * @see Format#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        return this.mInfo.get("description");
+    }
+
+    /**
+     * @see Format#getVendor()
+     */
+    @Override
+    public String getVendor() {
+        return this.mInfo.get("vendor");
+    }
+
+    /**
+     * @see Format#getDocURL()
+     */
+    @Override
+    public String getDocURL() {
+        return this.mInfo.get("docURL");
+    }
+
+    /**
+     * @see Format#getVersion()
+     */
+    @Override
+    public String getVersion() {
+        return this.mInfo.get("version");
+    }
+
+    /**
+     * Retrieves the default instance for the {@link ArcSDERasterFormat} of the
+     * {@link GeoToolsWriteParams} to control the writing process.
+     *
+     * @return a default instance for the {@link ArcSDERasterFormat} of the
+     *         {@link GeoToolsWriteParams} to control the writing process.
+     * @see AbstractGridFormat#getDefaultImageIOWriteParameters()
+     */
+    @Override
+    public GeoToolsWriteParams getDefaultImageIOWriteParameters() {
+        throw new UnsupportedOperationException("ArcSDE Rasters are read only for now.");
+    }
+
+    // ////////////////
+
+    /**
+     * @param input
+     *            either a {@link String} or a {@link File} instance representing the connection URL
+     *            to a given coverage
+     * @return the connection URL as a string
+     */
+    private String parseCoverageUrl(Object input) {
+        String coverageUrl;
+        if (input instanceof String) {
+            coverageUrl = (String) input;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.fine("connecting to ArcSDE Raster: " + coverageUrl);
+            }
+        } else if (input instanceof File) {
+            coverageUrl = ((File) input).getPath();
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.fine("connectiong via file-hack to ArcSDE Raster: " + coverageUrl);
+            }
+        } else {
+            throw new IllegalArgumentException("Unsupported input type: " + input.getClass());
+        }
+        return coverageUrl;
+    }
+
+    /**
+     * Checks the input provided to this {@link ArcSDERasterGridCoverage2DReader} and sets all the
+     * other objects and flags accordingly.
+     *
+     * @param sdeUrl
+     *            a url representing the connection parameters to an arcsde server instance provied
+     *            to this {@link ArcSDERasterGridCoverage2DReader}.
+     * @throws IOException
+     */
+    private ISessionPool setupConnectionPool(ArcSDEConnectionConfig sdeConfig) throws IOException {
+
+        if (LOGGER.isLoggable(Level.FINE)) {
+            LOGGER.fine("Getting ArcSDE connection pool for " + sdeConfig);
+        }
+
+        ISessionPool sessionPool;
+        sessionPool = SharedSessionPool.getInstance(sdeConfig, SessionPoolFactory.getInstance());
+
+        return sessionPool;
+    }
+
+    /**
+     * @param sdeUrl
+     *            - A StringBuffer containing a string of form
+     *            'sde://user:pass@sdehost:[port]/[dbname]
+     * @return a ConnectionConfig object representing these parameters
+     */
+    public static ArcSDEConnectionConfig sdeURLToConnectionConfig(StringBuffer sdeUrl) {
+        // annoyingly, geoserver currently stores the user-entered SDE string as
+        // a File, and passes us the
+        // File object. The File object strips the 'sde://user...' into a
+        // 'sde:/user..'. So we need to check
+        // for both forms of the url.
+        String sdeHost, sdeUser, sdePass, sdeDBName;
+        int sdePort;
+        if (sdeUrl.indexOf("sde:/") == -1) {
+            throw new IllegalArgumentException(
+                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName -- Got "
+                            + sdeUrl);
+        }
+        if (sdeUrl.indexOf("sde://") == -1) {
+            sdeUrl.delete(0, 5);
+        } else {
+            sdeUrl.delete(0, 6);
+        }
+
+        int idx = sdeUrl.indexOf(":");
+        if (idx == -1) {
+            throw new IllegalArgumentException(
+                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
+        }
+        sdeUser = sdeUrl.substring(0, idx);
+        sdeUrl.delete(0, idx);
+
+        idx = sdeUrl.indexOf("@");
+        if (idx == -1) {
+            throw new IllegalArgumentException(
+                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
+        }
+        sdePass = sdeUrl.substring(1, idx);
+        sdeUrl.delete(0, idx);
+
+        idx = sdeUrl.indexOf(":");
+        if (idx == -1) {
+            // there's no "port" specification. Assume 5151;
+            sdePort = 5151;
+
+            idx = sdeUrl.indexOf("/");
+            if (idx == -1) {
+                throw new IllegalArgumentException(
+                        "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
+            }
+            sdeHost = sdeUrl.substring(1, idx).toString();
+            sdeUrl.delete(0, idx);
+        } else {
+            sdeHost = sdeUrl.substring(1, idx).toString();
+            sdeUrl.delete(0, idx);
+
+            idx = sdeUrl.indexOf("/");
+            if (idx == -1) {
+                throw new IllegalArgumentException(
+                        "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
+            }
+            sdePort = Integer.parseInt(sdeUrl.substring(1, idx).toString());
+            sdeUrl.delete(0, idx);
+        }
+
+        idx = sdeUrl.indexOf("#");
+        if (idx == -1) {
+            throw new IllegalArgumentException(
+                    "ArcSDE Raster URL must be of the form sde://user:pass@sdehost:port/[dbname]#rasterTableName");
+        }
+        sdeDBName = sdeUrl.substring(1, idx).toString();
+        sdeUrl.delete(0, idx);
+
+        Map<String, String> params = new HashMap<String, String>();
+        params.put(ArcSDEConnectionConfig.SERVER_NAME_PARAM_NAME, sdeHost);
+        params.put(ArcSDEConnectionConfig.PORT_NUMBER_PARAM_NAME, String.valueOf(sdePort));
+        params.put(ArcSDEConnectionConfig.INSTANCE_NAME_PARAM_NAME, sdeDBName);
+        params.put(ArcSDEConnectionConfig.USER_NAME_PARAM_NAME, sdeUser);
+        params.put(ArcSDEConnectionConfig.PASSWORD_PARAM_NAME, sdePass);
+        params.put(ArcSDEConnectionConfig.MIN_CONNECTIONS_PARAM_NAME, "1");
+        params.put(ArcSDEConnectionConfig.MAX_CONNECTIONS_PARAM_NAME, "20");
+        params.put(ArcSDEConnectionConfig.CONNECTION_TIMEOUT_PARAM_NAME, "-1");// do not wait
+
+        ArcSDEConnectionConfig config = ArcSDEConnectionConfig.fromMap(params);
+        return config;
+    }
+
+    /**
+     * Used by test code to indicate wether to fail when a raster lacks statistics, since we can't
+     * create statistics with the ArcSDE Java API
+     *
+     * @param statisticsMandatory
+     */
+    void setStatisticsMandatory(final boolean statisticsMandatory) {
+        this.statisticsMandatory = statisticsMandatory;
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/CompressionType.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/CompressionType.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/CompressionType.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/CompressionType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,63 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.util.NoSuchElementException;
+
+import com.esri.sde.sdk.client.SeRaster;
+
+/**
+ * An enumeration that mirrors the different possible raster compression types in Arcsde (ie,
+ * {@code SeRaster#SE_COMPRESSION_*})
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/CompressionType.java $
+ */
+public enum CompressionType {
+    COMPRESSION_JP2, COMPRESSION_JPEG, COMPRESSION_LZ77, COMPRESSION_NONE;
+    static {
+        COMPRESSION_JP2.setSdeTypeId(SeRaster.SE_COMPRESSION_JP2);
+        COMPRESSION_JPEG.setSdeTypeId(SeRaster.SE_COMPRESSION_JPEG);
+        COMPRESSION_LZ77.setSdeTypeId(SeRaster.SE_COMPRESSION_LZ77);
+        COMPRESSION_NONE.setSdeTypeId(SeRaster.SE_COMPRESSION_NONE);
+    }
+
+    private int typeId;
+
+    private void setSdeTypeId(int typeId) {
+        this.typeId = typeId;
+    }
+
+    public int getSeCompressionType() {
+        return this.typeId;
+    }
+
+    public static CompressionType valueOf(final int seCompressionType) {
+        for (CompressionType type : CompressionType.values()) {
+            if (type.getSeCompressionType() == seCompressionType) {
+                return type;
+            }
+        }
+        throw new NoSuchElementException("Compression type " + seCompressionType
+                + " does not exist");
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/GatherCoverageMetadataCommand.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/GatherCoverageMetadataCommand.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/GatherCoverageMetadataCommand.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/GatherCoverageMetadataCommand.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,521 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.geom.Point2D;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.IndexColorModel;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.geotools.arcsde.ArcSdeException;
+import org.geotools.arcsde.session.Command;
+import org.geotools.arcsde.session.ISession;
+import org.geotools.arcsde.util.ArcSDEUtils;
+import org.geotools.data.DataSourceException;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.crs.DefaultEngineeringCRS;
+import org.geotools.util.logging.Logging;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import com.esri.sde.sdk.client.SDEPoint;
+import com.esri.sde.sdk.client.SeColumnDefinition;
+import com.esri.sde.sdk.client.SeConnection;
+import com.esri.sde.sdk.client.SeCoordinateReference;
+import com.esri.sde.sdk.client.SeException;
+import com.esri.sde.sdk.client.SeExtent;
+import com.esri.sde.sdk.client.SeQuery;
+import com.esri.sde.sdk.client.SeRaster;
+import com.esri.sde.sdk.client.SeRasterAttr;
+import com.esri.sde.sdk.client.SeRasterBand;
+import com.esri.sde.sdk.client.SeRasterColumn;
+import com.esri.sde.sdk.client.SeRow;
+import com.esri.sde.sdk.client.SeSqlConstruct;
+import com.esri.sde.sdk.client.SeTable;
+
+/**
+ * Session command to gather information for an ArcSDE Raster, such as dimensions, spatial extent,
+ * number of pyramid levels, etc; into a {@link RasterDatasetInfo}
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.8
+ * @source $UR$
+ */
+public class GatherCoverageMetadataCommand extends Command<RasterDatasetInfo> {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private final boolean statisticsMandatory;
+
+    private final String rasterTableName;
+
+    public GatherCoverageMetadataCommand(final String rasterTableName,
+            final boolean statisticsMandatory) {
+        this.rasterTableName = rasterTableName;
+        this.statisticsMandatory = statisticsMandatory;
+    }
+
+    /**
+     * @throws IOException
+     *             if an exception occurs accessing the raster metadata
+     * @throws SeException
+     * @throws IllegalArgumentException
+     *             if the raster has no CRS, contains no raster attributes, has no pyramids, no
+     *             bands or no statistics
+     */
+    @Override
+    public RasterDatasetInfo execute(ISession session, SeConnection connection) throws SeException,
+            IOException {
+        LOGGER.fine("Gathering raster dataset metadata for " + rasterTableName);
+        final String[] rasterColumns = getRasterColumns(connection, rasterTableName);
+        final List<RasterInfo> rastersLayoutInfo = new ArrayList<RasterInfo>();
+        {
+            final List<SeRasterAttr> rasterAttributes;
+            rasterAttributes = getSeRasterAttr(connection, rasterTableName, rasterColumns);
+
+            if (rasterAttributes.size() == 0) {
+                throw new IllegalArgumentException("Table " + rasterTableName
+                        + " contains no raster datasets");
+            }
+
+            final CoordinateReferenceSystem coverageCrs;
+
+            /*
+             * by bandId map of colormaps. The dataset may be composed of more than one raster so we
+             * gather all the colormaps once and held them here by rasterband id
+             */
+            final Map<Long, IndexColorModel> rastersColorMaps;
+            {
+                final SeRasterColumn rasterColumn;
+                final SeRasterBand sampleBand;
+                final long rasterColumnId;
+                final int bitsPerSample;
+                try {
+                    SeRasterAttr ratt = rasterAttributes.get(0);
+                    rasterColumn = new SeRasterColumn(connection, ratt.getRasterColumnId());
+                    rasterColumnId = rasterColumn.getID().longValue();
+                    sampleBand = ratt.getBands()[0];
+                    bitsPerSample = RasterCellType.valueOf(ratt.getPixelType()).getBitsPerSample();
+                } catch (SeException e) {
+                    throw new ArcSdeException(e);
+                }
+                final SeCoordinateReference seCoordRef = rasterColumn.getCoordRef();
+                if (seCoordRef == null) {
+                    throw new IllegalArgumentException(rasterTableName
+                            + " has no coordinate reference system set");
+                }
+                LOGGER.finer("Looking CRS for raster column " + rasterTableName);
+                coverageCrs = ArcSDEUtils.findCompatibleCRS(seCoordRef);
+                if (DefaultEngineeringCRS.CARTESIAN_2D == coverageCrs) {
+                    LOGGER.warning("Raster " + rasterTableName
+                            + " has not CRS set, using DefaultEngineeringCRS.CARTESIAN_2D");
+                }
+                if (sampleBand.hasColorMap()) {
+                    rastersColorMaps = loadColorMaps(rasterColumnId, bitsPerSample, connection);
+                } else {
+                    rastersColorMaps = Collections.emptyMap();
+                }
+
+            }
+            try {
+                for (SeRasterAttr rAtt : rasterAttributes) {
+                    LOGGER.fine("Gathering raster metadata for " + rasterTableName + " raster "
+                            + rAtt.getRasterId().longValue());
+
+                    if (rAtt.getMaxLevel() == 0) {
+                        throw new IllegalArgumentException(
+                                "Raster cotains no pyramid levels, we don't support non pyramid rasters");
+                    }
+                    if (rAtt.getNumBands() == 0) {
+                        throw new IllegalArgumentException("Raster "
+                                + rAtt.getRasterId().longValue() + " in " + rasterTableName
+                                + " contains no raster attribtues");
+                    }
+                    if (this.statisticsMandatory && !rAtt.getBandInfo(1).hasStats()) {
+                        throw new IllegalArgumentException(rasterTableName
+                                + " has no statistics generated (or not all it's rasters have). "
+                                + "Please use sderaster -o stats to create them before use");
+                    }
+
+                    RasterInfo rasterInfo = new RasterInfo(rAtt, coverageCrs);
+                    rastersLayoutInfo.add(rasterInfo);
+
+                    final GeneralEnvelope originalEnvelope;
+                    originalEnvelope = calculateOriginalEnvelope(rAtt, coverageCrs);
+                    rasterInfo.setOriginalEnvelope(originalEnvelope);
+                    final List<RasterBandInfo> bands;
+                    bands = setUpBandInfo(connection, rAtt, rastersColorMaps);
+                    rasterInfo.setBands(bands);
+                    if (LOGGER.isLoggable(Level.FINER)) {
+                        LOGGER.finer("Gathered metadata for " + rasterTableName + "#"
+                                + rAtt.getRasterId().longValue() + ":\n" + rasterInfo.toString());
+                    }
+                }
+            } catch (SeException e) {
+                throw new ArcSdeException("Gathering raster dataset information", e);
+            }
+        }
+
+        RasterDatasetInfo rasterInfo = new RasterDatasetInfo();
+        rasterInfo.setRasterTable(rasterTableName);
+        rasterInfo.setRasterColumns(rasterColumns);
+        rasterInfo.setPyramidInfo(rastersLayoutInfo);
+
+        return rasterInfo;
+    }
+
+    private String[] getRasterColumns(final SeConnection scon, final String rasterTable)
+            throws IOException, SeException {
+
+        String[] rasterColumns;
+        SeTable sTable = new SeTable(scon, rasterTable);
+        SeColumnDefinition[] cols;
+        try {
+            cols = sTable.describe();
+        } catch (SeException e) {
+            throw new ArcSdeException("Exception fetching the list of columns for table "
+                    + rasterTable, e);
+        }
+        List<String> fetchColumns = new ArrayList<String>(cols.length / 2);
+        for (int i = 0; i < cols.length; i++) {
+            if (cols[i].getType() == SeColumnDefinition.TYPE_RASTER)
+                fetchColumns.add(cols[i].getName());
+        }
+        if (fetchColumns.size() == 0) {
+            throw new DataSourceException("Couldn't find any TYPE_RASTER columns in ArcSDE table "
+                    + rasterTable);
+        }
+
+        rasterColumns = fetchColumns.toArray(new String[fetchColumns.size()]);
+        return rasterColumns;
+    }
+
+    private GeneralEnvelope calculateOriginalEnvelope(final SeRasterAttr rasterAttributes,
+            CoordinateReferenceSystem coverageCrs) throws IOException {
+        SeExtent sdeExtent;
+        try {
+            sdeExtent = rasterAttributes.getExtent();
+        } catch (SeException e) {
+            throw new ArcSdeException("Exception getting the raster extent", e);
+        }
+        GeneralEnvelope originalEnvelope = new GeneralEnvelope(coverageCrs);
+        originalEnvelope.setRange(0, sdeExtent.getMinX(), sdeExtent.getMaxX());
+        originalEnvelope.setRange(1, sdeExtent.getMinY(), sdeExtent.getMaxY());
+        return originalEnvelope;
+    }
+
+    private List<SeRasterAttr> getSeRasterAttr(SeConnection scon, String rasterTable,
+            String[] rasterColumns) throws IOException {
+
+        LOGGER.fine("Gathering raster attributes for " + rasterTable);
+        SeRasterAttr rasterAttributes;
+        LinkedList<SeRasterAttr> rasterAttList = new LinkedList<SeRasterAttr>();
+        SeQuery query = null;
+        try {
+            query = new SeQuery(scon, rasterColumns, new SeSqlConstruct(rasterTable));
+            query.prepareQuery();
+            query.execute();
+
+            SeRow row = query.fetch();
+            while (row != null) {
+                rasterAttributes = row.getRaster(0);
+                rasterAttList.addFirst(rasterAttributes);
+                row = query.fetch();
+            }
+        } catch (SeException se) {
+            throw new ArcSdeException("Error fetching raster attributes for " + rasterTable, se);
+        } finally {
+            if (query != null) {
+                try {
+                    query.close();
+                } catch (SeException e) {
+                    throw new ArcSdeException(e);
+                }
+            }
+        }
+        LOGGER.fine("Found " + rasterAttList.size() + " raster attributes for " + rasterTable);
+        return rasterAttList;
+    }
+
+    /**
+     *
+     * @param band
+     * @param scon
+     * @return
+     * @throws ArcSdeException
+     */
+    private Map<Long, IndexColorModel> loadColorMaps(final long rasterColumnId,
+            final int bitsPerSample, SeConnection scon) throws IOException {
+        LOGGER.fine("Reading colormap for raster column " + rasterColumnId);
+
+        final String auxTableName = getAuxTableName(rasterColumnId, scon);
+        LOGGER.fine("Quering auxiliary table " + auxTableName + " for color map data");
+
+        Map<Long, IndexColorModel> colorMaps = new HashMap<Long, IndexColorModel>();
+        SeQuery query = null;
+        try {
+            SeSqlConstruct sqlConstruct = new SeSqlConstruct();
+            sqlConstruct.setTables(new String[] { auxTableName });
+            String whereClause = "TYPE = 3";
+            sqlConstruct.setWhere(whereClause);
+
+            query = new SeQuery(scon, new String[] { "RASTERBAND_ID", "OBJECT" }, sqlConstruct);
+            query.prepareQuery();
+            query.execute();
+
+            long bandId;
+            ByteArrayInputStream colorMapIS;
+            DataBuffer colorMapData;
+            IndexColorModel colorModel;
+
+            SeRow row = query.fetch();
+            while (row != null) {
+                bandId = ((Number) row.getObject(0)).longValue();
+                colorMapIS = row.getBlob(1);
+
+                colorMapData = readColorMap(colorMapIS);
+                colorModel = RasterUtils.sdeColorMapToJavaColorModel(colorMapData, bitsPerSample);
+
+                colorMaps.put(Long.valueOf(bandId), colorModel);
+
+                row = query.fetch();
+            }
+        } catch (SeException e) {
+            throw new ArcSdeException("Error fetching colormap data for column " + rasterColumnId
+                    + " from table " + auxTableName, e);
+        } finally {
+            if (query != null) {
+                try {
+                    query.close();
+                } catch (SeException e) {
+                    LOGGER.log(Level.INFO, "ignoring exception when closing query to "
+                            + "fetch colormap data", e);
+                }
+            }
+        }
+        LOGGER.fine("Read color map data for " + colorMaps.size() + " rasters");
+        return colorMaps;
+    }
+
+    private DataBuffer readColorMap(final ByteArrayInputStream colorMapIS) throws IOException {
+
+        final DataInputStream dataIn = new DataInputStream(colorMapIS);
+        // discard unneeded data
+        dataIn.readInt();
+
+        final int colorSpaceType = dataIn.readInt();
+        final int numBanks;
+        if (colorSpaceType == SeRaster.SE_COLORMAP_RGB) {
+            numBanks = 3;
+        } else if (colorSpaceType == SeRaster.SE_COLORMAP_RGBA) {
+            numBanks = 4;
+        } else {
+            throw new IllegalStateException("Got unknown colormap type: " + colorSpaceType);
+        }
+        LOGGER.finest("Colormap has " + numBanks + " color components");
+
+        final int buffType = dataIn.readInt();
+        final int numElems = dataIn.readInt();
+        LOGGER.finest("ColorMap length: " + numElems);
+
+        final DataBuffer buff;
+        if (buffType == SeRaster.SE_COLORMAP_DATA_BYTE) {
+            LOGGER.finest("Creating Byte data buffer for " + numBanks + " banks and " + numElems
+                    + " elements per bank");
+            buff = new DataBufferByte(numElems, numBanks);
+            for (int elem = 0; elem < numElems; elem++) {
+                for (int bank = 0; bank < numBanks; bank++) {
+                    int val = dataIn.readUnsignedByte();
+                    buff.setElem(bank, elem, val);
+                }
+            }
+        } else if (buffType == SeRaster.SE_COLORMAP_DATA_SHORT) {
+            LOGGER.finest("Creating Short data buffer for " + numBanks + " banks and " + numElems
+                    + " elements per bank");
+            buff = new DataBufferUShort(numElems, numBanks);
+            for (int elem = 0; elem < numElems; elem++) {
+                for (int bank = 0; bank < numBanks; bank++) {
+                    int val = dataIn.readUnsignedShort();
+                    buff.setElem(bank, elem, val);
+                }
+            }
+        } else {
+            throw new IllegalStateException("Unknown databuffer type from colormap header: "
+                    + buffType + " expected one of TYPE_BYTE, TYPE_SHORT");
+        }
+
+        assert dataIn.read() == -1 : "color map data should have been exausted";
+        return buff;
+    }
+
+    private String getAuxTableName(long rasterColumnId, SeConnection scon) throws IOException {
+
+        final String owner;
+        SeQuery query = null;
+        try {
+            final String dbaName = scon.getSdeDbaName();
+            String rastersColumnsTable = dbaName + ".SDE_RASTER_COLUMNS";
+
+            SeSqlConstruct sqlCons = new SeSqlConstruct(rastersColumnsTable);
+            sqlCons.setWhere("RASTERCOLUMN_ID = " + rasterColumnId);
+
+            try {
+                query = new SeQuery(scon, new String[] { "OWNER" }, sqlCons);
+                query.prepareQuery();
+            } catch (SeException e) {
+                // sde 9.3 calls it raster_columns, not sde_raster_columns...
+                rastersColumnsTable = dbaName + ".RASTER_COLUMNS";
+                sqlCons = new SeSqlConstruct(rastersColumnsTable);
+                sqlCons.setWhere("RASTERCOLUMN_ID = " + rasterColumnId);
+                query = new SeQuery(scon, new String[] { "OWNER" }, sqlCons);
+                query.prepareQuery();
+            }
+            query.execute();
+
+            SeRow row = query.fetch();
+            if (row == null) {
+                throw new IllegalArgumentException("No raster column registered with id "
+                        + rasterColumnId);
+            }
+            owner = row.getString(0);
+            query.close();
+        } catch (SeException e) {
+            throw new ArcSdeException("Error getting auxiliary table for raster column "
+                    + rasterColumnId, e);
+        } finally {
+            if (query != null) {
+                try {
+                    query.close();
+                } catch (SeException e) {
+                    LOGGER.log(Level.INFO, "ignoring exception when closing query to "
+                            + "fetch colormap data", e);
+                }
+            }
+        }
+
+        final String auxTableName = owner + ".SDE_AUX_" + rasterColumnId;
+
+        return auxTableName;
+    }
+
+    private List<RasterBandInfo> setUpBandInfo(SeConnection scon, SeRasterAttr rasterAttributes,
+            Map<Long, IndexColorModel> rastersColorMaps) throws IOException {
+        final int numBands;
+        final SeRasterBand[] seBands;
+        final RasterCellType cellType;
+        try {
+            numBands = rasterAttributes.getNumBands();
+            seBands = rasterAttributes.getBands();
+            cellType = RasterCellType.valueOf(rasterAttributes.getPixelType());
+        } catch (SeException e) {
+            throw new ArcSdeException(e);
+        }
+
+        List<RasterBandInfo> detachedBandInfo = new ArrayList<RasterBandInfo>(numBands);
+
+        RasterBandInfo bandInfo;
+        SeRasterBand band;
+        for (int bandN = 0; bandN < numBands; bandN++) {
+            band = seBands[bandN];
+            bandInfo = new RasterBandInfo();
+            final int bitsPerSample = cellType.getBitsPerSample();
+            setBandInfo(numBands, bandInfo, band, scon, bitsPerSample, rastersColorMaps);
+            detachedBandInfo.add(bandInfo);
+        }
+        return detachedBandInfo;
+    }
+
+    /**
+     *
+     * @param numBands
+     * @param bandInfo
+     * @param band
+     * @param scon
+     * @param bitsPerSample
+     *            only used if the band is colormapped to create the IndexColorModel
+     * @throws IOException
+     */
+    private void setBandInfo(final int numBands, final RasterBandInfo bandInfo,
+            final SeRasterBand band, final SeConnection scon, int bitsPerSample,
+            final Map<Long, IndexColorModel> colorMaps) throws IOException {
+
+        bandInfo.bandId = band.getId().longValue();
+        bandInfo.bandNumber = band.getBandNumber();
+        bandInfo.bandName = "Band " + bandInfo.bandNumber;
+
+        final boolean hasColorMap = band.hasColorMap();
+        if (hasColorMap) {
+            IndexColorModel colorMap = colorMaps.get(Long.valueOf(bandInfo.bandId));
+            LOGGER.finest("Setting band's color map: " + colorMap);
+            bandInfo.nativeColorMap = colorMap;
+            bandInfo.colorMap = RasterUtils.ensureNoDataPixelIsAvailable(colorMap);
+        } else {
+            bandInfo.nativeColorMap = null;
+        }
+
+        bandInfo.compressionType = CompressionType.valueOf(band.getCompressionType());
+        bandInfo.cellType = RasterCellType.valueOf(band.getPixelType());
+        bandInfo.interleaveType = InterleaveType.valueOf(band.getInterleave());
+        bandInfo.interpolationType = InterpolationType.valueOf(band.getInterpolation());
+        bandInfo.hasStats = band.hasStats();
+        if (bandInfo.hasStats) {
+            try {
+                bandInfo.statsMin = band.getStatsMin();
+                bandInfo.statsMax = band.getStatsMax();
+                bandInfo.statsMean = band.getStatsMean();
+                bandInfo.statsStdDev = band.getStatsStdDev();
+            } catch (SeException e) {
+                throw new ArcSdeException(e);
+            }
+            // double noDataValue = 0;
+            // bandInfo.noDataValue = noDataValue;
+        } else {
+            bandInfo.statsMin = java.lang.Double.NaN;
+            bandInfo.statsMax = java.lang.Double.NaN;
+            bandInfo.statsMean = java.lang.Double.NaN;
+            bandInfo.statsStdDev = java.lang.Double.NaN;
+        }
+        if (bandInfo.getColorMap() != null) {
+            bandInfo.noDataValue = RasterUtils.determineNoDataValue(bandInfo.getColorMap());
+        } else {
+            double statsMin = bandInfo.getStatsMin();
+            double statsMax = bandInfo.getStatsMax();
+            RasterCellType nativeCellType = bandInfo.getCellType();
+            bandInfo.noDataValue = RasterUtils.determineNoDataValue(numBands, statsMin, statsMax,
+                    nativeCellType);
+        }
+        SDEPoint tOrigin;
+        try {
+            tOrigin = band.getTileOrigin();
+        } catch (SeException e) {
+            throw new ArcSdeException(e);
+        }
+        bandInfo.tileOrigin = new Point2D.Double(tOrigin.getX(), tOrigin.getY());
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterleaveType.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterleaveType.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterleaveType.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterleaveType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,66 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.util.NoSuchElementException;
+
+import com.esri.sde.sdk.client.SeRaster;
+
+/**
+ * An enumeration that mirrors the different possible band interleave types in Arcsde (ie, {@code
+ * SeRaster#SE_RASTER_INTERLEAVE_*})
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/InterleaveType.java $
+ */
+public enum InterleaveType {
+    INTERLEAVE_BIL, INTERLEAVE_BIL_91, INTERLEAVE_BIP, INTERLEAVE_BIP_91, INTERLEAVE_BSQ, INTERLEAVE_BSQ_91, INTERLEAVE_NONE;
+    static {
+        INTERLEAVE_BIL.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIL);
+        INTERLEAVE_BIL_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIL_91);
+        INTERLEAVE_BIP.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIP);
+        INTERLEAVE_BIP_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BIP_91);
+        INTERLEAVE_BSQ.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BSQ);
+        INTERLEAVE_BSQ_91.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_BSQ_91);
+        INTERLEAVE_NONE.setSdeTypeId(SeRaster.SE_RASTER_INTERLEAVE_NONE);
+    }
+
+    private int typeId;
+
+    private void setSdeTypeId(int typeId) {
+        this.typeId = typeId;
+    }
+
+    public int getSeRasterInterleaveType() {
+        return this.typeId;
+    }
+
+    public static InterleaveType valueOf(final int seRasterInterleaveType) {
+        for (InterleaveType type : InterleaveType.values()) {
+            if (type.getSeRasterInterleaveType() == seRasterInterleaveType) {
+                return type;
+            }
+        }
+        throw new NoSuchElementException("Raster interleave type " + seRasterInterleaveType
+                + " does not exist");
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterpolationType.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/InterpolationType.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterpolationType.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/InterpolationType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,63 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.util.NoSuchElementException;
+
+import com.esri.sde.sdk.client.SeRaster;
+
+/**
+ * An enumeration that mirrors the different possible raster interpolation types in Arcsde (ie,
+ * {@code SeRaster#SE_INTERPOLATION_*})
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/InterpolationType.java $
+ */
+public enum InterpolationType {
+    INTERPOLATION_BICUBIC, INTERPOLATION_BILINEAR, INTERPOLATION_NEAREST, INTERPOLATION_NONE;
+    static {
+        INTERPOLATION_BICUBIC.setSdeTypeId(SeRaster.SE_INTERPOLATION_BICUBIC);
+        INTERPOLATION_BILINEAR.setSdeTypeId(SeRaster.SE_INTERPOLATION_BILINEAR);
+        INTERPOLATION_NEAREST.setSdeTypeId(SeRaster.SE_INTERPOLATION_NEAREST);
+        INTERPOLATION_NONE.setSdeTypeId(SeRaster.SE_INTERPOLATION_NONE);
+    }
+
+    private int typeId;
+
+    private void setSdeTypeId(int typeId) {
+        this.typeId = typeId;
+    }
+
+    public int getSeInterpolationType() {
+        return this.typeId;
+    }
+
+    public static InterpolationType valueOf(final int seInterpolationType) {
+        for (InterpolationType type : InterpolationType.values()) {
+            if (type.getSeInterpolationType() == seInterpolationType) {
+                return type;
+            }
+        }
+        throw new NoSuchElementException("Interpolation type " + seInterpolationType
+                + " does not exist");
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/PyramidLevelInfo.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PyramidLevelInfo.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/PyramidLevelInfo.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/PyramidLevelInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,178 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.Point2D;
+
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Represents one level in an ArcSDE pyramid. Holds information about a given pyramid level, like
+ * resolution, x/y offsets, number of tiles high/wide, total pixel size and total envelope covered
+ * by this level.
+ *
+ * @author sfarber
+ *
+ */
+final class PyramidLevelInfo {
+    private int pyramidLevel, xTiles, yTiles;
+
+    Point2D extentOffset;
+
+    Point imageOffset;
+
+    private double xRes, yRes;
+
+    private ReferencedEnvelope envelope;
+
+    public Dimension size;
+
+    /**
+     *
+     * @param level
+     *            the level index
+     * @param extent
+     *            the geographical extent the level covers
+     * @param imgOffset
+     *            the offset of the image at this level
+     * @param extOffset
+     *            the offset of the image extent at this level
+     * @param numTilesWide
+     * @param numTilesHigh
+     * @param levelSize
+     *            the size of the actual image inside the tiled pixel range
+     */
+    PyramidLevelInfo(int level, ReferencedEnvelope extent, Point imgOffset, Point2D extOffset,
+            int numTilesWide, int numTilesHigh, Dimension levelSize) {
+        this.pyramidLevel = level;
+        this.xRes = extent.getWidth() / levelSize.width;
+        this.yRes = extent.getHeight() / levelSize.height;
+        this.envelope = extent;
+        this.imageOffset = imgOffset;
+        this.extentOffset = extOffset;
+        this.xTiles = numTilesWide;
+        this.yTiles = numTilesHigh;
+        this.size = levelSize;
+    }
+
+    /**
+     * @return Which level in the pyramid this object represents
+     */
+    public int getLevel() {
+        return pyramidLevel;
+    }
+
+    /**
+     * @return The X and Y resolution in units/pixel for pixels at this level
+     */
+    public double getXRes() {
+        return xRes;
+    }
+
+    /**
+     * @return The X and Y resolution in units/pixel for pixels at this level
+     */
+    public double getYRes() {
+        return yRes;
+    }
+
+    /**
+     * @return DOCUMENT ME!!!
+     */
+    public int getXOffset() {
+        return imageOffset.x;
+    }
+
+    /**
+     * @return DOCUMENT ME!!!
+     */
+    public int getYOffset() {
+        return imageOffset.y;
+    }
+
+    /**
+     * @return The total number of tiles covering the width of this level
+     */
+    public int getNumTilesWide() {
+        return xTiles;
+    }
+
+    /**
+     * @return The total number of tiles covering the height of this level
+     */
+    public int getNumTilesHigh() {
+        return yTiles;
+    }
+
+    /**
+     * The envelope covering the image grid range inside fully tiled image at this pyramid level
+     *
+     * @return The geographical area covered by the {@link #getImageRange() grid range} of the
+     *         raster at this pyramid level
+     */
+    public ReferencedEnvelope getImageEnvelope() {
+        final double deltaX = extentOffset.getX();
+        final double deltaY = extentOffset.getY();
+        double minx = this.envelope.getMinX() - deltaX;
+        double miny = this.envelope.getMinY() - deltaY;
+        double maxx = minx + this.envelope.getWidth();
+        double maxy = miny + this.envelope.getHeight();
+
+        CoordinateReferenceSystem crs = this.envelope.getCoordinateReferenceSystem();
+        ReferencedEnvelope imageExtent = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
+
+        return imageExtent;
+    }
+
+    /**
+     * @return The total number of pixels in the image at this level as whole tiles
+     */
+    public Dimension getSize() {
+        return size;
+    }
+
+    /**
+     * The rectangle covering the actual raster data inside the tiled space
+     *
+     * @return
+     */
+    public Rectangle getImageRange() {
+        final int offsetX = getXOffset();
+        final int offsetY = getYOffset();
+
+        /*
+         * get the range of actual data pixels in this pyramid level in pixel space, offset and
+         * trailing no data pixels to fill up the tile space do not count
+         */
+        final Rectangle levelRange = new Rectangle(offsetX, offsetY, size.width, size.height);
+        return levelRange;
+    }
+
+    @Override
+    public String toString() {
+        return "[level: " + pyramidLevel + " size: " + size.width + "x" + size.height + "  xRes: "
+                + xRes + "  yRes: " + yRes + "  xOffset: " + getXOffset() + "  yOffset: "
+                + getYOffset() + "  extent: " + envelope.getMinX() + "," + envelope.getMinY() + " "
+                + envelope.getMaxX() + "," + envelope.getMaxY() + "  tilesWide: " + xTiles
+                + "  tilesHigh: " + yTiles + "]";
+    }
+}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterBandInfo.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterBandInfo.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterBandInfo.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterBandInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,186 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.geom.Point2D;
+import java.awt.geom.Point2D.Double;
+import java.awt.image.IndexColorModel;
+
+/**
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/RasterBandInfo.java $
+ */
+public class RasterBandInfo {
+
+    long bandId;
+
+    String bandName;
+
+    int bandNumber;
+
+    /**
+     * the color map as it is on the database, except that we always create a color map with alpha
+     * channel regardless of whether the native on has alpha or not, to account for the no-data
+     * pixel to be a transparent one where appropriate
+     */
+    IndexColorModel nativeColorMap;
+
+    /**
+     * The color map as it is going to be used by this library. May differ from the native one
+     * either in the number of elements (when the native color map is not full and it has no
+     * transparent pixel to be used as no-data value), or in the pixel depth (when the native
+     * colormap is full, has no no-data pixel, and hence it needs to be promoted to a higher
+     * transfer type to make room for a no-data index)
+     */
+    IndexColorModel colorMap;
+
+    /**
+     * The band's no-data value.
+     */
+    Number noDataValue;
+
+    CompressionType compressionType;
+
+    RasterCellType cellType;
+
+    InterleaveType interleaveType;
+
+    InterpolationType interpolationType;
+
+    boolean hasStats;
+
+    Point2D.Double tileOrigin;
+
+    double statsMin;
+
+    double statsMax;
+
+    double statsMean;
+
+    double statsStdDev;
+
+    public RasterBandInfo() {
+        // do nothing
+    }
+
+    public RasterBandInfo(long bandId, RasterCellType nativeType, Number noDataValue,
+            double statsMin, double statsMax) {
+        this.bandId = bandId;
+        this.cellType = nativeType;
+        this.noDataValue = noDataValue;
+        this.statsMin = statsMin;
+        this.statsMax = statsMax;
+    }
+
+    /**
+     * @return the ArcSDE identifier for the band
+     */
+    public long getBandId() {
+        return bandId;
+    }
+
+    public String getBandName() {
+        return bandName;
+    }
+
+    public int getBandNumber() {
+        return bandNumber;
+    }
+
+    public boolean isColorMapped() {
+        return nativeColorMap != null;
+    }
+
+    public CompressionType getCompressionType() {
+        return compressionType;
+    }
+
+    public RasterCellType getCellType() {
+        return cellType;
+    }
+
+    public InterleaveType getInterleaveType() {
+        return interleaveType;
+    }
+
+    public InterpolationType getInterpolationType() {
+        return interpolationType;
+    }
+
+    public boolean isHasStats() {
+        return hasStats;
+    }
+
+    public Double getTileOrigin() {
+        return tileOrigin;
+    }
+
+    public IndexColorModel getNativeColorMap() {
+        return nativeColorMap;
+    }
+
+    public IndexColorModel getColorMap() {
+        return colorMap;
+    }
+
+    public double getStatsMin() {
+        return statsMin;
+    }
+
+    public double getStatsMax() {
+        return statsMax;
+    }
+
+    public double getStatsMean() {
+        return statsMean;
+    }
+
+    public double getStatsStdDev() {
+        return statsStdDev;
+    }
+
+    public Number getNoDataValue() {
+        return noDataValue;
+    }
+
+    @SuppressWarnings("nls")
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getBandName());
+        sb.append("[ id:").append(getBandId());
+        sb.append(", type:").append(getCellType());
+        sb.append(", samples: nodata=").append(getNoDataValue()).append(" min=").append(
+                getStatsMin()).append(" max=").append(getStatsMax()).append(" mean=").append(
+                getStatsMean()).append(" stddev=").append(getStatsStdDev());
+        /*
+         * sb.append(", tile origin: ").append((int) getTileOrigin().x).append(",").append( (int)
+         * getTileOrigin().y);
+         */
+        sb.append(", compression:").append(getCompressionType());
+        sb.append(", interpolation:").append(getInterpolationType());
+        sb.append(", Color Map: ").append(isColorMapped() ? "YES" : "NO");
+        return sb.toString();
+    }
+
+}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterCellType.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterCellType.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterCellType.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterCellType.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,121 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.image.DataBuffer;
+import java.util.NoSuchElementException;
+
+import org.geotools.util.NumberRange;
+
+import com.esri.sde.sdk.client.SeRaster;
+
+/**
+ * An enumeration that mirrors the different possible cell resolutions in Arcsde (ie, {@code
+ * SeRaster#SE_PIXEL_TYPE_*})
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/RasterCellType.java $
+ */
+public enum RasterCellType {
+    TYPE_16BIT_S(16, DataBuffer.TYPE_SHORT, true, NumberRange.create(Short.MIN_VALUE,
+            Short.MAX_VALUE)), //
+    TYPE_16BIT_U(16, DataBuffer.TYPE_USHORT, false, NumberRange.create((int) 0, (int) 65535)), //
+    TYPE_1BIT(1, DataBuffer.TYPE_BYTE, false, NumberRange.create((byte) 0, (byte) 1)), //
+    TYPE_32BIT_REAL(32, DataBuffer.TYPE_FLOAT, true, NumberRange.create(Float.MIN_VALUE,
+            Float.MAX_VALUE)), //
+    TYPE_32BIT_S(32, DataBuffer.TYPE_INT, true, NumberRange.create(Integer.MIN_VALUE,
+            Integer.MAX_VALUE)), //
+    TYPE_32BIT_U(32, DataBuffer.TYPE_INT, false, NumberRange.create(0L, (long) Math.pow(2, 32) - 1)), //
+    TYPE_4BIT(4, DataBuffer.TYPE_BYTE, false, NumberRange.create((byte) 0,
+            (byte) Math.pow(2, 4) - 1)), //
+    TYPE_64BIT_REAL(64, DataBuffer.TYPE_DOUBLE, true, NumberRange.create(Double.MIN_VALUE,
+            Double.MAX_VALUE)), //
+    TYPE_8BIT_S(8, DataBuffer.TYPE_BYTE, true, NumberRange.create(Byte.MIN_VALUE, Byte.MAX_VALUE)), //
+    TYPE_8BIT_U(8, DataBuffer.TYPE_BYTE, false, NumberRange.create((int) 0, (int) 255));
+    static {
+        // Setting the se_pixel_type in a static initializer to avoid having them linked to the fake
+        // values in the dummy api
+        TYPE_16BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_16BIT_S);
+        TYPE_16BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_16BIT_U);
+        TYPE_1BIT.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_1BIT);
+        TYPE_32BIT_REAL.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_REAL);
+        TYPE_32BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_S);
+        TYPE_32BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_32BIT_U);
+        TYPE_4BIT.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_4BIT);
+        TYPE_64BIT_REAL.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_64BIT_REAL);
+        TYPE_8BIT_S.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_8BIT_S);
+        TYPE_8BIT_U.setSdeTypeId(SeRaster.SE_PIXEL_TYPE_8BIT_U);
+    }
+
+    private int typeId;
+
+    private final int bitsPerSample;
+
+    private final int dataBufferType;
+
+    private final boolean signed;
+
+    private final NumberRange<?> sampleValueRange;
+
+    private RasterCellType(final int bitsPerSample, final int dataBufferType, final boolean signed,
+            final NumberRange<?> sampleValueRange) {
+        this.bitsPerSample = bitsPerSample;
+        this.dataBufferType = dataBufferType;
+        this.signed = signed;
+        this.sampleValueRange = sampleValueRange;
+    }
+
+    private void setSdeTypeId(int typeId) {
+        this.typeId = typeId;
+    }
+
+    public int getSeRasterPixelType() {
+        return this.typeId;
+    }
+
+    public int getBitsPerSample() {
+        return bitsPerSample;
+    }
+
+    public int getDataBufferType() {
+        return dataBufferType;
+    }
+
+    public boolean isSigned() {
+        return signed;
+    }
+
+    public static RasterCellType valueOf(final int seRasterPixelType) {
+        for (RasterCellType type : RasterCellType.values()) {
+            if (type.getSeRasterPixelType() == seRasterPixelType) {
+                return type;
+            }
+        }
+        throw new NoSuchElementException("Raster pixel type " + seRasterPixelType
+                + " does not exist");
+    }
+
+    public NumberRange<?> getSampleValueRange() {
+        return sampleValueRange;
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterDatasetInfo.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterDatasetInfo.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterDatasetInfo.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterDatasetInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,503 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.image.IndexColorModel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.imageio.ImageTypeSpecifier;
+
+import org.geotools.coverage.Category;
+import org.geotools.coverage.GridSampleDimension;
+import org.geotools.coverage.grid.GeneralGridEnvelope;
+import org.geotools.coverage.grid.io.OverviewPolicy;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.CRS;
+import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
+import org.geotools.referencing.operation.transform.LinearTransform1D;
+import org.geotools.resources.i18n.Vocabulary;
+import org.geotools.resources.i18n.VocabularyKeys;
+import org.geotools.util.NumberRange;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.opengis.referencing.operation.TransformException;
+
+/**
+ * Wraps metadata information for a raster dataset, whether it is composed of a single raster, or
+ * it's raster catalog, and provides some conveinent methods to get to the raster metadata of it's
+ * rasters and pyramid levels.
+ * <p>
+ * This is the single entry point to the metadata of a raster dataset. The associated classes
+ * {@link RasterInfo} and {@link PyramidLevelInfo} are to be considered private to this class.
+ * </p>
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/RasterDatasetInfo.java $
+ */
+@SuppressWarnings( { "nls" })
+public final class RasterDatasetInfo {
+
+    /** TRasterDatasetInfo the raster table we're pulling images from in this reader * */
+    private String rasterTable = null;
+
+    /**
+     * raster column names on this raster. If there's more than one raster column (is this
+     * possible?) then we just use the first one.
+     */
+    private String[] rasterColumns;
+
+    /** Array holding information on each level of the pyramid in this raster. * */
+    private List<RasterInfo> subRasterInfo;
+
+    /**
+     * The original (ie, pyramid level zero) envelope for the whole raster dataset
+     */
+    private GeneralEnvelope originalEnvelope;
+
+    private GeneralGridEnvelope originalGridRange;
+
+    private List<GridSampleDimension> gridSampleDimensions;
+
+    private final Map<Integer, ImageTypeSpecifier> renderedImageSpec = new HashMap<Integer, ImageTypeSpecifier>();
+
+    /**
+     * @param rasterTable
+     *            the rasterTable to set
+     */
+    void setRasterTable(String rasterTable) {
+        this.rasterTable = rasterTable;
+    }
+
+    /**
+     * @return the raster table name
+     */
+    public String getRasterTable() {
+        return rasterTable;
+    }
+
+    /**
+     * @param rasterColumns
+     *            the rasterColumns to set
+     */
+    void setRasterColumns(String[] rasterColumns) {
+        this.rasterColumns = rasterColumns;
+    }
+
+    /**
+     * @return the raster column names
+     */
+    public String[] getRasterColumns() {
+        return rasterColumns;
+    }
+
+    /**
+     * @param pyramidInfo
+     *            the pyramidInfo to set
+     */
+    public void setPyramidInfo(List<RasterInfo> pyramidInfo) {
+        this.subRasterInfo = pyramidInfo;
+    }
+
+    public GridSampleDimension[] getGridSampleDimensions() {
+        if (gridSampleDimensions == null) {
+            synchronized (this) {
+                if (gridSampleDimensions == null) {
+                    gridSampleDimensions = buildSampleDimensions();
+                }
+            }
+        }
+        return gridSampleDimensions.toArray(new GridSampleDimension[getNumBands()]);
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<GridSampleDimension> buildSampleDimensions() {
+
+        final int numBands = getNumBands();
+        List<GridSampleDimension> dimensions = new ArrayList<GridSampleDimension>(numBands);
+
+        final Color transparent = new Color(0, 0, 0, 0);
+
+        List<RasterBandInfo> bands = subRasterInfo.get(0).getBands();
+
+        for (RasterBandInfo band : bands) {
+            final int bandNumber = band.getBandNumber();
+            // use native cell type, in case no-data value has been computed to account for
+            // sample depth promotion, we want to category to keep being the native range for
+            // the values category
+            final RasterCellType targetCellType = getNativeCellType();
+            String bandName = band.getBandName();
+
+            final double statsMin = band.getStatsMin();
+            final double statsMax = band.getStatsMax();
+
+            NumberRange<?> sampleValueRange;
+            if (Double.isNaN(statsMin) || Double.isNaN(statsMax)) {
+                sampleValueRange = targetCellType.getSampleValueRange();
+            } else {
+                sampleValueRange = NumberRange.create(statsMin, statsMax);
+                Class elementClass = targetCellType.getSampleValueRange().getElementClass();
+                sampleValueRange = sampleValueRange.castTo(elementClass);
+            }
+
+            final Color[] colorRange = null;
+
+            final boolean geophysics = isGeoPhysics();
+
+            Category valuesCat = new Category("values", colorRange, sampleValueRange,
+                    LinearTransform1D.IDENTITY).geophysics(geophysics);
+
+            Category[] categories;
+            if (geophysics) {
+                double noDataValue = band.getNoDataValue().doubleValue();
+                // same as Category.NODATA but for the actual nodata value instead of hardcoded to
+                // zero
+                Category nodataCat = new Category(Vocabulary
+                        .formatInternational(VocabularyKeys.NODATA), transparent, noDataValue);
+                categories = new Category[] { valuesCat, nodataCat };
+            } else {
+                // do not build a nodata category. A nodata value that doesn't overlap the value
+                // range couldn't be determined
+                categories = new Category[] { valuesCat };
+            }
+            /*
+             * if (band.isHasStats()) { //can't do this, get an exception telling categories
+             * overlap.. so no real way to express the statistics, uh? Category catMin = new
+             * Category("Min", null, band.getStatsMin()).geophysics(true); Category catMax = new
+             * Category("Max", null, band.getStatsMin()).geophysics(true); Category catMean = new
+             * Category("Mean", null, band.getStatsMin()).geophysics(true); Category catStdDev = new
+             * Category("StdDev", null, band.getStatsMin()) .geophysics(true); categories = new
+             * Category[] { valuesCat, nodataCat, catMin, catMax, catMean, catStdDev }; } else {
+             * categories = new Category[] { valuesCat, nodataCat }; }
+             */
+
+            // .geophysics(false) because our sample model always corresponds to the packed view
+            // (whether it matches the underlying sample depth or we're promoting in order to make
+            // room for the nodata value).
+            GridSampleDimension sampleDim = new GridSampleDimension(bandName, categories, null)
+                    .geophysics(false);
+
+            dimensions.add(sampleDim);
+        }
+        return dimensions;
+    }
+
+    private boolean isGeoPhysics() {
+        if (isColorMapped()) {
+            return false;
+        }
+        return RasterUtils.isGeoPhysics(getNumBands(), getNativeCellType());
+    }
+
+    public int getNumBands() {
+        return subRasterInfo.get(0).getNumBands();
+    }
+
+    public int getImageWidth() {
+        final GeneralGridEnvelope originalGridRange = getOriginalGridRange();
+        final int width = originalGridRange.getSpan(0);
+        return width;
+    }
+
+    public int getImageHeight() {
+        final GeneralGridEnvelope originalGridRange = getOriginalGridRange();
+        final int height = originalGridRange.getSpan(1);
+        return height;
+    }
+
+    /**
+     * @return the coverageCrs
+     */
+    public CoordinateReferenceSystem getCoverageCrs() {
+        return subRasterInfo.get(0).getCoordinateReferenceSystem();
+    }
+
+    /**
+     * @return the originalGridRange for the whole raster dataset, based on the first raster in the
+     *         raster dataset
+     */
+    public GeneralGridEnvelope getOriginalGridRange() {
+        if (originalGridRange == null) {
+            final MathTransform modelToRaster;
+            try {
+                final MathTransform rasterToModel = getRasterToModel();
+                modelToRaster = rasterToModel.inverse();
+            } catch (NoninvertibleTransformException e) {
+                throw new IllegalStateException("Can't create transform from model to raster");
+            }
+
+            int minx = Integer.MAX_VALUE;
+            int miny = Integer.MAX_VALUE;
+            int maxx = Integer.MIN_VALUE;
+            int maxy = Integer.MIN_VALUE;
+
+            final int rasterCount = getNumRasters();
+            for (int rasterN = 0; rasterN < rasterCount; rasterN++) {
+                final GeneralEnvelope rasterEnvelope = getGridEnvelope(rasterN, 0);
+                GeneralEnvelope rasterGridRangeInDataSet;
+                try {
+                    rasterGridRangeInDataSet = CRS.transform(modelToRaster, rasterEnvelope);
+                } catch (NoninvertibleTransformException e) {
+                    throw new IllegalArgumentException(e);
+                } catch (TransformException e) {
+                    throw new IllegalArgumentException(e);
+                }
+
+                minx = Math.min(minx, (int) Math.floor(rasterGridRangeInDataSet.getMinimum(0)));
+                miny = Math.min(miny, (int) Math.floor(rasterGridRangeInDataSet.getMinimum(1)));
+                maxx = Math.max(maxx, (int) Math.ceil(rasterGridRangeInDataSet.getMaximum(0)));
+                maxy = Math.max(maxy, (int) Math.ceil(rasterGridRangeInDataSet.getMaximum(1)));
+            }
+            int width = maxx - minx;
+            int height = maxy - miny;
+            Rectangle range = new Rectangle(0, 0, width, height);
+            originalGridRange = new GeneralGridEnvelope(range, 2);
+        }
+        return originalGridRange;
+    }
+
+    public MathTransform getRasterToModel() {
+
+        GeneralEnvelope firstRasterEnvelope = getGridEnvelope(0, 0);
+        Rectangle firstRasterGridRange = getGridRange(0, 0);
+        GeneralGridEnvelope gridRange = new GeneralGridEnvelope(firstRasterGridRange, 2);
+
+        // create a raster to model transform, from this tile pixel space to the tile's geographic
+        // extent
+        GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(gridRange, firstRasterEnvelope);
+        geMapper.setPixelAnchor(PixelInCell.CELL_CORNER);
+
+        final MathTransform rasterToModel = geMapper.createTransform();
+        return rasterToModel;
+    }
+
+    /**
+     * @return the originalEnvelope
+     */
+    public GeneralEnvelope getOriginalEnvelope() {
+        if (originalEnvelope == null) {
+            GeneralEnvelope env = null;
+            for (RasterInfo raster : subRasterInfo) {
+                GeneralEnvelope rasterEnvelope = raster.getOriginalEnvelope();
+                if (env == null) {
+                    env = new GeneralEnvelope(rasterEnvelope);
+                } else {
+                    env.add(rasterEnvelope);
+                }
+            }
+            originalEnvelope = env;
+        }
+        return originalEnvelope;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("ArcSDE Raster: " + getRasterTable());
+        sb.append(", Raster columns: ").append(Arrays.asList(getRasterColumns()));
+        sb.append(", Num bands: ").append(getNumBands());
+        sb.append(", Dimension: ").append(getImageWidth()).append("x").append(getImageHeight());
+        sb.append(", Pixel type: ").append(getNativeCellType());
+        sb.append(", Has Color Map: ").append(isColorMapped());
+        for (int rasterIndex = 0; rasterIndex < getNumRasters(); rasterIndex++) {
+            RasterInfo raster = getRasterInfo(rasterIndex);
+            sb.append("\n ");
+            sb.append(raster.toString());
+        }
+        return sb.toString();
+    }
+
+    public int getNumRasters() {
+        return subRasterInfo.size();
+    }
+
+    public RasterBandInfo getBand(final int rasterIndex, final int bandIndex) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getBand(bandIndex);
+    }
+
+    public int getNumPyramidLevels(final int rasterIndex) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getNumLevels();
+    }
+
+    public GeneralEnvelope getGridEnvelope(final int rasterIndex, final int pyramidLevel) {
+        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
+        return new GeneralEnvelope(level.getImageEnvelope());
+    }
+
+    public Rectangle getGridRange(final int rasterIndex, final int pyramidLevel) {
+        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
+        Rectangle levelRange = level.getImageRange();
+        return levelRange;
+    }
+
+    public int getNumTilesWide(int rasterIndex, int pyramidLevel) {
+        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
+        return level.getNumTilesWide();
+    }
+
+    public int getNumTilesHigh(int rasterIndex, int pyramidLevel) {
+        PyramidLevelInfo level = getLevel(rasterIndex, pyramidLevel);
+        return level.getNumTilesHigh();
+    }
+
+    public int getTileWidth(final long rasterId) {
+        return getTileDimension(rasterId).width;
+    }
+
+    public int getTileHeight(final long rasterId) {
+        return getTileDimension(rasterId).height;
+    }
+
+    public Dimension getTileDimension(final long rasterId) {
+        final int rasterIndex = getRasterIndex(rasterId);
+        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getTileDimension();
+    }
+
+    public Dimension getTileDimension(int rasterIndex) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getTileDimension();
+    }
+
+    private PyramidLevelInfo getLevel(int rasterIndex, int pyramidLevel) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        PyramidLevelInfo level = rasterInfo.getPyramidLevel(pyramidLevel);
+        return level;
+    }
+
+    private RasterInfo getRasterInfo(int rasterIndex) {
+        RasterInfo rasterInfo = subRasterInfo.get(rasterIndex);
+        return rasterInfo;
+    }
+
+    public ImageTypeSpecifier getRenderedImageSpec(final long rasterId) {
+        final int rasterIndex = getRasterIndex(rasterId);
+        return getRenderedImageSpec(rasterIndex);
+    }
+
+    public ImageTypeSpecifier getRenderedImageSpec(final int rasterIndex) {
+        if (!this.renderedImageSpec.containsKey(Integer.valueOf(rasterIndex))) {
+            synchronized (this) {
+                if (!this.renderedImageSpec.containsKey(Integer.valueOf(rasterIndex))) {
+                    ImageTypeSpecifier imageTypeSpecifier;
+                    imageTypeSpecifier = RasterUtils
+                            .createFullImageTypeSpecifier(this, rasterIndex);
+                    renderedImageSpec.put(Integer.valueOf(rasterIndex), imageTypeSpecifier);
+                }
+            }
+        }
+        return this.renderedImageSpec.get(Integer.valueOf(rasterIndex));
+    }
+
+    public IndexColorModel getColorMap(final int rasterIndex) {
+        final RasterBandInfo bandOne = getBand(rasterIndex, 0);
+        return bandOne.getColorMap();
+    }
+
+    public boolean isColorMapped() {
+        RasterInfo rasterInfo = getRasterInfo(0);
+        return rasterInfo.isColorMapped();
+    }
+
+    public RasterCellType getNativeCellType() {
+        RasterInfo rasterInfo = getRasterInfo(0);
+        return rasterInfo.getNativeCellType();
+    }
+
+    public RasterCellType getTargetCellType(final int rasterIndex) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getTargetCellType();
+    }
+
+    public RasterCellType getTargetCellType(final long rasterId) {
+        final int rasterIndex = getRasterIndex(rasterId);
+        return getTargetCellType(rasterIndex);
+    }
+
+    public Long getRasterId(final int rasterIndex) {
+        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        return rasterInfo.getRasterId();
+    }
+
+    public int getOptimalPyramidLevel(final int rasterIndex, final OverviewPolicy policy,
+            final GeneralEnvelope requestedEnvelope, final Rectangle requestedDim) {
+
+        final RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+
+        double[] requestedRes = new double[2];
+        double reqSpanX = requestedEnvelope.getSpan(0);
+        double reqSpanY = requestedEnvelope.getSpan(1);
+        requestedRes[0] = reqSpanX / requestedDim.getWidth();
+        requestedRes[1] = reqSpanY / requestedDim.getHeight();
+
+        return rasterInfo.getOptimalPyramidLevel(policy, requestedRes);
+    }
+
+    public int getRasterIndex(Long rasterId) {
+        int index = -1;
+        for (RasterInfo p : subRasterInfo) {
+            index++;
+            if (rasterId.equals(p.getRasterId())) {
+                return index;
+            }
+        }
+        throw new IllegalArgumentException("rasterId: " + rasterId);
+    }
+
+    public double[] getResolution(int rasterN, int pyramidLevel) {
+        RasterInfo rasterInfo = getRasterInfo(rasterN);
+        double[] resolution = rasterInfo.getResolution(pyramidLevel);
+        return resolution;
+    }
+
+    public Point getTileOffset(final int rasterIndex, final int pyramidLevel) {
+        RasterInfo rasterInfo = getRasterInfo(rasterIndex);
+        PyramidLevelInfo level = rasterInfo.getPyramidLevel(pyramidLevel);
+        return new Point(level.getXOffset(), level.getYOffset());
+    }
+
+    public Number getNoDataValue(final int rasterIndex, final int bandIndex) {
+        RasterBandInfo band = getBand(rasterIndex, bandIndex);
+        Number noDataValue = band.getNoDataValue();
+        return noDataValue;
+    }
+
+    /**
+     * @param rasterIndex
+     *            the raster for which bands to return the no data values
+     * @return the list of no data values, one per band for the raster at index {@code rasterIndex}
+     */
+    public List<Number> getNoDataValues(final int rasterIndex) {
+        return getRasterInfo(rasterIndex).getNoDataValues();
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterInfo.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterInfo.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterInfo.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,406 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.geotools.coverage.grid.io.OverviewPolicy;
+import org.geotools.data.DataSourceException;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.referencing.CRS;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import com.esri.sde.sdk.client.SDEPoint;
+import com.esri.sde.sdk.client.SeException;
+import com.esri.sde.sdk.client.SeExtent;
+import com.esri.sde.sdk.client.SeRasterAttr;
+
+/**
+ * A RasterInfo gathers the metadata for a single raster in a raster dataset
+ * <p>
+ * Basically, it wraps the SeRasterAttr object and implements some convenience methods for doing
+ * calculations with it.
+ * </p>
+ *
+ * @author Saul Farber
+ * @author Gabriel Roldan
+ */
+public final class RasterInfo {
+
+    /**
+     * Orders pyramid levels by their level index
+     */
+    private static final Comparator<PyramidLevelInfo> levelComparator = new Comparator<PyramidLevelInfo>() {
+        public int compare(PyramidLevelInfo p0, PyramidLevelInfo p1) {
+            return (p0.getLevel() - p1.getLevel());
+        }
+    };
+
+    ArrayList<PyramidLevelInfo> pyramidList;
+
+    private int tileWidth;
+
+    private int tileHeight;
+
+    private GeneralEnvelope originalEnvelope;
+
+    private ArrayList<RasterBandInfo> bands;
+
+    private CoordinateReferenceSystem crs;
+
+    private Long rasterId;
+
+    /**
+     * Creates an in-memory representation of an ArcSDE Raster Pyramid. Basically it wraps the
+     * supplide SeRasterAttr object and implements some convenience logic for extracting
+     * information/ doing calculations with it.
+     *
+     * @param rasterAttributes
+     *            the SeRasterAttr object for the raster of interest.
+     * @param crs
+     * @throws DataSourceException
+     */
+    RasterInfo(final SeRasterAttr rasterAttributes, final CoordinateReferenceSystem crs)
+            throws DataSourceException {
+        this.crs = crs;
+        try {
+            this.rasterId = Long.valueOf(rasterAttributes.getRasterId().longValue());
+            // levels goes from 0 to N, maxLevel is the zero-based max index of levels
+            final int numLevels = rasterAttributes.getMaxLevel() + 1;
+
+            pyramidList = new ArrayList<PyramidLevelInfo>(numLevels);
+
+            tileWidth = rasterAttributes.getTileWidth();
+            tileHeight = rasterAttributes.getTileHeight();
+
+            for (int level = 0; level < numLevels; level++) {
+                if (level == 1 && rasterAttributes.skipLevelOne()) {
+                    continue;
+                }
+
+                /*
+                 * this extent corresponds to the actual image size inside the tiled grid. That is,
+                 * to getImageWidth/Height by level. The dimensions of this extent are correct, but
+                 * it needs to be shifted by SeRasterAttr.getExtentOffsetByLevel(level) the same way
+                 * the grid envelope does by SeRasterAttr.getImageOffsetByLevel(level)
+                 */
+                final SeExtent slExtent = rasterAttributes.getExtentByLevel(level);
+
+                final int levelWidth = rasterAttributes.getImageWidthByLevel(level);
+                final int levelHeight = rasterAttributes.getImageHeightByLevel(level);
+
+                Dimension levelImageSize = new Dimension(levelWidth, levelHeight);
+
+                Point imgOffset = new Point();
+                // extent offset equals imgOffset * pixel resolution (ie, if resx == 2 and offsetX =
+                // 10, extent offset x == 20)
+                Point2D extOffset = new Point2D.Double();
+                {
+                    SDEPoint imageOffset = rasterAttributes.getImageOffsetByLevel(level);
+                    int xOffset = (int) (imageOffset == null ? 0 : imageOffset.getX());
+                    int yOffset = (int) (imageOffset == null ? 0 : imageOffset.getY());
+                    imgOffset.setLocation(xOffset, yOffset);
+
+                    SDEPoint extentOffset = rasterAttributes.getExtentOffsetByLevel(level);
+                    double xOffsetExtent = extentOffset == null ? 0D : extentOffset.getX();
+                    double yOffsetExtent = extentOffset == null ? 0D : extentOffset.getY();
+                    extOffset.setLocation(xOffsetExtent, yOffsetExtent);
+                }
+
+                final int numTilesWide = rasterAttributes.getTilesPerRowByLevel(level);
+                final int numTileHigh = rasterAttributes.getTilesPerColByLevel(level);
+
+                ReferencedEnvelope levelExtent = new ReferencedEnvelope(slExtent.getMinX(),
+                        slExtent.getMaxX(), slExtent.getMinY(), slExtent.getMaxY(), crs);
+
+                addPyramidLevel(level, levelExtent, imgOffset, extOffset, numTilesWide,
+                        numTileHigh, levelImageSize);
+            }
+
+        } catch (SeException se) {
+            throw new DataSourceException(se);
+        }
+    }
+
+    public Long getRasterId() {
+        return rasterId;
+    }
+
+    public int getTileWidth() {
+        return tileWidth;
+    }
+
+    public int getTileHeight() {
+        return tileHeight;
+    }
+
+    /**
+     * Don't use this constructor. It only exists for unit testing purposes.
+     *
+     * @param tileWidth
+     *            DON'T USE
+     * @param tileHeight
+     *            DON'T USE
+     */
+    public RasterInfo(Long rasterId, int tileWidth, int tileHeight) {
+        this.rasterId = rasterId;
+        this.tileWidth = tileWidth;
+        this.tileHeight = tileHeight;
+        pyramidList = new ArrayList<PyramidLevelInfo>(4);
+    }
+
+    public Dimension getTileDimension() {
+        return new Dimension(tileWidth, tileHeight);
+    }
+
+    public PyramidLevelInfo getPyramidLevel(int level) {
+        return pyramidList.get(level);
+    }
+
+    public int getNumLevels() {
+        return pyramidList.size();
+    }
+
+    /**
+     * @param pyramidLevel
+     * @return resx, resy, scalefactor
+     */
+    double[] getResolution(final int pyramidLevel) {
+        final double highestRes = getPyramidLevel(0).getXRes();
+        PyramidLevelInfo level = getPyramidLevel(pyramidLevel);
+        double[] resolution = new double[3];
+        resolution[0] = level.getXRes();
+        resolution[1] = level.getYRes();
+        resolution[2] = level.getXRes() / highestRes;
+        return resolution;
+    }
+
+    /**
+     * <p>
+     * NOTE: logic stolen and adapted from {@code AbstractGridCoverage2DReader#getOverviewImage()}
+     * </p>
+     *
+     * @param policy
+     * @return
+     */
+    public int getOptimalPyramidLevel(final OverviewPolicy policy, final double[] requestedRes) {
+
+        int pyramidLevelChoice = 0;
+
+        // sort resolutions from smallest pixels (higher res) to biggest pixels (higher res)
+        // keeping a reference to the original image choice
+        final double[] highestRes = getResolution(0);
+
+        // Now search for the best matching resolution.
+        // Check also for the "perfect match"... unlikely in practice unless someone
+        // tunes the clients to request exactly the resolution embedded in
+        // the overviews, something a perf sensitive person might do in fact
+
+        // the requested resolutions
+        final double reqx = requestedRes[0];
+        final double reqy = requestedRes[1];
+
+        // requested scale factor for least reduced axis
+        final double requestedScaleFactorX = reqx / highestRes[0];
+        final double requestedScaleFactorY = reqy / highestRes[1];
+        final int leastReduceAxis = requestedScaleFactorX <= requestedScaleFactorY ? 0 : 1;
+        final double requestedScaleFactor = leastReduceAxis == 0 ? requestedScaleFactorX
+                : requestedScaleFactorY;
+
+        final int numLevels = getNumLevels();
+
+        // no pyramiding or are we looking for a resolution even higher than the native one?
+        if (0 == numLevels || requestedScaleFactor <= 1) {
+            pyramidLevelChoice = 0;
+        } else {
+            // are we looking for a resolution even lower than the smallest overview?
+            final double[] min = getResolution(numLevels - 1);
+            if (requestedScaleFactor >= min[2]) {
+                pyramidLevelChoice = numLevels - 1;
+            } else {
+                // Ok, so we know the overview is between min and max, skip the first
+                // and search for an overview with a resolution lower than the one requested,
+                // that one and the one from the previous step will bound the searched resolution
+                double[] prev = highestRes;
+                for (int levelN = 1; levelN < numLevels; levelN++) {
+                    final double[] curr = getResolution(levelN);
+                    // perfect match check
+                    if (curr[2] == requestedScaleFactor) {
+                        pyramidLevelChoice = levelN;
+                    } else {
+                        /*
+                         * middle check. The first part of the condition should be sufficient, but
+                         * there are cases where the x resolution is satisfied by the lowest
+                         * resolution, the y by the one before the lowest (so the aspect ratio of
+                         * the request is different than the one of the overviews), and we would end
+                         * up going out of the loop since not even the lowest can "top" the request
+                         * for one axis
+                         */
+                        if (curr[2] > requestedScaleFactor || levelN == numLevels - 1) {
+                            if (policy == OverviewPolicy.QUALITY) {
+                                pyramidLevelChoice = levelN - 1;
+                            } else if (policy == OverviewPolicy.SPEED) {
+                                return levelN;
+                            } else if (requestedScaleFactor - prev[2] < curr[2]
+                                    - requestedScaleFactor) {
+                                pyramidLevelChoice = levelN - 1;
+                            } else {
+                                pyramidLevelChoice = levelN;
+                            }
+                            break;
+                        }
+                        prev = curr;
+                    }
+                }
+            }
+        }
+        // fallback
+        return pyramidLevelChoice;
+    }
+
+    /**
+     * Don't use this method. It's only public for unit testing purposes.
+     *
+     * @param level
+     *            the zero-based level index for the new level
+     * @param extent
+     *            the geographical extent the level covers, may need to be offsetted by {@code
+     *            extOffset}
+     * @param imgOffset
+     *            the offset on the X and Y axes of the actual image inside the tile space for this
+     *            level
+     * @param extOffset
+     *            the offset on the X and Y axes of the actual image inside the tile space for this
+     *            level
+     * @param numTilesWide
+     *            the number of tiles that make up the level on the X axis
+     * @param numTilesHigh
+     *            the number of tiles that make up the level on the Y axis
+     * @param imageSize
+     *            the size of the actual image in pixels
+     */
+    public void addPyramidLevel(int level, ReferencedEnvelope extent, Point imgOffset,
+            Point2D extOffset, int numTilesWide, int numTilesHigh, Dimension imageSize) {
+
+        PyramidLevelInfo pyramidLevel;
+        pyramidLevel = new PyramidLevelInfo(level, extent, imgOffset, extOffset, numTilesWide,
+                numTilesHigh, imageSize);
+
+        pyramidList.add(pyramidLevel);
+
+        Collections.sort(pyramidList, levelComparator);
+    }
+
+    void setOriginalEnvelope(GeneralEnvelope originalEnvelope) {
+        this.originalEnvelope = originalEnvelope;
+    }
+
+    public GeneralEnvelope getOriginalEnvelope() {
+        return originalEnvelope;
+    }
+
+    public void setBands(List<RasterBandInfo> bands) {
+        this.bands = new ArrayList<RasterBandInfo>(bands);
+    }
+
+    public List<RasterBandInfo> getBands() {
+        return new ArrayList<RasterBandInfo>(bands);
+    }
+
+    public int getNumBands() {
+        return bands.size();
+    }
+
+    public RasterBandInfo getBand(final int index) {
+        return bands.get(index);
+    }
+
+    public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+        return crs;
+    }
+
+    public RasterCellType getTargetCellType() {
+        // if (isColorMapped()) {
+        // // color map is already promoted if needed
+        // return getNativeCellType();
+        // }
+        List<Number> noDataValues = getNoDataValues();
+        RasterCellType nativeCellType = getNativeCellType();
+        RasterCellType targetCellType = RasterUtils.determineTargetCellType(nativeCellType,
+                noDataValues);
+        return targetCellType;
+    }
+
+    public boolean isColorMapped() {
+        return getBand(0).isColorMapped();
+    }
+
+    public RasterCellType getNativeCellType() {
+        return getBand(0).getCellType();
+    }
+
+    public List<Number> getNoDataValues() {
+        final List<Number> noDataValues = new ArrayList<Number>();
+        for (RasterBandInfo band : getBands()) {
+            Number noDataValue = band.getNoDataValue();
+            noDataValues.add(noDataValue);
+        }
+        return noDataValues;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
+        sb.append("[Id: ").append(getRasterId());
+        String srs = null;
+        try {
+            srs = CRS.lookupIdentifier(getCoordinateReferenceSystem(), false);
+        } catch (FactoryException e) {
+            e.printStackTrace();
+        }
+        sb.append(", bands: ").append(getNumBands());
+        sb.append(", levels: ").append(getNumLevels());
+        sb.append(", tile size: ").append(getTileWidth()).append("x").append(getTileHeight());
+        sb.append(", crs: ").append(srs == null ? getCoordinateReferenceSystem().toWKT() : srs);
+        GeneralEnvelope env = getOriginalEnvelope();
+        sb.append(", Envelope: ").append(env.getMinimum(0)).append(",").append(env.getMinimum(1))
+                .append(" ").append(env.getMaximum(0)).append(",").append(env.getMaximum(1));
+
+        sb.append("]\n Bands[");
+        for (RasterBandInfo band : getBands()) {
+            sb.append("\n\t");
+            sb.append(band.toString());
+        }
+        sb.append("\n ]");
+        sb.append("\n Pyramid[");
+        for (int l = 0; l < getNumLevels(); l++) {
+            sb.append("\n\t").append(getPyramidLevel(l).toString());
+        }
+        sb.append("\n ]");
+        return sb.toString();
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterQueryInfo.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterQueryInfo.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterQueryInfo.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterQueryInfo.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,216 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import java.awt.Rectangle;
+import java.awt.image.RenderedImage;
+import java.util.logging.Logger;
+
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.util.logging.Logging;
+
+/**
+ * Captures information about a query for a single raster in a raster dataset.
+ *
+ * @author Gabriel Roldan
+ * @version $Id$
+ * @since 2.5.6
+ * @see RasterUtils#findMatchingRasters
+ * @see RasterUtils#fitRequestToRaster
+ */
+public final class RasterQueryInfo {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private GeneralEnvelope requestedEnvelope;
+
+    private Rectangle requestedDim;
+
+    private int pyramidLevel;
+
+    /**
+     * The two-dimensional range of tile indices whose envelope intersect the requested extent. Will
+     * have negative width and height if none of the tiles do.
+     */
+    private Rectangle matchingTiles;
+
+    private GeneralEnvelope resultEnvelope;
+
+    private Rectangle resultDimension;
+
+    private Long rasterId;
+
+    private Rectangle mosaicLocation;
+
+    private RenderedImage resultImage;
+
+    private Rectangle tiledImageSize;
+
+    private double[] resolution;
+
+    private int rasterIndex;
+
+    /**
+     * The full tile range for the matching pyramid level
+     */
+    private Rectangle levelTileRange;
+
+    public RasterQueryInfo() {
+        setResultDimensionInsideTiledImage(new Rectangle(0, 0, 0, 0));
+        setMatchingTiles(new Rectangle(0, 0, 0, 0));
+        setResultEnvelope(null);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder("[Raster query info:");
+        s.append("\n\tRaster ID            : ").append(getRasterId());
+        s.append("\n\tPyramid level        : ").append(getPyramidLevel());
+        s.append("\n\tResolution           : ").append(
+                getResolution()[0] + "," + getResolution()[1]);
+        s.append("\n\tRequested envelope   : ").append(getRequestedEnvelope());
+        s.append("\n\tRequested dimension  : ").append(getRequestedDim());
+        Rectangle mt = getMatchingTiles();
+        Rectangle ltr = getLevelTileRange();
+        String matching = "x=" + mt.x + "-" + (mt.x + mt.width - 1) + ", y=" + mt.y + "-"
+                + (mt.y + mt.height - 1);
+        String level = "x=" + ltr.x + "-" + (ltr.width - 1) + ", y=" + ltr.y + "-"
+                + (ltr.height - 1);
+        s.append("\n\tMatching tiles       : ").append(matching).append(" out of ").append(level);
+        s.append("\n\tTiled image size     : ").append(getTiledImageSize());
+        s.append("\n\tResult dimension     : ").append(getResultDimensionInsideTiledImage());
+        s.append("\n\tMosaiced dimension   : ").append(getMosaicLocation());
+        s.append("\n\tResult envelope      : ").append(getResultEnvelope());
+        s.append("\n]");
+        return s.toString();
+    }
+
+    /**
+     * @return the rasterId (as in SeRaster.getId()) for the raster in the raster dataset this query
+     *         works upon
+     */
+    public Long getRasterId() {
+        return rasterId;
+    }
+
+    public GeneralEnvelope getRequestedEnvelope() {
+        return requestedEnvelope;
+    }
+
+    public Rectangle getRequestedDim() {
+        return requestedDim;
+    }
+
+    public int getPyramidLevel() {
+        return pyramidLevel;
+    }
+
+    public Rectangle getMatchingTiles() {
+        return matchingTiles;
+    }
+
+    public GeneralEnvelope getResultEnvelope() {
+        return resultEnvelope;
+    }
+
+    public Rectangle getResultDimensionInsideTiledImage() {
+        return resultDimension;
+    }
+
+    void setRasterId(Long rasterId) {
+        this.rasterId = rasterId;
+    }
+
+    void setPyramidLevel(int pyramidLevel) {
+        this.pyramidLevel = pyramidLevel;
+    }
+
+    void setRequestedEnvelope(GeneralEnvelope requestedEnvelope) {
+        this.requestedEnvelope = requestedEnvelope;
+    }
+
+    void setRequestedDim(Rectangle requestedDim) {
+        this.requestedDim = requestedDim;
+    }
+
+    void setResultEnvelope(GeneralEnvelope resultEnvelope) {
+        this.resultEnvelope = resultEnvelope;
+    }
+
+    void setMatchingTiles(Rectangle matchingTiles) {
+        this.matchingTiles = matchingTiles;
+    }
+
+    void setResultDimensionInsideTiledImage(Rectangle resultDimension) {
+        this.resultDimension = resultDimension;
+    }
+
+    void setMosaicLocation(Rectangle rasterMosaicLocation) {
+        this.mosaicLocation = rasterMosaicLocation;
+    }
+
+    public Rectangle getMosaicLocation() {
+        return mosaicLocation;
+    }
+
+    public void setResultImage(RenderedImage rasterImage) {
+        this.resultImage = rasterImage;
+        if (rasterImage.getWidth() != tiledImageSize.width
+                || rasterImage.getHeight() != tiledImageSize.height) {
+            LOGGER.warning("Result image and expected dimensions don't match: image="
+                    + resultImage.getWidth() + "x" + resultImage.getHeight() + ", expected="
+                    + tiledImageSize.width + "x" + tiledImageSize.height);
+        }
+    }
+
+    public RenderedImage getResultImage() {
+        return resultImage;
+    }
+
+    void setTiledImageSize(Rectangle tiledImageSize) {
+        this.tiledImageSize = tiledImageSize;
+    }
+
+    public Rectangle getTiledImageSize() {
+        return tiledImageSize;
+    }
+
+    void setResolution(double[] resolution) {
+        this.resolution = resolution;
+    }
+
+    public double[] getResolution() {
+        return resolution == null ? new double[] { -1, -1 } : resolution;
+    }
+
+    void setRasterIndex(int rasterN) {
+        this.rasterIndex = rasterN;
+    }
+
+    public int getRasterIndex() {
+        return rasterIndex;
+    }
+
+    void setLevelTileRange(Rectangle levelTileRange) {
+        this.levelTileRange = levelTileRange;
+    }
+
+    public Rectangle getLevelTileRange() {
+        return levelTileRange;
+    }
+}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterUtils.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterUtils.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterUtils.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/info/RasterUtils.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,880 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.info;
+
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_S;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_U;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_1BIT;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_REAL;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_S;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_U;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_4BIT;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_64BIT_REAL;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_8BIT_U;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BandedSampleModel;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
+import java.awt.image.SampleModel;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.imageio.ImageTypeSpecifier;
+
+import org.geotools.coverage.GridSampleDimension;
+import org.geotools.coverage.grid.GeneralGridEnvelope;
+import org.geotools.coverage.grid.io.OverviewPolicy;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.CRS;
+import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
+import org.geotools.resources.image.ColorUtilities;
+import org.geotools.resources.image.ComponentColorModelJAI;
+import org.geotools.util.NumberRange;
+import org.geotools.util.logging.Logging;
+import org.opengis.geometry.Envelope;
+import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.opengis.referencing.operation.TransformException;
+
+import com.sun.imageio.plugins.common.BogusColorSpace;
+
+/**
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/raster/info/RasterUtils.java $
+ */
+@SuppressWarnings( { "nls" })
+public class RasterUtils {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private RasterUtils() {
+        // do nothing
+    }
+
+    public static MathTransform createRasterToModel(final Rectangle levelGridRange,
+            final GeneralEnvelope levelEnvelope) {
+        // create a raster to model transform, from this tile pixel space to the tile's geographic
+        // extent
+        GeneralGridEnvelope gridRange = new GeneralGridEnvelope(levelGridRange, 2);
+        GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(gridRange, levelEnvelope);
+        geMapper.setPixelAnchor(PixelInCell.CELL_CORNER);
+
+        final MathTransform rasterToModel = geMapper.createTransform();
+        return rasterToModel;
+    }
+
+    private static Rectangle getResultDimensionForTileRange(final Rectangle tiledImageGridRange,
+            final Rectangle matchingLevelRange) {
+
+        int minx = Math.max(tiledImageGridRange.x, matchingLevelRange.x);
+        int miny = Math.max(tiledImageGridRange.y, matchingLevelRange.y);
+        int maxx = (int) Math.min(tiledImageGridRange.getMaxX(), matchingLevelRange.getMaxX());
+        int maxy = (int) Math.min(tiledImageGridRange.getMaxY(), matchingLevelRange.getMaxY());
+
+        return new Rectangle(minx, miny, maxx - minx, maxy - miny);
+    }
+
+    /**
+     * Returns the rectangle specifying the matching tiles for a given pyramid level and rectangle
+     * specifying the overlapping area to request in the level's pixel space.
+     *
+     * @param pixelRange
+     * @param tilesHigh
+     * @param tilesWide
+     * @param tileSize
+     * @param numTilesHigh
+     * @param numTilesWide
+     *
+     * @param pixelRange
+     * @param level
+     *
+     * @return a rectangle holding the coordinates in tile space that fully covers the requested
+     *         pixel range for the given pyramid level, or a negative area rectangle
+     */
+    private static Rectangle findMatchingTiles(final Dimension tileSize, int numTilesWide,
+            int numTilesHigh, final Rectangle pixelRange) {
+
+        final int minPixelX = pixelRange.x;
+        final int minPixelY = pixelRange.y;
+
+        // TODO: WARNING, we're not considering the possible x/y offsets on the level range for the
+        // given pyramid level here!
+
+        int minTileX = (int) Math.floor(minPixelX / tileSize.getWidth());
+        int minTileY = (int) Math.floor(minPixelY / tileSize.getHeight());
+
+        int numTilesX = (int) Math.ceil(pixelRange.getWidth() / tileSize.getWidth());
+        int numTilesY = (int) Math.ceil(pixelRange.getHeight() / tileSize.getHeight());
+
+        int maxTiledX = (minTileX + numTilesX) * tileSize.width;
+        int maxTiledY = (minTileY + numTilesY) * tileSize.height;
+
+        if (maxTiledX < pixelRange.getMaxX() && (minTileX + numTilesX) < numTilesWide) {
+            numTilesX++;
+        }
+
+        if (maxTiledY < pixelRange.getMaxY() && (minTileY + numTilesY) < numTilesHigh) {
+            numTilesY++;
+        }
+
+        Rectangle matchingTiles = new Rectangle(minTileX, minTileY, numTilesX, numTilesY);
+        return matchingTiles;
+    }
+
+    private static Rectangle getTargetGridRange(final MathTransform modelToRaster,
+            final Envelope requestedEnvelope) {
+        Rectangle levelOverlappingPixels;
+        int levelMinPixelX;
+        int levelMaxPixelX;
+        int levelMinPixelY;
+        int levelMaxPixelY;
+        {
+            // use a model to raster transform to find out which pixel range at the specified level
+            // better match the requested extent
+            GeneralEnvelope requestedPixels;
+            try {
+                requestedPixels = CRS.transform(modelToRaster, requestedEnvelope);
+            } catch (NoninvertibleTransformException e) {
+                throw new IllegalArgumentException(e);
+            } catch (TransformException e) {
+                throw new IllegalArgumentException(e);
+            }
+
+            levelMinPixelX = (int) Math.floor(requestedPixels.getMinimum(0));
+            levelMaxPixelX = (int) Math.floor(requestedPixels.getMaximum(0));
+
+            levelMinPixelY = (int) Math.ceil(requestedPixels.getMinimum(1));
+            levelMaxPixelY = (int) Math.ceil(requestedPixels.getMaximum(1));
+
+            final int width = levelMaxPixelX - levelMinPixelX;
+            final int height = levelMaxPixelY - levelMinPixelY;
+            levelOverlappingPixels = new Rectangle(levelMinPixelX, levelMinPixelY, width, height);
+        }
+        return levelOverlappingPixels;
+    }
+
+    /**
+     * Creates an IndexColorModel out of a DataBuffer obtained from an ArcSDE's raster color map.
+     *
+     * @param colorMapData
+     * @return
+     */
+    public static IndexColorModel sdeColorMapToJavaColorModel(final DataBuffer colorMapData,
+            final int bitsPerSample) {
+        if (colorMapData == null) {
+            throw new NullPointerException("colorMapData");
+        }
+
+        if (colorMapData.getNumBanks() < 3 || colorMapData.getNumBanks() > 4) {
+            throw new IllegalArgumentException("colorMapData shall have 3 or 4 banks: "
+                    + colorMapData.getNumBanks());
+        }
+
+        if (bitsPerSample != 8 && bitsPerSample != 16) {
+            throw new IllegalAccessError("bits per sample shall be either 8 or 16. Got "
+                    + bitsPerSample);
+        }
+
+        final int numBanks = colorMapData.getNumBanks();
+        final int mapSize = colorMapData.getSize();
+
+        byte[] r = new byte[mapSize];
+        byte[] g = new byte[mapSize];
+        byte[] b = new byte[mapSize];
+        byte[] a = new byte[mapSize];
+
+        for (int i = 0; i < mapSize; i++) {
+            r[i] = (byte) (colorMapData.getElem(0, i) & 0xFF);
+            g[i] = (byte) (colorMapData.getElem(1, i) & 0xFF);
+            b[i] = (byte) (colorMapData.getElem(2, i) & 0xFF);
+            a[i] = (byte) ((numBanks == 3 ? 255 : colorMapData.getElem(3, i)) & 0xFF);
+        }
+
+        IndexColorModel colorModel = new IndexColorModel(bitsPerSample, mapSize, r, g, b, a);
+
+        return colorModel;
+    }
+
+    public static ImageTypeSpecifier createFullImageTypeSpecifier(
+            final RasterDatasetInfo rasterInfo, final int rasterIndex) {
+
+        final int numberOfBands = rasterInfo.getNumBands();
+        final RasterCellType nativePixelType = rasterInfo.getNativeCellType();
+        final RasterCellType pixelType = rasterInfo.getTargetCellType(rasterIndex);
+
+        // Prepare temporary colorModel and sample model, needed to build the final
+        // ArcSDEPyramidLevel level;
+        int sampleImageWidth = 1;// rasterInfo.getImageWidth();
+        int sampleImageHeight = 1;// rasterInfo.getImageHeight();
+
+        final ImageTypeSpecifier its;
+        // treat special cases...
+        final int bitsPerSample = pixelType.getBitsPerSample();
+        final int dataType = pixelType.getDataBufferType();
+        final boolean hasColorMap = rasterInfo.isColorMapped();
+
+        if (hasColorMap) {
+            // special case, a single band colormapped image
+            IndexColorModel colorMap = rasterInfo.getColorMap(rasterIndex);
+            its = createColorMappedImageSpec(colorMap, sampleImageWidth, sampleImageHeight);
+
+        } else if (nativePixelType == TYPE_1BIT && numberOfBands == 1) {
+            byte noDataValue = rasterInfo.getNoDataValue(rasterIndex, 0).byteValue();
+            // special case, a single band 1-bit
+            its = createOneBitColorMappedImageSpec(sampleImageWidth, sampleImageHeight, noDataValue);
+
+        } else if (nativePixelType == TYPE_4BIT && numberOfBands == 1) {
+            byte noDataValue = rasterInfo.getNoDataValue(rasterIndex, 0).byteValue();
+            // special case, a single band 4-bit
+            its = createFourBitColorMappedImageSpec(sampleImageWidth, sampleImageHeight,
+                    noDataValue);
+        } else if (numberOfBands == 1) {
+            // special case, a single band grayscale image, no matter the pixel depth
+            its = createGrayscaleImageSpec(sampleImageWidth, sampleImageHeight, dataType,
+                    bitsPerSample);
+
+        } else if (numberOfBands == 3 && pixelType == TYPE_8BIT_U) {
+            // special case, an optimizable RGB image
+            its = createRGBImageSpec(sampleImageWidth, sampleImageHeight, dataType);
+
+        } else if (numberOfBands == 4 && pixelType == TYPE_8BIT_U) {
+            // special case, an optimizable RGBA image
+            its = createRGBAImageSpec(sampleImageWidth, sampleImageHeight, dataType);
+
+        } else {
+            /*
+             * not an special case, go for a more generic sample model, potentially slower than the
+             * special case ones, but that'll work anyway
+             */
+
+            final ColorModel colorModel;
+            final SampleModel sampleModel;
+            {
+                final ColorSpace colorSpace;
+                colorSpace = new BogusColorSpace(numberOfBands);
+                int[] numBits = new int[numberOfBands];
+                for (int i = 0; i < numberOfBands; i++) {
+                    numBits[i] = bitsPerSample;
+                }
+                colorModel = new ComponentColorModelJAI(colorSpace, numBits, false, false,
+                        Transparency.OPAQUE, dataType);
+            }
+            {
+                int[] bankIndices = new int[numberOfBands];
+                int[] bandOffsets = new int[numberOfBands];
+                // int bandOffset = (tileWidth * tileHeight * pixelType.getBitsPerSample()) / 8;
+                for (int i = 0; i < numberOfBands; i++) {
+                    bankIndices[i] = i;
+                    bandOffsets[i] = 0;// (i * bandOffset);
+                }
+                sampleModel = new BandedSampleModel(dataType, sampleImageWidth, sampleImageHeight,
+                        sampleImageWidth, bankIndices, bandOffsets);
+            }
+            its = new ImageTypeSpecifier(colorModel, sampleModel);
+        }
+
+        return its;
+    }
+
+    private static ImageTypeSpecifier createFourBitColorMappedImageSpec(int sampleImageWidth,
+            int sampleImageHeight, byte noDataValue) {
+
+        int maxValue = (int) TYPE_4BIT.getSampleValueRange().getMaximum();
+
+        int mapSize = noDataValue > maxValue ? noDataValue : maxValue + 1;
+
+        int[] cmap = new int[mapSize];
+        ColorUtilities.expand(new Color[] { Color.BLACK, Color.WHITE }, cmap, 0, maxValue);
+
+        for (int i = maxValue; i < mapSize; i++) {
+            cmap[i] = ColorUtilities.getIntFromColor(0, 0, 0, 0);
+        }
+
+        int transparentPixel = noDataValue;
+        IndexColorModel colorModel = new IndexColorModel(8, mapSize, cmap, 0, true,
+                transparentPixel, DataBuffer.TYPE_BYTE);
+
+        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
+                sampleImageHeight);
+        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createOneBitColorMappedImageSpec(int sampleImageWidth,
+            int sampleImageHeight, byte noDataValue) {
+
+        assert noDataValue == 2;
+
+        final int FALSE = ColorUtilities.getIntFromColor(255, 255, 255, 255);
+        final int TRUE = ColorUtilities.getIntFromColor(255, 0, 0, 255);
+        final int NODATA = ColorUtilities.getIntFromColor(0, 255, 0, 255);
+
+        final int mapSize = 3;
+        int[] cmap = new int[mapSize];
+        cmap[0] = FALSE;
+        cmap[1] = TRUE;
+        cmap[2] = NODATA;
+
+        int transparentPixel = noDataValue;
+        IndexColorModel colorModel = new IndexColorModel(8, mapSize, cmap, 0, false,
+                transparentPixel, DataBuffer.TYPE_BYTE);
+
+        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
+                sampleImageHeight);
+        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createRGBAImageSpec(int sampleImageWidth,
+            int sampleImageHeight, final int dataType) {
+
+        final ImageTypeSpecifier its;
+
+        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        boolean hasAlpha = true;
+        boolean isAlphaPremultiplied = false;
+        int transparency = Transparency.TRANSLUCENT;
+        int transferType = dataType;
+
+        int[] nBits = { 8, 8, 8, 8 };
+        ColorModel colorModel = new ComponentColorModelJAI(colorSpace, nBits, hasAlpha,
+                isAlphaPremultiplied, transparency, transferType);
+
+        /*
+         * Do not use colorModel.createCompatibleSampleModel cause it creates a
+         * PixelInterleavedSampleModel and we need a BandedSampleModel so it matches how the data
+         * comes out of ArcSDE
+         */
+        SampleModel sampleModel = new BandedSampleModel(dataType, sampleImageWidth,
+                sampleImageHeight, 4);
+
+        its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createRGBImageSpec(int sampleImageWidth,
+            int sampleImageHeight, final int dataType) {
+
+        final ImageTypeSpecifier its;
+        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        boolean hasAlpha = false;
+        boolean isAlphaPremultiplied = false;
+        int transparency = Transparency.OPAQUE;
+        int transferType = dataType;
+        ColorModel colorModel = new ComponentColorModel(colorSpace, new int[] { 8, 8, 8 },
+                hasAlpha, isAlphaPremultiplied, transparency, transferType);
+
+        SampleModel sampleModel = new BandedSampleModel(dataType, sampleImageWidth,
+                sampleImageHeight, 3);
+
+        its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createGrayscaleImageSpec(int sampleImageWidth,
+            int sampleImageHeight, final int dataType, int bitsPerPixel) {
+        final ImageTypeSpecifier its;
+        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+        boolean hasAlpha = false;
+        boolean isAlphaPremultiplied = false;
+        int transparency = Transparency.OPAQUE;
+        int transferType = dataType;
+        int[] nbits = { bitsPerPixel };
+        ColorModel colorModel = new ComponentColorModelJAI(colorSpace, nbits, hasAlpha,
+                isAlphaPremultiplied, transparency, transferType);
+
+        SampleModel sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth,
+                sampleImageHeight);
+        its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createOneBitImageSpec(final RasterDatasetInfo rasterInfo,
+            final int numberOfBands, int sampleImageWidth, int sampleImageHeight,
+            final int bitsPerSample, final int dataType) {
+        final ColorModel colorModel;
+        final SampleModel sampleModel;
+        if (numberOfBands != 1) {
+            throw new IllegalArgumentException(bitsPerSample
+                    + "-Bit rasters are only supported for one band");
+        }
+        int[] argb = new int[(int) Math.pow(2, bitsPerSample)];
+        ColorUtilities.expand(new Color[] { Color.WHITE, Color.BLACK }, argb, 0, argb.length);
+        GridSampleDimension gridSampleDimension = rasterInfo.getGridSampleDimensions()[0];
+        colorModel = gridSampleDimension.getColorModel(0, numberOfBands, dataType);
+        sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth, sampleImageHeight);
+
+        ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+    }
+
+    private static ImageTypeSpecifier createColorMappedImageSpec(final IndexColorModel colorModel,
+            int sampleImageWidth, int sampleImageHeight) {
+
+        final SampleModel sampleModel;
+        final ImageTypeSpecifier its;
+        LOGGER.fine("Found single-band colormapped raster, using its index color model");
+        sampleModel = colorModel.createCompatibleSampleModel(sampleImageWidth, sampleImageHeight);
+        its = new ImageTypeSpecifier(colorModel, sampleModel);
+        return its;
+
+    }
+
+    /**
+     * Given a collection of {@link RasterQueryInfo} instances holding information about how a
+     * request fits for each individual raster composing a catalog, figure out where their resulting
+     * images fit into the overall mosaic that's gonna be the result of the request.
+     *
+     * @param rasterInfo
+     * @param resultEnvelope
+     * @param results
+     * @return
+     */
+    public static Rectangle setMosaicLocations(final RasterDatasetInfo rasterInfo,
+            final GeneralEnvelope resultEnvelope, final List<RasterQueryInfo> results) {
+        final Rectangle mosaicDimension;
+        final MathTransform modelToRaster;
+        final MathTransform rasterToModel;
+        {
+            /*
+             * Of all the rasters that match the requested envelope, chose the one with the lowest
+             * resolution as the base to compute the final mosaic layout, so we avoid JAI upsamples,
+             * which are buggy and produce repeated patterns over the x axis instead of just scaling
+             * up the image.
+             */
+            RasterQueryInfo dimensionChoice = findLowestResolution(results);
+            Long rasterId = dimensionChoice.getRasterId();
+            int pyramidLevel = dimensionChoice.getPyramidLevel();
+            int rasterIndex = rasterInfo.getRasterIndex(rasterId);
+            Rectangle levelRange = rasterInfo.getGridRange(rasterIndex, pyramidLevel);
+            GeneralEnvelope levelEnvelope = rasterInfo.getGridEnvelope(rasterIndex, pyramidLevel);
+            rasterToModel = createRasterToModel(levelRange, levelEnvelope);
+            try {
+                modelToRaster = rasterToModel.inverse();
+            } catch (NoninvertibleTransformException e) {
+                throw new RuntimeException(e);
+            }
+            mosaicDimension = getTargetGridRange(modelToRaster, resultEnvelope);
+        }
+
+        for (RasterQueryInfo rasterResultInfo : results) {
+            final GeneralEnvelope rasterResultEnvelope = rasterResultInfo.getResultEnvelope();
+
+            final Rectangle targetRasterGridRange;
+            targetRasterGridRange = getTargetGridRange(modelToRaster, rasterResultEnvelope);
+
+            rasterResultInfo.setMosaicLocation(targetRasterGridRange);
+        }
+
+        return mosaicDimension;
+    }
+
+    private static RasterQueryInfo findLowestResolution(List<RasterQueryInfo> results) {
+        double[] prev = { Double.MIN_VALUE, Double.MIN_VALUE };
+        RasterQueryInfo lowestResQuery = null;
+
+        double[] curr;
+        for (RasterQueryInfo query : results) {
+            curr = query.getResolution();
+            if (curr[0] > prev[0]) {
+                prev = curr;
+                lowestResQuery = query;
+            }
+        }
+        return lowestResQuery;
+    }
+
+    /**
+     * Find out the raster ids and their pyramid levels in the raster dataset for the rasters whose
+     * envelope overlaps the requested one
+     *
+     * @param rasterInfo
+     * @param requestedEnvelope
+     * @param requestedDim
+     * @param overviewPolicy
+     * @return
+     */
+    public static List<RasterQueryInfo> findMatchingRasters(final RasterDatasetInfo rasterInfo,
+            final GeneralEnvelope requestedEnvelope, final Rectangle requestedDim,
+            final OverviewPolicy overviewPolicy) {
+
+        final int numRasters = rasterInfo.getNumRasters();
+        List<RasterQueryInfo> matchingRasters = new ArrayList<RasterQueryInfo>(numRasters);
+
+        int optimalPyramidLevel;
+        GeneralEnvelope gridEnvelope;
+        for (int rasterN = 0; rasterN < numRasters; rasterN++) {
+            optimalPyramidLevel = rasterInfo.getOptimalPyramidLevel(rasterN, overviewPolicy,
+                    requestedEnvelope, requestedDim);
+            gridEnvelope = rasterInfo.getGridEnvelope(rasterN, optimalPyramidLevel);
+            final boolean edgesInclusive = true;
+            if (requestedEnvelope.intersects(gridEnvelope, edgesInclusive)) {
+                RasterQueryInfo match = new RasterQueryInfo();
+                match.setRequestedEnvelope(requestedEnvelope);
+                match.setRequestedDim(requestedDim);
+
+                match.setRasterId(rasterInfo.getRasterId(rasterN));
+                match.setRasterIndex(rasterN);
+                match.setPyramidLevel(optimalPyramidLevel);
+                match.setResolution(rasterInfo.getResolution(rasterN, optimalPyramidLevel));
+                matchingRasters.add(match);
+            }
+        }
+        return matchingRasters;
+    }
+
+    public static void fitRequestToRaster(final GeneralEnvelope requestedEnvelope,
+            final RasterDatasetInfo rasterInfo, final RasterQueryInfo query) {
+
+        final int rasterIndex = query.getRasterIndex();
+        final int pyramidLevel = query.getPyramidLevel();
+        final Rectangle rasterGridRange = rasterInfo.getGridRange(rasterIndex, pyramidLevel);
+        final GeneralEnvelope rasterEnvelope = rasterInfo
+                .getGridEnvelope(rasterIndex, pyramidLevel);
+
+        double delta = requestedEnvelope.getMinimum(0) - rasterEnvelope.getMinimum(0);
+        double resX = rasterInfo.getResolution(rasterIndex, pyramidLevel)[0];
+        int xMinPixel = (int) Math.floor(delta / resX);
+
+        delta = requestedEnvelope.getMaximum(0) - rasterEnvelope.getMinimum(0);
+        int xMaxPixel = (int) Math.ceil(delta / resX);
+
+        delta = rasterEnvelope.getMaximum(1) - requestedEnvelope.getMaximum(1);
+        double resY = rasterInfo.getResolution(rasterIndex, pyramidLevel)[1];
+        // Distance in pixels from the top of the whole pyramid image to the top
+        // of our AOI.
+        // If we're off the top, this number will be negative.
+        int yMinPixel = (int) Math.floor(delta / resY);
+
+        delta = rasterEnvelope.getMaximum(1) - requestedEnvelope.getMinimum(1);
+        int yMaxPixel = (int) Math.ceil(delta / resY);
+
+        xMinPixel = Math.max(xMinPixel, rasterGridRange.x);
+        yMinPixel = Math.max(yMinPixel, rasterGridRange.y);
+        xMaxPixel = Math.min(xMaxPixel, rasterGridRange.x + rasterGridRange.width);
+        yMaxPixel = Math.min(yMaxPixel, rasterGridRange.y + rasterGridRange.height);
+
+        final int widthPixel = xMaxPixel - xMinPixel;
+        final int heightPixel = yMaxPixel - yMinPixel;
+
+        final double xMinGeo = rasterEnvelope.getMinimum(0) + resX * xMinPixel;
+        final double yMinGeo = rasterEnvelope.getMaximum(1) - resY * (yMinPixel + heightPixel);
+        final double widthGeo = resX * widthPixel;
+        final double heightGeo = resY * heightPixel;
+
+        final Rectangle resultGridRange;
+        final GeneralEnvelope resultEnvelope;
+
+        resultEnvelope = new GeneralEnvelope(new double[] { xMinGeo, yMinGeo }, new double[] {
+                xMinGeo + widthGeo, yMinGeo + heightGeo });
+        resultEnvelope.setCoordinateReferenceSystem(rasterEnvelope.getCoordinateReferenceSystem());
+
+        resultGridRange = new Rectangle(xMinPixel, yMinPixel, widthPixel, heightPixel);
+
+        final Rectangle matchingTiles;
+        final Rectangle levelTileRange;
+        final Rectangle tiledImageGridRange;
+        {
+            final Dimension tileSize = rasterInfo.getTileDimension(rasterIndex);
+            final int numTilesWide = rasterInfo.getNumTilesWide(rasterIndex, pyramidLevel);
+            final int numTilesHigh = rasterInfo.getNumTilesHigh(rasterIndex, pyramidLevel);
+            final Point tileOffset = rasterInfo.getTileOffset(rasterIndex, pyramidLevel);
+            levelTileRange = new Rectangle(0, 0, numTilesWide, numTilesHigh);
+            matchingTiles = findMatchingTiles(tileSize, numTilesWide, numTilesHigh, resultGridRange);
+
+            int tiledImageMinX = (matchingTiles.x * tileSize.width);
+            int tiledImageMinY = (matchingTiles.y * tileSize.height);
+
+            int tiledWidth = (matchingTiles.width * tileSize.width);
+            int tiledHeight = (matchingTiles.height * tileSize.height);
+
+            tiledImageGridRange = new Rectangle(tiledImageMinX, tiledImageMinY, tiledWidth,
+                    tiledHeight);
+        }
+
+        /*
+         * What is the grid range inside the whole level grid range that fits into the matching
+         * tiles
+         */
+        Rectangle resultDimensionInsideTiledImage;
+        resultDimensionInsideTiledImage = getResultDimensionForTileRange(tiledImageGridRange,
+                resultGridRange);
+
+        query.setResultEnvelope(resultEnvelope);
+        query.setResultDimensionInsideTiledImage(resultDimensionInsideTiledImage);
+        query.setTiledImageSize(tiledImageGridRange);
+        query.setLevelTileRange(levelTileRange);
+        query.setMatchingTiles(matchingTiles);
+    }
+
+    /**
+     * Returns a color model based on {@code colorMap} that's guaranteed to have at least one
+     * transparent pixel whose index can be used as no-data value for colormapped rasters, even if
+     * the returned IndexColorModel needs to be of a higher sample depth (ie, 16 instead of 8 bit)
+     * to satisfy that.
+     *
+     * @param colorMap
+     *            the raster's native color map the returned one will be based on
+     * @return the same {@code colorMap} if it has a transparent pixel, another, possibly of a
+     *         higher depth one if not, containing all the colors from {@code colorMap} and a newly
+     *         allocated cell for the transparent pixel if necessary
+     */
+    public static IndexColorModel ensureNoDataPixelIsAvailable(final IndexColorModel colorMap) {
+        int transparentPixel = colorMap.getTransparentPixel();
+        if (transparentPixel > -1) {
+            return colorMap;
+        }
+
+        final int transferType = colorMap.getTransferType();
+        final int mapSize = colorMap.getMapSize();
+        final int maxSize = 65536;// true for either transfer type
+
+        if (mapSize == maxSize) {
+            LOGGER.fine("There's no room for a new transparent pixel, "
+                    + "returning the original colorMap as is");
+            return colorMap;
+        }
+
+        /*
+         * The original map size is lower than the maximum allowed by a UShort color map, so expand
+         * the colormap by one and make that new entry transparent
+         */
+        final int newMapSize = mapSize + 1;
+        final int[] argb = new int[newMapSize];
+        colorMap.getRGBs(argb);
+
+        // set the last entry as transparent
+        argb[newMapSize - 1] = ColorUtilities.getIntFromColor(0, 0, 0, 0);
+
+        IndexColorModel targetColorModel;
+        final int significantBits;
+        final int newTransferType;
+
+        {
+            if (DataBuffer.TYPE_BYTE == transferType && newMapSize <= 256) {
+                /*
+                 * REVISIT: check if this needs to be promoted depending on whether I decide to
+                 * treat 1 and 4 bit images as indexed with 1 and 4 significant bits respectively
+                 */
+                significantBits = colorMap.getPixelSize();
+                newTransferType = DataBuffer.TYPE_BYTE;
+            } else {
+                // it's either being promoted or was already 16-bit
+                significantBits = 16;
+                newTransferType = DataBuffer.TYPE_USHORT;
+            }
+        }
+
+        final int transparentPixelIndex = newMapSize - 1;
+        final boolean hasalpha = true;
+        final int startIndex = 0;
+
+        targetColorModel = new IndexColorModel(significantBits, newMapSize, argb, startIndex,
+                hasalpha, transparentPixelIndex, newTransferType);
+
+        return targetColorModel;
+    }
+
+    /**
+     * For a color-mapped raster, the no-data value is set to the
+     * {@link IndexColorModel#getTransparentPixel() transparent pixel}
+     *
+     * @param colorMap
+     * @return the index in the colorMap that's the transparent pixel as is to be used as no-data
+     *         value
+     */
+    public static Number determineNoDataValue(IndexColorModel colorMap) {
+        int noDataPixel = colorMap.getTransparentPixel();
+        if (-1 == noDataPixel) {
+            // there were no room for a transparent pixel, find out the closest match
+            noDataPixel = ColorUtilities.getTransparentPixel(colorMap);
+        }
+        return Integer.valueOf(noDataPixel);
+    }
+
+    /**
+     * @param numBands
+     *            number of bands in the raster dataset for the band whose nodata value is to be
+     *            determined. Might be useful to treat special cases where some assumptions are made
+     *            depending on the cell type and number of bands
+     * @param statsMin
+     *            the minimum sample value for the band as reported by the band's statistics, or
+     *            {@code NaN}
+     * @param statsMax
+     *            the maximum sample value for the band as reported by the band's statistics, or
+     *            {@code NaN}
+     * @param nativeCellType
+     *            the band's native cell type
+     * @return
+     */
+    public static Number determineNoDataValue(final int numBands, final double statsMin,
+            final double statsMax, final RasterCellType nativeCellType) {
+
+        final Number nodata;
+
+        if (nativeCellType == TYPE_32BIT_REAL) {
+            LOGGER.fine("no data value is Float.NaN");
+            return Float.valueOf(Float.NaN);
+        } else if (nativeCellType == TYPE_64BIT_REAL) {
+            LOGGER.fine("no data value is Double.NaN");
+            return Double.valueOf(Double.NaN);
+        } else if (nativeCellType == TYPE_1BIT) {
+            LOGGER.fine("1BIT images no-data value is set to 2,"
+                    + " regardless of the raster statistics");
+            return Double.valueOf(2);
+        } else if (nativeCellType == TYPE_4BIT) {
+            LOGGER.fine("4BIT images no-data value is set to 16,"
+                    + " regardless of the raster statistics");
+            return Double.valueOf(16);
+        } else if (!isGeoPhysics(numBands, nativeCellType)) {
+            LOGGER.fine("3 or 4 band, 8 bit unsigned image, assumed to be "
+                    + "RGB or RGBA respectively and nodata value hardcoded to 255");
+            return (Number) nativeCellType.getSampleValueRange().getMaxValue();
+        }
+
+        final NumberRange<?> sampleValueRange = nativeCellType.getSampleValueRange();
+
+        final double minimumSample = sampleValueRange.getMinimum(true);
+        final double maximumSample = sampleValueRange.getMaximum(true);
+
+        double lower;
+        double greater;
+        if (Double.isNaN(statsMin) || Double.isNaN(statsMax)) {
+            lower = Math.ceil(minimumSample - 1);
+            greater = Math.floor(maximumSample + 1);
+        } else {
+            lower = Math.ceil(statsMin - 1);
+            greater = Math.floor(statsMax + 1);
+        }
+
+        final boolean isUnsigned = minimumSample == 0;
+
+        if (sampleValueRange.contains((Number) Double.valueOf(lower))) {
+            // lower is ok
+            nodata = lower;
+        } else if (sampleValueRange.contains((Number) Double.valueOf(greater))) {
+            // upper is ok
+            nodata = greater;
+        } else if (isUnsigned) {
+            // need to set no-data to the higher value, floor is zero
+            nodata = greater;
+            // if (cellType == TYPE_1BIT || cellType == TYPE_4BIT) {
+            // nodata = greater;
+            // } else {
+            // // best guess without promoting. We don't actually want to promote a raster that is
+            // // non
+            // // colormapped and either has no statistics or it's range is full to preserve the
+            // // cases
+            // // were it may affect badly the visualization (for example, a 3 band 8bit raster
+            // // promoted to 3 band 16bit is gonna look almost black
+            // nodata = maximumSample;
+            // }
+        } else {
+            // no-data as the lower value is ok, floor is non zero (the celltype is signed)
+            nodata = lower;
+        }
+
+        return nodata;
+    }
+
+    public static boolean isGeoPhysics(final int numBands, final RasterCellType nativeCellType) {
+        boolean geophysics = true;
+        if (nativeCellType == TYPE_8BIT_U && (numBands == 3 || numBands == 4)) {
+            geophysics = false;
+        }
+        return geophysics;
+    }
+
+    public static RasterCellType determineTargetCellType(final RasterCellType nativeCellType,
+            final List<Number> noDataValues) {
+
+        if (TYPE_32BIT_REAL == nativeCellType || TYPE_64BIT_REAL == nativeCellType) {
+            // no data value is NaN, so no need to promote. For other types NaN is not available
+            for (Number nodata : noDataValues) {
+                if (!Double.isNaN(nodata.doubleValue())) {
+                    throw new IllegalArgumentException("no data values for float and "
+                            + "double cell types shall be NaN: " + nodata);
+                }
+            }
+            return nativeCellType;
+        }
+
+        // find a cell type that's deep enough for all the bands in the given raster
+        double noDataMin = Double.POSITIVE_INFINITY, noDataMax = Double.NEGATIVE_INFINITY;
+        {
+            for (Number noData : noDataValues) {
+                noDataMin = Math.min(noDataMin, noData.doubleValue());
+                noDataMax = Math.max(noDataMax, noData.doubleValue());
+            }
+        }
+        final NumberRange<Double> sampleValueRange;
+        sampleValueRange = nativeCellType.getSampleValueRange().castTo(Double.class);
+
+        final RasterCellType targetCellType;
+
+        if (sampleValueRange.contains((Number) Double.valueOf(noDataMin))
+                && sampleValueRange.contains((Number) Double.valueOf(noDataMax))) {
+            /*
+             * The native cell type can hold the no-data values for all bands in the raster
+             */
+            targetCellType = nativeCellType;
+        } else {
+            targetCellType = promote(nativeCellType);
+        }
+        return targetCellType;
+    }
+
+    private static RasterCellType promote(final RasterCellType nativeCellType) {
+        switch (nativeCellType) {
+        case TYPE_1BIT:
+        case TYPE_4BIT:
+            return TYPE_8BIT_U;
+        case TYPE_8BIT_U:
+            return TYPE_16BIT_U;
+        case TYPE_8BIT_S:
+            return TYPE_16BIT_S;
+        case TYPE_16BIT_U:
+            return TYPE_32BIT_U;
+        case TYPE_16BIT_S:
+            return TYPE_32BIT_S;
+        case TYPE_32BIT_S:
+        case TYPE_32BIT_REAL:
+        case TYPE_32BIT_U:
+            return TYPE_64BIT_REAL;
+        default:
+            throw new IllegalArgumentException(
+                    "Can't promote a raster of type 64-bit-real, there's "
+                            + "no higher pixel depth than that!");
+        }
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/BitmaskToNoDataConverter.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/BitmaskToNoDataConverter.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/BitmaskToNoDataConverter.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/BitmaskToNoDataConverter.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,237 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.io;
+
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_8BIT_U;
+
+import java.awt.Dimension;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.geotools.arcsde.raster.info.RasterCellType;
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+
+/**
+ * A helper class to set nodata values directly onto the arcsde tile's returned {@code byte[]}
+ *
+ * @author Gabriel Roldan
+ * @since 2.5.6
+ * @version $Id$
+ *
+ */
+class BitmaskToNoDataConverter {
+
+    public static final BitmaskToNoDataConverter NO_ACTION_CONVERTER = new BitmaskToNoDataConverter(
+            0, 0, null) {
+
+        @Override
+        public void setNoData(Long bandId, byte[] tileData, byte[] bitMaskData) {
+            // no action
+        }
+
+        @Override
+        public void setAll(Long bandId, byte[] tileData) {
+            // no action
+        }
+
+        @Override
+        public void setNoData(Long bandId, int sampleN, byte[] tileData) {
+            // no action
+        }
+
+    };
+
+    protected final int pixelsPerTile;
+
+    protected final Map<Long, byte[]> byBandIdNoDataValues;
+
+    protected final int bitsPerSample;
+
+    /**
+     *
+     * @param pixelsPerTile
+     * @param bitsPerSample
+     * @param byBandIdNoDataValues
+     */
+    private BitmaskToNoDataConverter(final int pixelsPerTile, final int bitsPerSample,
+            final Map<Long, byte[]> byBandIdNoDataValues) {
+
+        this.pixelsPerTile = pixelsPerTile;
+        this.bitsPerSample = bitsPerSample;
+        this.byBandIdNoDataValues = byBandIdNoDataValues;
+
+    }
+
+    /**
+     * Creates a "nodata setter" for the given raster determined by the raster dataset and the
+     * raster index inside the dataset
+     *
+     * @param rasterInfo
+     * @param rasterIndex
+     * @return
+     */
+    public static BitmaskToNoDataConverter getInstance(final RasterDatasetInfo rasterInfo,
+            final long rasterId) {
+
+        final int rasterIndex = rasterInfo.getRasterIndex(rasterId);
+        final int numBands = rasterInfo.getNumBands();
+        final RasterCellType targetType = rasterInfo.getTargetCellType(rasterIndex);
+
+        Map<Long, byte[]> byBandIdNoDataValues = new HashMap<Long, byte[]>();
+
+        Dimension tileDimension = rasterInfo.getTileDimension(rasterIndex);
+        final int samplesPerTile = tileDimension.width * tileDimension.height;
+
+        for (int bandN = 0; bandN < numBands; bandN++) {
+            long bandId = rasterInfo.getBand(rasterIndex, bandN).getBandId();
+            Number noDataValue = rasterInfo.getNoDataValue(rasterIndex, bandN);
+            byte[] noDataValueBytes = toBytes(noDataValue, targetType);
+            byBandIdNoDataValues.put(Long.valueOf(bandId), noDataValueBytes);
+        }
+
+        final int bitsPerSample = targetType.getBitsPerSample();
+        BitmaskToNoDataConverter noDataSetter;
+        if (targetType == TYPE_8BIT_U) {
+            noDataSetter = new Unsigned8bitConverter(samplesPerTile, bitsPerSample,
+                    byBandIdNoDataValues);
+        } else {
+            noDataSetter = new BitmaskToNoDataConverter(samplesPerTile, bitsPerSample,
+                    byBandIdNoDataValues);
+        }
+
+        return noDataSetter;
+    }
+
+    static byte[] toBytes(final Number noDataValue, final RasterCellType targetType) {
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        DataOutputStream writer = new DataOutputStream(out);
+
+        try {
+            switch (targetType) {
+            case TYPE_16BIT_S:
+                writer.writeShort(noDataValue.intValue());
+                break;
+            case TYPE_16BIT_U:
+                writer.writeShort(noDataValue.intValue());
+                break;
+            case TYPE_32BIT_REAL:
+                writer.writeFloat(noDataValue.floatValue());
+                break;
+            case TYPE_32BIT_S:
+                writer.writeInt(noDataValue.intValue());
+                break;
+            case TYPE_32BIT_U:
+                writer.writeInt(noDataValue.intValue());
+                break;
+            case TYPE_64BIT_REAL:
+                writer.writeDouble(noDataValue.doubleValue());
+                break;
+            case TYPE_8BIT_S:
+                writer.writeByte(noDataValue.byteValue());
+                break;
+            case TYPE_8BIT_U:
+                writer.writeByte(noDataValue.intValue());
+                break;
+            default:
+                throw new UnsupportedOperationException(
+                        "No no-data converter exists for sample type " + targetType);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Can't happen!", e);
+        }
+
+        byte[] no_data_bytes = out.toByteArray();
+        return no_data_bytes;
+    }
+
+    /**
+     * Returns whether the sample N in the bitmask byte array is marked as a no-data pixel
+     */
+    public final boolean isNoData(int sampleN, byte[] bitmaskData) {
+        boolean isNoData = ((bitmaskData[sampleN / 8] >> (7 - (sampleN % 8))) & 0x01) == 0x00;
+        return isNoData;
+    }
+
+    /**
+     * Sets all the samples of {@code tileData} marked as no-data pixel in {@code bitmaskData} to
+     * the no-data value for band {@code bandId}
+     */
+    public void setNoData(final Long bandId, final byte[] tileData, final byte[] bitmaskData) {
+        for (int sampleN = 0; sampleN < pixelsPerTile; sampleN++) {
+            if (isNoData(sampleN, bitmaskData)) {
+                setNoData(bandId, sampleN, tileData);
+            }
+        }
+    }
+
+    /**
+     * Sets all the samples in {@code tileData} to the no-data value for the band {@code bandId}
+     * <p>
+     * Default implementation is to call {@link #setNoData(Long, int, byte[])} as many times as
+     * number of samples in a tile. Subclasses may override to optimize.
+     * </p>
+     */
+    public void setAll(final Long bandId, final byte[] tileData) {
+        for (int sampleN = 0; sampleN < pixelsPerTile; sampleN++) {
+            setNoData(bandId, sampleN, tileData);
+        }
+    }
+
+    /**
+     * Sets the sample N for the band {@code bandId} on {@code tileData} to the no-data value
+     */
+    public void setNoData(final Long bandId, final int sampleN, final byte[] tileData) {
+        byte[] noData = byBandIdNoDataValues.get(bandId);
+        int pixArrayOffset = (sampleN * bitsPerSample) / 8;
+        System.arraycopy(noData, 0, tileData, pixArrayOffset, noData.length);
+    }
+
+    /**
+     * A subclass that provides some optimization for the case where the target cell type is
+     * {@link RasterCellType#TYPE_8BIT_U}
+     */
+    static final class Unsigned8bitConverter extends BitmaskToNoDataConverter {
+
+        public Unsigned8bitConverter(final int samplesPerTile, final int bitsPerSample,
+                final Map<Long, byte[]> byBandIdNoDataValues) {
+            super(samplesPerTile, bitsPerSample, byBandIdNoDataValues);
+        }
+
+        /**
+         * Overrides to use the faster {@link Arrays#fill(byte[], byte)} method rather than calling
+         * {@link #setNoData(Long, int, byte[])} {@code samplesPerTile} times
+         */
+        @Override
+        public void setAll(Long bandId, byte[] tileData) {
+            byte noDataValue = byBandIdNoDataValues.get(bandId)[0];
+            Arrays.fill(tileData, noDataValue);
+        }
+
+        @Override
+        public void setNoData(Long bandId, int sampleN, byte[] tileData) {
+            byte noDataValue = byBandIdNoDataValues.get(bandId)[0];
+            tileData[sampleN] = noDataValue;
+        }
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/DefaultTiledRasterReader.java (from rev 34312, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/DefaultTiledRasterReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/DefaultTiledRasterReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/DefaultTiledRasterReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,221 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ */
+package org.geotools.arcsde.raster.io;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.image.ColorModel;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.stream.ImageInputStream;
+import javax.media.jai.ImageLayout;
+
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.raster.jai.ArcSDEImageReader;
+import org.geotools.arcsde.session.ISessionPool;
+import org.geotools.util.logging.Logging;
+
+import com.esri.sde.sdk.client.SeQuery;
+
+/**
+ * The default implementation for {@link TiledRasterReader}.
+ * <p>
+ * This implementation holds a connection and an open {@link SeQuery query} until the reader is
+ * exhausted or {@link #dispose()} is called.
+ * </p>
+ *
+ * @author Gabriel Roldan
+ * @version $Id$
+ * @since 2.5.7
+ */
+class DefaultTiledRasterReader implements TiledRasterReader {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private RasterDatasetInfo rasterInfo;
+
+    private final ISessionPool sessionPool;
+
+    /**
+     * Creates an {@link DefaultTiledRasterReader} that uses the given connection to fetch raster
+     * data for the given {@link RasterDatasetInfo rasterInfo}.
+     * <p>
+     * </p>
+     *
+     * @param sessionPool
+     *            where to grab sessions from to query the rasters described by {@code rasterInfo}
+     * @param rasterInfo
+     * @throws IOException
+     */
+    public DefaultTiledRasterReader(final ISessionPool sessionPool,
+            final RasterDatasetInfo rasterInfo) throws IOException {
+        this.sessionPool = sessionPool;
+        this.rasterInfo = rasterInfo;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TiledRasterReader#read
+     */
+    public RenderedImage read(final long rasterId, final int pyramidLevel, final Rectangle tileRange)
+            throws IOException {
+        final RenderedImage rasterImage;
+
+        rasterImage = getRasterMatchingTileRange(rasterId, pyramidLevel, tileRange);
+
+        return rasterImage;
+    }
+
+    private RenderedImage getRasterMatchingTileRange(final long rasterId, int pyramidLevel,
+            final Rectangle matchingTiles) throws IOException {
+
+        final TileReader tileReader;
+        tileReader = TileReaderFactory.getInstance(sessionPool, rasterInfo, rasterId, pyramidLevel,
+                matchingTiles);
+
+        // covers an area of full tiles
+        final RenderedImage fullTilesRaster;
+
+        /*
+         * Create the tiled raster covering the full area of the matching tiles
+         */
+
+        fullTilesRaster = createTiledRaster(tileReader, matchingTiles, rasterId);
+
+        return fullTilesRaster;
+    }
+
+    /**
+     * @param tileReader
+     * @param matchingTiles
+     * @param rasterId
+     * @return
+     * @throws IOException
+     */
+    private RenderedImage createTiledRaster(final TileReader tileReader,
+            final Rectangle matchingTiles, final long rasterId) throws IOException {
+        // Prepare temporary colorModel and sample model, needed to build the final
+        // ArcSDEPyramidLevel level;
+        final Dimension tiledImageSize;
+        final ColorModel colorModel;
+        final SampleModel sampleModel;
+        {
+            final int tiledImageWidth = tileReader.getTilesWide() * tileReader.getTileWidth();
+            final int tiledImageHeight = tileReader.getTilesHigh() * tileReader.getTileHeight();
+            tiledImageSize = new Dimension(tiledImageWidth, tiledImageHeight);
+
+            final ImageTypeSpecifier fullImageSpec = rasterInfo.getRenderedImageSpec(rasterId);
+            colorModel = fullImageSpec.getColorModel();
+            sampleModel = fullImageSpec.getSampleModel(tiledImageWidth, tiledImageHeight);
+        }
+
+        final int tileWidth = tileReader.getTileWidth();
+        final int tileHeight = tileReader.getTileHeight();
+
+        // building the final image layout
+        final ImageLayout imageLayout;
+        {
+            // the value for the resulting image.getMinX() and image.getMinY() reflecting its
+            // position in the whole image at the pyramid level
+            int minX = (matchingTiles.x * tileWidth);
+            int minY = (matchingTiles.y * tileHeight);
+
+            int width = tiledImageSize.width;
+            int height = tiledImageSize.height;
+
+            int tileGridXOffset = minX;
+            int tileGridYOffset = minY;
+
+            // imageLayout = new ImageLayout(minX, minY, width, height, tileGridXOffset,
+            // tileGridYOffset, tileWidth, tileHeight, sampleModel, colorModel);
+            imageLayout = new ImageLayout(0, 0, width, height, 0, 0, tileWidth, tileHeight,
+                    sampleModel, colorModel);
+        }
+
+        // Finally, build the image input stream
+        final ImageInputStream raw;
+        final ImageReader readerInstance;
+        {
+            final long[] imageOffsets = new long[] { 0 };
+            final Dimension[] imageDimensions = new Dimension[] { tiledImageSize };
+
+            final ImageTypeSpecifier its = new ImageTypeSpecifier(colorModel, sampleModel);
+            //
+            // final ImageInputStream tiledImageInputStream;
+            // tiledImageInputStream = new ArcSDETiledImageInputStream(tileReader);
+            // raw = new RawImageInputStream(tiledImageInputStream, its, imageOffsets,
+            // imageDimensions);
+            // ImageReaderSpi imageIOSPI = new RawImageReaderSpi();
+            // readerInstance = imageIOSPI.createReaderInstance();
+
+            // final InputStream is = new RasterInputStream(tileReader);
+            // final ImageInputStream tiledImageInputStream;
+            // tiledImageInputStream = ImageIO.createImageInputStream(is);
+            //
+            // raw = new RawImageInputStream(tiledImageInputStream, its, imageOffsets,
+            // imageDimensions);
+            // ImageReaderSpi imageIOSPI = new RawImageReaderSpi();
+            // readerInstance = imageIOSPI.createReaderInstance();
+
+            ArcSDEImageReader reader = new ArcSDEImageReader(its);
+            reader.setInput(tileReader, true, true);
+
+            RenderedImage image = reader.readAsRenderedImage(0, null);
+            // image.getData();
+            return image;
+        }
+
+        // First operator: read the image
+        // final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout);
+        //
+        // ParameterBlock pb = new ParameterBlock();
+        // pb.add(raw);// Input
+        // /*
+        // * image index, always 0 since we're already fetching the required pyramid level
+        // */
+        // pb.add(Integer.valueOf(0)); // Image index
+        // pb.add(Boolean.FALSE); // Read metadata
+        // pb.add(Boolean.FALSE);// Read thumbnails
+        // pb.add(Boolean.FALSE);// Verify input
+        // pb.add(null);// Listeners
+        // pb.add(null);// Locale
+        // final ImageReadParam rParam = new ImageReadParam();
+        // pb.add(rParam);// ReadParam
+        // pb.add(readerInstance);// Reader
+        //
+        // RenderedImage image = JAI.create("ImageRead", pb, hints);
+        // // image.getData();
+        // // // translate
+        // // int minX = (matchingTiles.x * tileWidth);
+        // // int minY = (matchingTiles.y * tileHeight);
+        // // pb = new ParameterBlock();
+        // // pb.addSource(image);
+        // // pb.add(Float.valueOf(minX));
+        // // pb.add(Float.valueOf(minY));
+        // // pb.add(null);
+        // //
+        // // image = JAI.create("translate", pb);
+        //
+        // return image;
+
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java (from rev 34302, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/NativeTileReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,530 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.io;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.geotools.arcsde.ArcSdeException;
+import org.geotools.arcsde.raster.info.RasterCellType;
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.session.Command;
+import org.geotools.arcsde.session.ISession;
+import org.geotools.arcsde.session.ISessionPool;
+import org.geotools.arcsde.session.UnavailableConnectionException;
+import org.geotools.util.logging.Logging;
+
+import com.esri.sde.sdk.client.SeConnection;
+import com.esri.sde.sdk.client.SeException;
+import com.esri.sde.sdk.client.SeQuery;
+import com.esri.sde.sdk.client.SeRaster;
+import com.esri.sde.sdk.client.SeRasterConstraint;
+import com.esri.sde.sdk.client.SeRasterTile;
+import com.esri.sde.sdk.client.SeRow;
+import com.esri.sde.sdk.client.SeSqlConstruct;
+import com.esri.sde.sdk.client.SeStreamOp;
+
+/**
+ * Offers an iterator like interface to fetch ArcSDE raster tiles.
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/NativeTileReader.java $
+ */
+@SuppressWarnings( { "nls" })
+final class NativeTileReader implements TileReader {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private final RasterDatasetInfo rasterInfo;
+
+    private final long rasterId;
+
+    private final int pyramidLevel;
+
+    private final Rectangle requestedTiles;
+
+    private final ISessionPool sessionPool;
+
+    private ISession session;
+
+    private TileFetchCommand tileFetchCommand;
+
+    /**
+     * {@link SeStreamOp} held to be closed at {@link #dispose()}
+     *
+     * @see #execute()
+     */
+    private SeQuery preparedQuery;
+
+    private TileInfo nextTile;
+
+    private boolean started;
+
+    private final int bitmaskDataLength;
+
+    private final BitmaskToNoDataConverter noData;
+
+    private final int pixelsPerTile;
+
+    private final int tileDataLength;
+
+    private int bitsPerSample;
+
+    /**
+     * Command to fetch an {@link SeRasterTile tile}
+     */
+    private static class TileFetchCommand extends Command<TileInfo> {
+
+        private final SeRow row;
+
+        private final int tileDataLength;
+
+        public TileFetchCommand(final SeRow row, final int tileDataLength) {
+            this.row = row;
+            this.tileDataLength = tileDataLength;
+        }
+
+        @Override
+        public TileInfo execute(ISession session, SeConnection connection) throws SeException,
+                IOException {
+            SeRasterTile tile = row.getRasterTile();
+            final TileInfo tileInfo;
+            if (tile == null) {
+                tileInfo = null;
+            } else {
+                byte[] bitMaskData = tile.getBitMaskData();
+                int numPixelsRead = tile.getNumPixels();
+                byte[] tileData;
+                if (numPixelsRead == 0) {
+                    tileData = new byte[tileDataLength];
+                } else {
+                    tileData = tile.getPixelData();
+                }
+                long bandId = tile.getBandId().longValue();
+                int colIndex = tile.getColumnIndex();
+                int rowIndex = tile.getRowIndex();
+                tileInfo = new TileInfo(bandId, colIndex, rowIndex, numPixelsRead, tileData,
+                        bitMaskData);
+            }
+            return tileInfo;
+        }
+    }
+
+    /**
+     * @see DefaultTiledRasterReader#nextRaster()
+     */
+    private static class QueryRasterCommand extends Command<Void> {
+
+        private SeQuery preparedQuery;
+
+        private SeRow row;
+
+        private final SeRasterConstraint rasterConstraint;
+
+        private final String rasterColumn;
+
+        private final String rasterTable;
+
+        private final long rasterId;
+
+        /**
+         *
+         * @param rConstraint
+         *            indicates which bands, pyramid level and grid envelope to query
+         * @param rasterTable
+         *            indicates which raster table to query
+         * @param rasterColumn
+         *            indicates what raster column in the raster table to query
+         * @param rasterId
+         *            indicates which raster in the raster catalog to query
+         */
+        public QueryRasterCommand(final SeRasterConstraint rConstraint, final String rasterTable,
+                final String rasterColumn, final long rasterId) {
+            this.rasterConstraint = rConstraint;
+            this.rasterTable = rasterTable;
+            this.rasterColumn = rasterColumn;
+            this.rasterId = rasterId;
+        }
+
+        @Override
+        public Void execute(ISession session, SeConnection connection) throws SeException,
+                IOException {
+
+            final SeSqlConstruct sqlConstruct = new SeSqlConstruct(rasterTable);
+            /*
+             * Filter by the given raster id
+             */
+            final String rasterIdFilter = rasterColumn + " = " + rasterId;
+            sqlConstruct.setWhere(rasterIdFilter);
+
+            final String[] rasterColumns = { rasterColumn };
+            preparedQuery = new SeQuery(connection, rasterColumns, sqlConstruct);
+            preparedQuery.prepareQuery();
+            preparedQuery.execute();
+
+            this.row = preparedQuery.fetch();
+            if (row == null) {
+                return null;
+            }
+
+            preparedQuery.queryRasterTile(rasterConstraint);
+
+            return null;
+        }
+
+        public SeQuery getPreparedQuery() {
+            return preparedQuery;
+        }
+
+        public SeRow getSeRow() {
+            return row;
+        }
+    }
+
+    /**
+     * Creates a {@link TileReader} that reads tiles out of ArcSDE for the given {@code
+     * preparedQuery} and {@code SeRow} using the given {@code session}, in the native raster
+     * format.
+     * <p>
+     * As for any object that receives a {@link ISession session}, the same rule applies: this class
+     * is not responsible of {@link ISession#dispose() disposing} the session, but the calling code
+     * is.
+     * </p>
+     *
+     * @param preparedQuery
+     *            the query stream to close when done
+     * @param row
+     * @param imageDimensions
+     *            the image size, x and y are the offsets, width and height the actual width and
+     *            height, used to ignore incomming pixel data as appropriate to fit the image
+     *            dimensions
+     * @param bitsPerSample
+     * @param numberOfBands2
+     * @param requestedTiles
+     */
+    NativeTileReader(final ISessionPool sessionPool, final RasterDatasetInfo rasterInfo,
+            final long rasterId, final int pyramidLevel, final Rectangle requestedTiles,
+            final BitmaskToNoDataConverter noData) {
+        this.sessionPool = sessionPool;
+        this.rasterInfo = rasterInfo;
+        this.rasterId = rasterId;
+        this.pyramidLevel = pyramidLevel;
+        this.requestedTiles = requestedTiles;
+        this.noData = noData;
+
+        final Dimension tileSize = rasterInfo.getTileDimension(rasterId);
+
+        this.pixelsPerTile = tileSize.width * tileSize.height;
+
+        final RasterCellType nativeCellType = rasterInfo.getNativeCellType();
+        this.bitsPerSample = nativeCellType.getBitsPerSample();
+        this.tileDataLength = (int) Math
+                .ceil(((double) pixelsPerTile * (double) bitsPerSample) / 8D);
+        this.bitmaskDataLength = (int) Math.ceil(pixelsPerTile / 8D);
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getBitsPerSample()
+     */
+    public int getBitsPerSample() {
+        return bitsPerSample;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getPixelsPerTile()
+     */
+    public int getPixelsPerTile() {
+        return pixelsPerTile;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getNumberOfBands()
+     */
+    public int getNumberOfBands() {
+        return rasterInfo.getNumBands();
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getTileWidth()
+     */
+    public int getTileWidth() {
+        return rasterInfo.getTileWidth(rasterId);
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getTileHeight()
+     */
+    public int getTileHeight() {
+        return rasterInfo.getTileHeight(rasterId);
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getTilesWide()
+     */
+    public int getTilesWide() {
+        return requestedTiles.width;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getTilesHigh()
+     */
+    public int getTilesHigh() {
+        return requestedTiles.height;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#getBytesPerTile()
+     */
+    public int getBytesPerTile() {
+        return tileDataLength;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#hasNext()
+     */
+    public boolean hasNext() throws IOException {
+        if (!started) {
+            execute();
+            try {
+                nextTile = session.issue(tileFetchCommand);
+            } catch (IOException e) {
+                dispose();
+                throw e;
+            } catch (RuntimeException e) {
+                dispose();
+                throw e;
+            }
+            started = true;
+            if (nextTile == null) {
+                dispose();
+                LOGGER.fine("No tiles to fetch at all, releasing connection");
+            }
+        }
+        return nextTile != null;
+    }
+
+    /**
+     * Creates and executes the {@link SeQuery} that's used to fetch the required tiles from the
+     * specified raster, and stores (as member variables) the {@link SeRow} to fetch the tiles from
+     * and the {@link SeQuery} to be closed at the TileReader's disposal
+     *
+     * @throws IOException
+     */
+    private void execute() throws IOException {
+
+        final int rasterIndex = rasterInfo.getRasterIndex(rasterId);
+        final int tileWidth = rasterInfo.getTileWidth(rasterId);
+        final int tileHeight = rasterInfo.getTileHeight(rasterId);
+
+        /*
+         * Create the raster constraint to query the needed tiles out of the specified raster at the
+         * given pyramid level
+         */
+        final SeRasterConstraint rConstraint;
+        try {
+            final int numberOfBands;
+            numberOfBands = rasterInfo.getNumBands();
+
+            int[] bandsToQuery = new int[numberOfBands];
+            for (int bandN = 1; bandN <= numberOfBands; bandN++) {
+                bandsToQuery[bandN - 1] = bandN;
+            }
+
+            int minTileX = requestedTiles.x;
+            int minTileY = requestedTiles.y;
+            int maxTileX = minTileX + requestedTiles.width - 1;
+            int maxTileY = minTileY + requestedTiles.height - 1;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.fine("Requesting tiles [x=" + minTileX + "-" + maxTileX + ", y=" + minTileY
+                        + "-" + maxTileY + "] from tile range [x=0-"
+                        + (rasterInfo.getNumTilesWide(rasterIndex, pyramidLevel) - 1) + ", y=0-"
+                        + (rasterInfo.getNumTilesHigh(rasterIndex, pyramidLevel) - 1) + "]");
+            }
+            // SDEPoint tileOrigin = rAttr.getTileOrigin();
+
+            if (LOGGER.isLoggable(Level.FINE)) {
+                Rectangle tiledImageSize = new Rectangle(0, 0, tileWidth * requestedTiles.width,
+                        tileHeight * requestedTiles.height);
+
+                LOGGER.fine("Tiled image size: " + tiledImageSize);
+            }
+
+            final int interleaveType = SeRaster.SE_RASTER_INTERLEAVE_BIP;
+
+            rConstraint = new SeRasterConstraint();
+            rConstraint.setBands(bandsToQuery);
+            rConstraint.setLevel(pyramidLevel);
+            rConstraint.setEnvelope(minTileX, minTileY, maxTileX, maxTileY);
+            rConstraint.setInterleave(interleaveType);
+        } catch (SeException se) {
+            throw new ArcSdeException(se);
+        }
+
+        /*
+         * Obtain the ISession this tile reader will work with until exhausted
+         */
+        try {
+            // lets share connections as we're going to do read only operations
+            final boolean transactional = false;
+            this.session = sessionPool.getSession(transactional);
+            // System.err.println("----> Using " + session + " to read raster #" + rasterId
+            // + " on Thread " + Thread.currentThread().getName() + ". Tile set: "
+            // + requestedTiles);
+            if (LOGGER.isLoggable(Level.FINER)) {
+                LOGGER.finer("Using " + session + " to read raster #" + rasterId + " on Thread "
+                        + Thread.currentThread().getName() + ". Tile set: " + requestedTiles);
+            }
+        } catch (UnavailableConnectionException e) {
+            // really bad luck..
+            throw new RuntimeException(e);
+        }
+
+        final String rasterTable = rasterInfo.getRasterTable();
+        final String rasterColumn = rasterInfo.getRasterColumns()[0];
+        final QueryRasterCommand queryCommand = new QueryRasterCommand(rConstraint, rasterTable,
+                rasterColumn, rasterId);
+
+        session.issue(queryCommand);
+
+        final SeRow row = queryCommand.getSeRow();
+
+        this.tileFetchCommand = new TileFetchCommand(row, tileDataLength);
+        this.preparedQuery = queryCommand.getPreparedQuery();
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#next()
+     */
+    public TileInfo next() throws IOException {
+        final TileInfo tile;
+        final boolean hasNext = hasNext();
+        if (hasNext) {
+            tile = nextTile();
+        } else {
+            throw new IllegalStateException("There're no more tiles to fetch");
+        }
+
+        try {
+            final byte[] bitMaskData = tile.getBitmaskData();
+
+            if (LOGGER.isLoggable(Level.FINEST)) {
+                LOGGER.finest(" >> Fetching " + tile + " - bitmask: " + bitMaskData.length);
+            }
+
+            assert bitMaskData.length == 0 ? true : bitmaskDataLength == bitMaskData.length;
+
+            final int numPixels = tile.getNumPixelsRead();
+            final byte[] rawTileData = tile.getTileData();
+
+            final Long bandId = tile.getBandId();
+
+            if (0 == numPixels) {
+                if (LOGGER.isLoggable(Level.FINER)) {
+                    LOGGER.finer("tile contains no pixel data, skipping: " + tile);
+                }
+                noData.setAll(bandId, rawTileData);
+            } else if (pixelsPerTile == numPixels) {
+
+                if (bitMaskData.length > 0) {
+                    noData.setNoData(bandId, rawTileData, bitMaskData);
+                }
+
+                if (LOGGER.isLoggable(Level.FINEST)) {
+                    LOGGER.finest("returning " + numPixels + " pixels data packaged into "
+                            + tileDataLength + " bytes for tile [" + tile.getColumnIndex() + ","
+                            + tile.getRowIndex() + "]");
+                }
+            } else {
+                throw new IllegalStateException("Expected pixels per tile == " + pixelsPerTile
+                        + " but got " + numPixels + ": " + tile);
+            }
+
+            // return new TileInfo(bandId, bitMaskData, numPixels);
+            return tile;
+
+        } catch (RuntimeException e) {
+            dispose();
+            throw e;
+        }
+    }
+
+    private TileInfo nextTile() throws IOException {
+        if (nextTile == null) {
+            dispose();
+            throw new EOFException("No more tiles to read");
+        }
+        TileInfo curr = nextTile;
+
+        try {
+            nextTile = session.issue(tileFetchCommand);
+        } catch (IOException e) {
+            dispose();
+            throw e;
+        } catch (RuntimeException e) {
+            dispose();
+            throw e;
+        }
+        if (nextTile == null) {
+            dispose();
+            LOGGER.finer("There're no more tiles to fetch");
+        }
+
+        return curr;
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#dispose()
+     */
+    public void dispose() {
+        if (session != null) {
+            // System.err.println("TileReader disposing " + session + " on Thread "
+            // + Thread.currentThread().getName());
+            if (LOGGER.isLoggable(Level.FINER)) {
+                LOGGER.finer("TileReader disposing " + session + " on Thread "
+                        + Thread.currentThread().getName());
+            }
+            try {
+                session.close(this.preparedQuery);
+            } catch (Exception e) {
+                LOGGER.log(Level.WARNING, "Closing tile reader's prepared Query", e);
+            }
+            session.dispose();
+            session = null;
+        }
+    }
+
+    /**
+     * Disposes as to make sure the {@link ISession session} is returned to the pool even if a
+     * failing or non careful client left this object hanging around
+     *
+     * @see #dispose()
+     * @see java.lang.Object#finalize()
+     */
+    @Override
+    protected void finalize() {
+        dispose();
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java (from rev 34312, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/PromotingTileReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,205 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.io;
+
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_S;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_U;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_1BIT;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_S;
+import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_8BIT_U;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.geotools.arcsde.raster.info.RasterCellType;
+import org.geotools.util.logging.Logging;
+
+/**
+ * A {@link TileReader} decorator
+ *
+ * @author Gabriel Roldan
+ * @version $Id$
+ * @since 2.5.6
+ */
+final class PromotingTileReader implements TileReader {
+
+    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
+
+    private final TileReader nativeReader;
+
+    private final RasterCellType targetType;
+
+    private final SampleDepthPromoter promoter;
+
+    private final BitmaskToNoDataConverter noData;
+
+    public PromotingTileReader(final TileReader nativeTileReader, final RasterCellType sourceType,
+            final RasterCellType targetType, final BitmaskToNoDataConverter noData) {
+
+        this.nativeReader = nativeTileReader;
+        this.targetType = targetType;
+        this.noData = noData;
+        this.promoter = SampleDepthPromoter.createFor(sourceType, targetType);
+        LOGGER.fine("Using sample depth promoting tile reader, from " + sourceType + " to "
+                + targetType);
+    }
+
+    public int getBitsPerSample() {
+        return targetType.getBitsPerSample();
+    }
+
+    public int getBytesPerTile() {
+        double pixelsPerTile = getPixelsPerTile();
+        double bitsPerSample = getBitsPerSample();
+        int bytesPerTile = (int) Math.floor((pixelsPerTile * bitsPerSample) / 8D);
+        return bytesPerTile;
+    }
+
+    public int getNumberOfBands() {
+        return nativeReader.getNumberOfBands();
+    }
+
+    public int getPixelsPerTile() {
+        return nativeReader.getPixelsPerTile();
+    }
+
+    public int getTileHeight() {
+        return nativeReader.getTileHeight();
+    }
+
+    public int getTileWidth() {
+        return nativeReader.getTileWidth();
+    }
+
+    public int getTilesHigh() {
+        return nativeReader.getTilesHigh();
+    }
+
+    public int getTilesWide() {
+        return nativeReader.getTilesWide();
+    }
+
+    public boolean hasNext() throws IOException {
+        return nativeReader.hasNext();
+    }
+
+    public TileInfo next() throws IOException {
+        final TileInfo tileInfo = nativeReader.next();
+        final byte[] nativeTileData = tileInfo.getTileData();
+        final byte[] tileData = new byte[getBytesPerTile()];
+        try {
+            final byte[] bitmaskData = tileInfo.getBitmaskData();
+            final boolean hasNoDataPixels = bitmaskData.length > 0;
+            final Long bandId = tileInfo.getBandId();
+
+            final int numPixelsRead = tileInfo.getNumPixelsRead();
+            if (numPixelsRead == 0) {
+                noData.setAll(bandId, tileData);
+            } else {
+                final int numSamples = getPixelsPerTile();
+                assert numPixelsRead == numSamples;
+
+                for (int sampleN = 0; sampleN < numSamples; sampleN++) {
+                    if (hasNoDataPixels && noData.isNoData(sampleN, bitmaskData)) {
+                        noData.setNoData(bandId, sampleN, tileData);
+                    } else {
+                        promoter.promote(sampleN, nativeTileData, tileData);
+                    }
+                }
+            }
+
+        } catch (RuntimeException e) {
+            dispose();
+            throw e;
+        }
+
+        TileInfo promotedTileInfo = new TileInfo(tileInfo.getBandId(), tileInfo.getColumnIndex(),
+                tileInfo.getRowIndex(), tileInfo.getNumPixelsRead(), tileData, tileInfo
+                        .getBitmaskData());
+        return promotedTileInfo;
+    }
+
+    /**
+     *
+     * @author Gabriel Roldan
+     */
+    private static abstract class SampleDepthPromoter {
+
+        public abstract void promote(int sampleN, byte[] nativeTileData, byte[] tileData);
+
+        public static SampleDepthPromoter createFor(final RasterCellType source,
+                final RasterCellType target) {
+
+            if (source == TYPE_1BIT && target == RasterCellType.TYPE_8BIT_U) {
+                return new OneBitToUchar();
+            } else if (source == TYPE_8BIT_U && target == TYPE_16BIT_U) {
+                return new UcharToUshort();
+            } else if (source == TYPE_16BIT_S && target == TYPE_32BIT_S) {
+                return new ShortToInt();
+            }
+
+            UnsupportedOperationException exception = new UnsupportedOperationException(
+                    "Promoting from " + source + " to " + target + " not yet implemented");
+            LOGGER.log(Level.WARNING, "Can't promote", exception);
+            throw exception;
+        }
+    }
+
+    private static final class UcharToUshort extends SampleDepthPromoter {
+
+        @Override
+        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
+            int pixArrayOffset = 2 * sampleN;
+            tileData[pixArrayOffset] = 0;
+            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 0) & 0xFF);
+        }
+    }
+
+    private static final class OneBitToUchar extends SampleDepthPromoter {
+
+        @Override
+        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
+            int pixArrayOffset = sampleN / 8;
+            int bit = sampleN % 8;
+            int _byte = nativeTileData[pixArrayOffset];
+            byte ucharvalue = (byte) ((_byte >> (7 - bit)) & 0x01);
+            tileData[sampleN] = ucharvalue;
+        }
+    }
+
+    private static final class ShortToInt extends SampleDepthPromoter {
+
+        @Override
+        public void promote(int sampleN, byte[] nativeTileData, byte[] tileData) {
+            int pixArrayOffset = 4 * sampleN;
+
+            tileData[pixArrayOffset] = 0;
+            tileData[pixArrayOffset + 1] = 0;
+            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 8) & 0xFF);
+            tileData[pixArrayOffset + 1] = (byte) ((nativeTileData[sampleN] >>> 0) & 0xFF);
+        }
+    }
+
+    /**
+     * @see org.geotools.arcsde.raster.io.TileReader#dispose()
+     */
+    public void dispose() {
+        this.nativeReader.dispose();
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/RasterReaderFactory.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/RasterReaderFactory.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/RasterReaderFactory.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/RasterReaderFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,57 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ */
+package org.geotools.arcsde.raster.io;
+
+import java.io.IOException;
+
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.session.ISessionPool;
+
+/**
+ *
+ * @author Gabriel Roldan
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/RasterReaderFactory.java $
+ * @version $Id$
+ * @since 2.5.7
+ */
+public class RasterReaderFactory {
+
+    private final ISessionPool sessionPool;
+
+    public RasterReaderFactory(final ISessionPool connectionPool) {
+        this.sessionPool = connectionPool;
+    }
+
+    /**
+     * Creates a {@link TiledRasterReader} that's able to read one or more raster for the given
+     * {@link RasterDatasetInfo}, depending on if {@code rasterInfo} represents a single raster or a
+     * raster catalog.
+     *
+     * @param rasterInfo
+     * @return
+     * @throws IOException
+     */
+    public TiledRasterReader create(final RasterDatasetInfo rasterInfo) throws IOException {
+        TiledRasterReader rasterReader = new DefaultTiledRasterReader(sessionPool, rasterInfo);
+
+        return rasterReader;
+    }
+
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java (from rev 34302, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,150 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.io;
+
+import java.io.IOException;
+
+/**
+ * Offers an iterator like interface to read ArcSDE raster tiles into a {@code byte[]}
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/TileReader.java $
+ */
+public interface TileReader {
+
+    public class TileInfo {
+        private final long bandId;
+
+        private final byte[] bitmaskData;
+
+        private final int numPixelsRead;
+
+        private final byte[] tileDta;
+
+        private final int columnIndex;
+
+        private final int rowIndex;
+
+        public TileInfo(long bandId, int colIndex, int rowIndex, int numPixelsRead,
+                byte[] tileData, byte[] bitMaskData) {
+            this.bandId = bandId;
+            this.columnIndex = colIndex;
+            this.rowIndex = rowIndex;
+            this.numPixelsRead = numPixelsRead;
+            this.tileDta = tileData;
+            this.bitmaskData = bitMaskData;
+        }
+
+        public Long getBandId() {
+            return bandId;
+        }
+
+        public byte[] getBitmaskData() {
+            return bitmaskData;
+        }
+
+        public int getNumPixelsRead() {
+            return numPixelsRead;
+        }
+
+        public byte[] getTileData() {
+            return tileDta;
+        }
+
+        public int getColumnIndex() {
+            return columnIndex;
+        }
+
+        public int getRowIndex() {
+            return rowIndex;
+        }
+    }
+
+    /**
+     * @return number of bits per sample
+     */
+    public abstract int getBitsPerSample();
+
+    /**
+     * @return number of samples per tile
+     */
+    public abstract int getPixelsPerTile();
+
+    /**
+     * @return numbre of bands being fetched
+     */
+    public abstract int getNumberOfBands();
+
+    /**
+     * @return number of pixels per tile over the X axis
+     */
+    public abstract int getTileWidth();
+
+    /**
+     * @return number of pixels per tile over the Y axis
+     */
+    public abstract int getTileHeight();
+
+    /**
+     * @return number of tiles being fetched over the X axis
+     */
+    public abstract int getTilesWide();
+
+    /**
+     * @return number of tiles being fetched over the Y axis
+     */
+    public abstract int getTilesHigh();
+
+    /**
+     * @return number of bytes in the raw pixel content of a tile, not taking into account any
+     *         trailing bitmask data.
+     */
+    public abstract int getBytesPerTile();
+
+    /**
+     * @return whether there are more tiles to fetch
+     * @throws IOException
+     */
+    public abstract boolean hasNext() throws IOException;
+
+    /**
+     * Fetches a tile and fills {@code tileData} with its raw pixel data packaged as bytes according
+     * to the number of bits per sample
+     *
+     * @param tileData
+     *            a possibly {@code null} array where to store the next tile data. If {@code null} a
+     *            new byte[] of length {@link #getBytesPerTile()} will be allocated and filled up
+     *            with the raw tile pixel data.
+     * @return the bitmask data, or an empty array if the tile is full
+     * @throws IOException
+     * @throws {@link IllegalArgumentException} if tileData is not null and its size is less than
+     *         {@link #getBytesPerTile()}
+     */
+    public abstract TileInfo next() throws IOException;
+
+    /**
+     * Disposes any resource being held by this TileReader, making the TileReader unusable and the
+     * behaviour of {@link #hasNext()} and {@link #next} unpredictable
+     */
+    public abstract void dispose();
+
+}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReaderFactory.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TileReaderFactory.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReaderFactory.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReaderFactory.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,54 @@
+package org.geotools.arcsde.raster.io;
+
+import java.awt.Rectangle;
+
+import org.geotools.arcsde.raster.info.RasterCellType;
+import org.geotools.arcsde.raster.info.RasterDatasetInfo;
+import org.geotools.arcsde.session.ISessionPool;
+
+public class TileReaderFactory {
+
+    /**
+     *
+     * @param preparedQuery
+     * @param row
+     * @param nativeType
+     * @param targetType
+     * @param noDataValues
+     * @param numberOfBands
+     * @param requestedTiles
+     * @param tileSize
+     * @return
+     */
+    public static TileReader getInstance(final ISessionPool sessionPool,
+            final RasterDatasetInfo rasterInfo, final long rasterId, final int pyramidLevel,
+            final Rectangle requestedTiles) {
+
+        final TileReader tileReader;
+
+        final RasterCellType nativeType = rasterInfo.getNativeCellType();
+        final RasterCellType targetType = rasterInfo.getTargetCellType(rasterId);
+
+        final BitmaskToNoDataConverter noData;
+        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, rasterId);
+
+        if (targetType == nativeType) {
+
+            TileReader nativeTileReader = new NativeTileReader(sessionPool, rasterInfo, rasterId,
+                    pyramidLevel, requestedTiles, noData);
+
+            tileReader = nativeTileReader;
+
+        } else {
+            // need to promote native to target sample depth
+            TileReader nativeTileReader;
+            nativeTileReader = new NativeTileReader(sessionPool, rasterInfo, rasterId,
+                    pyramidLevel, requestedTiles, BitmaskToNoDataConverter.NO_ACTION_CONVERTER);
+
+            TileReader promotingTileReader = new PromotingTileReader(nativeTileReader, nativeType,
+                    targetType, noData);
+            tileReader = promotingTileReader;
+        }
+        return tileReader;
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TiledRasterReader.java (from rev 34277, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/TiledRasterReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TiledRasterReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TiledRasterReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,93 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ */
+package org.geotools.arcsde.raster.io;
+
+import java.awt.Rectangle;
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+
+/**
+ * An Iterator like interface to read ArcSDE rasters for a given ArcSDE raster dataset (whether it
+ * is a single raster or a raster catalog).
+ * <p>
+ * Sample usage: <code>
+ * <pre>
+ * RasterReaderFactory readerFactory = ....
+ * RasterDatasetInfo raserInfo = ...
+ * ArcSDERasterReader reader = readerFactory.create(rasterInfo);
+ * try{
+ *      Long nextRasterId;
+ *      while((nextRasterId = reader.nextRaster()) != null){
+ *          if(amIInterestedInThisRaster(nextRasterId)){
+ *              int pyramidLevel = ...
+ *              Rectangle tileRange = ...
+ *              RenderedImage raster = reader.read(pyramidLevel, tileRange);
+ *          }
+ *      }
+ * }finally{
+ *      reader.dispose();
+ * }
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * So one has to call {@code nextRaster()} to get the id of the raster immediately available to be
+ * read through {@link #read()}. This is so because there might be more than one raster on a raster
+ * dataset and the order they are fetched from the ArcSDE server is non deterministic, and once you
+ * opened a stream to a raster you can't open another one and then read the former.
+ * </p>
+ *
+ * @author Gabriel Roldan
+ * @version $Id$
+ * @since 2.5.7
+ */
+public interface TiledRasterReader {
+
+    /**
+     * Disposes any resource being held by this reader, whether it's a connection to the ArcSDE
+     * server, opened streams, etc.
+     */
+    // void dispose();
+
+    /**
+     * Advances to the next available raster in the raster dataset this reader works upon and
+     * returns it's {@link SeRasterAttr#getRasterId() raster id}.
+     *
+     * @return the ID for the raster ready to be read from the queried raster column in the raster
+     *         dataset, or {@code null} if there are no more rasters to be read.
+     * @throws IOException
+     *             for any problem occurred retrieving the next {@link SeRasterAttr} in the request
+     */
+    // Long nextRaster() throws IOException;
+
+    /**
+     * Reads the image subset determined by the given pyramid level and tile range for the currently
+     * available raster attribute in the requested raster column for the given raster dataset.
+     *
+     * @param pyramidLevel
+     *            the pyramid level to read
+     * @param tileRange
+     *            the range of tiles to read at the given pyramid level. The boundaries of the tile
+     *            range are inclusive and starts at {@code 0,0} for the upper left most tile.
+     * @return the rendered image determined by the requested pyramid level and tile range
+     * @throws IOException
+     *             for any exception occurred while reading the image
+     */
+    RenderedImage read(final long rasterId, final int pyramidLevel, final Rectangle tileRange)
+            throws IOException;
+
+}
\ No newline at end of file

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java (from rev 34312, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDEImageReader.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,187 @@
+package org.geotools.arcsde.raster.jai;
+
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.media.jai.PlanarImage;
+
+import org.geotools.arcsde.raster.io.TileReader;
+import org.geotools.arcsde.raster.io.TileReader.TileInfo;
+
+import com.sun.media.imageioimpl.common.SimpleRenderedImage;
+
+public class ArcSDEImageReader extends ImageReader {
+
+    private TileReader tileReader;
+
+    private ImageTypeSpecifier typeSpec;
+
+    public ArcSDEImageReader(final ImageTypeSpecifier typeSpec) {
+        super(null);
+        this.typeSpec = typeSpec;
+    }
+
+    @Override
+    public int getWidth(int imageIndex) throws IOException {
+        int w = tileReader.getTilesWide() * tileReader.getTileWidth();
+        return w;
+    }
+
+    @Override
+    public int getHeight(int imageIndex) throws IOException {
+        int h = tileReader.getTilesHigh() * tileReader.getTileHeight();
+        return h;
+    }
+
+    @Override
+    public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
+        return null;
+    }
+
+    @Override
+    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
+        return Collections.singleton(typeSpec).iterator();
+    }
+
+    @Override
+    public int getNumImages(boolean allowSearch) throws IOException {
+        return 1;
+    }
+
+    @Override
+    public IIOMetadata getStreamMetadata() throws IOException {
+        return null;
+    }
+
+    @Override
+    public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param)
+            throws IOException {
+        // return read(imageIndex, param);
+
+        RenderedImage image = new ArcSDETiledRenderedImage(tileReader, typeSpec);
+
+        // BufferedImage bufferedImage = PlanarImage.wrapRenderedImage(image).getAsBufferedImage();
+        // return bufferedImage;
+        return image;
+    }
+
+    @Override
+    public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
+        if (param == null) {
+            param = getDefaultReadParam();
+        }
+
+        RenderedImage rendered = readAsRenderedImage(imageIndex, param);
+
+        BufferedImage bufferedImage = PlanarImage.wrapRenderedImage(rendered).getAsBufferedImage();
+
+        return bufferedImage;
+    }
+
+    @Override
+    public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
+        this.tileReader = (TileReader) input;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static class ArcSDETiledRenderedImage extends SimpleRenderedImage {
+
+        private TileReader tileReader;
+
+        public ArcSDETiledRenderedImage(TileReader tileReader, ImageTypeSpecifier typeSpec) {
+            System.err.println(tileReader);
+            this.tileReader = tileReader;
+            super.colorModel = typeSpec.getColorModel();
+            super.sampleModel = typeSpec.getSampleModel();
+            super.height = tileReader.getTilesHigh() * tileReader.getTileHeight();
+            super.width = tileReader.getTilesWide() * tileReader.getTileWidth();
+            super.minX = 0;
+            super.minY = 0;
+            super.tileGridXOffset = 0;
+            super.tileGridYOffset = 0;
+            super.tileHeight = tileReader.getTileHeight();
+            super.tileWidth = tileReader.getTileWidth();
+        }
+
+        private WritableRaster[][] tileCache = null;
+
+        /**
+         * @see java.awt.image.RenderedImage#getTile(int, int)
+         */
+        public Raster getTile(final int tileX, final int tileY) {
+            // System.err.printf("getTile(%d, %d)\n", tileX, tileY);
+            if (tileCache == null) {
+                tileCache = new WritableRaster[tileReader.getTilesWide()][tileReader.getTilesHigh()];
+            }
+
+            WritableRaster currentTile = tileCache[tileX][tileY];
+            if (currentTile == null) {
+                final int tilesWide = tileReader.getTilesWide();
+                final int tilesHigh = tileReader.getTilesHigh();
+
+                for (int ty = 0; ty < tilesHigh; ty++) {
+                    for (int tx = 0; tx < tilesWide; tx++) {
+
+                        currentTile = tileCache[tx][ty];
+
+                        if (currentTile == null) {
+                            int x = tileXToX(tx);
+                            int y = tileYToY(ty);
+                            // System.err.println("fetching tile " + tx + "," + ty);
+                            currentTile = fetchTile(x, y);
+                            tileCache[tx][ty] = currentTile;
+                        }
+                        if (tx == tileX && ty == tileY) {
+                            return currentTile;
+                        }
+                    }
+                }
+            }
+            // currentTile = tileCache[tileX][tileY];
+            return currentTile;
+        }
+
+        private WritableRaster fetchTile(final int xOrigin, final int yOrigin) {
+            final int numBands = sampleModel.getNumBands();
+
+            final SampleModel tileSampleModel = super.sampleModel.createCompatibleSampleModel(
+                    tileWidth, tileHeight);
+
+            DataBuffer dataBuffer = sampleModel.createDataBuffer();
+            for (int bandN = 0; bandN < numBands; bandN++) {
+                TileInfo tileInfo;
+                try {
+                    tileInfo = tileReader.next();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+
+                byte[] rawBandData = tileInfo.getTileData();
+
+                final int numPixels = tileWidth * tileHeight;
+                for (int pixelN = 0; pixelN < numPixels; pixelN++) {
+                    int val = rawBandData[2 * pixelN + 1] & 0xFF;
+                    dataBuffer.setElem(bandN, pixelN, val);
+                }
+            }
+
+            WritableRaster currentTile;
+            currentTile = Raster.createWritableRaster(tileSampleModel, dataBuffer, new Point(
+                    xOrigin, yOrigin));
+            return currentTile;
+        }
+
+    }
+}

Copied: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledImageInputStream.java (from rev 34305, trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/gce/ArcSDETiledImageInputStream.java)
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledImageInputStream.java                        (rev 0)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledImageInputStream.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -0,0 +1,141 @@
+/*
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ *
+ *    (C) 2002-2009, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package org.geotools.arcsde.raster.jai;
+
+import java.io.IOException;
+
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageInputStreamImpl;
+
+import org.geotools.arcsde.raster.io.TileReader;
+import org.geotools.arcsde.raster.io.TileReader.TileInfo;
+
+/**
+ * An {@link ImageInputStream} that reads ArcSDE raster tiles in a band interleaved order.
+ *
+ * @author Gabriel Roldan (OpenGeo)
+ * @since 2.5.4
+ * @version $Id$
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/gce/ArcSDETiledImageInputStream.java $
+ */
+@Deprecated
+final class ArcSDETiledImageInputStream extends ImageInputStreamImpl implements ImageInputStream {
+
+    private final TileReader tileReader;
+
+    private final int tileDataLength;
+
+    private byte[] currTileData;
+
+    private int currTileDataIndex;
+
+    private int currTileIndex = -1;
+
+    private final int length;
+
+    public ArcSDETiledImageInputStream(final TileReader tileReader) {
+        super();
+        this.tileReader = tileReader;
+        final int bytesPerTile = tileReader.getBytesPerTile();
+        this.tileDataLength = bytesPerTile;
+        this.currTileData = new byte[bytesPerTile];
+        // force load at the first read invocation
+        this.currTileDataIndex = tileDataLength;
+
+        final int tilesWide = tileReader.getTilesWide();
+        final int tilesHigh = tileReader.getTilesHigh();
+        final int numberOfBands = tileReader.getNumberOfBands();
+
+        length = bytesPerTile * tilesWide * tilesHigh * numberOfBands;
+    }
+
+    /**
+     * Returns the computed lenght of the stream based on the tile dimensions, number of tiles,
+     * number of bands, and bits per sample
+     */
+    @Override
+    public long length() {
+        return length;
+    }
+
+    @Override
+    public int read() throws IOException {
+        final byte[] data = getTileData();
+        if (data == null) {
+            close();
+            return -1;
+        }
+        byte b = data[currTileDataIndex];
+        ++currTileDataIndex;
+        ++streamPos;
+        return b;
+    }
+
+    @Override
+    public int read(byte[] buff, int off, int len) throws IOException {
+        final byte[] data = getTileData();
+        if (data == null) {
+            close();
+            return -1;
+        }
+        final int available = data.length - currTileDataIndex;
+        final int count = Math.min(available, len);
+        System.arraycopy(data, currTileDataIndex, buff, off, count);
+        currTileDataIndex += count;
+        streamPos += count;
+        return count;
+    }
+
+    /**
+     * Fetches a tile from the {@code tileReader} if necessary and returns the current tile data.
+     * <p>
+     * It is needed to fetch a new tile if {@link #currTileDataIndex} indicates all the current tile
+     * data has been already read. If so, {@code currTileDataIndex} is reset to 0. The {@code read}
+     * operations are responsible of incrementing {@code currTileDataIndex} depending on how many
+     * bytes have been consumed from the tile data returned by this method.
+     * </p>
+     *
+     * @return {@code null} if there's no more tiles to fetch, the current tile data otherwise
+     * @throws IOException
+     */
+    private byte[] getTileData() throws IOException {
+        if (currTileDataIndex == tileDataLength) {
+            if (!tileReader.hasNext()) {
+                return null;
+            }
+
+            currTileDataIndex = 0;
+            ++currTileIndex;
+            TileInfo tile = tileReader.next();
+            currTileData = tile.getTileData();
+
+            if (!tileReader.hasNext()) {
+                tileReader.dispose();
+            }
+        }
+        return currTileData;
+    }
+
+    @Override
+    public void close() throws IOException {
+        tileReader.dispose();
+        super.close();
+    }
+}
\ No newline at end of file

Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/util/ArcSDEUtils.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/util/ArcSDEUtils.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/util/ArcSDEUtils.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -40,8 +40,10 @@
  * implementations
  *
  * @author Gabriel Roldan
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org
+ *         /geotools/arcsde/util/ArcSDEUtils.java $
  * @version $Id$
  * @since 2.5.6
  *

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEDataStoreFactoryTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEDataStoreFactoryTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEDataStoreFactoryTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -39,7 +39,6 @@
 import org.geotools.arcsde.session.UnavailableConnectionException;
 import org.geotools.data.DataAccessFactory;
 import org.geotools.data.DataAccessFinder;
-import org.geotools.data.DataSourceException;
 import org.geotools.data.DataStore;
 import org.geotools.data.DataStoreFactorySpi;
 import org.geotools.data.DataStoreFinder;
@@ -206,7 +205,8 @@
      * @throws UnavailableConnectionException
      */
     @Test
-    public void testCreateDataStoreWithInProcessViews() throws IOException, SeException, UnavailableConnectionException {
+    public void testCreateDataStoreWithInProcessViews() throws IOException, SeException,
+            UnavailableConnectionException {
         ISession session = testData.getConnectionPool().getSession(true);
         try {
             InProcessViewSupportTestData.setUp(session, testData);

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactoryTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactoryTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/ArcSDEJNDIDataStoreFactoryTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -51,8 +51,10 @@
 
 /**
  * @author Gabriel Roldan (OpenGeo)
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/ArcSDEJNDIDataStoreFactoryTest.java $
  * @version $Id$
  * @since 2.5.7
  */

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreNonSpatialTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreNonSpatialTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreNonSpatialTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -67,8 +67,10 @@
  * required by the new feature <a href="http://jira.codehaus.org/browse/GEOT-2548">GEOT-2548</a>
  *
  * @author Gabriel Roldan, OpenGeo
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/data/ArcSDEDataStoreNonSpatialTest.java $
  * @version $Id$
  * @since 2.5.6
  */

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEDataStoreTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -327,7 +327,8 @@
 
     @SuppressWarnings("unchecked")
     @Test
-    public void testCreateNillableShapeSchema() throws IOException, SchemaException, SeException, UnavailableConnectionException {
+    public void testCreateNillableShapeSchema() throws IOException, SchemaException, SeException,
+            UnavailableConnectionException {
         SimpleFeatureType type;
         final String typeName = "GT_TEST_CREATE";
         SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
@@ -348,7 +349,7 @@
         ds.createSchema(type, hints);
         testData.deleteTable(typeName);
     }
-    
+
     // ///////////////// HELPER FUNCTIONS ////////////////////////
 
     /**

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEJavaApiTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEJavaApiTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ArcSDEJavaApiTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1034,8 +1034,7 @@
     } // End method createBaseTable
 
     @Test
-    public void testDeleteById() throws IOException, UnavailableConnectionException,
-            SeException {
+    public void testDeleteById() throws IOException, UnavailableConnectionException, SeException {
 
         final String typeName = testData.getTempTableName();
         final SeQuery query = session.createAndExecuteQuery(new String[] { "ROW_ID", "INT32_COL" },

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ClobTestData.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ClobTestData.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/ClobTestData.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -125,12 +125,14 @@
         }
     }
 
-    public SeTable getTempTable(ISession session) throws IOException, UnavailableConnectionException {
+    public SeTable getTempTable(ISession session) throws IOException,
+            UnavailableConnectionException {
         final String tempTableName = getTempTableName();
         return session.getTable(tempTableName);
     }
 
-    public SeLayer getTempLayer(ISession session) throws IOException, UnavailableConnectionException {
+    public SeLayer getTempLayer(ISession session) throws IOException,
+            UnavailableConnectionException {
         final String tempTableName = getTempTableName();
         return session.getLayer(tempTableName);
     }

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/FIDReaderTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/FIDReaderTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/FIDReaderTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -38,8 +38,10 @@
 
 /**
  * @author Gabriel Roldan (TOPP)
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/data/FIDReaderTest.java $
  * @version $Id$
  * @since 2.5.x
  */

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/SDEJavaApiJoinTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/SDEJavaApiJoinTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/SDEJavaApiJoinTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -140,8 +140,10 @@
  * /arcsde/data/SDEJavaApiJoinTest.java $ @version $Id: SDEJavaApiJoinTest.java 31903
  * 2008-11-22 20:44:25Z groldan $ @since 2.3.x
  *
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/data/SDEJavaApiJoinTest.java $
  */
 public class SDEJavaApiJoinTest {
     /** package logger */
@@ -161,7 +163,7 @@
      * @throws SeException
      * @throws FactoryException
      * @throws NoSuchAuthorityCodeException
-     * @throws UnavailableConnectionException
+     * @throws UnavailableConnectionException
      */
     @BeforeClass
     public static void oneTimeSetUp() throws IOException, SeException,

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestFeatureListener.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestFeatureListener.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestFeatureListener.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -27,8 +27,10 @@
  * This class copies out some of the details about each event received.
  *
  * @author Jody Garnett
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/data/TestFeatureListener.java $
  */
 public class TestFeatureListener implements FeatureListener {
     List<FeatureEvent> list = new LinkedList<FeatureEvent>();

Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestProgressListener.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestProgressListener.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/data/TestProgressListener.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -27,8 +27,10 @@
  * This implementation is good about throwing illegal state exceptions and so forth.
  *
  * @author Jody
- *
- * @source $URL$
+ *
+ * @source $URL:
+ *         http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
+ *         /geotools/arcsde/data/TestProgressListener.java $
  */
 public class TestProgressListener implements ProgressListener {
     int progressCount;

Deleted: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,546 +0,0 @@
-/**
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.awt.Rectangle;
-import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.renderable.ParameterBlock;
-import java.io.File;
-import java.io.IOException;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-import javax.media.jai.JAI;
-import javax.media.jai.PlanarImage;
-
-import org.geotools.arcsde.ArcSDERasterFormatFactory;
-import org.geotools.arcsde.session.ArcSDEConnectionConfig;
-import org.geotools.coverage.grid.GridCoverage2D;
-import org.geotools.coverage.grid.GridEnvelope2D;
-import org.geotools.coverage.grid.GridGeometry2D;
-import org.geotools.coverage.grid.ViewType;
-import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
-import org.geotools.coverage.grid.io.AbstractGridFormat;
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.gce.geotiff.GeoTiffWriter;
-import org.geotools.geometry.Envelope2D;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.parameter.Parameter;
-import org.geotools.util.logging.Logging;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opengis.coverage.grid.GridEnvelope;
-import org.opengis.geometry.Envelope;
-import org.opengis.parameter.GeneralParameterValue;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import com.vividsolutions.jts.util.Stopwatch;
-
-/**
- * Tests over legacy data that should not be deleted
- *
- */
-@SuppressWarnings( { "deprecation", "nls" })
-public class ArcSDEGridCoverage2DReaderJAILegacyOnlineTest {
-
-    private static final String RASTER_TEST_DEBUG_TO_DISK = "raster.test.debugToDisk";
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    /**
-     * Whether to write the fetched rasters to disk or not
-     */
-    private static boolean DEBUG;
-
-    static RasterTestData rasterTestData;
-
-    private static String tableName;
-
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-        rasterTestData = new RasterTestData();
-        rasterTestData.setUp();
-        DEBUG = Boolean
-                .valueOf(rasterTestData.getRasterTestDataProperty(RASTER_TEST_DEBUG_TO_DISK));
-        rasterTestData.setOverrideExistingTestTables(false);
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() throws Exception {
-        rasterTestData.tearDown();
-    }
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        // nothing to do
-    }
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @After
-    public void tearDown() throws Exception {
-        // try {
-        // LOGGER.info("tearDown: deleting " + tableName);
-        // // wait I may delete an actual business table, comment out until this suite is fully
-        // // based on fake data rasterTestData.deleteTable(tableName);
-        // } catch (Exception e) {
-        // LOGGER.log(Level.INFO, "Error deleting test table " + tableName, e);
-        // }
-    }
-
-    /**
-     * Test method for {@link org.geotools.arcsde.gce.ArcSDEGridCoverage2DReaderJAI#getInfo()}.
-     */
-    @Test
-    @Ignore
-    public void testGetInfo() {
-        fail("Not yet implemented");
-    }
-
-    @Test
-    public void testIMG_USGSQUAD_SGBASE() throws Exception {
-        tableName = "SDE.RASTER.IMG_USGSQUAD_SGBASE";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final int count = 0;
-        long time = 0;
-        // warm up
-        _testIMG_USGSQUAD_SGBASE(reader);
-        for (int i = 0; i < count; i++) {
-            time += _testIMG_USGSQUAD_SGBASE(reader);
-        }
-        System.err.println(count + " reads in " + time + "ms");
-    }
-
-    private long _testIMG_USGSQUAD_SGBASE(AbstractGridCoverage2DReader reader) throws Exception {
-
-        // http://localhost:8080/geoserver/wms?WIDTH=256&LAYERS=sde%3AIMG_USGSQUAD_SGBASE&STYLES=&SRS=EPSG%3A26986&HEIGHT=256&FORMAT=image%2Fjpeg&TILED=true&TILESORIGIN=169118.35%2C874964.388&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=239038.74625,916916.62575,253022.8255,930900.705
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-
-        final int reqWidth = 256;
-        final int reqHeight = 256;
-
-        GeneralEnvelope reqEnvelope = new GeneralEnvelope(originalEnvelope);
-        reqEnvelope.setEnvelope(239038.74625, 916916.62575, 253022.8255, 930900.705);
-
-        Stopwatch sw = new Stopwatch();
-        sw.start();
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        RenderedImage image = coverage.getRenderedImage();
-        writeToDisk(image, "testRead_" + tableName);
-        sw.stop();
-        return sw.getTime();
-    }
-
-    @Test
-    public void testIMG_USGSQUAD_SGBASE2() throws Exception {
-        tableName = "SDE.RASTER.IMG_USGSQUAD_SGBASE";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        // http://localhost:8080/geoserver/wms?WIDTH=256&LAYERS=sde%3AIMG_USGSQUAD_SGBASE&STYLES=&SRS=EPSG%3A26986&HEIGHT=256&FORMAT=image%2Fjpeg&TILED=true&TILESORIGIN=169118.35%2C874964.388&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=239038.74625,916916.62575,253022.8255,930900.705
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 30;
-        final int reqHeight = originalGridRange.getSpan(1) / 30;
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, originalEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        RenderedImage image = coverage.getRenderedImage();
-        writeToDisk(image, "testRead_" + tableName);
-    }
-
-    @Test
-    public void testCOLOROQ_TEST() throws Exception {
-        tableName = "SDE.RASTER.COLOROQ_TEST";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        System.out.println(reader.getInfo().getDescription());
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = 225;
-        final int reqHeight = 512;
-
-        GeneralEnvelope reqEnvelope = originalEnvelope;
-
-        assertTrue(originalEnvelope.intersects(reqEnvelope, true));
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        writeToDisk(coverage, "testRead_" + tableName);
-
-        RenderedImage image = coverage.view(ViewType.RENDERED).getRenderedImage();
-        // writeToDisk(image, tableName);
-    }
-
-    @Test
-    public void testReadIMG_USGSQUADM_Buggy() throws Exception {
-        // http://localhost:8080/geoserver/wms?HEIGHT=500&WIDTH=1200&LAYERS=sde:IMG_USGSQUADM&STYLES=&SRS=EPSG%3A26986&FORMAT=image%2Fjpeg&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=253178.45971681,872419.13604732,253521.78247071,872562.18719478
-        tableName = "SDE.RASTER.IMG_USGSQUADM";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope requestEnvelope = new GeneralEnvelope(reader.getOriginalEnvelope());
-        requestEnvelope.setEnvelope(253178.45971681, 872419.13604732, 253521.78247071,
-                872562.18719478);
-
-        final int reqWidth = 1200;
-        final int reqHeight = 500;
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, requestEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        RenderedImage image = coverage.view(ViewType.PHOTOGRAPHIC).getRenderedImage();
-        writeToDisk(image, "testRead_" + tableName);
-    }
-
-    @Test
-    public void testReadIMG_USGSQUADM() throws Exception {
-        tableName = "SDE.RASTER.IMG_USGSQUADM";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 200;
-        final int reqHeight = originalGridRange.getSpan(1) / 200;
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, originalEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        RenderedImage image = coverage.view(ViewType.PHOTOGRAPHIC).getRenderedImage();
-        writeToDisk(image, "testRead_" + tableName);
-    }
-
-    @Test
-    public void testReadIMGCOQ_2005() throws Exception {
-        tableName = "SDE.RASTER.IMG_COQ2005_CLIP_BOS";
-
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 2;
-        final int reqHeight = originalGridRange.getSpan(1) / 2;
-
-        Envelope reqEnvelope = originalEnvelope;
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        GridGeometry2D gg = coverage.getGridGeometry();
-        Envelope2D envelope2D = gg.getEnvelope2D();
-        GridEnvelope gridRange = gg.getGridRange();
-
-        System.out.println("requested size: " + reqWidth + "x" + reqHeight);
-        System.out.println("result size   : " + gridRange.getSpan(0) + "x" + gridRange.getSpan(1));
-
-        System.out.println("requested envelope: " + reqEnvelope);
-
-        System.out.println("result envelope   : " + envelope2D);
-
-        // RenderedImage image = coverage.getRenderedImage();
-        // writeToDisk(coverage, "testRead_" + tableName);
-
-        RenderedImage image = coverage.view(ViewType.RENDERED).getRenderedImage();
-        writeToDisk(image, tableName);
-
-        writeBand(image, new int[] { 0 }, "red");
-        writeBand(image, new int[] { 1 }, "green");
-        writeBand(image, new int[] { 2 }, "blue");
-        writeBand(image, new int[] { 3 }, "alpha");
-
-        writeBand(image, new int[] { 0, 1, 2 }, "rgb");
-    }
-
-    @Test
-    public void testIMG_WIND_SPD30M_ADAMS() throws Exception {
-        tableName = "SDE.RASTER.IMG_WIND_SPD30M_ADAMS";
-
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0);
-        final int reqHeight = originalGridRange.getSpan(1);
-
-        GeneralEnvelope reqEnvelope = originalEnvelope;
-        reqEnvelope.setCoordinateReferenceSystem(originalEnvelope.getCoordinateReferenceSystem());
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        GridGeometry2D gg = coverage.getGridGeometry();
-        Envelope2D envelope2D = gg.getEnvelope2D();
-        GridEnvelope gridRange = gg.getGridRange();
-
-        System.out.println("requested size: " + reqWidth + "x" + reqHeight);
-        System.out.println("result size   : " + gridRange.getSpan(0) + "x" + gridRange.getSpan(1));
-
-        System.out.println("requested envelope: " + reqEnvelope);
-
-        System.out.println("result envelope   : " + envelope2D);
-
-        // writeToDisk(coverage, "testRead_" + tableName);
-    }
-
-    @Test
-    public void testReadNOAA_13006_1() throws Exception {
-        tableName = "SDE.RASTER.NOAA_13006_1";
-
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = 100;// 800;// originalGridRange.getSpan(0) / 8;
-        final int reqHeight = 75;// 595;// originalGridRange.getSpan(1) / 8;
-
-        GeneralEnvelope reqEnvelope = new GeneralEnvelope(new double[] { 274059, 837434 },
-                new double[] { 355782, 898216 });
-        reqEnvelope.setCoordinateReferenceSystem(originalEnvelope.getCoordinateReferenceSystem());
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        GridGeometry2D gg = coverage.getGridGeometry();
-        Envelope2D envelope2D = gg.getEnvelope2D();
-        GridEnvelope gridRange = gg.getGridRange();
-
-        System.out.println("requested size: " + reqWidth + "x" + reqHeight);
-        System.out.println("result size   : " + gridRange.getSpan(0) + "x" + gridRange.getSpan(1));
-
-        System.out.println("requested envelope: " + reqEnvelope);
-
-        System.out.println("result envelope   : " + envelope2D);
-
-        writeToDisk(coverage, "testRead_" + tableName);
-
-        RenderedImage image = coverage.getRenderedImage();
-        ColorModel colorModel = image.getColorModel();
-        SampleModel sampleModel = image.getSampleModel();
-
-        assertTrue(colorModel instanceof IndexColorModel);
-        IndexColorModel cm = ((IndexColorModel) colorModel);
-
-        int numComponents = cm.getMapSize();
-        byte[] r = new byte[numComponents];
-        byte[] g = new byte[numComponents];
-        byte[] b = new byte[numComponents];
-        byte[] a = new byte[numComponents];
-        cm.getReds(r);
-        cm.getGreens(g);
-        cm.getBlues(b);
-        cm.getAlphas(a);
-        for (int i = 0; i < numComponents; i++) {
-            System.out.print(i + " = ");
-            System.out.print((int) r[i] & 0xFF);
-            System.out.print(',');
-            System.out.print((int) g[i] & 0xFF);
-            System.out.print(',');
-            System.out.print((int) b[i] & 0xFF);
-            System.out.print(',');
-            System.out.print((int) a[i] & 0xFF);
-            System.out.print('\n');
-        }
-    }
-
-    private void writeBand(RenderedImage image, int[] bands, String channel) throws Exception {
-        ParameterBlock pb = new ParameterBlock();
-        pb.addSource(image);
-        pb.add(bands);
-        PlanarImage alpha = JAI.create("bandSelect", pb);
-        writeToDisk(alpha, tableName + "_" + channel);
-    }
-
-    @Test
-    public void testReadIMGCOQ_2001() throws Exception {
-        tableName = "SDE.RASTER.IMG_COQ2001_CLIP_BOS_1";
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 4;
-        final int reqHeight = originalGridRange.getSpan(1) / 4;
-
-        Envelope reqEnvelope = originalEnvelope;
-        // GeneralEnvelope reqEnvelope = new GeneralEnvelope(originalEnvelope
-        // .getCoordinateReferenceSystem());
-        //
-        // final double reqMinx = 235901.26048201;
-        // final double reqMiny = 901552.0880242661;
-        // final double reqMaxx = 236781.26048201;
-        // final double reqMaxy = 902253.0880242661;
-        //
-        // reqEnvelope.setEnvelope(reqMinx, reqMiny, reqMaxx, reqMaxy);
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        GridGeometry2D gg = coverage.getGridGeometry();
-        Envelope2D envelope2D = gg.getEnvelope2D();
-        GridEnvelope gridRange = gg.getGridRange();
-
-        System.out.println("requested size: " + reqWidth + "x" + reqHeight);
-        System.out.println("result size   : " + gridRange.getSpan(0) + "x" + gridRange.getSpan(1));
-
-        System.out.println("requested envelope: " + reqEnvelope);
-
-        System.out.println("result envelope   : " + envelope2D);
-
-        // RenderedImage image = coverage.getRenderedImage();
-        // writeToDisk(coverage, "testRead_" + tableName);
-    }
-
-    private void writeToDisk(GridCoverage2D coverage, String fileName) throws Exception {
-        Object destination;
-        {
-            String file = System.getProperty("user.home");
-            file += File.separator + "arcsde_test" + File.separator + fileName + ".tiff";
-            File path = new File(file);
-            path.getParentFile().mkdirs();
-            destination = path;
-        }
-        GeoTiffWriter writer = new GeoTiffWriter(destination);
-
-        System.out.println("\n --- Writing to " + destination);
-        try {
-            long t = System.currentTimeMillis();
-            writer.write(coverage, null);
-            System.out.println(" - wrote in " + t + "ms" + destination);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private void writeToDisk(final RenderedImage image, String fileName) throws Exception {
-        if (!DEBUG) {
-            LOGGER.fine("DEBUG == false, not writing image to disk");
-            return;
-        }
-        String file = System.getProperty("user.home");
-        file += File.separator + "arcsde_test" + File.separator + fileName + ".tiff";
-        File path = new File(file);
-        path.getParentFile().mkdirs();
-
-        System.out.println("\n --- Writing to " + file);
-        try {
-            long t = System.currentTimeMillis();
-            ImageIO.write(image, "TIFF", path);
-            t = System.currentTimeMillis() - t;
-            System.out.println(" - wrote in " + t + "ms" + file);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private GridCoverage2D readCoverage(final AbstractGridCoverage2DReader reader,
-            final int reqWidth, final int reqHeight, final Envelope reqEnv) throws Exception {
-
-        GeneralParameterValue[] requestParams = new Parameter[2];
-        final CoordinateReferenceSystem crs = reader.getCrs();
-
-        GridGeometry2D gg2d;
-        gg2d = new GridGeometry2D(new GridEnvelope2D(new Rectangle(reqWidth, reqHeight)), reqEnv);
-
-        requestParams[0] = new Parameter<GridGeometry2D>(AbstractGridFormat.READ_GRIDGEOMETRY2D,
-                gg2d);
-        requestParams[1] = new Parameter<OverviewPolicy>(AbstractGridFormat.OVERVIEW_POLICY,
-                OverviewPolicy.QUALITY);
-
-        final GridCoverage2D coverage;
-        coverage = (GridCoverage2D) reader.read(requestParams);
-
-        return coverage;
-    }
-
-    private AbstractGridCoverage2DReader getReader() throws IOException {
-        final ArcSDEConnectionConfig config = rasterTestData.getConnectionPool().getConfig();
-
-        final String rgbUrl = "sde://" + config.getUserName() + ":" + config.getPassword() + "@"
-                + config.getServerName() + ":" + config.getPortNumber() + "/"
-                + config.getDatabaseName() + "#" + tableName;
-
-        final ArcSDERasterFormat format = new ArcSDERasterFormatFactory().createFormat();
-
-        AbstractGridCoverage2DReader reader = format.getReader(rgbUrl);
-        return reader;
-    }
-
-    @Test
-    public void testReadRUGGED_RD() throws Exception {
-        tableName = "SDE.RASTER.RUGGED_RD";
-
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 8;
-        final int reqHeight = originalGridRange.getSpan(1) / 8;
-
-        Envelope reqEnvelope = originalEnvelope;
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        GridGeometry2D gg = coverage.getGridGeometry();
-        Envelope2D envelope2D = gg.getEnvelope2D();
-        GridEnvelope gridRange = gg.getGridRange();
-
-        System.out.println("requested size: " + reqWidth + "x" + reqHeight);
-        System.out.println("result size   : " + gridRange.getSpan(0) + "x" + gridRange.getSpan(1));
-
-        System.out.println("requested envelope: " + reqEnvelope);
-
-        System.out.println("result envelope   : " + envelope2D);
-
-        // RenderedImage image = coverage.getRenderedImage();
-        // writeToDisk(coverage, "testRead_" + tableName);
-
-        RenderedImage image = coverage.view(ViewType.RENDERED).getRenderedImage();
-        // writeToDisk(image, tableName);
-
-        // writeBand(image, new int[] { 0 }, "band1");
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAIOnlineTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAIOnlineTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/ArcSDEGridCoverage2DReaderJAIOnlineTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,719 +0,0 @@
-/**
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_1BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_4BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_64BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.awt.color.ColorSpace;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.IndexColorModel;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.io.File;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-import javax.media.jai.operator.FormatDescriptor;
-
-import org.geotools.arcsde.ArcSDERasterFormatFactory;
-import org.geotools.arcsde.session.ArcSDEConnectionConfig;
-import org.geotools.coverage.grid.GridCoverage2D;
-import org.geotools.coverage.grid.GridEnvelope2D;
-import org.geotools.coverage.grid.GridGeometry2D;
-import org.geotools.coverage.grid.ViewType;
-import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
-import org.geotools.coverage.grid.io.AbstractGridFormat;
-import org.geotools.coverage.grid.io.OverviewPolicy;
-import org.geotools.gce.geotiff.GeoTiffWriter;
-import org.geotools.geometry.Envelope2D;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.parameter.Parameter;
-import org.geotools.resources.image.ColorUtilities;
-import org.geotools.util.logging.Logging;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opengis.coverage.grid.GridEnvelope;
-import org.opengis.geometry.Envelope;
-import org.opengis.parameter.GeneralParameterValue;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import com.esri.sde.sdk.client.SeRaster;
-
-/**
- * @author groldan
- *
- */
-@SuppressWarnings( { "deprecation", "nls" })
-public class ArcSDEGridCoverage2DReaderJAIOnlineTest {
-
-    private static final String RASTER_TEST_DEBUG_TO_DISK = "raster.test.debugToDisk";
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    /**
-     * Whether to write the fetched rasters to disk or not
-     */
-    private static boolean DEBUG;
-
-    static RasterTestData rasterTestData;
-
-    private static String tableName;
-
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-        // rasterTestData = new RasterTestData();
-        // rasterTestData.setUp();
-        // DEBUG = Boolean
-        // .valueOf(rasterTestData.getRasterTestDataProperty(RASTER_TEST_DEBUG_TO_DISK));
-        // rasterTestData.setOverrideExistingTestTables(false);
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() throws Exception {
-        // rasterTestData.tearDown();
-    }
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        rasterTestData = new RasterTestData();
-        rasterTestData.setUp();
-        DEBUG = Boolean
-                .valueOf(rasterTestData.getRasterTestDataProperty(RASTER_TEST_DEBUG_TO_DISK));
-        rasterTestData.setOverrideExistingTestTables(false);
-    }
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @After
-    public void tearDown() throws Exception {
-        try {
-            LOGGER.info("tearDown: deleting " + tableName);
-            rasterTestData.deleteTable(tableName);
-            rasterTestData.tearDown();
-        } catch (Exception e) {
-            LOGGER.log(Level.INFO, "Error deleting test table " + tableName, e);
-        }
-    }
-
-    @Test
-    public void testRead_01bit_1Band() throws Exception {
-        testReadFullLevel0(TYPE_1BIT, 1);
-    }
-
-    @Test
-    public void testRead_01bit_MoreThanOneBandIsUnsupported() throws Exception {
-        try {
-            testReadFullLevel0(TYPE_1BIT, 2);
-            fail("Expected IAE");
-        } catch (IllegalArgumentException e) {
-            assertTrue(true);
-        }
-    }
-
-    /*
-     * 4bit rasters are not supported by now, need to check exactly what color model/sample model
-     * combination makes JAI happy, or to unpack the incoming samples into full bytes
-     */
-    @Test
-    @Ignore
-    public void testRead_04bit_1Band() throws Exception {
-        testReadFullLevel0(TYPE_4BIT, 1);
-    }
-
-    @Test
-    public void testRead_04bit_MoreThanOneBandIsUnsupported() throws Exception {
-        try {
-            testReadFullLevel0(TYPE_4BIT, 2);
-            fail("Expected IAE");
-        } catch (IllegalArgumentException e) {
-            assertTrue(true);
-        }
-    }
-
-    @Test
-    public void testRead_08bit_U_1Band() throws Exception {
-        testReadFullLevel0(TYPE_8BIT_U, 1, TYPE_16BIT_U);
-    }
-
-    @Test
-    public void testRead_08bit_U_4Band() throws Exception {
-        GridCoverage2D coverage = testReadFullLevel0(TYPE_8BIT_U, 4);
-
-        final RenderedImage image = coverage.view(ViewType.GEOPHYSICS).getRenderedImage();
-        assertEquals(DataBuffer.TYPE_BYTE, image.getSampleModel().getTransferType());
-
-        ColorModel colorModel = image.getColorModel();
-
-        assertEquals(ColorSpace.TYPE_RGB, colorModel.getColorSpace().getType());
-        assertEquals(4, colorModel.getNumComponents());
-        assertTrue(colorModel.hasAlpha());
-    }
-
-    @Test
-    public void testRead_08bit_U_3Band() throws Exception {
-        GridCoverage2D coverage = testReadFullLevel0(TYPE_8BIT_U, 3);
-
-        final RenderedImage image = coverage.view(ViewType.GEOPHYSICS).getRenderedImage();
-        assertEquals(DataBuffer.TYPE_BYTE, image.getSampleModel().getTransferType());
-
-        ColorModel colorModel = image.getColorModel();
-
-        assertEquals(ColorSpace.TYPE_RGB, colorModel.getColorSpace().getType());
-        assertEquals(3, colorModel.getNumComponents());
-        assertFalse(colorModel.hasAlpha());
-    }
-
-    @Test
-    public void testRead_08bit_U_7Band() throws Exception {
-        testReadFullLevel0(TYPE_8BIT_U, 7);
-    }
-
-    @Test
-    public void testRead_08bitU_ColorMapped() throws Exception {
-        tableName = rasterTestData.loadRGBColorMappedRaster();
-        testReadFullLevel0(TYPE_8BIT_U, 1, TYPE_8BIT_U, "testRead_8bitU_RGBColorMappedRaster");
-    }
-
-    @Test
-    public void testRead_08bit_S_1Band() throws Exception {
-        testReadFullLevel0(TYPE_8BIT_S, 1);
-    }
-
-    @Test
-    public void testRead_08bit_S_7Band() throws Exception {
-        testReadFullLevel0(TYPE_8BIT_S, 7);
-    }
-
-    @Test
-    public void testRead_16bit_S_1Band() throws Exception {
-        testReadFullLevel0(TYPE_16BIT_S, 1);
-    }
-
-    @Test
-    public void testRead_16bit_S_7Band() throws Exception {
-        testReadFullLevel0(TYPE_16BIT_S, 7);
-    }
-
-    @Test
-    public void testRead_16bit_U_1Band() throws Exception {
-        testReadFullLevel0(TYPE_16BIT_U, 1);
-    }
-
-    @Test
-    public void testRead_16bit_U_7Band() throws Exception {
-        testReadFullLevel0(TYPE_16BIT_U, 7);
-    }
-
-    @Test
-    public void testRead_16bit_U_ColorMapped() throws Exception {
-        int[] ARGB = new int[65536];
-        ColorUtilities.expand(new Color[] { Color.BLACK, Color.WHITE }, ARGB, 0, ARGB.length);
-        IndexColorModel colorModel = ColorUtilities.getIndexColorModel(ARGB);
-        tableName = rasterTestData.getRasterTableName(TYPE_16BIT_U, 1, true);
-        rasterTestData.loadTestRaster(tableName, 1, TYPE_16BIT_U, colorModel);
-        testReadFullLevel0(TYPE_16BIT_U, 1, TYPE_16BIT_U, "testRead_16bit_U_ColorMapped");
-    }
-
-    @Test
-    public void testRead_32bit_REAL_1Band() throws Exception {
-        GridCoverage2D coverage = testReadFullLevel0(TYPE_32BIT_REAL, 1);
-
-        RenderedImage geophysics = coverage.geophysics(true).getRenderedImage();
-        RenderedImage rendered = coverage.geophysics(false).getRenderedImage();
-
-        ColorModel gpCm = geophysics.getColorModel();
-        SampleModel gpSm = geophysics.getSampleModel();
-
-        ColorModel rCm = rendered.getColorModel();
-        SampleModel rSm = geophysics.getSampleModel();
-
-        System.out.println("Geophysics: \t" + gpCm + "\n\t" + gpSm);
-        System.out.println("Rendered  : \t" + rCm + "\n\t" + rSm);
-
-        System.out.println(Float.NaN);
-        Float valueOf = Float.valueOf("NaN");
-        System.out.println(valueOf);
-        System.out.println(valueOf.floatValue());
-    }
-
-    @Test
-    public void testRead_32bit_REAL_7Band() throws Exception {
-        testReadFullLevel0(TYPE_32BIT_REAL, 7);
-    }
-
-    @Test
-    public void testRead_32bit_U_1Band() throws Exception {
-        testReadFullLevel0(TYPE_32BIT_U, 1);
-    }
-
-    @Test
-    public void testRead_32bit_U_7Band() throws Exception {
-        testReadFullLevel0(TYPE_32BIT_U, 7);
-    }
-
-    @Test
-    public void testRead_32bit_S_1Band() throws Exception {
-        testReadFullLevel0(TYPE_32BIT_S, 1);
-    }
-
-    @Test
-    public void testRead_32bit_S_7Band() throws Exception {
-        testReadFullLevel0(TYPE_32BIT_S, 7);
-    }
-
-    @Test
-    public void testRead_64bit_REAL_1Band() throws Exception {
-        testReadFullLevel0(TYPE_64BIT_REAL, 1);
-    }
-
-    @Test
-    public void testRead_64bit_REAL_7Band() throws Exception {
-        testReadFullLevel0(TYPE_64BIT_REAL, 7);
-    }
-
-    @Test
-    public void testReadSampleRGB() throws Exception {
-        tableName = rasterTestData.loadRGBRaster();
-        testReadFullLevel0(TYPE_8BIT_U, 3, TYPE_8BIT_U, "sampleRGB");
-    }
-
-    @Test
-    public void testReadRasterCatalogFull() throws Exception {
-        tableName = rasterTestData.loadRasterCatalog();
-        GridCoverage2D coverage = testReadFullLevel0(TYPE_8BIT_U, 3, TYPE_8BIT_U, "RasterCatalog");
-
-        GridGeometry2D gridGeometry = coverage.getGridGeometry();
-        Envelope2D envelope2D = gridGeometry.getEnvelope2D();
-        GridEnvelope2D gridRange2D = gridGeometry.getGridRange2D();
-
-        // assertEquals(0, envelope2D.getMinX(), 1);
-        // assertEquals(0, envelope2D.getMinY(), 1);
-        // assertEquals(512, envelope2D.getMaxX(), 1);
-        // assertEquals(512, envelope2D.getMaxY(), 1);
-        //        
-        // assertEquals(512, gridRange2D.width);
-        // assertEquals(512, gridRange2D.height);
-    }
-
-    @Test
-    public void testReadRasterCatalogSubset() throws Exception {
-        tableName = rasterTestData.loadRasterCatalog();
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 2;
-        final int reqHeight = originalGridRange.getSpan(1) / 2;
-
-        GeneralEnvelope reqEnvelope = new GeneralEnvelope(originalEnvelope
-                .getCoordinateReferenceSystem());
-        double deltaX = originalEnvelope.getSpan(0) / 6;
-        double deltaY = originalEnvelope.getSpan(1) / 6;
-
-        double minx = originalEnvelope.getMinimum(0) + deltaX;
-        double miny = originalEnvelope.getMinimum(1) + deltaY;
-        double maxx = originalEnvelope.getMaximum(0) - deltaX;
-        double maxy = originalEnvelope.getMaximum(1) - deltaY;
-        reqEnvelope.setEnvelope(minx, miny, maxx, maxy);
-
-        assertTrue(originalEnvelope.intersects(reqEnvelope, true));
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        writeToDisk(coverage, "testReadRasterCatalogSubset");
-    }
-
-    @Test
-    public void testReadRasterCatalog2() throws Exception {
-        tableName = rasterTestData.loadRasterCatalog();
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + tableName, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int reqWidth = originalGridRange.getSpan(0) / 10;
-        final int reqHeight = originalGridRange.getSpan(1) / 10;
-
-        GeneralEnvelope reqEnvelope = new GeneralEnvelope(originalEnvelope
-                .getCoordinateReferenceSystem());
-        double minx = originalEnvelope.getMinimum(0);
-        double miny = originalEnvelope.getMinimum(1);
-        double maxx = minx + originalEnvelope.getSpan(0);// / 2;
-        double maxy = miny + originalEnvelope.getSpan(1);// / 2;
-        reqEnvelope.setEnvelope(minx, miny, maxx, maxy);
-
-        assertTrue(originalEnvelope.intersects(reqEnvelope, true));
-
-        final GridCoverage2D coverage = readCoverage(reader, reqWidth, reqHeight, reqEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        writeToDisk(coverage, "testReadRasterCatalog2");
-    }
-
-    private GridCoverage2D testReadFullLevel0(final RasterCellType cellType, final int numBands)
-            throws Exception {
-        return testReadFullLevel0(cellType, numBands, cellType);
-    }
-
-    private GridCoverage2D testReadFullLevel0(final RasterCellType cellType, final int numBands,
-            final RasterCellType resultingCellType) throws Exception {
-
-        tableName = rasterTestData.getRasterTableName(cellType, numBands, false);
-        rasterTestData.loadTestRaster(tableName, numBands, cellType, null);
-        return testReadFullLevel0(cellType, numBands, resultingCellType, tableName + "_" + numBands
-                + "-Band");
-    }
-
-    private GridCoverage2D testReadFullLevel0(final RasterCellType cellType, final int numBands,
-            final RasterCellType resultingCellType, final String fileNamePostFix) throws Exception {
-
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull("Couldn't obtain a reader for " + fileNamePostFix, reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-
-        final int origWidth = originalGridRange.getSpan(0);
-        final int origHeight = originalGridRange.getSpan(1);
-
-        final GridCoverage2D coverage = readCoverage(reader, origWidth, origHeight,
-                originalEnvelope);
-        assertNotNull("read coverage returned null", coverage);
-
-        assertEquals(numBands, coverage.getNumSampleDimensions());
-        // for (int i = 0; i < numBands; i++) {
-        // NumberRange<?> range = cellType.getSampleValueRange();
-        // GridSampleDimension sampleDimension = coverage.getSampleDimension(i);
-        // assertNotNull("Sample dimension #" + i, sampleDimension);
-        // assertEquals(range, sampleDimension.getRange());
-        // }
-
-        assertNotNull(coverage.getEnvelope());
-        GeneralEnvelope envelope = (GeneralEnvelope) coverage.getEnvelope();
-        assertTrue(originalEnvelope.intersects(envelope, true));
-
-        GridGeometry2D gridGeometry = coverage.getGridGeometry();
-
-        // ///////////////////////////////////////////////////////////assertEquals(originalGridRange,
-        // gridGeometry.getGridRange());
-
-        final RenderedImage geophysics = coverage.view(ViewType.NATIVE).getRenderedImage();
-        assertNotNull(geophysics);
-
-        final String fileName = "testReadFullLevel0_" + fileNamePostFix;
-
-        if (!(geophysics.getColorModel() instanceof IndexColorModel)) {
-            // not sure why, but the geotiff writer goes OOM if it's an indexed image
-            writeToDisk(coverage, fileName);
-        }
-        writeToDisk(geophysics, fileName);
-
-        // ////assertEquals(cellType.getDataBufferType(), image.getSampleModel().getDataType());
-        final int[] sampleSize = geophysics.getSampleModel().getSampleSize();
-        final ColorModel colorModel = geophysics.getColorModel();
-
-        if (colorModel instanceof IndexColorModel) {
-            switch (cellType) {
-            case TYPE_1BIT:
-                assertEquals("1-bit image should have been promoted to 8-bit", 8, sampleSize[0]);
-                break;
-            case TYPE_8BIT_U:
-                assertEquals("8-bit indexed image should have been "
-                        + "promoted to 16bit to account for no-data values", 16, sampleSize[0]);
-                break;
-            case TYPE_16BIT_U:
-                assertEquals(16, sampleSize[0]);
-                break;
-            default:
-                throw new IllegalArgumentException(cellType.toString());
-            }
-        } else {
-            for (int band = 0; band < numBands; band++) {
-                assertEquals(resultingCellType.getBitsPerSample(), sampleSize[band]);
-            }
-        }
-
-        return coverage;
-    }
-
-    @Test
-    public void tesReadOverlapsSampleRGBIamge() throws Exception {
-        tableName = rasterTestData.getRasterTableName(RasterCellType.TYPE_8BIT_U, 3);
-        rasterTestData.loadRGBRaster();
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull(reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-
-        final CoordinateReferenceSystem originalCrs = originalEnvelope
-                .getCoordinateReferenceSystem();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-        final int requestedWidth = originalGridRange.getSpan(0);
-        final int requestedHeight = originalGridRange.getSpan(1);
-
-        final GeneralEnvelope requestedEnvelope;
-        final GridCoverage2D coverage;
-        {
-            final double minx = originalEnvelope.getMinimum(0);
-            final double miny = originalEnvelope.getMinimum(1);
-
-            double shiftX = originalEnvelope.getSpan(0) / 2;
-            double shiftY = originalEnvelope.getSpan(1) / 2;
-
-            double x1 = minx - shiftX;
-            double x2 = minx + shiftX;
-            double y1 = miny + shiftY;
-            double y2 = miny + 2 * shiftY;
-
-            requestedEnvelope = new GeneralEnvelope(new ReferencedEnvelope(x1, x2, y1, y2,
-                    originalCrs));
-            coverage = readCoverage(reader, requestedWidth, requestedHeight, requestedEnvelope);
-        }
-        assertNotNull(coverage);
-        assertNotNull(coverage.getRenderedImage());
-        CoordinateReferenceSystem crs = coverage.getCoordinateReferenceSystem();
-        assertNotNull(crs);
-
-        final String fileName = "tesReadOverlapsSampleRGBIamge";
-
-        final RenderedImage image = coverage.view(ViewType.GEOPHYSICS).getRenderedImage();
-        assertNotNull(image);
-        writeToDisk(coverage, fileName);
-
-        assertSame(originalCrs, crs);
-
-        final Envelope returnedEnvelope = coverage.getEnvelope();
-
-        // these ones should equal to the tile dimension in the arcsde raster
-        int tileWidth = image.getTileWidth();
-        int tileHeight = image.getTileHeight();
-        assertTrue(tileWidth > 0);
-        assertTrue(tileHeight > 0);
-
-        int fullWidth = originalGridRange.getSpan(0);
-        int fullHeight = originalGridRange.getSpan(1);
-
-        GeneralEnvelope expectedEnvelope = new GeneralEnvelope(originalCrs);
-        expectedEnvelope.setRange(0, originalEnvelope.getMinimum(0), originalEnvelope.getMinimum(0)
-                + (originalEnvelope.getSpan(0) / 2));
-
-        expectedEnvelope.setRange(1, originalEnvelope.getMinimum(1), originalEnvelope.getMinimum(1)
-                + (originalEnvelope.getSpan(1) / 2));
-
-        LOGGER.info("\nRequested width : " + requestedWidth + "\nReturned width  :"
-                + image.getWidth() + "\nRequested height:" + requestedHeight
-                + "\nReturned height :" + image.getHeight());
-
-        LOGGER.info("\nOriginal envelope  : " + originalEnvelope + "\n requested envelope :"
-                + requestedEnvelope + "\n expected envelope  :" + expectedEnvelope
-                + "\n returned envelope  :" + returnedEnvelope);
-
-        assertEquals(501, image.getWidth());
-        assertEquals(501, image.getHeight());
-        // assertEquals(expectedEnvelope, returnedEnvelope);
-    }
-
-    @Test
-    public void tesReadOverlaps() throws Exception {
-        tableName = rasterTestData.getRasterTableName(RasterCellType.TYPE_8BIT_U, 1);
-        rasterTestData.loadTestRaster(tableName, 1, 100, 100, TYPE_8BIT_U, null, true, false,
-                SeRaster.SE_INTERPOLATION_NEAREST, null);
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull(reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-
-        final CoordinateReferenceSystem originalCrs = originalEnvelope
-                .getCoordinateReferenceSystem();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-        final int requestedWidth = originalGridRange.getSpan(0);
-        final int requestedHeight = originalGridRange.getSpan(1);
-
-        final GeneralEnvelope requestedEnvelope;
-        requestedEnvelope = new GeneralEnvelope(new ReferencedEnvelope(-100, 100, -100, 100,
-                originalCrs));
-
-        final GridCoverage2D coverage;
-        coverage = readCoverage(reader, requestedWidth, requestedHeight, requestedEnvelope);
-
-        assertNotNull(coverage);
-        assertNotNull(coverage.getRenderedImage());
-
-        final String fileName = "tesReadOverlaps_Level0_8BitU_1-Band";
-
-        final RenderedImage image = coverage.view(ViewType.GEOPHYSICS).getRenderedImage();
-        assertNotNull(image);
-        writeToDisk(coverage, fileName);
-
-        final Envelope returnedEnvelope = coverage.getEnvelope();
-
-        // these ones should equal to the tile dimension in the arcsde raster
-        int tileWidth = image.getTileWidth();
-        int tileHeight = image.getTileHeight();
-        assertTrue(tileWidth > 0);
-        assertTrue(tileHeight > 0);
-
-        int fullWidth = originalGridRange.getSpan(0);
-        int fullHeight = originalGridRange.getSpan(1);
-
-        GeneralEnvelope expectedEnvelope = new GeneralEnvelope(originalCrs);
-        expectedEnvelope.setRange(0, 0, 100);
-        expectedEnvelope.setRange(1, 0, 100);
-
-        LOGGER.info("\nRequested width : " + requestedWidth + "\nReturned width  :"
-                + image.getWidth() + "\nRequested height:" + requestedHeight
-                + "\nReturned height :" + image.getHeight());
-
-        LOGGER.info("\nOriginal envelope  : " + originalEnvelope + "\n requested envelope :"
-                + requestedEnvelope + "\n expected envelope  :" + expectedEnvelope
-                + "\n returned envelope  :" + returnedEnvelope);
-
-        assertEquals(50, image.getWidth());
-        assertEquals(50, image.getHeight());
-        // assertEquals(expectedEnvelope, returnedEnvelope);
-    }
-
-    @Test
-    public void tesReadNotOverlaps() throws Exception {
-        tableName = rasterTestData.getRasterTableName(RasterCellType.TYPE_8BIT_U, 1);
-        rasterTestData.loadTestRaster(tableName, 1, 100, 100, TYPE_8BIT_U, null, true, false,
-                SeRaster.SE_INTERPOLATION_NEAREST, null);
-        final AbstractGridCoverage2DReader reader = getReader();
-        assertNotNull(reader);
-
-        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
-
-        final CoordinateReferenceSystem originalCrs = originalEnvelope
-                .getCoordinateReferenceSystem();
-        final GridEnvelope originalGridRange = reader.getOriginalGridRange();
-        final int requestedWidth = originalGridRange.getSpan(0);
-        final int requestedHeight = originalGridRange.getSpan(1);
-
-        final GeneralEnvelope nonOverlappingEnvelope;
-        nonOverlappingEnvelope = new GeneralEnvelope(new ReferencedEnvelope(300, 500, 300, 500,
-                originalCrs));
-
-        final GridCoverage2D coverage;
-        try {
-            coverage = readCoverage(reader, requestedWidth, requestedHeight, nonOverlappingEnvelope);
-            fail("Expected IAE, envelopes does not overlap");
-        } catch (IllegalArgumentException e) {
-            assertTrue(true);
-        }
-    }
-
-    private void writeToDisk(GridCoverage2D coverage, String fileName) throws Exception {
-        Object destination;
-        {
-            String file = System.getProperty("user.home");
-            file += File.separator + "arcsde_test" + File.separator + fileName + ".tiff";
-            File path = new File(file);
-            path.getParentFile().mkdirs();
-            destination = path;
-        }
-        GeoTiffWriter writer = new GeoTiffWriter(destination);
-
-        System.out.println("\n --- Writing to " + destination);
-        try {
-            long t = System.currentTimeMillis();
-            writer.write(coverage, null);
-            System.out.println(" - wrote in " + t + "ms" + destination);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private void writeToDisk(final RenderedImage image, String fileName) throws Exception {
-        if (!DEBUG) {
-            LOGGER.fine("DEBUG == false, not writing image to disk");
-            return;
-        }
-        String file = System.getProperty("user.home");
-        file += File.separator + "arcsde_test" + File.separator + fileName;
-        File geophysics = new File(file + "_geophysics.tiff");
-        File rendered = new File(file + "_rendered.tiff");
-        geophysics.getParentFile().mkdirs();
-        System.out.println("\n --- Writing to " + file);
-
-        try {
-            ImageIO.write(image, "TIFF", geophysics);
-
-            ImageIO.write(FormatDescriptor.create(image, Integer.valueOf(DataBuffer.TYPE_BYTE),
-                    null), "TIFF", rendered);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private GridCoverage2D readCoverage(final AbstractGridCoverage2DReader reader,
-            final int reqWidth, final int reqHeight, final Envelope reqEnv) throws Exception {
-
-        GeneralParameterValue[] requestParams = new Parameter[2];
-        final CoordinateReferenceSystem crs = reader.getCrs();
-
-        GridGeometry2D gg2d;
-        gg2d = new GridGeometry2D(new GridEnvelope2D(new Rectangle(reqWidth, reqHeight)), reqEnv);
-
-        requestParams[0] = new Parameter<GridGeometry2D>(AbstractGridFormat.READ_GRIDGEOMETRY2D,
-                gg2d);
-        requestParams[1] = new Parameter<OverviewPolicy>(AbstractGridFormat.OVERVIEW_POLICY,
-                OverviewPolicy.SPEED);
-
-        final GridCoverage2D coverage;
-        coverage = (GridCoverage2D) reader.read(requestParams);
-
-        return coverage;
-    }
-
-    private AbstractGridCoverage2DReader getReader() throws IOException {
-        final ArcSDEConnectionConfig config = rasterTestData.getConnectionPool().getConfig();
-
-        final String rgbUrl = "sde://" + config.getUserName() + ":" + config.getPassword() + "@"
-                + config.getServerName() + ":" + config.getPortNumber() + "/"
-                + config.getDatabaseName() + "#" + tableName;
-
-        final ArcSDERasterFormat format = new ArcSDERasterFormatFactory().createFormat();
-        // we can't create statistics here so tell ArcSDERasterFormat not to fail
-        format.setStatisticsMandatory(false);
-
-        AbstractGridCoverage2DReader reader = format.getReader(rgbUrl);
-        return reader;
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/BitmaskToNoDataConverterTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/BitmaskToNoDataConverterTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/BitmaskToNoDataConverterTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,271 +0,0 @@
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_1BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_4BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.geotools.arcsde.gce.BitmaskToNoDataConverter.Unsigned8bitConverter;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.junit.Test;
-
-public class BitmaskToNoDataConverterTest {
-
-    @Test
-    public void testGetInstance8BitU() throws IOException {
-        RasterDatasetInfo rasterInfo;
-        BitmaskToNoDataConverter noData;
-
-        int noDataValue;
-        double statsMin;
-        double statsMax;
-
-        noDataValue = 0;
-        statsMin = 1;
-        statsMax = 255;
-        rasterInfo = createRasterInfo(TYPE_8BIT_U, noDataValue, statsMin, statsMax);
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-        assertNotNull(noData);
-
-        noDataValue = 255;
-        statsMin = 0;
-        statsMax = 254;
-        rasterInfo = createRasterInfo(TYPE_8BIT_U, noDataValue, statsMin, statsMax);
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-        assertNotNull(noData);
-        assertTrue(noData instanceof BitmaskToNoDataConverter.Unsigned8bitConverter);
-
-        final int samplesPerTile = rasterInfo.getTileDimension(0).width
-                * rasterInfo.getTileDimension(0).height;
-
-        /*
-         * bulk set, a whole no-data tile
-         */
-        byte[] tileData = new byte[samplesPerTile];
-        noData.setAll(1L, tileData);
-        DataInputStream in = new DataInputStream(new ByteArrayInputStream(tileData));
-        for (int sampleN = 0; sampleN < samplesPerTile; sampleN++) {
-            assertEquals(255, in.readByte() & 0xFF);
-        }
-
-        /*
-         * bitmask data states the first 8 and last 8 samples are no-data
-         */
-        byte[] bitmaskData = new byte[(int) Math.ceil(samplesPerTile / 8D)];
-        Arrays.fill(bitmaskData, (byte) 0xFF);
-        // set the first 8 and last 8 samples to no-data
-        bitmaskData[0] = 0x00;
-        bitmaskData[bitmaskData.length - 1] = 0x00;
-
-        final byte dataValue = 5;
-        byte[] expected = new byte[samplesPerTile];
-        Arrays.fill(expected, dataValue);
-        Arrays.fill(expected, 0, 8, (byte) noDataValue);
-        Arrays.fill(expected, expected.length - 8, expected.length, (byte) noDataValue);
-
-        tileData = new byte[samplesPerTile];
-        Arrays.fill(tileData, dataValue);
-        noData.setNoData(1L, tileData, bitmaskData);
-        assertTrue("Arrays differ, expected:" + Arrays.toString(expected) + ", actual:"
-                + Arrays.toString(tileData), Arrays.equals(expected, tileData));
-
-        /*
-         * set individual sample
-         */
-        tileData = new byte[samplesPerTile];
-        noData.setNoData(1L, 0, tileData);
-        assertEquals(noDataValue, tileData[0] & 0xFF);
-        noData.setNoData(1L, 5, tileData);
-        assertEquals(noDataValue, tileData[5] & 0xFF);
-        noData.setNoData(1L, tileData.length - 1, tileData);
-        assertEquals(noDataValue, tileData[tileData.length - 1] & 0xFF);
-    }
-
-    @Test
-    public void testGetInstance1Bit() {
-        RasterDatasetInfo rasterInfo;
-        BitmaskToNoDataConverter noData;
-
-        int noDataValue;
-        double statsMin;
-        double statsMax;
-
-        noDataValue = 0;
-        statsMin = 0;
-        statsMax = 1;
-        rasterInfo = createRasterInfo(TYPE_1BIT, noDataValue, statsMin, statsMax);
-        try {
-            noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-            fail("Expected UOE, noDataValue == 0 is non valid");
-        } catch (UnsupportedOperationException e) {
-            assertTrue(true);
-        }
-
-        noDataValue = 2;
-        statsMin = 0;
-        statsMax = 1;
-        rasterInfo = createRasterInfo(TYPE_1BIT, noDataValue, statsMin, statsMax);
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-        assertNotNull(noData);
-        // make sure promotion from 1 to 8 bit is being taking place here and hence we got a 8-bit-u
-        // no-data setter
-        assertTrue(noData instanceof Unsigned8bitConverter);
-    }
-
-    @Test
-    public void testGetInstance4Bit() {
-        RasterDatasetInfo rasterInfo;
-        BitmaskToNoDataConverter noData;
-
-        int noDataValue;
-        double statsMin;
-        double statsMax;
-
-        statsMin = TYPE_4BIT.getSampleValueRange().getMinimum();
-        statsMax = TYPE_4BIT.getSampleValueRange().getMaximum();
-        noDataValue = 0;
-
-        rasterInfo = createRasterInfo(TYPE_4BIT, noDataValue, statsMin, statsMax);
-        try {
-            noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-            fail("Expected UOE, noDataValue == 0 is non valid");
-        } catch (UnsupportedOperationException e) {
-            assertTrue(true);
-        }
-
-        noDataValue = (int) (statsMax + 1);
-
-        rasterInfo = createRasterInfo(TYPE_4BIT, noDataValue, statsMin, statsMax);
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-        assertNotNull(noData);
-        // make sure promotion from 4 to 8 bit is being taking place here and hence we got a 8-bit-u
-        // no-data setter
-        assertTrue(noData instanceof Unsigned8bitConverter);
-    }
-
-    @Test
-    public void testGetInstance16BitU() throws IOException {
-        RasterDatasetInfo rasterInfo;
-        BitmaskToNoDataConverter noData;
-
-        final int noDataValue = (int) TYPE_16BIT_U.getSampleValueRange().getMaximum();
-        double statsMin;
-        double statsMax;
-
-        statsMin = TYPE_16BIT_U.getSampleValueRange().getMinimum();
-        statsMax = TYPE_16BIT_U.getSampleValueRange().getMaximum() - 1;
-        rasterInfo = createRasterInfo(TYPE_16BIT_U, noDataValue, statsMin, statsMax);
-        noData = BitmaskToNoDataConverter.getInstance(rasterInfo, 0);
-        assertNotNull(noData);
-
-        final int samplesPerTile = rasterInfo.getTileDimension(0).width
-                * rasterInfo.getTileDimension(0).height;
-
-        final int dataValue = 5;
-
-        byte[] tileData = new byte[TYPE_16BIT_U.getBitsPerSample() * samplesPerTile];
-        noData.setAll(1L, tileData);
-        DataInputStream in = new DataInputStream(new ByteArrayInputStream(tileData));
-        for (int sampleN = 0; sampleN < samplesPerTile; sampleN++) {
-            assertEquals(noDataValue, in.readUnsignedShort());
-        }
-
-        byte[] bitmaskData = new byte[(int) Math.ceil(samplesPerTile / 8D)];
-        Arrays.fill(bitmaskData, (byte) 0xFF);
-        // set the first 8 and last 8 samples to no-data
-        bitmaskData[0] = 0x00;
-        bitmaskData[bitmaskData.length - 1] = 0x00;
-
-        byte[] expected;
-        {
-            ByteArrayOutputStream actualOut = new ByteArrayOutputStream();
-            DataOutputStream actualWriter = new DataOutputStream(actualOut);
-
-            ByteArrayOutputStream expectedOut = new ByteArrayOutputStream();
-            DataOutputStream expectedWriter = new DataOutputStream(expectedOut);
-            for (int i = 0; i < samplesPerTile; i++) {
-                actualWriter.writeShort(dataValue);
-
-                if (i < 8 || i >= samplesPerTile - 8) {
-                    expectedWriter.writeShort(noDataValue);
-                } else {
-                    expectedWriter.writeShort(dataValue);
-                }
-            }
-            tileData = actualOut.toByteArray();
-            expected = expectedOut.toByteArray();
-        }
-
-        noData.setNoData(1L, tileData, bitmaskData);
-        assertTrue("Arrays differ, expected:" + Arrays.toString(expected) + ", actual:"
-                + Arrays.toString(tileData), Arrays.equals(expected, tileData));
-
-        /*
-         * set individual sample
-         */
-        final int bitsPerSample = TYPE_16BIT_U.getBitsPerSample();
-        tileData = new byte[bitsPerSample * samplesPerTile];
-
-        in = new DataInputStream(new ByteArrayInputStream(tileData));
-        noData.setNoData(1L, 0, tileData);
-        assertEquals(noDataValue, in.readUnsignedShort());
-
-        in = new DataInputStream(new ByteArrayInputStream(tileData, 5 * (bitsPerSample / 8), 2));
-        noData.setNoData(1L, 5, tileData);
-        assertEquals(noDataValue, in.readUnsignedShort());
-
-        in = new DataInputStream(new ByteArrayInputStream(tileData, (samplesPerTile - 1)
-                * (bitsPerSample / 8), 2));
-        noData.setNoData(1L, samplesPerTile - 1, tileData);
-        assertEquals(noDataValue, in.readUnsignedShort());
-    }
-
-    private RasterDatasetInfo createRasterInfo(RasterCellType nativeType, Number noDataValue,
-            double statsMin, double statsMax) {
-
-        RasterDatasetInfo datasetInfo = new RasterDatasetInfo();
-
-        List<RasterInfo> datasetRasters = new ArrayList<RasterInfo>();
-        // fake a 3x8 pixel raster so it's a matrix of 24 elements and it matches a full bitmask
-        // array (no unused bitmask bits)
-        RasterInfo rasterInfo = new RasterInfo(3, 8);
-        datasetRasters.add(rasterInfo);
-
-        rasterInfo.addPyramidLevel(0, new ReferencedEnvelope(), new Point(), new Point(), 10, 10,
-                new Dimension(100, 100));
-        List<RasterBandInfo> bands = new ArrayList<RasterBandInfo>();
-        RasterBandInfo bandInfo = new RasterBandInfo();
-        bands.add(bandInfo);
-
-        bandInfo.bandId = 1L;
-        // the native type
-        bandInfo.cellType = nativeType;
-        // the target type will be determined based on the native type bounds and the band's
-        // statistics
-        bandInfo.noDataValue = noDataValue;
-        bandInfo.statsMin = statsMin;
-        bandInfo.statsMax = statsMax;
-
-        rasterInfo.setBands(bands);
-
-        datasetInfo.setPyramidInfo(datasetRasters);
-
-        return datasetInfo;
-    }
-
-}

Deleted: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterInfoTest.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterInfoTest.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterInfoTest.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,192 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.geom.Point2D;
-import java.awt.geom.Point2D.Double;
-import java.io.IOException;
-
-import org.geotools.arcsde.session.Command;
-import org.geotools.arcsde.session.ISession;
-import org.geotools.arcsde.session.ISessionPool;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.referencing.CRS;
-import org.geotools.referencing.crs.DefaultEngineeringCRS;
-import org.junit.Test;
-import org.opengis.referencing.FactoryException;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import com.esri.sde.sdk.client.SeConnection;
-import com.esri.sde.sdk.client.SeCoordinateReference;
-import com.esri.sde.sdk.client.SeException;
-import com.esri.sde.sdk.client.SeObjectId;
-import com.esri.sde.sdk.client.SeQuery;
-import com.esri.sde.sdk.client.SeRaster;
-import com.esri.sde.sdk.client.SeRasterAttr;
-import com.esri.sde.sdk.client.SeRasterColumn;
-import com.esri.sde.sdk.client.SeRow;
-import com.esri.sde.sdk.client.SeSqlConstruct;
-
-/**
- * Tests the functionality of the ArcSDE raster-display package to read rasters from an ArcSDE
- * database
- *
- * @author Saul Farber, (based on ArcSDEPoolTest by Gabriel Roldan)
- * @source $URL:
- *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/arcsde/datastore/src/test/java
- *         /org/geotools/arcsde/gce/ArcSDEPyramidTest.java $
- * @version $Id$
- */
-public class RasterInfoTest {
-
-    /**
-     * test case for {@link RasterInfo#pickOptimalRasterLevel(ReferencedEnvelope, Rectangle)}
-     */
-    @Test
-    public void testPickOptimalPyramidLevel() {
-
-    }
-
-    /**
-     * Creates a pyramid equivalent to the one created by ArcSDE: <code>
-     * <pre>
-     * ArcSDEPyramid[Nº levels: 10, tile size: 63x63
-     * Levels:
-     *  [0 size: 1013x1021  xRes: 2.0000000000000004  yRes: 2.0  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[0.0 : 2026.0000000000002, 0.0 : 2042.0]  tilesWide: 17  tilesHigh: 17]
-     *  [1 size: 507x511  xRes: 3.996055226824458  yRes: 3.996086105675147  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[0.0 : 2026.0000000000002, 0.0 : 2042.0]  tilesWide: 9  tilesHigh: 9]
-     *  [2 size: 254x256  xRes: 7.976377952755906  yRes: 7.9765625  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[2.0019762845849804 : 2028.0019762845852, -2.0019607843137237 : 2039.9980392156863]  tilesWide: 5  tilesHigh: 5]
-     *  [3 size: 127x128  xRes: 15.889701534343782  yRes: 15.890563725490196  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[6.005928853754941 : 2023.9980237154152, 2.0019607843137237 : 2035.9941176470588]  tilesWide: 3  tilesHigh: 3]
-     *  [4 size: 64x64  xRes: 31.53112648221344  yRes: 31.530882352941177  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[14.013833992094863 : 2032.005928853755, 10.009803921568619 : 2027.986274509804]  tilesWide: 2  tilesHigh: 2]
-     *  [5 size: 32x32  xRes: 62.06126482213439  yRes: 62.06078431372549  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[30.029644268774707 : 2015.9901185770752, 26.025490196078408 : 2011.9705882352941]  tilesWide: 1  tilesHigh: 1]
-     *  [6 size: 16x16  xRes: 120.11857707509883  yRes: 120.11764705882354  xOffset: 0  yOffset: 0  extent: ReferencedEnvelope[62.06126482213439 : 1983.9584980237157, 58.05686274509799 : 1979.9392156862746]  tilesWide: 1  tilesHigh: 1]
-     * ]
-     * </pre>
-     * </code>
-     *
-     * @return
-     */
-    private RasterInfo createPyramid() {
-
-        RasterInfo pyramid = new RasterInfo(1013, 1021);
-
-        final CoordinateReferenceSystem crs = DefaultEngineeringCRS.CARTESIAN_2D;
-
-        final Point imageOffset = new Point(0, 0);
-        final Point2D extentOffset = new Double(0, 0);
-
-        pyramid.addPyramidLevel(0, new ReferencedEnvelope(0, 2026, 0, 2042, crs), imageOffset,
-                extentOffset, 17, 17, new Dimension(1013, 1021));
-        pyramid.addPyramidLevel(1, new ReferencedEnvelope(0, 2026.0000000000002, 0, 2042, crs),
-                imageOffset, extentOffset, 9, 9, new Dimension(507, 511));
-
-        pyramid.addPyramidLevel(2, new ReferencedEnvelope(2.0019762845849804, 2028.0019762845852,
-                -2.0019607843137237, 2039.9980392156863, crs), imageOffset, extentOffset, 5, 5,
-                new Dimension(254, 256));
-
-        pyramid.addPyramidLevel(3, new ReferencedEnvelope(6.005928853754941, 2023.9980237154152,
-                2.0019607843137237, 2035.9941176470588, crs), imageOffset, extentOffset, 3, 3,
-                new Dimension(127, 128));
-
-        pyramid.addPyramidLevel(4, new ReferencedEnvelope(4.013833992094863, 2032.005928853755,
-                10.009803921568619, 2027.986274509804, crs), imageOffset, extentOffset, 2, 2,
-                new Dimension(64, 64));
-
-        pyramid.addPyramidLevel(5, new ReferencedEnvelope(30.029644268774707, 2015.9901185770752,
-                26.025490196078408, 2011.9705882352941, crs), imageOffset, extentOffset, 1, 1,
-                new Dimension(32, 23));
-
-        pyramid.addPyramidLevel(6, new ReferencedEnvelope(62.06126482213439, 1983.9584980237157,
-                58.05686274509799, 1979.9392156862746, crs), imageOffset, extentOffset, 1, 1,
-                new Dimension(16, 16));
-        return pyramid;
-    }
-
-    @Test
-    public void testArcSDEPyramidHypothetical() throws Exception {
-        RasterInfo pyramid = createPyramid();
-        System.out.println(pyramid);
-
-        RasterTestData testData = new RasterTestData();
-        testData.setUp();
-        String tableName = testData.getRasterTableName(RasterCellType.TYPE_8BIT_U, 1, false);
-        testData.loadTestRaster(tableName, 1, 1013, 1021, RasterCellType.TYPE_8BIT_U, null, true,
-                false, SeRaster.SE_INTERPOLATION_NEAREST, 9);
-
-        ISessionPool pool = testData.getConnectionPool();
-        ISession conn = pool.getSession();
-
-        final SeQuery q = conn.createAndExecuteQuery(new String[] { "RASTER" }, new SeSqlConstruct(
-                tableName));
-
-        try {
-            pyramid = conn.issue(new Command<RasterInfo>() {
-                @Override
-                public RasterInfo execute(ISession session, SeConnection connection)
-                        throws SeException, IOException {
-                    SeRow r = q.fetch();
-                    SeRasterAttr rAttr = r.getRaster(0);
-
-                    SeObjectId rasterColumnId = rAttr.getRasterColumnId();
-                    SeRasterColumn rasterColumn = new SeRasterColumn(connection, rasterColumnId);
-                    SeCoordinateReference coordRef = rasterColumn.getCoordRef();
-                    String coordRefWKT = coordRef.getCoordSysDescription();
-                    CoordinateReferenceSystem crs;
-                    try {
-                        crs = CRS.parseWKT(coordRefWKT);
-                    } catch (FactoryException e) {
-                        throw new RuntimeException(e);
-                    }
-
-                    RasterInfo pyramid = new RasterInfo(rAttr, crs);
-                    return pyramid;
-                }
-            });
-        } finally {
-            conn.dispose();
-        }
-
-        System.out.println(pyramid);
-
-        /*
-         * ArcSDEPyramid pyramid = new ArcSDEPyramid(10, 10); pyramid.addPyramidLevel(0, new
-         * SeExtent(0, 0, 100, 100), null, null, 10, 10, new Dimension( 100, 100));
-         * pyramid.addPyramidLevel(1, new SeExtent(0, 0, 100, 100), null, null, 5, 5, new Dimension(
-         * 50, 50));
-         *
-         * RasterQueryInfo ret = pyramid.fitExtentToRasterPixelGrid(new ReferencedEnvelope(0, 10, 0,
-         * 10, null), 0); assertTrue(ret.envelope.equals(new ReferencedEnvelope(0, 10, 0, 10,
-         * null))); assertTrue(ret.image.width == 10 && ret.image.height == 10);
-         *
-         * ret = pyramid.fitExtentToRasterPixelGrid(new ReferencedEnvelope(0, 9, 0, 9, null), 0);
-         * assertTrue(ret.envelope.intersects((BoundingBox) new ReferencedEnvelope(0, 9, 0, 9,
-         * null))); assertTrue(ret.image.width == 9 && ret.image.height == 9);
-         *
-         * ret = pyramid.fitExtentToRasterPixelGrid(new ReferencedEnvelope(15, 300, 15, 300, null),
-         * 1); assertTrue(ret.envelope.equals(new ReferencedEnvelope(14, 300, 14, 300, null)));
-         * assertTrue(ret.image.width == 143 && ret.image.height == 143);
-         *
-         * ret = pyramid.fitExtentToRasterPixelGrid( new ReferencedEnvelope(-100, 200, -100, 200,
-         * null), 1); assertTrue(ret.envelope.equals(new ReferencedEnvelope(-100, 200, -100, 200,
-         * null))); assertTrue(ret.image.width == 150 && ret.image.height == 150);
-         */
-    }
-
-}
\ No newline at end of file

Deleted: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterTestData.java
===================================================================
--- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterTestData.java 2009-11-03 15:07:00 UTC (rev 34312)
+++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/gce/RasterTestData.java 2009-11-03 16:03:24 UTC (rev 34313)
@@ -1,1581 +0,0 @@
-/*
- *    GeoTools - The Open Source Java GIS Toolkit
- *    http://geotools.org
- *
- *    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- *    This library is free software; you can redistribute it and/or
- *    modify it under the terms of the GNU Lesser General Public
- *    License as published by the Free Software Foundation;
- *    version 2.1 of the License.
- *
- *    This library is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *    Lesser General Public License for more details.
- *
- */
-package org.geotools.arcsde.gce;
-
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_16BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_1BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_32BIT_U;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_4BIT;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_64BIT_REAL;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_S;
-import static org.geotools.arcsde.gce.RasterCellType.TYPE_8BIT_U;
-
-import java.awt.Rectangle;
-import java.awt.Transparency;
-import java.awt.color.ColorSpace;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
-import java.awt.image.ComponentSampleModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferShort;
-import java.awt.image.DataBufferUShort;
-import java.awt.image.IndexColorModel;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-
-import org.geotools.arcsde.ArcSdeException;
-import org.geotools.arcsde.data.TestData;
-import org.geotools.arcsde.gce.producer.ArcSDERasterFloatProducerImpl;
-import org.geotools.arcsde.gce.producer.ArcSDERasterOneBitPerBandProducerImpl;
-import org.geotools.arcsde.gce.producer.ArcSDERasterOneBytePerBandProducerImpl;
-import org.geotools.arcsde.gce.producer.ArcSDERasterProducer;
-import org.geotools.arcsde.session.ArcSDEConnectionConfig;
-import org.geotools.arcsde.session.Command;
-import org.geotools.arcsde.session.ISession;
-import org.geotools.arcsde.session.ISessionPool;
-import org.geotools.arcsde.session.UnavailableConnectionException;
-import org.geotools.util.logging.Logging;
-
-import com.esri.sde.sdk.client.SDEPoint;
-import com.esri.sde.sdk.client.SeColumnDefinition;
-import com.esri.sde.sdk.client.SeConnection;
-import com.esri.sde.sdk.client.SeCoordinateReference;
-import com.esri.sde.sdk.client.SeException;
-import com.esri.sde.sdk.client.SeExtent;
-import com.esri.sde.sdk.client.SeInsert;
-import com.esri.sde.sdk.client.SeQuery;
-import com.esri.sde.sdk.client.SeRaster;
-import com.esri.sde.sdk.client.SeRasterAttr;
-import com.esri.sde.sdk.client.SeRasterBand;
-import com.esri.sde.sdk.client.SeRasterColumn;
-import com.esri.sde.sdk.client.SeRasterConstraint;
-import com.esri.sde.sdk.client.SeRasterConsumer;
-import com.esri.sde.sdk.client.SeRasterProducer;
-import com.esri.sde.sdk.client.SeRasterRenderedImage;
-import com.esri.sde.sdk.client.SeRegistration;
-import com.esri.sde.sdk.client.SeRow;
-import com.esri.sde.sdk.client.SeSqlConstruct;
-import com.esri.sde.sdk.client.SeTable;
-import com.esri.sde.sdk.pe.PeFactory;
-import com.esri.sde.sdk.pe.PePCSDefs;
-import com.esri.sde.sdk.pe.PeProjectedCS;
-
-@SuppressWarnings( { "nls", "deprecation" })
-public class RasterTestData {
-
-    private TestData testData;
-
-    private static final Logger LOGGER = Logging.getLogger("org.geotools.arcsde.gce");
-
-    private boolean overrideExistingTables;
-
-    public void setUp() throws IOException {
-        // load a raster dataset into SDE
-        testData = new TestData();
-        testData.setUp();
-        overrideExistingTables = true;
-    }
-
-    public void tearDown() throws Exception {
-        // destroy all sample tables;
-        // for (RasterTableName table : RasterTableName.values()) {
-        // String tableName = getRasterTableName(table);
-        // testData.deleteTable(tableName);
-        // }
-        testData.tearDown(false, true);
-    }
-
-    public void deleteTable(final String tableName) throws Exception {
-        testData.deleteTable(tableName, false);
-    }
-
-    public ISessionPool getConnectionPool() throws IOException {
-        return testData.getConnectionPool();
-    }
-
-    public String getRasterTableName(final RasterCellType cellType, final int numBands,
-            final boolean colorMapped) throws IOException {
-        String testTableName = getRasterTableName(cellType, numBands);
-        if (colorMapped) {
-            testTableName += "_CM";
-        }
-        return testTableName;
-    }
-
-    public String getRasterTableName(final RasterCellType cellType, final int numBands)
-            throws IOException {
-        String typeString = cellType.toString();
-        typeString = typeString.substring("TYPE_".length());
-        String testTableName = testData.getTempTableName() + "_" + cellType + "_" + numBands
-                + "_BAND";
-        return testTableName;
-    }
-
-    public String createCoverageUrl(final RasterCellType cellType, final int numBands)
-            throws IOException {
-        final String rasterTableName = getRasterTableName(cellType, numBands);
-        return createCoverageUrl(rasterTableName);
-    }
-
-    public String createCoverageUrl(final RasterCellType cellType, final int numBands,
-            final boolean colorMapped) throws IOException {
-        final String rasterTableName = getRasterTableName(cellType, numBands, colorMapped);
-        return createCoverageUrl(rasterTableName);
-    }
-
-    public String createCoverageUrl(final String rasterTableName) throws IOException {
-        final ArcSDEConnectionConfig config = getConnectionPool().getConfig();
-        String url = "sde://" + config.getUserName() + ":" + config.getPassword() + "@"
-                + config.getServerName() + ":" + config.getPortNumber() + "/"
-                + config.getDatabaseName() + "#" + rasterTableName;
-        return url;
-    }
-
-    public String getRasterTestDataProperty(String propName) {
-        return testData.getConProps().get(propName);
-    }
-
-    // public void load1bitRaster() throws Exception {
-    // final String tableName = getRasterTableName(RasterTableName.ONEBIT);
-    // final int numberOfBands = 1;
-    // final int pixelType = SeRaster.SE_PIXEL_TYPE_1BIT;
-    // final boolean pyramiding = true;
-    // final boolean skipLevelOne = false;
-    // final int interpolationType = SeRaster.SE_INTERPOLATION_NEAREST;
-    // final IndexColorModel colorModel = null;
-    // loadTestRaster(tableName, numberOfBands, pixelType, colorModel, pyramiding, skipLevelOne,
-    // interpolationType);
-    // }
-
-    /**
-     * Loads the 1bit raster test data into the table given in
-     * {@link RasterTestData#get1bitRasterTableName()}
-     *
-     * @throws Exception
-     */
-    public String load1bitRaster() throws Exception {
-        ISession session = getConnectionPool().getSession();
-        final String tableName = getRasterTableName(TYPE_1BIT, 1);
-
-        // clean out the table if it's currently in-place
-        testData.deleteTable(tableName);
-        // build the base business table. We'll add the raster data to it in a bit
-        createRasterBusinessTempTable(tableName, session);
-        session.dispose();
-
-        SeExtent imgExtent = new SeExtent(231000, 898000, 231000 + 500, 898000 + 500);
-        SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-        String rasterFilename = testData.getConProps().get("sampledata.onebitraster");
-        ArcSDERasterProducer producer = new ArcSDERasterOneBitPerBandProducerImpl();
-
-        importRasterImage(tableName, crs, rasterFilename, SeRaster.SE_PIXEL_TYPE_1BIT, imgExtent,
-                producer);
-
-        return tableName;
-    }
-
-    /**
-     * Loads the 1bit raster test data into the table given in
-     * {@link RasterTestData#get1bitRasterTableName()}
-     *
-     * @throws Exception
-     */
-    public String loadRGBRaster() throws Exception {
-        final String tableName = getRasterTableName(TYPE_8BIT_U, 3);
-
-        // clean out the table if it's currently in-place
-        testData.deleteTable(tableName);
-        // build the base business table. We'll add the raster data to it in a bit
-        ISession session = getConnectionPool().getSession();
-        try {
-            createRasterBusinessTempTable(tableName, session);
-        } finally {
-            session.dispose();
-        }
-
-        SeExtent imgExtent = new SeExtent(231000, 898000, 231000 + 501, 898000 + 501);
-        SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-        String rasterFilename = testData.getConProps().get("sampledata.rgbraster");
-        ArcSDERasterProducer prod = new ArcSDERasterOneBytePerBandProducerImpl();
-
-        importRasterImage(tableName, crs, rasterFilename, SeRaster.SE_PIXEL_TYPE_8BIT_U, imgExtent,
-                prod);
-
-        return tableName;
-    }
-
-    public String loadRGBColorMappedRaster() throws Exception {
-        final String tableName = getRasterTableName(TYPE_8BIT_U, 1, true);
-
-        // clean out the table if it's currently in-place
-        testData.deleteTable(tableName);
-
-        // build the base business table. We'll add the raster data to it in a bit
-        // Note that this DOESN'T LOAD THE COLORMAP RIGHT NOW.
-        ISession session = getConnectionPool().getSession();
-        try {
-            createRasterBusinessTempTable(tableName, session);
-        } finally {
-            session.dispose();
-        }
-
-        SeExtent imgExtent = new SeExtent(231000, 898000, 231000 + 500, 898000 + 500);
-        SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-        String rasterFilename = testData.getConProps().get("sampledata.rgbraster-colormapped");
-        ArcSDERasterProducer prod = new ArcSDERasterOneBytePerBandProducerImpl();
-
-        importRasterImage(tableName, crs, rasterFilename, SeRaster.SE_PIXEL_TYPE_8BIT_U, imgExtent,
-                prod);
-        return tableName;
-    }
-
-    public String loadOneByteGrayScaleRaster() throws Exception {
-        final String tableName = getRasterTableName(TYPE_8BIT_U, 1);
-
-        // clean out the table if it's currently in-place
-        testData.deleteTable(tableName);
-        // build the base business table. We'll add the raster data to it in a bit
-        // Note that this DOESN'T LOAD THE COLORMAP RIGHT NOW.
-        ISession session = getConnectionPool().getSession();
-        try {
-            createRasterBusinessTempTable(tableName, session);
-        } finally {
-            session.dispose();
-        }
-
-        SeExtent imgExtent = new SeExtent(231000, 898000, 231000 + 500, 898000 + 500);
-        SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-        String rasterFilename = testData.getConProps().get("sampledata.onebyteonebandraster");
-        ArcSDERasterProducer prod = new ArcSDERasterOneBytePerBandProducerImpl();
-
-        importRasterImage(tableName, crs, rasterFilename, SeRaster.SE_PIXEL_TYPE_8BIT_U, imgExtent,
-                prod);
-
-        return tableName;
-    }
-
-    public String loadFloatRaster() throws Exception {
-        final String tableName = getRasterTableName(TYPE_32BIT_REAL, 1);
-
-        // clean out the table if it's currently in-place
-        testData.deleteTable(tableName);
-        // build the base business table. We'll add the raster data to it in a bit
-        // Note that this DOESN'T LOAD THE COLORMAP RIGHT NOW.
-        ISession session = getConnectionPool().getSession();
-        try {
-            createRasterBusinessTempTable(tableName, session);
-        } finally {
-            session.dispose();
-        }
-
-        SeExtent imgExtent = new SeExtent(245900, 899600, 246300, 900000);
-        SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-        String rasterFilename = testData.getConProps().get("sampledata.floatraster");
-        ArcSDERasterProducer prod = new ArcSDERasterFloatProducerImpl();
-
-        importRasterImage(tableName, crs, rasterFilename, SeRaster.SE_PIXEL_TYPE_32BIT_REAL,
-                imgExtent, prod);
-
-        return tableName;
-    }
-
-    public SeCoordinateReference getSeCRSFromPeProjectedCSId(int PeProjectedCSId) {
-        SeCoordinateReference crs;
-        try {
-            PeProjectedCS pcs = (PeProjectedCS) PeFactory.factory(PeProjectedCSId);
-            crs = new SeCoordinateReference();
-            crs.setCoordSysByDescription(pcs.toString());
-        } catch (Throwable t) {
-            throw new RuntimeException(t);
-        }
-        return crs;
-    }
-
-    public void createRasterBusinessTempTable(final String tableName, final ISession conn)
-            throws Exception {
-        conn.issue(new Command<Void>() {
-
-            @Override
-            public Void execute(ISession session, SeConnection connection) throws SeException,
-                    IOException {
-                SeColumnDefinition[] colDefs = new SeColumnDefinition[1];
-                SeTable table = new SeTable(connection, tableName);
-
-                // first column to be SDE managed feature id
-                colDefs[0] = new SeColumnDefinition("ROW_ID", SeColumnDefinition.TYPE_INTEGER, 10,
-                        0, false);
-                table.create(colDefs, testData.getConfigKeyword());
-
-                /*
-                 * Register the column to be used as feature id and managed by sde
-                 */
-                SeRegistration reg = new SeRegistration(connection, table.getName());
-                LOGGER.fine("setting rowIdColumnName to ROW_ID in table " + reg.getTableName());
-                reg.setRowIdColumnName("ROW_ID");
-                final int rowIdColumnType = SeRegistration.SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE;
-                reg.setRowIdColumnType(rowIdColumnType);
-                reg.alter();
-                return null;
-            }
-        });
-    }
-
-    public void importRasterImage(final String tableName, SeCoordinateReference crs,
-            final String rasterFilename, final int sePixelType, SeExtent extent,
-            ArcSDERasterProducer prod) throws Exception {
-        importRasterImage(tableName, crs, rasterFilename, sePixelType, extent, prod, null);
-    }
-
-    public void importRasterImage(final String tableName, final SeCoordinateReference crs,
-            final String rasterFilename, final int sePixelType, final SeExtent extent,
-            final ArcSDERasterProducer prod, final IndexColorModel colorModel) throws Exception {
-
-        Command<Void> importRasterCmd = new Command<Void>() {
-            @Override
-            public Void execute(ISession session, SeConnection connection) throws SeException,
-                    IOException {
-                createRasterColumn(tableName, crs, session);
-
-                IndexColorModel indexCM = colorModel;
-
-                // now start loading the actual raster data
-                BufferedImage sampleImage = ImageIO.read(org.geotools.test.TestData.getResource(
-                        null, rasterFilename));
-                {
-                    ColorModel imgColorModel = sampleImage.getColorModel();
-                    if (imgColorModel instanceof IndexColorModel) {
-                        indexCM = (IndexColorModel) imgColorModel;
-                    }
-                }
-                int imageWidth = sampleImage.getWidth(), imageHeight = sampleImage.getHeight();
-
-                SeRasterAttr attr = new SeRasterAttr(true);
-                attr.setImageSize(imageWidth, imageHeight, sampleImage.getSampleModel()
-                        .getNumBands());
-                int tileWidth = imageWidth >> 3;// 128;
-                int tileHeight = imageHeight >> 3;// 128;
-                attr.setTileSize(tileWidth, tileHeight);
-                attr.setPixelType(sePixelType);
-                attr.setCompressionType(SeRaster.SE_COMPRESSION_NONE);
-
-                int maxLevels = (imageWidth / (2 * tileWidth)) - 1;
-                attr.setPyramidInfo(maxLevels, false, SeRaster.SE_INTERPOLATION_BILINEAR);
-                attr.setMaskMode(false);
-                attr.setImportMode(false);
-
-                attr.setExtent(extent);
-
-                // attr.setImageOrigin();
-
-                prod.setSeRasterAttr(attr);
-                prod.setSourceImage(sampleImage);
-                attr.setRasterProducer(prod);
-
-                try {
-                    SeInsert insert = new SeInsert(connection);
-                    insert.intoTable(tableName, new String[] { "RASTER" });
-                    // no buffered writes on raster loads
-                    insert.setWriteMode(false);
-                    SeRow row = insert.getRowToSet();
-                    row.setRaster(0, attr);
-
-                    insert.execute();
-                    insert.close();
-                } catch (SeException se) {
-                    se.printStackTrace();
-                    throw se;
-                }
-
-                // if there's a colormap to insert, let's add that too
-                if (indexCM != null) {
-                    attr = getRasterAttributes(tableName, new Rectangle(0, 0, 0, 0), 0,
-                            new int[] { 1 });
-                    final int numEntries = indexCM.getMapSize();
-                    // number of colors, including alpha, if any
-                    final int numBanks = indexCM.getNumComponents();
-                    final int colorMapType = numBanks == 3 ? SeRaster.SE_COLORMAP_RGB
-                            : SeRaster.SE_COLORMAP_RGBA;
-                    DataBufferByte dataBuffer = new DataBufferByte(numEntries, numBanks);
-                    for (int elem = 0; elem < numEntries; elem++) {
-                        dataBuffer.setElem(0, elem, indexCM.getRed(elem));
-                        dataBuffer.setElem(1, elem, indexCM.getGreen(elem));
-                        dataBuffer.setElem(2, elem, indexCM.getBlue(elem));
-                        if (numBanks == 4) {
-                            dataBuffer.setElem(3, elem, indexCM.getAlpha(elem));
-                        }
-                    }
-                    SeRaster raster;
-                    try {
-                        raster = attr.getRasterInfo();
-                    } catch (CloneNotSupportedException e) {
-                        throw new RuntimeException(e);
-                    }
-                    SeRasterBand[] bands = raster.getBands();
-                    SeRasterBand band = bands[0];
-                    band.setColorMap(colorMapType, dataBuffer);
-                    band.alter();
-                }
-                return null;
-            }
-        };
-        final ISession session = getConnectionPool().getSession();
-        try {
-            session.issue(importRasterCmd);
-        } finally {
-            session.dispose();
-        }
-    }
-
-    public void loadUshortRaster() throws Exception {
-        final RasterCellType pixelType = TYPE_16BIT_U;
-        final int numberOfBands = 1;
-        final String tableName = getRasterTableName(pixelType, numberOfBands);
-        final boolean pyramiding = true;
-        final boolean skipLevelOne = false;
-        final int interpolationType = SeRaster.SE_INTERPOLATION_NEAREST;
-        final IndexColorModel colorModel = null;
-        final int imageWidth = 256;
-        final int imageHeight = 256;
-
-        try {
-            loadTestRaster(tableName, numberOfBands, imageWidth, imageHeight, pixelType,
-                    colorModel, pyramiding, skipLevelOne, interpolationType, null);
-        } catch (SeException e) {
-            throw new ArcSdeException(e);
-        }
-    }
-
-    public String loadShortRaster() throws Exception {
-        final int numberOfBands = 1;
-        final RasterCellType pixelType = TYPE_16BIT_S;
-        final String tableName = getRasterTableName(pixelType, numberOfBands);
-        final boolean pyramiding = true;
-        final boolean skipLevelOne = false;
-        final int interpolationType = SeRaster.SE_INTERPOLATION_NEAREST;
-        final IndexColorModel colorModel = null;
-        final int imageWidth = 256;
-        final int imageHeight = 256;
-
-        try {
-            loadTestRaster(tableName, numberOfBands, imageWidth, imageHeight, pixelType,
-                    colorModel, pyramiding, skipLevelOne, interpolationType, null);
-        } catch (SeException e) {
-            throw new ArcSdeException(e);
-        }
-        return tableName;
-    }
-
-    /**
-     * Creates a 4 band raster, with 8 bit unsigned pixel type and no colormap, and pyramid
-     *
-     * @throws Exception
-     * @see {@link #loadTestRaster(String, int, int, IndexColorModel, boolean, boolean, int)
-
-     */
-    public String loadRGBARaster() throws Exception {
-        final int numberOfBands = 4;
-        final RasterCellType pixelType = TYPE_8BIT_U;
-        final String tableName = getRasterTableName(pixelType, numberOfBands);
-        final boolean pyramiding = true;
-        final boolean skipLevelOne = false;
-        final int interpolationType = SeRaster.SE_INTERPOLATION_NEAREST;
-        final IndexColorModel colorModel = null;
-        final int imageWidth = 256;
-        final int imageHeight = 256;
-        loadTestRaster(tableName, numberOfBands, imageWidth, imageHeight, pixelType, colorModel,
-                pyramiding, skipLevelOne, interpolationType, null);
-        return tableName;
-    }
-
-    public String load8bitUnsignedColorMappedRaster() throws Exception {
-        final int numberOfBands = 1;
-        final RasterCellType pixelType = TYPE_8BIT_U;
-        final String tableName = getRasterTableName(pixelType, numberOfBands);
-        final boolean pyramiding = true;
-        final boolean skipLevelOne = false;
-        final int interpolationType = SeRaster.SE_INTERPOLATION_NEAREST;
-
-        int cmBits = 8;
-        int cmSize = 1;
-        byte[] cmR = { 0x00 };
-        byte[] cmG = { 0x00 };
-        byte[] cmB = { (byte) 0xFF };
-        final IndexColorModel colorModel = new IndexColorModel(cmBits, cmSize, cmR, cmG, cmB);
-        final int imageWidth = 256;
-        final int imageHeight = 256;
-
-        loadTestRaster(tableName, numberOfBands, imageWidth, imageHeight, pixelType, colorModel,
-                pyramiding, skipLevelOne, interpolationType, null);
-
-        return tableName;
-    }
-
-    /**
-     * Creates a a raster in the database with NO pyramiding, some default settings and the provided
-     * parameters.
-     * <p>
-     * Default settings
-     * <ul>
-     * <li>CRS: PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M
-     * <li>Extent: minx=0, miny=0, maxx=512, maxy=512
-     * <li>Width: 256
-     * <li>Height: 256
-     * <li>Tile size: 64x64 (being less than the recommended minimum of 128, but ok for our testing
-     * purposes)
-     * <li>Compression: none
-     * <li>Pyramid: none
-     * </ul>
-     * </p>
-     *
-     * @param tableName
-     *            the name of the table to create
-     * @param numberOfBands
-     *            the number of bands of the raster
-     * @param pixelType
-     *            the pixel (cell) depth of the raster bands (one of the {@code
-     *            SeRaster#SE_PIXEL_TYPE_*} constants)
-     * @param colorModel
-     *            the color model to apply to the raster, may be {@code null}. A non null value adds
-     *            as precondition that {@code numberOfBands == 1}
-     * @throws Exception
-     */
-    public void loadTestRaster(final String tableName, final int numberOfBands,
-            final RasterCellType pixelType, final IndexColorModel colorModel) throws Exception {
-        final boolean pyramiding = true;
-        final boolean skipLevelOne = false;
-        final int interpolationType = SeRaster.SE_INTERPOLATION_BILINEAR;
-        final int imageWidth = 256;
-        final int imageHeight = 256;
-
-        loadTestRaster(tableName, numberOfBands, imageWidth, imageHeight, pixelType, colorModel,
-                pyramiding, skipLevelOne, interpolationType, null);
-    }
-
-    /**
-     * Creates a simple raster catalog, extent and grid range coincide for easier assertions.
-     * <p>
-     * The catalog rasters are not inserted in left-right, top-bottom direction though, as it may
-     * happen in real life.
-     * </p>
-     * <p>
-     * The grid extent layout is as follows (invert Y for pixel layout):
-     *
-     * <pre>
-     *   0,512       256,512       512,512
-     *       _____________________
-     *      |          |          |
-     *      |          |          |
-     *      |     3    |    1     |
-     *      |          |          |
-     *      |__________|__________| 512,256
-     *  0,256          |256,256   |
-     *                 |          |
-     *                 |    2     |
-     *                 |          |
-     *                 |__________|
-     *    0,0       256,0          512,0
-     * </pre>
-     *
-     * </p>
-     *
-     * @return
-     * @throws Exception
-     */
-    public String loadRasterCatalog() throws Exception {
-        final int numberOfBands = 3;
-        final RasterCellType pixelType = TYPE_8BIT_U;
-        final String tableName = getRasterTableName(pixelType, numberOfBands) + "_CAT";
-
-        {
-            // clean out the table if it's currently in-place
-            testData.deleteTable(tableName);
-            // build the base business table. We'll add the raster data to it in a bit
-            // Note that this DOESN'T LOAD THE COLORMAP RIGHT NOW.
-            ISession session = getConnectionPool().getSession();
-            try {
-                createRasterBusinessTempTable(tableName, session);
-            } finally {
-                session.dispose();
-            }
-        }
-
-        final SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-
-        final ISession session = getConnectionPool().getSession();
-        try {
-            createRasterColumn(tableName, crs, session);
-
-            int imageWidth;
-            int imageHeight;
-            SeExtent extent;
-            int maxLevels;
-
-            maxLevels = 2;
-            extent = new SeExtent(0, 0, 256, 256);
-            imageWidth = 228;
-            imageHeight = 228;
-            addRasterToCatalog(session, tableName, crs, numberOfBands, imageWidth, imageHeight,
-                    pixelType, maxLevels, extent);
-
-            maxLevels = 3;
-            extent = new SeExtent(512, 512, 768, 768);
-            imageWidth = 456;
-            imageHeight = 456;
-            addRasterToCatalog(session, tableName, crs, numberOfBands, imageWidth, imageHeight,
-                    pixelType, maxLevels, extent);
-
-            maxLevels = 3;
-            extent = new SeExtent(512, 0, 768, 256);
-            imageWidth = 532;
-            imageHeight = 532;
-            addRasterToCatalog(session, tableName, crs, numberOfBands, imageWidth, imageHeight,
-                    pixelType, maxLevels, extent);
-
-            maxLevels = 3;
-            extent = new SeExtent(0, 512, 256, 768);
-            imageWidth = 1024;
-            imageHeight = 1024;
-            addRasterToCatalog(session, tableName, crs, numberOfBands, imageWidth, imageHeight,
-                    pixelType, maxLevels, extent);
-
-            maxLevels = 3;
-            extent = new SeExtent(256, 256, 512, 512);
-            imageWidth = 99;
-            imageHeight = 99;
-            addRasterToCatalog(session, tableName, crs, numberOfBands, imageWidth, imageHeight,
-                    pixelType, maxLevels, extent);
-        } finally {
-            session.dispose();
-        }
-
-        return tableName;
-    }
-
-    private void addRasterToCatalog(ISession session, String tableName, SeCoordinateReference crs,
-            int numberOfBands, int imageWidth, int imageHeight, RasterCellType pixelType,
-            int maxLevels, SeExtent extent) throws IOException {
-
-        IndexColorModel colorModel = null;
-        boolean skipLevelOne = false;
-        int interpolationType = SeRaster.SE_INTERPOLATION_BICUBIC;
-
-        addRasterAttribute(tableName, numberOfBands, imageWidth, imageHeight, pixelType,
-                colorModel, maxLevels, skipLevelOne, interpolationType, extent, session);
-
-    }
-
-    /**
-     * Creates a a raster in the database with some default settings and the provided parameters.
-     * <p>
-     * Default settings
-     * <ul>
-     * <li>CRS: PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M
-     * <li>Extent: minx=0, miny=0, maxx=512, maxy=512
-     * <li>Width: 256
-     * <li>Height: 256
-     * <li>Tile size: 64x64 (being less than the recommended minimum of 128, but ok for our testing
-     * purposes)
-     * <li>Compression: none
-     * </ul>
-     * </p>
-     *
-     * @param tableName
-     *            the name of the table to create
-     * @param numberOfBands
-     *            the number of bands of the raster
-     * @param pixelType
-     *            the pixel (cell) depth of the raster bands (one of the {@code
-     *            SeRaster#SE_PIXEL_TYPE_*} constants)
-     * @param colorModel
-     *            the color model to apply to the raster, may be {@code null}. A non null value adds
-     *            as precondition that {@code numberOfBands == 1}
-     * @param pyramiding
-     *            whether to create tiles or not for the raster. If {@code true} and {@code
-     *            skipLevelOne == true} a pyramid with three levels will be created, avoiding to
-     *            create the pyramid tiles for level 0 (same dimension as the source raster). If
-     *            {@code skipLevelOne == false}, even for level 0 the pyramid tiles will be created,
-     *            that is, four levels.
-     * @param skipLevelOne
-     *            only relevant if {@code pyramiding == true}, {@code true} indicates not to create
-     *            pyramid tiles for the first level, since its equal in dimension than the source
-     *            raster
-     * @param interpolationType
-     *            only relevant if {@code pyramiding == true}, indicates which interpolation method
-     *            to use in building the pyramid tiles. Shall be one of
-     *            {@link SeRaster#SE_INTERPOLATION_BICUBIC},
-     *            {@link SeRaster#SE_INTERPOLATION_BILINEAR},
-     *            {@link SeRaster#SE_INTERPOLATION_NEAREST}. Otherwise
-     *            {@link SeRaster#SE_INTERPOLATION_NONE}
-     * @throws Exception
-     */
-    public void loadTestRaster(final String tableName, final int numberOfBands,
-            final int imageWidth, final int imageHeight, final RasterCellType pixelType,
-            final IndexColorModel colorModel, final boolean pyramiding, final boolean skipLevelOne,
-            final int interpolationType, final Integer forceNumLevels) throws Exception {
-
-        if (colorModel != null && numberOfBands > 1) {
-            throw new IllegalArgumentException(
-                    "Indexed rasters shall contain a single band. numberOfBands = " + numberOfBands);
-        }
-        {
-            // clean out the table if it's currently in-place
-            testData.deleteTable(tableName);
-            // build the base business table. We'll add the raster data to it in a bit
-            // Note that this DOESN'T LOAD THE COLORMAP RIGHT NOW.
-            ISession session = getConnectionPool().getSession();
-            try {
-                createRasterBusinessTempTable(tableName, session);
-            } finally {
-                session.dispose();
-            }
-        }
-
-        final SeExtent extent = new SeExtent(0, 0, 2 * imageWidth, 2 * imageHeight);
-        final SeCoordinateReference crs = getSeCRSFromPeProjectedCSId(PePCSDefs.PE_PCS_NAD_1983_HARN_MA_M);
-
-        final ISession session = getConnectionPool().getSession();
-        try {
-            createRasterColumn(tableName, crs, session);
-
-            int maxLevels;
-            if (pyramiding) {
-                int tileWidth = imageWidth >> 4;
-                if (forceNumLevels == null) {
-                    maxLevels = (imageWidth / (4 * tileWidth)) - 1;
-                } else {
-                    maxLevels = forceNumLevels;
-                }
-            } else {
-                maxLevels = 0;
-            }
-            addRasterAttribute(tableName, numberOfBands, imageWidth, imageHeight, pixelType,
-                    colorModel, maxLevels, skipLevelOne, interpolationType, extent, session);
-
-        } finally {
-            session.dispose();
-        }
-    }
-
-    private void addRasterAttribute(final String tableName, final int numberOfBands,
-            final int imageWidth, final int imageHeight, final RasterCellType pixelType,
-            final IndexColorModel colorModel, final int maxPyramidLevel,
-            final boolean skipLevelOne, final int interpolationType, final SeExtent extent,
-            final ISession session) throws IOException {
-
-        // attr.setImageOrigin();
-
-        final SeRasterProducer prod = new SeRasterProducer() {
-            public void addConsumer(SeRasterConsumer consumer) {
-            }
-
-            public boolean isConsumer(SeRasterConsumer consumer) {
-                return false;
-            }
-
-            public void removeConsumer(SeRasterConsumer consumer) {
-            }
-
-            /**
-             * Note that due to some synchronization problems inherent in the SDE api code, the
-             * startProduction() method MUST return before consumer.setScanLines() or
-             * consumer.setRasterTiles() is called. Hence the thread implementation.
-             */
-            public void startProduction(final SeRasterConsumer consumer) {
-                if (!(consumer instanceof SeRasterRenderedImage)) {
-                    throw new IllegalArgumentException(
-                            "You must set SeRasterAttr.setImportMode(false) to "
-                                    + "load data using this SeProducer implementation.");
-                }
-
-                Thread runme = new Thread() {
-                    @Override
-                    public void run() {
-                        try {
-                            PixelSampler sampler = PixelSampler.getSampler(pixelType);
-                            // for each band...
-                            for (int bandN = 0; bandN < numberOfBands; bandN++) {
-                                final byte[] imgBandData;
-                                imgBandData = sampler.getImgBandData(imageWidth, imageHeight,
-                                        bandN, numberOfBands);
-                                consumer.setScanLines(imageHeight, imgBandData, null);
-                                consumer.rasterComplete(SeRasterConsumer.SINGLEFRAMEDONE);
-                            }
-                            consumer.rasterComplete(SeRasterConsumer.STATICIMAGEDONE);
-                        } catch (Exception se) {
-                            se.printStackTrace();
-                            consumer.rasterComplete(SeRasterConsumer.IMAGEERROR);
-                        }
-                    }
-                };
-                runme.start();
-            }
-        };
-
-        session.issue(new Command<Void>() {
-            @Override
-            public Void execute(ISession session, SeConnection connection) throws SeException,
-                    IOException {
-                {
-                    SeRasterAttr attr = new SeRasterAttr(true);
-                    attr.setImageSize(imageWidth, imageHeight, numberOfBands);
-                    int tileWidth = imageWidth >> 4;
-                    int tileHeight = imageHeight >> 4;
-                    attr.setTileSize(tileWidth, tileHeight); // this is lower than the recommended
-                    // minimum
-                    // of 128,128 but
-                    // it's ok for our testing purposes
-                    attr.setPixelType(pixelType.getSeRasterPixelType());
-                    attr.setCompressionType(SeRaster.SE_COMPRESSION_NONE);
-
-                    attr.setPyramidInfo(maxPyramidLevel, skipLevelOne, interpolationType);
-
-                    attr.setInterleave(true, SeRaster.SE_RASTER_INTERLEAVE_BIP);
-                    attr.setMaskMode(false);
-                    attr.setImportMode(false);
-
-                    attr.setExtent(extent);
-                    attr.setRasterProducer(prod);
-
-                    SeInsert insert = new SeInsert(connection);
-                    insert.intoTable(tableName, new String[] { "RASTER" });
-                    // no buffered writes on raster loads
-                    insert.setWriteMode(false);
-                    SeRow row = insert.getRowToSet();
-                    row.setRaster(0, attr);
-                    // import the data
-                    insert.execute();
-                    insert.close();
-                }
-                // if there's a colormap to insert, let's add that too
-                if (colorModel != null) {
-                    try {
-                        SeQuery query = new SeQuery(connection, new String[] { "RASTER" },
-                                new SeSqlConstruct(tableName));
-                        query.prepareQuery();
-                        query.execute();
-                        SeRow row = query.fetch();
-                        SeRasterAttr attr = row.getRaster(0);
-                        SeRaster raster;
-                        try {
-                            raster = attr.getRasterInfo();
-                        } catch (CloneNotSupportedException e) {
-                            throw new RuntimeException(e);
-                        }
-                        SeRasterBand band1 = raster.getBands()[0];
-                        final int numEntries = colorModel.getMapSize();
-                        // number of colors, including alpha, if any
-                        final int numBanks = colorModel.getNumComponents();
-                        final int colorMapType = numBanks == 3 ? SeRaster.SE_COLORMAP_RGB
-                                : SeRaster.SE_COLORMAP_RGBA;
-                        final int dataType = pixelType.getDataBufferType();
-                        DataBuffer dataBuffer;
-                        if (DataBuffer.TYPE_BYTE == dataType) {
-                            dataBuffer = new DataBufferByte(numEntries, numBanks);
-                        } else if (DataBuffer.TYPE_USHORT == dataType) {
-                            /*
-                             * beware we're using DataBufferShort instead of DataBufferUShort as
-                             * that's what the esri api expects
-                             */
-                            dataBuffer = new DataBufferShort(numEntries, numBanks);
-                        } else {
-                            throw new IllegalArgumentException("data type: " + pixelType);
-                        }
-                        for (int elem = 0; elem < numEntries; elem++) {
-                            dataBuffer.setElem(0, colorModel.getRed(elem));
-                            dataBuffer.setElem(1, colorModel.getGreen(elem));
-                            dataBuffer.setElem(2, colorModel.getBlue(elem));
-                            if (numBanks == 4) {
-                                dataBuffer.setElem(3, colorModel.getAlpha(elem));
-                            }
-                        }
-                        band1.setColorMap(colorMapType, dataBuffer);
-                        band1.alter();
-                    } catch (SeException e) {
-                        e.printStackTrace();
-                        throw new ArcSdeException(e);
-                    }
-                }
-                return null;
-            }
-        });
-    }
-
-    private void createRasterColumn(final String tableName, final SeCoordinateReference crs,
-            final ISession session) throws IOException {
-        // much of this code is from
-        // http://edndoc.esri.com/arcsde/9.2/concepts/rasters/dataloading/dataloading.htm
-        session.issue(new Command<Void>() {
-
-            @Override
-            public Void execute(ISession session, SeConnection connection) throws SeException,
-                    IOException {
-                SeRasterColumn rasCol = new SeRasterColumn(connection);
-                rasCol.setTableName(tableName);
-                rasCol.setDescription("Sample geotools ArcSDE raster test-suite data.");
-                rasCol.setRasterColumnName("RASTER");
-                rasCol.setCoordRef(crs);
-                rasCol.setConfigurationKeyword(testData.getConfigKeyword());
-
-                rasCol.create();
-                return null;
-            }
-        });
-    }
-
-    /**
-     * convenience method to test if two images are identical in their RGB pixel values
-     *
-     * @param image
-     * @param fileName
-     * @return
-     * @throws IOException
-     */
-    public static boolean imageEquals(RenderedImage image, String fileName) throws IOException {
-        InputStream in = org.geotools.test.TestData.url(null, fileName).openStream();
-        BufferedImage expected = ImageIO.read(in);
-
-        return imageEquals(image, expected);
-    }
-
-    public static boolean imageEquals(RenderedImage image1, RenderedImage image2) {
-        return imageEquals(image1, image2, true);
-    }
-
-    /**
-     * convenience method to test if two images are identical in their RGB pixel values
-     *
-     * @param image1
-     * @param image2
-     * @return
-     */
-    public static boolean imageEquals(RenderedImage image1, RenderedImage image2,
-            boolean ignoreAlpha) {
-
-        final int h = image1.getHeight();
-        final int w = image2.getWidth();
-
-        int skipBand = -1;
-        if (ignoreAlpha) {
-            skipBand = 3;
-        }
-
-        for (int b = 0; b < image1.getData().getNumBands(); b++) {
-            if (b == skipBand)
-                continue;
-            int[] img1data = image1.getData().getSamples(0, 0, image1.getWidth(),
-                    image1.getHeight(), b, new int[image1.getHeight() * image1.getWidth()]);
-            int[] img2data = image2.getData().getSamples(0, 0, image1.getWidth(),
-                    image1.getHeight(), b, new int[image1.getHeight() * image1.getWidth()]);
-
-            if (!Arrays.equals(img1data, img2data)) {
-                // try to figure out which pixel (exactly) was different
-                for (int i = 0; i < img1data.length; i++) {
-                    if (img1data[i] != img2data[i]) {
-                        final int x = i % image1.getWidth();
-                        final int y = i / image1.getHeight();
-                        System.out.println("pixel " + i + " (possibly " + x + "," + y
-                                + ") differs: " + img1data[i] + " != " + img2data[i]);
-                        return false;
-                    }
-                }
-            }
-
-            /*
-             * for (int xpos = 0; xpos < image1.getWidth(); xpos++) { System.out.println("checking
-             * column " + xpos); int[] img1data = image1.getData().getSamples(xpos, 0, 1,
-             * image1.getHeight(), b, new int[image1.getHeight()]); int[] img2data =
-             * image2.getData().getSamples(xpos, 0, 1, image1.getHeight(), b, new
-             * int[image1.getHeight()]); if (!Arrays.equals(img1data, img2data)) {
-             * System.out.println("pixels in column " + xpos + " are different"); return false; } }
-             */
-
-        }
-        return true;
-    }
-
-    public SeRasterAttr getRasterAttributes(final String rasterName, final Rectangle tiles,
-            final int level, final int[] bands) throws IOException {
-
-        ISession conn;
-        try {
-            conn = getConnectionPool().getSession();
-        } catch (UnavailableConnectionException e) {
-            throw new RuntimeException(e);
-        }
-
-        try {
-            final SeQuery query = conn.createAndExecuteQuery(new String[] { conn.getRasterColumn(
-                    rasterName).getName() }, new SeSqlConstruct(rasterName));
-
-            return conn.issue(new Command<SeRasterAttr>() {
-
-                @Override
-                public SeRasterAttr execute(ISession session, SeConnection connection)
-                        throws SeException, IOException {
-                    final SeRow r = query.fetch();
-
-                    // Now build a SeRasterConstraint object which queries the db for
-                    // the right tiles/bands/pyramid level
-                    SeRasterConstraint rConstraint = new SeRasterConstraint();
-                    rConstraint.setEnvelope((int) tiles.getMinX(), (int) tiles.getMinY(),
-                            (int) tiles.getMaxX(), (int) tiles.getMaxY());
-                    rConstraint.setLevel(level);
-                    rConstraint.setBands(bands);
-
-                    // Finally, execute the raster query aganist the already-opened
-                    // SeQuery object which already has an SeRow fetched against it.
-
-                    query.queryRasterTile(rConstraint);
-                    final SeRasterAttr rattr = r.getRaster(0);
-
-                    query.close();
-
-                    return rattr;
-                }
-            });
-        } finally {
-            conn.dispose();
-        }
-    }
-
-    public static abstract class PixelSampler {
-
-        private static Map<RasterCellType, PixelSampler> byPixelTypeSamplers = new HashMap<RasterCellType, PixelSampler>();
-        static {
-            byPixelTypeSamplers.put(TYPE_1BIT, new SamplerType1Bit());
-            byPixelTypeSamplers.put(TYPE_4BIT, new SamplerType4Bit());
-            byPixelTypeSamplers.put(TYPE_8BIT_U, new SamplerType8BitUnsigned());
-            byPixelTypeSamplers.put(TYPE_8BIT_S, new SamplerType8BitSigned());
-            byPixelTypeSamplers.put(TYPE_16BIT_U, new SamplerType16BitUnsigned());
-            byPixelTypeSamplers.put(TYPE_16BIT_S, new SamplerType16BitSigned());
-            byPixelTypeSamplers.put(TYPE_32BIT_U, new SamplerType32BitUnsigned());
-            byPixelTypeSamplers.put(TYPE_32BIT_S, new SamplerType32BitSigned());
-            byPixelTypeSamplers.put(TYPE_32BIT_REAL, new SamplerType32BitReal());
-            byPixelTypeSamplers.put(TYPE_64BIT_REAL, new SamplerType64BitReal());
-     &nb