Package org.geoserver.wcs2_0

Source Code of org.geoserver.wcs2_0.WCSTestSupport

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wcs2_0;

import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;

import java.awt.geom.AffineTransform;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.imageio.metadata.IIOMetadataNode;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.custommonkey.xmlunit.SimpleNamespaceContext;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.DimensionInfo;
import org.geoserver.catalog.DimensionPresentation;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.impl.DimensionInfoImpl;
import org.geoserver.config.GeoServer;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.test.GeoServerSystemTestSupport;
import org.geoserver.wcs.CoverageCleanerCallback;
import org.geoserver.wcs.WCSInfo;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.imageio.geotiff.GeoTiffConstants;
import org.geotools.data.DataUtilities;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.operation.matrix.XAffineTransform;
import org.geotools.wcs.v2_0.WCSConfiguration;
import org.geotools.xml.Parser;
import org.junit.After;
import org.opengis.coverage.Coverage;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridGeometry;
import org.opengis.referencing.operation.MathTransform;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.SAXParseException;

import com.mockrunner.mock.web.MockHttpServletResponse;

/**
* Base support class for wcs tests.
*
* @author Andrea Aime, GeoSolutions
*
*/
@SuppressWarnings("serial")
public abstract class WCSTestSupport extends GeoServerSystemTestSupport {
    protected static XpathEngine xpath;

    protected static final boolean IS_WINDOWS;

    protected static final Schema WCS20_SCHEMA;
   
    List<GridCoverage> coverages = new ArrayList<GridCoverage>();
   
    protected final static String VERSION=WCS20Const.CUR_VERSION;


    /**
     * Small value for comparaison of sample values. Since most grid coverage implementations in
     * Geotools 2 store geophysics values as {@code float} numbers, this {@code EPS} value must
     * be of the order of {@code float} relative precision, not {@code double}.
     */
    static final float EPS = 1E-5f;

    static {
        final Map<String, String> namespaceMap = new HashMap<String, String>() {
            {
                put("http://www.opengis.net/wcs/2.0", "./src/main/resources/schemas/wcs/2.0/");
                put("http://www.opengis.net/gmlcov/1.0", "./src/main/resources/schemas/gmlcov/1.0/");
                put("http://www.opengis.net/gml/3.2", "./src/main/resources/schemas/gml/3.2.1/");
                put("http://www.w3.org/1999/xlink", "./src/test/resources/schemas/xlink/");
                put("http://www.w3.org/XML/1998/namespace", "./src/test/resources/schemas/xml/");
                put("http://www.isotc211.org/2005/gmd", "./src/main/resources/schemas/iso/19139/20070417/gmd/");
                put("http://www.isotc211.org/2005/gco", "./src/main/resources/schemas/iso/19139/20070417/gco/");
                put("http://www.isotc211.org/2005/gss", "./src/main/resources/schemas/iso/19139/20070417/gss/");
                put("http://www.isotc211.org/2005/gts", "./src/main/resources/schemas/iso/19139/20070417/gts/");
                put("http://www.isotc211.org/2005/gsr", "./src/main/resources/schemas/iso/19139/20070417/gsr/");
                put("http://www.opengis.net/swe/2.0", "./src/main/resources/schemas/sweCommon/2.0/");
                put("http://www.opengis.net/ows/2.0", "./src/main/resources/schemas/ows/2.0/");
            }
        };

        try {
            final SchemaFactory factory = SchemaFactory
                    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
           
            factory.setResourceResolver(new LSResourceResolver() {
               
                DOMImplementationLS dom;
               
                {
                    try {
                        // ok, this is ugly.. the only way I've found to create an InputLS without
                        // having to really implement every bit of it is to create a DOMImplementationLS
                        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
                        builderFactory.setNamespaceAware( true );
                      
                        DocumentBuilder builder = builderFactory.newDocumentBuilder();
                        // fake xml to parse
                        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><empty></empty>";
                        dom = (DOMImplementationLS) builder.parse(new ByteArrayInputStream(xml.getBytes())).getImplementation();
                    } catch(Exception e) {
                        throw new RuntimeException(e);
                    }
                }
               
                @Override
                public LSInput resolveResource(String type, String namespaceURI, String publicId,
                        String systemId, String baseURI) {
                   
                    String localPosition = namespaceMap.get(namespaceURI);
                    if (localPosition != null) {
                        try {
                            if (systemId.contains("/")) {
                                systemId = systemId.substring(systemId.lastIndexOf("/") + 1);
                            }
                            File file = new File(localPosition + systemId);
                            if (file.exists()) {
                                URL url = DataUtilities.fileToURL(file);
                                systemId = url.toURI().toASCIIString();
                                LSInput input = dom.createLSInput();
                                input.setPublicId(publicId);
                                input.setSystemId(systemId);
                                return input;
                            }
                        } catch (Exception e) {
                            return null;
                        }
                    }
                    return null;
                }
            });
            WCS20_SCHEMA = factory.newSchema(WCSTestSupport.class.getResource("/schemas/wcs/2.0/wcsAll.xsd"));
        } catch (Exception e) {
            throw new RuntimeException("Could not parse the WCS 2.0 schemas", e);
        }
        boolean windows = false;
        try {
            windows = System.getProperty("os.name").matches(".*Windows.*");
        } catch (Exception e) {
            // no os.name? oh well, never mind
        }
        IS_WINDOWS = windows;
    }

    /**
     * @return The global wcs instance from the application context.
     */
    protected WCSInfo getWCS() {
        return getGeoServer().getService(WCSInfo.class);
    }

    /**
     * Only setup coverages
     */
    protected void setUpTestData(SystemTestData testData) throws Exception {
        super.setUpTestData(testData);
        testData.setUpDefaultRasterLayers();
        testData.setUpWcs10RasterLayers();
        testData.setUpWcs11RasterLayers();
       
       
    }

    @Override
    protected void onSetUp(SystemTestData testData) throws Exception {

        super.onSetUp(testData);

        // init xmlunit
        Map<String, String> namespaces = new HashMap<String, String>();
        namespaces.put("wcs", "http://www.opengis.net/wcs/2.0");
        namespaces.put("wcscrs", "http://www.opengis.net/wcs/service-extension/crs/1.0");
        namespaces.put("ows", "http://www.opengis.net/ows/2.0");
        namespaces.put("xlink", "http://www.w3.org/1999/xlink");
        namespaces.put("int", "http://www.opengis.net/WCS_service-extension_interpolation/1.0");
        namespaces.put("gmlcov", "http://www.opengis.net/gmlcov/1.0");
        namespaces.put("swe", "http://www.opengis.net/swe/2.0");
        namespaces.put("gml", "http://www.opengis.net/gml/3.2");
        namespaces.put("wcsgs", "http://www.geoserver.org/wcsgs/2.0");
        XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(namespaces));
        xpath = XMLUnit.newXpathEngine();

    }

    @Override
    protected boolean isMemoryCleanRequired() {
        return IS_WINDOWS;
    }

    /**
     * Validates a document against the
     *
     * @param dom
     * @param configuration
     */
    @SuppressWarnings("rawtypes")
    protected void checkValidationErrors(Document dom) throws Exception {
        Parser p = new Parser(new WCSConfiguration());
        p.setValidating(true);
        p.parse(new DOMSource(dom));

        if (!p.getValidationErrors().isEmpty()) {
            for (Iterator e = p.getValidationErrors().iterator(); e.hasNext();) {
                SAXParseException ex = (SAXParseException) e.next();
                System.out.println(ex.getLineNumber() + "," + ex.getColumnNumber() + " -"
                        + ex.toString());
            }
            fail("Document did not validate.");
        }
    }
   
    /**
     * Marks the coverage to be cleaned when the test ends
     * @param coverage
     */
    protected void scheduleForCleaning(GridCoverage coverage) {
        if(coverage != null) {
            coverages.add(coverage);
        }
    }

    @After
    public void cleanCoverages() {
        for (GridCoverage coverage : coverages) {
            CoverageCleanerCallback.disposeCoverage(coverage);
        }
    }

    protected void checkFullCapabilitiesDocument(Document dom) throws Exception {
        checkValidationErrors(dom, WCS20_SCHEMA);
       
        // TODO: check all the layers are here, the profiles, and so on
       
        // check that we have the crs extension
        assertXpathEvaluatesTo("1", "count(//ows:ServiceIdentification[ows:Profile='http://www.opengis.net/spec/WCS_service-extension_crs/1.0/conf/crs'])", dom);
        assertXpathEvaluatesTo("1", "count(//wcs:ServiceMetadata/wcs:Extension[wcscrs:crsSupported = 'http://www.opengis.net/def/crs/EPSG/0/4326'])", dom);
       
        // check the interpolation extension
        assertXpathEvaluatesTo("1", "count(//ows:ServiceIdentification[ows:Profile='http://www.opengis.net/spec/WCS_service-extension_interpolation/1.0/conf/interpolation'])", dom);
        assertXpathEvaluatesTo("1", "count(//wcs:ServiceMetadata/wcs:Extension[int:interpolationSupported='http://www.opengis.net/def/interpolation/OGC/1/nearest-neighbor'])", dom);
        assertXpathEvaluatesTo("1", "count(//wcs:ServiceMetadata/wcs:Extension[int:interpolationSupported='http://www.opengis.net/def/interpolation/OGC/1/linear'])", dom);
        assertXpathEvaluatesTo("1", "count(//wcs:ServiceMetadata/wcs:Extension[int:interpolationSupported='http://www.opengis.net/def/interpolation/OGC/1/cubic'])", dom);
    }

    /**
     * Gets a TIFFField node with the given tag number. This is done by searching for a TIFFField
     * with attribute number whose value is the specified tag value.
     *
     * @param tag DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    protected IIOMetadataNode getTiffField(Node rootNode, final int tag) {
        Node node = rootNode.getFirstChild();
        if (node != null){
            node = node.getFirstChild();
            for (; node != null; node = node.getNextSibling()) {
                Node number = node.getAttributes().getNamedItem(GeoTiffConstants.NUMBER_ATTRIBUTE);
                if (number != null && tag == Integer.parseInt(number.getNodeValue())) {
                    return (IIOMetadataNode) node;
                }
            }
        }
        return null;
    }

    @Override
    protected String getLogConfiguration() {
        return "/DEFAULT_LOGGING.properties";
    }

    protected void setInputLimit(int kbytes) {
        GeoServer gs = getGeoServer();
        WCSInfo info = gs.getService(WCSInfo.class);
        info.setMaxInputMemory(kbytes);
        gs.save(info);
    }

    protected void setOutputLimit(int kbytes) {
        GeoServer gs = getGeoServer();
        WCSInfo info = gs.getService(WCSInfo.class);
        info.setMaxOutputMemory(kbytes);
        gs.save(info);
    }

    /**
     * Compares the envelopes of two coverages for equality using the smallest
     * scale factor of their "grid to world" transform as the tolerance.
     *
     * @param expected The coverage having the expected envelope.
     * @param actual   The coverage having the actual envelope.
     */
    protected static void assertEnvelopeEquals(Coverage expected, Coverage actual) {
        final double scaleA = getScale(expected);
        final double scaleB = getScale(actual);
   
        assertEnvelopeEquals((GeneralEnvelope)expected.getEnvelope(),scaleA,(GeneralEnvelope)actual.getEnvelope(),scaleB);
    }

    protected static void assertEnvelopeEquals(GeneralEnvelope expected,double scaleExpected, GeneralEnvelope actual,double scaleActual) {
        final double tolerance;
        if (scaleExpected <= scaleActual) {
            tolerance = scaleExpected*1E-1;
        } else if (!Double.isNaN(scaleActual)) {
            tolerance = scaleActual*1E-1;
        } else {
            tolerance = EPS;
        }
        assertTrue(expected.equals(actual, tolerance, false));
    }

    /**
     * Returns the "Sample to geophysics" transform as an affine transform, or {@code null}
     * if none. Note that the returned instance may be an immutable one, not necessarly the
     * default Java2D implementation.
     *
     * @param  coverage The coverage for which to get the "grid to CRS" affine transform.
     * @return The "grid to CRS" affine transform of the given coverage, or {@code null}
     *         if none or if the transform is not affine.
     */
    protected static AffineTransform getAffineTransform(final Coverage coverage) {
        if (coverage instanceof GridCoverage) {
            final GridGeometry geometry = ((GridCoverage) coverage).getGridGeometry();
            if (geometry != null) {
                final MathTransform gridToCRS;
                if (geometry instanceof GridGeometry2D) {
                    gridToCRS = ((GridGeometry2D) geometry).getGridToCRS();
                } else {
                    gridToCRS = geometry.getGridToCRS();
                }
                if (gridToCRS instanceof AffineTransform) {
                    return (AffineTransform) gridToCRS;
                }
            }
        }
        return null;
    }

    /**
     * Returns the scale of the "grid to CRS" transform, or {@link Double#NaN} if unknown.
     *
     * @param  coverage The coverage for which to get the "grid to CRS" scale, or {@code null}.
     * @return The "grid to CRS" scale, or {@code NaN} if none or if the transform is not affine.
     */
    protected static double getScale(final Coverage coverage) {
        final AffineTransform gridToCRS = getAffineTransform(coverage);
        return (gridToCRS != null) ? XAffineTransform.getScale(gridToCRS) : Double.NaN;
    }
   
    /**
     * Parses a multipart message from the response
     * @param response
     * @return
     * @throws MessagingException
     * @throws IOException
     */
    protected Multipart getMultipart(MockHttpServletResponse response) throws MessagingException,
            IOException {
        MimeMessage body = new MimeMessage((Session) null, getBinaryInputStream(response));
        Multipart multipart = (Multipart) body.getContent();
        return multipart;
    }

    /**
     * Configures the specified dimension for a coverage
     *
     * @param coverageName
     * @param metadataKey
     * @param presentation
     * @param resolution
     */
    protected void setupRasterDimension(String coverageName, String metadataKey, DimensionPresentation presentation, Double resolution) {
        CoverageInfo info = getCatalog().getCoverageByName(coverageName);
        DimensionInfo di = new DimensionInfoImpl();
        di.setEnabled(true);
        di.setPresentation(presentation);
        if(resolution != null) {
            di.setResolution(new BigDecimal(resolution));
        }
        info.getMetadata().put(metadataKey, di);
        getCatalog().save(info);
    }
   
    /**
     * Configures the specified dimension for a coverage
     *
     * @param coverageName
     * @param metadataKey
     * @param presentation
     * @param resolution
     * @param unitSymbol
     */
    protected void setupRasterDimension(String coverageName, String metadataKey, DimensionPresentation presentation, Double resolution, String unitSymbol) {
        CoverageInfo info = getCatalog().getCoverageByName(coverageName);
        DimensionInfo di = new DimensionInfoImpl();
        di.setEnabled(true);
        di.setPresentation(presentation);
        if(resolution != null) {
            di.setResolution(new BigDecimal(resolution));
        }
        if(unitSymbol != null) {
            di.setUnitSymbol(unitSymbol);
        }
        info.getMetadata().put(metadataKey, di);
        getCatalog().save(info);
    }
   
    /**
     * Clears dimension information from the specified coverage
     *
     * @param coverageName
     * @param metadataKey
     * @param presentation
     * @param resolution
     */
    protected void clearDimensions(String coverageName) {
        CoverageInfo info = getCatalog().getCoverageByName(coverageName);
        info.getMetadata().remove(ResourceInfo.TIME);
        info.getMetadata().remove(ResourceInfo.ELEVATION);
        getCatalog().save(info);
    }
   
}
TOP

Related Classes of org.geoserver.wcs2_0.WCSTestSupport

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.