org.geopublishing.atlasViewer.dp.layer.DpLayerRaster_Reader.java Source code

Java tutorial

Introduction

Here is the source code for org.geopublishing.atlasViewer.dp.layer.DpLayerRaster_Reader.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Stefan A. Tzeggai.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Stefan A. Tzeggai - initial API and implementation
 ******************************************************************************/
package org.geopublishing.atlasViewer.dp.layer;

import java.awt.Component;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.geopublishing.atlasViewer.AtlasConfig;
import org.geopublishing.atlasViewer.dp.DpEntryType;
import org.geopublishing.atlasViewer.swing.AVDialogManager;
import org.geopublishing.atlasViewer.swing.AVSwingUtil;
import org.geopublishing.atlasViewer.swing.internal.AtlasExportTask;
import org.geotools.coverage.grid.GeneralGridEnvelope;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.data.DataUtilities;
import org.geotools.gce.arcgrid.ArcGridReader;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.gce.image.WorldImageReader;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.parameter.Parameter;
import org.geotools.styling.Style;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Envelope;

import de.schmitzm.geotools.ZoomRestrictableGridInterface;
import de.schmitzm.geotools.data.rld.RasterLegendData;
import de.schmitzm.geotools.grid.GridUtil;
import de.schmitzm.geotools.io.GeoImportUtil;
import de.schmitzm.geotools.io.GeoImportUtil.ARCASCII_POSTFIXES;
import de.schmitzm.geotools.io.GeoImportUtil.GEOTIFF_POSTFIXES;
import de.schmitzm.geotools.io.GeoImportUtil.IMAGE_POSTFIXES;
import de.schmitzm.geotools.io.GeoImportUtil.WORLD_POSTFIXES;
import de.schmitzm.geotools.styling.StyledGridCoverageReaderInterface;
import de.schmitzm.geotools.styling.StyledLayerUtil;
import de.schmitzm.i18n.Translation;
import de.schmitzm.io.IOUtil;
import de.schmitzm.jfree.chart.style.ChartStyle;

/**
 * This class represents any {@link GridCoverage2D} that is read from one file.
 * 
 * @see DpLayerRasterPyramid
 * 
 * @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a>
 */
public class DpLayerRaster_Reader extends DpLayerRaster<AbstractGridCoverage2DReader, ChartStyle>
        implements StyledGridCoverageReaderInterface, ZoomRestrictableGridInterface {

    static final private Logger LOGGER = Logger.getLogger(DpLayerRaster_Reader.class);
    /**
     * 
     * caches the {@link GridCoverage2D} Can be un-cached by calling uncache()
     */
    protected AbstractGridCoverage2DReader gc;

    private RasterLegendData legendMetaData;

    /**
     * 0 wenn noch nicht bestimmt.
     */
    private int bandCount = 0;

    /**
     * Creates an empty {@link DpLayerRaster_Reader}.
     * 
     * @param ac
     *            {@link AtlasConfig}
     */
    public DpLayerRaster_Reader(AtlasConfig ac) {
        super(ac);
        setType(DpEntryType.RASTER);
    }

    /**
     * Exports the raster file and all related files. Only failure on the main
     * file produces an {@link IOException}
     */
    @Override
    public void exportWithGUI(Component owner) throws IOException {

        AtlasExportTask exportTask = new AtlasExportTask(owner, getTitle().toString()) {

            @Override
            protected Boolean doInBackground() throws Exception {

                setPrefix("Exporting ");

                try {
                    // waitDialog.setVisible(false);
                    exportDir = AVSwingUtil.selectExportDir(owner, getAtlasConfig());
                    // waitDialog.setVisible(true);

                    if (exportDir == null) {
                        // The fodler selection was cancelled.
                        return false;
                    }

                    URL url = AVSwingUtil.getUrl(DpLayerRaster_Reader.this, owner);
                    final File file = new File(exportDir, getFilename());

                    // ****************************************************************************
                    // Copy main file and possibly throw an Exception
                    // ****************************************************************************
                    publish(file.getAbsolutePath());
                    FileUtils.copyURLToFile(AVSwingUtil.getUrl(DpLayerRaster_Reader.this, owner), file);

                    // Try to copy pending world files...
                    for (WORLD_POSTFIXES pf : GeoImportUtil.WORLD_POSTFIXES.values()) {
                        final File changeFileExt = IOUtil.changeFileExt(file, pf.toString());
                        publish(changeFileExt.getAbsolutePath());
                        AtlasConfig.exportURLtoFileNoEx(IOUtil.changeUrlExt(url, pf.toString()), changeFileExt);
                    }

                    final File changeFileExt = IOUtil.changeFileExt(file, "prj");
                    publish(changeFileExt.getAbsolutePath());
                    AtlasConfig.exportURLtoFileNoEx(IOUtil.changeUrlExt(url, "prj"), changeFileExt);
                    AtlasConfig.exportURLtoFileNoEx(IOUtil.changeUrlExt(url, "sld"),
                            IOUtil.changeFileExt(file, "sld"));
                    // publish("done");
                    success = true;
                } catch (Exception e) {
                    done();
                }
                return success;
            }

        };
        exportTask.execute();
    }

    /**
     * This method is caching the geotools object, and can be uncached by
     * calling uncache()
     */
    @Override
    public AbstractGridCoverage2DReader getGeoObject() {

        try {

            if (gc == null) {

                /**
                 * Can we define transparent colors here?
                 */
                GeneralParameterValue[] readParams = null;

                URL url;
                url = getUrl();

                /**
                 * GEOTiffReader fails for jar:file:....jar!bla.tif URLs :-(
                 */
                if (url.getProtocol().startsWith("jar")
                // && url.getPath().startsWith("file")
                ) {
                    // We copy the Tiff to the local temp dir
                    File inTemp = new File(IOUtil.getTempDir(), getFilename());
                    LOGGER.debug("Workaround for the GeoTiffReader bug, new source = " + inTemp);
                    if (!inTemp.exists()) {
                        /**
                         * This is a work-around for GeoTiffReader problems for
                         * jar:// URLs We just all files to the local tempdir.
                         */
                        LOGGER.debug("Local copy does not exist, so we copy " + url + " to " + inTemp);
                        FileUtils.copyURLToFile(url, inTemp);

                        // Try to copy pending world files...
                        for (WORLD_POSTFIXES pf : GeoImportUtil.WORLD_POSTFIXES.values()) {
                            final URL src = IOUtil.changeUrlExt(url, pf.toString());

                            // clean = false, because we only clean
                            // filenames on import
                            IOUtil.copyURLNoException(src, IOUtil.getTempDir(), false);
                        }

                        // Copy optional .prj file to data directory
                        IOUtil.copyURLNoException(IOUtil.changeUrlExt(url, "prj"), IOUtil.getTempDir(), false);

                        // Copy optional .prj file to data directory
                        IOUtil.copyURLNoException(IOUtil.changeUrlExt(url, "tfw"), IOUtil.getTempDir(), false);

                        // Copy optional .sld file to data directory
                        IOUtil.copyURLNoException(IOUtil.changeUrlExt(url, "sld"), IOUtil.getTempDir(), false);

                    }

                    LOGGER.info("Changed the URL from " + url + " to " + inTemp);
                    url = DataUtilities.fileToURL(inTemp);
                }

                final String filename = getFilename().toLowerCase();

                // ****************************************************************************
                // Check if the ending suggests a GeoTIFF
                // ****************************************************************************
                for (GEOTIFF_POSTFIXES ending : GeoImportUtil.GEOTIFF_POSTFIXES.values()) {
                    if (filename.endsWith(ending.toString())) {

                        gc = new GeoTiffReader(url);
                        setType(DpEntryType.RASTER_GEOTIFF);
                    }
                }

                // ****************************************************************************
                // Check if the ending suggests a Arc/Info ASCII Grid
                // ****************************************************************************
                for (ARCASCII_POSTFIXES ending : GeoImportUtil.ARCASCII_POSTFIXES.values()) {
                    if (filename.endsWith(ending.toString())) {
                        gc = new ArcGridReader(url);
                        setType(DpEntryType.RASTER_ARCASCII);
                    }
                }
                // ****************************************************************************
                // Check if the ending suggests normal image file with worldfile
                // ****************************************************************************
                for (IMAGE_POSTFIXES ending : GeoImportUtil.IMAGE_POSTFIXES.values()) {
                    if (filename.endsWith(ending.toString())) {
                        gc = new WorldImageReader(url);
                        setType(DpEntryType.RASTER_IMAGEWORLD);
                    }
                }

                if (gc == null)
                    throw (new IllegalArgumentException("File doesn't seem to be a GeoTIFF nor a GIF"));

                // Create an Envelope that contains all information of the
                // raster
                // MS-01.sc
                // Envelope e = gc.getEnvelope();
                // envelope = new com.vividsolutions.jts.geom.Envelope(e
                // .getUpperCorner().getOrdinate(0), // X1
                // e.getLowerCorner().getOrdinate(0), // X2
                // e.getUpperCorner().getOrdinate(1), // Y1dddd
                // e.getLowerCorner().getOrdinate(1) // Y2
                // );

                // GridEnvelope e = gc.getOriginalGridRange();
                // envelope = new com.vividsolutions.jts.geom.Envelope(
                // e.getHigh(0), // X1
                // e.getLow(0), // X2
                // e.getHigh(1), // Y1
                // e.getLow(1) // Y2
                //
                // ServiceInfo info = gc.getInfo();
                //
                // Object source = gc.getSource();
                //
                // LOGGER.debug(info);
                // LOGGER.debug(source);
                // envelope = new com.vividsolutions.jts.geom.Envelope(
                // e.getHigh(0), // X1
                // e.getLow(0), // X2
                // e.getHigh(1), // Y1
                // e.getLow(1) // Y2
                // );

                double[] lower = gc.getOriginalEnvelope().getLowerCorner().getCoordinate();
                double[] upper = gc.getOriginalEnvelope().getUpperCorner().getCoordinate();
                envelope = new Envelope(lower[0], lower[1], upper[0], upper[1]);

                // LOGGER.info("Evaluated the following Enveloper for GeoTiffReader "
                // + envelope);

                crs = gc.getCrs();

                // Object object = gc.getProperties().get("GC_NODATA");
                // gc.getSampleDimension(0).getNoDataValues();
                // log.debug(object);
            }

            return gc;

        } catch (Exception e) {
            throw new RuntimeException("Exception while accessing the GeoObject for " + getId() + " " + this, e);
        }
    }

    /**
     * Returns the cached {@link Style} for this Layer. Tries to load the
     * {@link Style} from a file with the same URL but the ending
     * <code>.sld</code>. If it doesn't exist, returns a default RasterStyle.
     * 
     * @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a>
     */
    @Override
    public Style getStyle() {
        if (StyledLayerUtil.isStyleable(this) && super.getStyle() == null) {
            setStyle(GridUtil.createDefaultStyle());
        }
        return super.getStyle();
    }

    /**
     * Clears all memory-intensive cache objects
     */
    @Override
    public void uncache() {
        // LOGGER.debug("unchaching " + getId() + " aka " + getTitle());
        super.uncache();

        /** Close any open attribute table for this layer */
        AVDialogManager.dm_AtlasStyler.disposeInstanceFor(this);

        if (gc != null) {
            gc.dispose();
            gc = null;
        }

        envelope = null;
    }

    /**
     * This method returns the value/{@link Translation} pairs that will be
     * shown in the Legend
     */
    @Override
    public RasterLegendData getLegendMetaData() {
        if (legendMetaData == null) {
            legendMetaData = new RasterLegendData(false);
        }
        return legendMetaData;
    }

    @Override
    public void dispose() {
        if (isDisposed())
            return;
        disposed = true;
        uncache();
    }

    /**
     * Calculates the width's resolution in it's
     * {@link CoordinateReferenceSystem}:
     * 
     * @return width in CRS units divided by pixel width
     */
    @Override
    public Double getMaxResolution() {
        // MS-01.sc
        // try {
        // double pixelwidth = getGeoObject().getGridGeometry().getGridRange()
        // .getHigh().getCoordinateValues()[0];
        // double crswidth = getGeoObject().getEnvelope().getUpperCorner()
        // .getDirectPosition().getCoordinate()[0]
        // - getGeoObject().getEnvelope().getLowerCorner()
        // .getDirectPosition().getCoordinate()[0];
        // // LOGGER.debug("resolution of " + getTitle().toString() + " = "
        // // + crswidth / pixelwidth);
        // return crswidth / pixelwidth;
        // } catch (Exception e) {
        // LOGGER.error(e);
        //
        // return 0.;
        // }
        //   LOGGER.warn("DpLayerRaster.getMaxResolution() not yet implemented for AbstractGridCoverage2DReader!");
        return null;
        // MS-01.ec
    }

    @Override
    public Double getMinResolution() {
        // docme Auto-generated method stub
        return null;
    }

    @Override
    public void setLegendMetaData(RasterLegendData legendMetaData) {
        this.legendMetaData = legendMetaData;
    }

    // /**
    // * Returns the number of bands contained in this {@link Coverage}
    // */
    // public int getNumSampleDimensions() {
    // // TODO: Determine the sample dimensions from
    // AbstractGridCoverage2DReader
    // LOGGER.error("DpLayerRaster.getNumSampleDimensions() not yet implemented correctly for AbstractGridCoverage2DReader!");
    // // return getGeoObject().getNumSampleDimensions();
    // return 1;
    // }

    @Override
    public DpLayerRaster_Reader copy() {
        DpLayerRaster_Reader copy = new DpLayerRaster_Reader(ac);
        return (DpLayerRaster_Reader) copyTo(copy);
    }

    @Override
    public DpLayer<AbstractGridCoverage2DReader, ChartStyle> copyTo(
            DpLayer<AbstractGridCoverage2DReader, ChartStyle> target) {

        DpLayerRaster_Reader copy = (DpLayerRaster_Reader) super.copyTo(target);

        copy.setLegendMetaData(getLegendMetaData()); // TODO should be copied!

        return copy;
    }

    @Override
    public ReferencedEnvelope getReferencedEnvelope() {
        if (getEnvelope() == null)
            return null;
        return new ReferencedEnvelope(getEnvelope(), getCrs());
    }

    @Override
    public int getBandCount() {
        if (bandCount == 0) {
            Parameter readGG = new Parameter(AbstractGridFormat.READ_GRIDGEOMETRY2D);

            ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(getEnvelope(),
                    getCrs());
            //
            // readGG.setValue(new GridGeometry2D(new GeneralGridEnvelope(
            // getBounds()), mapExtend));
            readGG.setValue(new GridGeometry2D(new GeneralGridEnvelope(new Rectangle(1, 1)), mapExtend));

            try {
                GridCoverage2D sourceGrid = getGeoObject().read(new GeneralParameterValue[] { readGG });
                bandCount = sourceGrid.getNumSampleDimensions();
            } catch (Exception e) {
                LOGGER.error("read(new GeneralParameterValue[] { readGG })", e);
            }
        }
        return bandCount;
    }

    @Override
    public Translation[] getBandNames() {
        if (bandNames.length == 0) {
            for (int i = 0; i < getBandCount(); i++) {
                setBandNames(new Translation(""));
            }
        }
        return bandNames;
    }

}