Package org.geotools.coverageio

Source Code of org.geotools.coverageio.BaseGridCoverage2DReader

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2007-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.coverageio;

import it.geosolutions.imageio.imageioimpl.imagereadmt.ImageReadDescriptorMT;
import it.geosolutions.imageio.stream.input.FileImageInputStreamExt;
import it.geosolutions.imageio.stream.input.FileImageInputStreamExtImpl;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi;
import javax.media.jai.JAI;

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.GridCoverage2DReader;
import org.geotools.data.DataSourceException;
import org.geotools.data.DefaultResourceInfo;
import org.geotools.data.DefaultServiceInfo;
import org.geotools.data.PrjFileReader;
import org.geotools.data.ResourceInfo;
import org.geotools.data.ServiceInfo;
import org.geotools.data.WorldFileReader;
import org.geotools.factory.Hints;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.metadata.iso.spatial.PixelTranslation;
import org.geotools.referencing.CRS;
import org.geotools.resources.coverage.CoverageUtilities;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridCoverageReader;
import org.opengis.geometry.Envelope;
import org.opengis.parameter.GeneralParameterValue;
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.TransformException;

/**
* Base class for GridCoverage data access
*
* @author Daniele Romagnoli, GeoSolutions
* @author Simone Giannecchini, GeoSolutions
*
*
*
*
* @source $URL$
*/
public abstract class BaseGridCoverage2DReader extends AbstractGridCoverage2DReader implements GridCoverage2DReader {

    /** Logger. */
    private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.coverageio.gdal");
   
    /** registering ImageReadMT JAI operation (for multithread ImageRead) */
    static {
        try {
                ImageReadDescriptorMT.register(JAI.getDefaultInstance());
        }
        catch (Exception e) {
                if(LOGGER.isLoggable(Level.FINE))
                        LOGGER.log(Level.FINE,e.getLocalizedMessage(),e);
                }
    }

    /**
     * The format specific world file extension.
     */
    private final String worldFileExt;
   
    /** Caches an {@code ImageReaderSpi}. */
    private final ImageReaderSpi readerSPI;

    /**
     * Implement this method to setup the coverage properties (Envelope, CRS,
     * GridRange) using the provided {@code ImageReader}
     */
    protected abstract void setCoverageProperties(ImageReader reader)
            throws IOException;

    // ////////////////////////////////////////////////////////////////////////
    // 
    // Referencing related fields (CRS and Envelope)
    // 
    // ////////////////////////////////////////////////////////////////////////

    /** Envelope read from file */
    private GeneralEnvelope nativeEnvelope = null;

    /** The CRS for the coverage */
    private CoordinateReferenceSystem nativeCRS = null;

    // ////////////////////////////////////////////////////////////////////////
    // 
    // Data source properties and field for management
    // 
    // ////////////////////////////////////////////////////////////////////////

    /** Source given as input to the reader */
    private File inputFile = null;

    /** Coverage name */
    private String localCoverageName = "geotools_coverage";

    /**
     * The base {@link GridRange} for the {@link GridCoverage2D} of this reader.
     */
    private GridEnvelope2D nativeGridRange = null;

    /** Absolute path to the parent dir for this coverage. */
    private String parentPath;

  private ServiceInfo serviceInfo;

  private ResourceInfo resourceInfo;

    /**
     * Creates a new instance of a {@link BaseGridCoverage2DReader}. I assume
     * nothing about file extension.
     *
     * @param input
     *                Source object for which we want to build a
     *                {@link BaseGridCoverage2DReader}.
     * @param hints
     *                Hints to be used by this reader throughout his life.
     * @param worldFileExtension
     *                the specific world file extension of the underlying format
     * @param formatSpecificSpi
     *                an instance of a proper {@code ImageReaderSpi}.
     * @throws DataSourceException
     */
    protected BaseGridCoverage2DReader(
        final Object input,
        final Hints hints,
        final String worldFileExtension,
            final ImageReaderSpi formatSpecificSpi) throws DataSourceException {
        super(input, hints);
       
      ImageReader reader=null;
      FileImageInputStreamExt fiis = null;
        try {
           

            readerSPI = formatSpecificSpi;
            worldFileExt = worldFileExtension;

            // //
            //
            // Source management
            //
            // //
            checkSource(input);
           
            // //
            //
            // Setting Envelope, GridRange and CRS
            //
            // //
            reader = readerSPI.createReaderInstance();
            fiis = new FileImageInputStreamExtImpl(inputFile);
            reader.setInput(fiis);
            setLayout(reader);
            setCoverageProperties(reader);

            // //
            //
            // Information about multiple levels and such
            //
            // //
            getResolutionInfo(reader);

        } catch (IOException e) {
            if (LOGGER.isLoggable(Level.SEVERE))
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);

            throw new DataSourceException(e);
        } catch (TransformException e) {
            if (LOGGER.isLoggable(Level.SEVERE))
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);

            throw new DataSourceException(e);
        }
        finally {

            // //
            //
            // Reset and dispose reader
            //
            // //
          if(reader!=null) {
            try {
              reader.reset();
            }catch (Exception e) {
                    if (LOGGER.isLoggable(Level.FINE))
                        LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
        }
           
            try {
              reader.dispose();
            }catch (Exception e) {
                    if (LOGGER.isLoggable(Level.FINE))
                        LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
        }           
               
          }
         
          if (fiis!=null){
              try {
                        fiis.close();
                    }catch (Exception e) {
                        if (LOGGER.isLoggable(Level.FINE))
                            LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
                    }
                   
          }
        }
    }

    /** Package scope highest resolution serviceInfo accessor */
    double[] getHighestRes() {
        return highestRes;
    }

    /** Package scope hints accessor */
    Hints getHints() {
        return hints;
    }

    /** Package scope grid to world transformation accessor */
    MathTransform getRaster2Model() {
        return raster2Model;
    }

    /**
     * Checks the input provided to this {@link BaseGridCoverage2DReader} and
     * sets all the other objects and flags accordingly.
     *
     * @param input
     *                provided to this {@link BaseGridCoverage2DReader}.
     *                Actually supported input types for the underlying
     *                ImageIO-Ext GDAL framework are: {@code File}, {@code URL}
     *                pointing to a file and {@link FileImageInputStreamExt}
     * @param hints
     *                Hints to be used by this reader throughout his life.
     *
     * @throws UnsupportedEncodingException
     * @throws DataSourceException
     * @throws IOException
     * @throws FileNotFoundException
     */
    private void checkSource(Object input) throws UnsupportedEncodingException,
            DataSourceException, IOException, FileNotFoundException {

        this.source = null;

        // //
        //
        // URL to FIle
        //
        // //
        // if it is an URL pointing to a File I convert it to a file.
        if (input instanceof URL) {
            // URL that point to a file
            final URL sourceURL = ((URL) input);
            this.source = sourceURL;

            if (sourceURL.getProtocol().compareToIgnoreCase("file") == 0) {
                this.inputFile = new File(URLDecoder.decode(
                        sourceURL.getFile(), "UTF-8"));
                input = this.inputFile;
            } else {
                throw new IllegalArgumentException("Unsupported input type");
            }
        }

        if (input instanceof FileImageInputStreamExt) {
            if (source == null) {
                source = input;
            }

            inputFile = ((FileImageInputStreamExt) input).getFile();
            input = inputFile;
        }

        // //
        //       
        // File
        //       
        // //
        if (input instanceof File) {
            final File sourceFile = (File) input;

            if (source == null) {
                source = sourceFile;
            }

            if (inputFile == null) {
                inputFile = sourceFile;
            }

            if (!sourceFile.exists() || sourceFile.isDirectory()
                    || !sourceFile.canRead()) {
                throw new DataSourceException(
                        "Provided file does not exist or is a directory or is not readable!");
            }

            this.parentPath = sourceFile.getParent();
            localCoverageName = sourceFile.getName();

            final int dotIndex = localCoverageName.lastIndexOf(".");
            localCoverageName = (dotIndex == -1) ? localCoverageName : localCoverageName
                    .substring(0, dotIndex);

        } else {
            throw new IllegalArgumentException("Unsupported input type");
        }
    }

    /**
     * Gets resolution information about the coverage itself.
     *
     * @param reader
     *                an {@link ImageReader} to use for getting the resolution
     *                information.
     * @throws IOException
     * @throws TransformException
     * @throws DataSourceException
     */
    private void getResolutionInfo(ImageReader reader) throws IOException,
            TransformException {
        // //
        //
        // get the dimension of the high resolution image and compute the
        // resolution
        //
        // //
        final Rectangle originalDim = new Rectangle(0, 0, reader.getWidth(0),
                reader.getHeight(0));
        if (getCoverageGridRange() == null) {
            setCoverageGridRange(new GridEnvelope2D(originalDim));
        }

        // ///
        //
        // setting the higher resolution available for this coverage
        //
        // ///
        highestRes = CoverageUtilities
                .getResolution((AffineTransform) raster2Model);

        if (LOGGER.isLoggable(Level.FINE))
            LOGGER
                    .fine(new StringBuffer("Highest Resolution = [").append(
                            highestRes[0]).append(",").append(highestRes[1])
                            .toString());
    }

    /**
     * Returns a {@link GridCoverage} from this reader in compliance with the
     * specified parameters.
     *
     * @param params
     *                a {@code GeneralParameterValue} array to customize the
     *                read operation.
     */
    public GridCoverage2D read(GeneralParameterValue[] params)
            throws IllegalArgumentException, IOException {

        // Setup a new coverage request
        final RasterLayerRequest request = new RasterLayerRequest(params,this);
       

        // compute the request.
        return (GridCoverage2D) requestCoverage(request).getGridCoverage();
    }
   
    /**
     * Gets the coordinate reference system that will be associated to the
     * {@link GridCoverage} by looking for a related PRJ.
     */
    protected void parsePRJFile() {
        String prjPath = null;

        setCoverageCRS(null);
        prjPath = new StringBuilder(this.parentPath).append(File.separatorChar)
                .append(localCoverageName).append(".prj").toString();

        // read the prj serviceInfo from the file
        PrjFileReader projReader = null;

        try {
            final File prj = new File(prjPath);

            if (prj.exists()) {
                projReader = new PrjFileReader(new FileInputStream(prj)
                        .getChannel());
                setCoverageCRS(projReader.getCoordinateReferenceSystem());
            }
            // If some exception occurs, warn about the error but proceed
            // using a default CRS
        } catch (FileNotFoundException e) {
            if (LOGGER.isLoggable(Level.WARNING)) {
                LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
            }
        } catch (IOException e) {
            if (LOGGER.isLoggable(Level.WARNING)) {
                LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
            }
        } catch (FactoryException e) {
            if (LOGGER.isLoggable(Level.WARNING)) {
                LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
            }
        } finally {
            if (projReader != null) {
                try {
                    projReader.close();
                } catch (IOException e) {
                    if (LOGGER.isLoggable(Level.WARNING)) {
                        LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
                    }
                }
            }
        }
    }

    /**
     * Checks whether a world file is associated with the data source. If found,
     * set a proper envelope.
     *
     * @throws IllegalStateException
     * @throws IOException
     */
    protected void parseWorldFile() throws IOException {
        final String worldFilePath = new StringBuffer(this.parentPath).append(
                GridCoverageUtilities.SEPARATOR).append(localCoverageName).toString();

        File file2Parse = null;
        boolean worldFileExists = false;
        // //
        //
        // Check for a world file with the format specific extension
        //
        // //
        if (worldFileExt != null && worldFileExt.length() > 0) {
            file2Parse = new File(worldFilePath + worldFileExt);
            worldFileExists = file2Parse.exists();
        }

        // //
        //
        // Check for a world file with the default extension
        //
        // //
        if (!worldFileExists) {
            file2Parse = new File(worldFilePath + GridCoverageUtilities.DEFAULT_WORLDFILE_EXT);
            worldFileExists = file2Parse.exists();
        }

        if (worldFileExists) {
            final WorldFileReader reader = new WorldFileReader(file2Parse);
            raster2Model = reader.getTransform();
           
            // //
            //
            // In case we read from a real world file we have together the
            // envelope. World file transformation assumes to work in the
            // CELL_CENTER condition
            //
            // //
            MathTransform tempTransform = PixelTranslation.translate(raster2Model, PixelInCell.CELL_CENTER, PixelInCell.CELL_CORNER);
            try {
                final Envelope gridRange = new GeneralEnvelope(getCoverageGridRange().getBounds2D());
                final GeneralEnvelope coverageEnvelope = CRS.transform(
                                tempTransform, gridRange);
                setCoverageEnvelope(coverageEnvelope);
            } catch (TransformException e) {
                if (LOGGER.isLoggable(Level.WARNING)) {
                    LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
                }
            } catch (IllegalStateException e) {
                if (LOGGER.isLoggable(Level.WARNING)) {
                    LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
                }
            }
        }
    }

    /**
     * Information about this source. Subclasses should provide additional
     * format specific information.
     *
     * @return ServiceInfo describing getSource().
     */
    @Override
    public synchronized ServiceInfo getInfo() {
      if (serviceInfo!=null)
        return new DefaultServiceInfo(this.serviceInfo);
     
        DefaultServiceInfo localInfo = new DefaultServiceInfo();
        serviceInfo=localInfo;
        localInfo.setDescription(source.toString());

        if (source instanceof URL) {
            URL url = (URL) source;
            localInfo.setTitle(url.getFile());

            try {
                localInfo.setSource(url.toURI());
            } catch (URISyntaxException e) {
            }
        } else if (source instanceof File) {
            File file = (File) source;
            String filename = file.getName();

            if ((filename == null) || (filename.length() == 0)) {
                localInfo.setTitle(file.getName());
            }

            localInfo.setSource(file.toURI());
        }

        return new DefaultServiceInfo(localInfo);
    }
   
    protected void writePrj(final File outLocation, final String wkt) throws IOException {
        writePrj(new BufferedWriter(new FileWriter(outLocation), 4096), wkt);
    }

    private void writePrj(BufferedWriter writer, String wkt) {
        try {
            writer.write(wkt);
            close(writer);
            return;

        } catch (IOException e) {
            if (LOGGER.isLoggable(Level.SEVERE))
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
        } finally {
            close(writer);
        }
    }

    private void close(BufferedWriter writer) {
        try {
            writer.close();
        } catch (Throwable t) {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.log(Level.FINE, t.getLocalizedMessage(), t);
        }
    }

    /**
     * Information about the named gridcoverage.
     *
     * @param subname
     *                Name indicing grid coverage to describe
     * @return ResourceInfo describing grid coverage indicated
     */
    public synchronized ResourceInfo getInfo(String subname) {

        if (this.resourceInfo!=null)
        return new DefaultResourceInfo(this.resourceInfo);
     
        DefaultResourceInfo localInfo = new DefaultResourceInfo();
  resourceInfo=localInfo;     
  localInfo.setName(subname);
        localInfo.setBounds(new ReferencedEnvelope(this.getOriginalEnvelope()));
        localInfo.setCRS(this.getCrs());
        localInfo.setTitle(subname);

        return new DefaultResourceInfo(this.resourceInfo);
    }

    /**
     * Returns a {@link RasterLayerResponse} from the specified
     * {@link RasterLayerRequest}.
     *
     * @param request
     *                a previously set {@link RasterLayerRequest} defining a set of
     *                parameters to get a specific coverage
     * @return the computed {@code RasterLayerResponse}
     * @todo Future versions may cache requestes<->responses using hashing
     */
    private RasterLayerResponse requestCoverage(RasterLayerRequest request) {
        final RasterLayerResponse response = new RasterLayerResponse(request,
                coverageFactory, readerSPI);
        try {
            response.compute();
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
            return null;
        }
        return response;
    }

    /**
     * @param nativeCRS
     *                the nativeCRS to set
     */
    protected void setCoverageCRS(CoordinateReferenceSystem coverageCRS) {
        this.nativeCRS = coverageCRS;
    }

    /**
     * @return the nativeCRS
     */
    protected CoordinateReferenceSystem getCoverageCRS() {
        return nativeCRS;
    }

    /**
     * @param nativeEnvelope
     *                the nativeEnvelope to set
     */
    protected void setCoverageEnvelope(GeneralEnvelope coverageEnvelope) {
        this.nativeEnvelope = coverageEnvelope;
    }

    /**
     * @return the nativeEnvelope
     */
    protected GeneralEnvelope getCoverageEnvelope() {
        return nativeEnvelope;
    }

    /**
     * @param nativeGridRange
     *                the nativeGridRange to set
     */
    protected void setCoverageGridRange(GridEnvelope2D coverageGridRange) {
        this.nativeGridRange = coverageGridRange;
    }

    /**
     * @return the nativeGridRange
     */
    protected GridEnvelope2D getCoverageGridRange() {
        return nativeGridRange;
    }

    /**
     * @return the input file
     */
    protected File getInputFile() {
        return inputFile;
    }

    /**
     * @return the coverage name
     */
    public String getCoverageName() {
        return localCoverageName;
    }

    /**
     * @return the gridCoverage count
     */
    @Override
    public int getGridCoverageCount() {
        return 1;
    }

    /**
     * @see org.opengis.coverage.grid.GridCoverageReader#hasMoreGridCoverages()
     */
    @Override
    public boolean hasMoreGridCoverages() {
        return false;
    }
   
}
TOP

Related Classes of org.geotools.coverageio.BaseGridCoverage2DReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.