org.geotools.gce.imagemosaic.ImageMosaicPostgisIndexTest.java Source code

Java tutorial

Introduction

Here is the source code for org.geotools.gce.imagemosaic.ImageMosaicPostgisIndexTest.java

Source

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

import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.data.Query;
import org.geotools.factory.Hints;
import org.geotools.filter.SortByImpl;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.resources.coverage.FeatureUtilities;
import org.geotools.test.OnlineTestCase;
import org.geotools.test.TestData;
import org.geotools.util.NumberRange;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.sort.SortBy;
import org.opengis.filter.sort.SortOrder;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;

/**
 * Testing index in postgis database
 * @author Simone Giannecchini, GeoSolutions SAS
 *
 */
public class ImageMosaicPostgisIndexTest extends OnlineTestCase {

    /**
     * Simple Class for better testing raster manager
     * @author Simone Giannecchini, GeoSolutions SAS
     *
     */
    private static class MyImageMosaicReader extends ImageMosaicReader {

        public MyImageMosaicReader(Object source) throws IOException {
            super(source);
        }

        public MyImageMosaicReader(Object source, Hints uHints) throws IOException {
            super(source, uHints);
        }

        public RasterManager getRasterManager() {
            return rasterManager;
        }

    }

    @Override
    protected Properties createExampleFixture() {
        // create sample properties file for postgis datastore
        final Properties props = new Properties();
        props.setProperty("SPI", "org.geotools.data.postgis.PostgisNGDataStoreFactory");
        props.setProperty("host", "localhost");
        props.setProperty("port", "5432");
        props.setProperty("user", "xxx");
        props.setProperty("passwd", "xxx");
        props.setProperty("database", "ddd");
        props.setProperty("schema", "public");
        props.setProperty("Loose bbox", "true");
        props.setProperty("Estimated extends=", "false");
        props.setProperty("validate connections", "true");
        props.setProperty("Connection timeout", "10");
        props.setProperty("preparedStatements", "false");
        return props;
    }

    /* (non-Javadoc)
     * @see org.geotools.test.OnlineTestCase#getFixtureId()
     */
    @Override
    protected String getFixtureId() {
        return "postgis_datastore";
    }

    /**
     * Complex test for Postgis indexing on db.
     * 
     * @throws Exception
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Test
    public void testPostgisIndexing() throws Exception {
        final File workDir = new File(TestData.file(this, "."), "watertemp4");
        assertTrue(workDir.mkdir());
        FileUtils.copyFile(TestData.file(this, "watertemp.zip"), new File(workDir, "watertemp.zip"));
        TestData.unzipFile(this, "watertemp4/watertemp.zip");
        final URL timeElevURL = TestData.url(this, "watertemp4");

        //place datastore.properties file in the dir for the indexing
        FileWriter out = null;
        try {
            out = new FileWriter(new File(TestData.file(this, "."), "/watertemp4/datastore.properties"));

            final Set<Object> keyset = fixture.keySet();
            for (Object key : keyset) {
                final String key_ = (String) key;
                final String value = fixture.getProperty(key_);

                out.write(key_.replace(" ", "\\ ") + "=" + value.replace(" ", "\\ ") + "\n");
            }
            out.flush();
        } finally {
            if (out != null) {
                IOUtils.closeQuietly(out);
            }
        }

        // now start the test
        final AbstractGridFormat format = TestUtils.getFormat(timeElevURL);
        assertNotNull(format);
        ImageMosaicReader reader = TestUtils.getReader(timeElevURL, format);
        assertNotNull(reader);

        final String[] metadataNames = reader.getMetadataNames();
        assertNotNull(metadataNames);
        assertEquals(metadataNames.length, 10);

        assertEquals("true", reader.getMetadataValue("HAS_TIME_DOMAIN"));
        final String timeMetadata = reader.getMetadataValue("TIME_DOMAIN");
        assertNotNull(timeMetadata);
        assertEquals(2, timeMetadata.split(",").length);
        assertEquals(timeMetadata.split(",")[0], reader.getMetadataValue("TIME_DOMAIN_MINIMUM"));
        assertEquals(timeMetadata.split(",")[1], reader.getMetadataValue("TIME_DOMAIN_MAXIMUM"));

        assertEquals("true", reader.getMetadataValue("HAS_ELEVATION_DOMAIN"));
        final String elevationMetadata = reader.getMetadataValue("ELEVATION_DOMAIN");
        assertNotNull(elevationMetadata);
        assertEquals(2, elevationMetadata.split(",").length);
        assertEquals(Double.parseDouble(elevationMetadata.split(",")[0]),
                Double.parseDouble(reader.getMetadataValue("ELEVATION_DOMAIN_MINIMUM")), 1E-6);
        assertEquals(Double.parseDouble(elevationMetadata.split(",")[1]),
                Double.parseDouble(reader.getMetadataValue("ELEVATION_DOMAIN_MAXIMUM")), 1E-6);

        // limit yourself to reading just a bit of it
        final ParameterValue<GridGeometry2D> gg = AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
        final GeneralEnvelope envelope = reader.getOriginalEnvelope();
        final Dimension dim = new Dimension();
        dim.setSize(reader.getOriginalGridRange().getSpan(0) / 2.0, reader.getOriginalGridRange().getSpan(1) / 2.0);
        final Rectangle rasterArea = ((GridEnvelope2D) reader.getOriginalGridRange());
        rasterArea.setSize(dim);
        final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
        gg.setValue(new GridGeometry2D(range, envelope));

        // use imageio with defined tiles
        final ParameterValue<List> time = ImageMosaicFormat.TIME.createValue();
        final List<Date> timeValues = new ArrayList<Date>();
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
        Date date = sdf.parse("2008-10-31T00:00:00.000Z");
        timeValues.add(date);
        time.setValue(timeValues);

        final ParameterValue<double[]> bkg = ImageMosaicFormat.BACKGROUND_VALUES.createValue();
        bkg.setValue(new double[] { -9999.0 });

        final ParameterValue<Boolean> direct = ImageMosaicFormat.USE_JAI_IMAGEREAD.createValue();
        direct.setValue(false);

        final ParameterValue<List> elevation = ImageMosaicFormat.ELEVATION.createValue();
        elevation.setValue(Arrays.asList(100.0));

        // Test the output coverage
        TestUtils.checkCoverage(reader, new GeneralParameterValue[] { gg, time, bkg, elevation, direct },
                "Time-Elevation Test");

        reader = TestUtils.getReader(timeElevURL, format);

        // Test the output coverage
        elevation.setValue(Arrays.asList(NumberRange.create(0.0, 10.0)));
        TestUtils.checkCoverage(reader, new GeneralParameterValue[] { gg, time, bkg, elevation, direct },
                "Time-Elevation Test");

        reader.dispose();

    }

    /**
     * Complex test for Postgis indexing on db.
     * 
     * @throws Exception
     */
    @Test
    public void testSortingAndLimiting() throws Exception {
        final File workDir = new File(TestData.file(this, "."), "watertemp4");
        assertTrue(workDir.mkdir());
        FileUtils.copyFile(TestData.file(this, "watertemp.zip"), new File(workDir, "watertemp.zip"));
        TestData.unzipFile(this, "watertemp4/watertemp.zip");
        final URL timeElevURL = TestData.url(this, "watertemp4");

        //place datastore.properties file in the dir for the indexing
        FileWriter out = null;
        try {
            out = new FileWriter(new File(TestData.file(this, "."), "/watertemp4/datastore.properties"));

            final Set<Object> keyset = fixture.keySet();
            for (Object key : keyset) {
                final String key_ = (String) key;
                final String value = fixture.getProperty(key_);
                out.write(key_.replace(" ", "\\ ") + "=" + value.replace(" ", "\\ ") + "\n");
            }
            out.flush();
        } finally {
            if (out != null) {
                IOUtils.closeQuietly(out);
            }
        }

        // now start the test
        final AbstractGridFormat format = TestUtils.getFormat(timeElevURL);
        assertNotNull(format);
        ImageMosaicReader reader = TestUtils.getReader(timeElevURL, format);
        assertNotNull(reader);

        final String[] metadataNames = reader.getMetadataNames();
        assertNotNull(metadataNames);
        assertEquals(metadataNames.length, 10);

        assertEquals("true", reader.getMetadataValue("HAS_TIME_DOMAIN"));
        assertEquals("true", reader.getMetadataValue("HAS_ELEVATION_DOMAIN"));

        // dispose and create new reader
        reader.dispose();
        final MyImageMosaicReader reader1 = new MyImageMosaicReader(timeElevURL);
        final RasterManager rm = reader1.getRasterManager();

        // query
        final SimpleFeatureType type = rm.granuleCatalog.getType();
        Query query = null;
        if (type != null) {
            // creating query
            query = new Query(rm.granuleCatalog.getType().getTypeName());

            // sorting and limiting
            // max number of elements
            query.setMaxFeatures(1);

            // sorting
            final SortBy[] clauses = new SortBy[] {
                    new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property("ingestion"),
                            SortOrder.DESCENDING),
                    new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property("elevation"),
                            SortOrder.ASCENDING), };
            query.setSortBy(clauses);

        }

        // checking that we get a single feature and that feature is correct
        Collection<GranuleDescriptor> features = rm.getGranules(query);
        assertEquals(features.size(), 1);
        GranuleDescriptor granule = features.iterator().next();
        SimpleFeature sf = granule.getOriginator();
        assertNotNull(sf);
        Object ingestion = sf.getAttribute("ingestion");
        assertTrue(ingestion instanceof Timestamp);
        final GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
        gc.setTimeInMillis(1225497600000l);
        assertEquals(0, (((Timestamp) ingestion).compareTo(gc.getTime())));
        Object elevation = sf.getAttribute("elevation");
        assertTrue(elevation instanceof Integer);
        assertEquals(((Integer) elevation).intValue(), 0);

        // Reverting order (the previous timestamp shouldn't match anymore)
        final SortBy[] clauses = new SortBy[] {
                new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property("ingestion"), SortOrder.ASCENDING),
                new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property("elevation"),
                        SortOrder.DESCENDING), };
        query.setSortBy(clauses);

        // checking that we get a single feature and that feature is correct
        features = rm.getGranules(query);
        assertEquals(features.size(), 1);
        granule = features.iterator().next();
        sf = granule.getOriginator();
        assertNotNull(sf);
        ingestion = sf.getAttribute("ingestion");
        assertTrue(ingestion instanceof Timestamp);
        assertNotSame(0, (((Timestamp) ingestion).compareTo(gc.getTime())));
        elevation = sf.getAttribute("elevation");
        assertTrue(elevation instanceof Integer);
        assertNotSame(((Integer) elevation).intValue(), 0);

    }

    @Override
    protected void setUpInternal() throws Exception {
        super.setUpInternal();

        //make sure CRS ordering is correct
        System.setProperty("org.geotools.referencing.forceXY", "true");
        System.setProperty("user.timezone", "GMT");
    }

    @Override
    protected void tearDownInternal() throws Exception {

        // clean up disk
        if (!ImageMosaicReaderTest.INTERACTIVE) {
            FileUtils.deleteDirectory(TestData.file(this, "watertemp4"));
        }

        // delete tables
        Class.forName("org.postgresql.Driver");
        Connection connection = DriverManager.getConnection(
                "jdbc:postgresql://" + fixture.getProperty("host") + ":" + fixture.getProperty("port") + "/"
                        + fixture.getProperty("database"),
                fixture.getProperty("user"), fixture.getProperty("passwd"));
        Statement st = connection.createStatement();
        st.execute("DROP TABLE IF EXISTS watertemp4");
        st.close();
        connection.close();

        System.clearProperty("org.geotools.referencing.forceXY");

        super.tearDownInternal();

    }

}