Package org.vfny.geoserver.wcs.responses

Source Code of org.vfny.geoserver.wcs.responses.CoverageResponse

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wcs.responses;

import java.awt.Rectangle;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.media.jai.Interpolation;

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.ServiceInfo;
import org.geoserver.data.util.CoverageUtils;
import org.geoserver.platform.ServiceException;
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.factory.Hints;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.coverage.Coverage;
import org.opengis.coverage.grid.Format;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.vfny.geoserver.Request;
import org.vfny.geoserver.Response;
import org.vfny.geoserver.util.WCSUtils;
import org.vfny.geoserver.wcs.WcsException;
import org.vfny.geoserver.wcs.WcsException.WcsExceptionCode;
import org.vfny.geoserver.wcs.requests.CoverageRequest;


/**
* DOCUMENT ME!
*
* @author $Author: Alessio Fabiani (alessio.fabiani@gmail.com) $ (last
*         modification)
* @author $Author: Simone Giannecchini (simboss1@gmail.com) $ (last
*         modification)
*/
public class CoverageResponse implements Response {
    /** Standard logging instance for class */
    private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.vfny.geoserver.responses");
    private final static Hints LENIENT_HINT = new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE);
    private final static Hints hints = new Hints();

    static {
        // ///////////////////////////////////////////////////////////////////
        //
        // HINTS
        //
        // ///////////////////////////////////////////////////////////////////
        hints.add(LENIENT_HINT);
    }

    /**
     *
     */
    CoverageResponseDelegate delegate;

    /**
     * This is the request provided to the execute( Request ) method.
     *
     * <p>
     * We save it so we can access the handle provided by the user for error
     * reporting during the writeTo( OutputStream ) opperation.
     * </p>
     *
     * <p>
     * This value will be <code>null</code> until execute is called.
     * </p>
     *
     * @uml.property name="request"
     * @uml.associationEnd multiplicity="(0 1)"
     */
    private CoverageRequest request;

    /**
     * Empty constructor
     */
    public CoverageResponse() {
        request = null;
    }

    /**
     * Returns any extra headers that this service might want to set in the HTTP response object.
     * @see org.vfny.geoserver.Response#getResponseHeaders()
     */
    public HashMap getResponseHeaders() {
        return null;
    }

    /**
     * DOCUMENT ME!
     *
     * @param gs
     *            DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getContentType(GeoServer geoServer) {
        return delegate.getContentType();
    }

    public String getContentEncoding() {
        return delegate.getContentEncoding();
    }

    public String getContentDisposition() {
        return delegate.getContentDisposition();
    }

    /**
     * Jody here with one pass replacement for writeTo.
     *
     * <p>
     * This code is a discussion point, when everyone has had there input we
     * will try and set things up properly.
     * </p>
     *
     * <p>
     * I am providing a mirror of the existing desing: - execute gathers the
     * resultList - sets up the header
     * </p>
     *
     * @param out
     *            DOCUMENT ME!
     *
     * @throws WcsException
     *             DOCUMENT ME!
     * @throws IOException
     *             DOCUMENT ME!
     * @throws IllegalStateException
     *             DOCUMENT ME!
     */
    public void writeTo(OutputStream out) throws ServiceException, IOException {
        if ((request == null) || (delegate == null)) {
            throw new IllegalStateException("execute has not been called prior to writeTo");
        }

        delegate.encode(out);
    }

    /**
     * Executes CoverageRequest.
     *
     * <p>
     * Willing to execute a CoverageRequest.
     * </p>
     *
     * @param req
     *            DOCUMENT ME!
     *
     * @throws WcsException
     *             DOCUMENT ME!
     */
    public void execute(Request req) throws WcsException {
        execute((CoverageRequest) req);
    }

    public void execute(CoverageRequest request) throws WcsException {
        if (LOGGER.isLoggable(Level.FINEST)) {
            LOGGER.finest(new StringBuffer("execute CoverageRequest response. Called request is: ").append(
                    request).toString());
        }

        this.request = request;

        final String outputFormat = request.getOutputFormat();

        delegate = CoverageResponseDelegateFactory.encoderFor(outputFormat);
        if(delegate == null)
            throw new WcsException("Output format: " + outputFormat + " not supported by geoserver " +
                "for this Coverage", WcsExceptionCode.InvalidParameterValue, "format");

        final Catalog catalog = request.getWCS().getGeoServer().getCatalog();
        CoverageInfo meta = null;
        GridCoverage coverage = null;

        try {
            meta = catalog.getCoverageByName(request.getCoverage());

            if (!meta.getSupportedFormats().contains(outputFormat.toUpperCase())) {
                WcsException newEx = new WcsException(new StringBuffer("output format: ").append(
                            outputFormat).append(" not ")
                                                                                         .append("supported by geoserver for this Coverage")
                                                                                         .toString());
                throw newEx;
            }

            final Format format = meta.getStore().getFormat();
            final AbstractGridCoverage2DReader reader =
              (AbstractGridCoverage2DReader) catalog.getResourcePool().getGridCoverageReader(meta.getStore(),hints);

            // /////////////////////////////////////////////////////////
            //
            // Setting coverage reading params.
            //
            // /////////////////////////////////////////////////////////
            final ParameterValueGroup params = reader.getFormat().getReadParameters();

            final GridCoverage2D finalCoverage = getFinalCoverage(request, meta, reader,
                    CoverageUtils.getParametersKVP(params));
            delegate.prepare(outputFormat, finalCoverage);
        } catch (IOException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());

            throw newEx;
        } catch (NoSuchElementException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (IllegalArgumentException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (SecurityException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (WcsException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (FactoryException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (IndexOutOfBoundsException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        } catch (TransformException e) {
            final WcsException newEx = new WcsException(e, "problem with CoverageResults",
                    request.getHandle());
            throw newEx;
        }
    }

    /**
     * Release locks if we are into that sort of thing.
     *
     * @see org.vfny.geoserver.responses.Response#abort()
     */
    public void abort(ServiceInfo gs) {
        if (request == null) {
            return; // request was not attempted
        }
    }

    /**
     * GetCroppedCoverage
     *
     * @param request CoverageRequest
     * @param meta CoverageInfo
     * @param parameters
     * @param coverage GridCoverage
     * @return GridCoverage2D
     * @throws WcsException
     * @throws IOException
     * @throws IndexOutOfBoundsException
     * @throws FactoryException
     * @throws TransformException
     */
    private static GridCoverage2D getFinalCoverage(CoverageRequest request, CoverageInfo meta,
        AbstractGridCoverage2DReader coverageReader /*GridCoverage coverage*/, Map parameters)
        throws WcsException, IOException, IndexOutOfBoundsException, FactoryException,
            TransformException {
        // This is the final Response CRS
        final String responseCRS = request.getResponseCRS();

        // - first check if the responseCRS is present on the Coverage
        // ResponseCRSs list
        if (!meta.getResponseSRS().contains(responseCRS)) {
            throw new WcsException("This Coverage does not support the requested Response-CRS.");
        }

        // - then create the Coordinate Reference System
        final CoordinateReferenceSystem targetCRS = CRS.decode(responseCRS);

        // This is the CRS of the requested Envelope
        final String requestCRS = request.getCRS();

        // - first check if the requestCRS is present on the Coverage
        // RequestCRSs list
        if (!meta.getResponseSRS().contains(requestCRS)) {
            throw new WcsException("This Coverage does not support the requested CRS.");
        }

        // - then create the Coordinate Reference System
        final CoordinateReferenceSystem sourceCRS = CRS.decode(requestCRS);

        // This is the CRS of the Coverage Envelope
        final CoordinateReferenceSystem cvCRS = ((GeneralEnvelope) coverageReader
            .getOriginalEnvelope()).getCoordinateReferenceSystem();
        final MathTransform GCCRSTodeviceCRSTransformdeviceCRSToGCCRSTransform = CRS
            .findMathTransform(cvCRS, sourceCRS, true);
        final MathTransform GCCRSTodeviceCRSTransform = CRS.findMathTransform(cvCRS, targetCRS, true);
        final MathTransform deviceCRSToGCCRSTransform = GCCRSTodeviceCRSTransformdeviceCRSToGCCRSTransform
            .inverse();

        com.vividsolutions.jts.geom.Envelope envelope = request.getEnvelope();
        GeneralEnvelope destinationEnvelope;
        final boolean lonFirst = sourceCRS.getCoordinateSystem().getAxis(0).getDirection().absolute()
                                          .equals(AxisDirection.EAST);

        // the envelope we are provided with is lon,lat always
        if (!lonFirst) {
            destinationEnvelope = new GeneralEnvelope(new double[] {
                        envelope.getMinY(), envelope.getMinX()
                    }, new double[] { envelope.getMaxY(), envelope.getMaxX() });
        } else {
            destinationEnvelope = new GeneralEnvelope(new double[] {
                        envelope.getMinX(), envelope.getMinY()
                    }, new double[] { envelope.getMaxX(), envelope.getMaxY() });
        }

        destinationEnvelope.setCoordinateReferenceSystem(sourceCRS);

        // this is the destination envelope in the coverage crs
        final GeneralEnvelope destinationEnvelopeInSourceCRS = (!deviceCRSToGCCRSTransform
            .isIdentity()) ? CRS.transform(deviceCRSToGCCRSTransform, destinationEnvelope)
                           : new GeneralEnvelope(destinationEnvelope);
        destinationEnvelopeInSourceCRS.setCoordinateReferenceSystem(cvCRS);

        /**
         * Reading Coverage on Requested Envelope
         */
        Rectangle destinationSize = null;

        if ((request.getGridLow() != null) && (request.getGridHigh() != null)) {
            final int[] lowers = new int[] {
                    request.getGridLow()[0].intValue(), request.getGridLow()[1].intValue()
                };
            final int[] highers = new int[] {
                    request.getGridHigh()[0].intValue(), request.getGridHigh()[1].intValue()
                };

            destinationSize = new Rectangle(lowers[0], lowers[1], highers[0], highers[1]);
        } else {
            /*destinationSize = coverageReader.getOriginalGridRange().toRectangle();*/
            throw new WcsException("Neither Grid Size nor Grid Resolution have been specified.");
        }

        /**
         * Checking for supported Interpolation Methods
         */
        Interpolation interpolation = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
        final String interpolationType = request.getInterpolation();

        if (interpolationType != null) {
            boolean interpolationSupported = false;
            Iterator internal = meta.getInterpolationMethods().iterator();

            while (internal.hasNext()) {
                if (interpolationType.equalsIgnoreCase((String) internal.next())) {
                    interpolationSupported = true;
                }
            }

            if (!interpolationSupported) {
                throw new WcsException(
                    "The requested Interpolation method is not supported by this Coverage.");
            } else {
                if (interpolationType.equalsIgnoreCase("bilinear")) {
                    interpolation = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
                } else if (interpolationType.equalsIgnoreCase("bicubic")) {
                    interpolation = Interpolation.getInstance(Interpolation.INTERP_BICUBIC);
                }
            }
        }

        // /////////////////////////////////////////////////////////
        //
        // Reading the coverage
        //
        // /////////////////////////////////////////////////////////
        parameters.put(AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString(),
            new GridGeometry2D(new GeneralGridEnvelope(destinationSize), destinationEnvelopeInSourceCRS));

        final GridCoverage coverage = coverageReader.read(CoverageUtils.getParameters(
                    coverageReader.getFormat().getReadParameters(), parameters, true));

        if ((coverage == null) || !(coverage instanceof GridCoverage2D)) {
            throw new IOException("The requested coverage could not be found.");
        }

        /**
         * Band Select
         */
        Coverage bandSelectedCoverage = null;

        bandSelectedCoverage = WCSUtils.bandSelect(request.getParameters(), coverage);

        /**
         * Crop
         */
        final GridCoverage2D croppedGridCoverage = WCSUtils.crop(bandSelectedCoverage,
                (GeneralEnvelope) coverage.getEnvelope(), cvCRS, destinationEnvelopeInSourceCRS,
                Boolean.TRUE);

        /**
         * Scale/Resampling (if necessary)
         */
        GridCoverage2D subCoverage = croppedGridCoverage;
        final GeneralGridEnvelope newGridrange = new GeneralGridEnvelope(destinationSize);

        /*if (!newGridrange.equals(croppedGridCoverage.getGridGeometry()
                        .getGridRange())) {*/
        subCoverage = WCSUtils.scale(croppedGridCoverage, newGridrange, croppedGridCoverage, cvCRS,
                destinationEnvelopeInSourceCRS);
        //}

        /**
         * Reproject
         */
        subCoverage = WCSUtils.reproject(subCoverage, sourceCRS, targetCRS, interpolation);

        return subCoverage;
    }
}
TOP

Related Classes of org.vfny.geoserver.wcs.responses.CoverageResponse

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.