Package org.geoserver.wcs2_0.response

Source Code of org.geoserver.wcs2_0.response.WCSDimensionsHelper

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

import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.DimensionInfo;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.util.ReaderDimensionsAccessor;
import org.geoserver.util.ISO8601Formatter;
import org.geoserver.wcs2_0.exception.WCS20Exception;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geotools.coverage.grid.io.DimensionDescriptor;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.StructuredGridCoverage2DReader;
import org.geotools.util.Utilities;
import org.vfny.geoserver.wcs.WcsException;

/**
* Provides support to build the coverage description for time/elevation/additional dim based data
*
* @author Andrea Aime - GeoSolutions
* @author Daniele Romagnoli - GeoSolutions
*/
public class WCSDimensionsHelper {

    /**
     * Duration in ms of well know time periods
     */
    static final BigDecimal[] DURATIONS = new BigDecimal[] { new BigDecimal(31536000000L),
            new BigDecimal(2628000000L), new BigDecimal(86400000L), new BigDecimal(3600000L),
            new BigDecimal(60000), new BigDecimal(1000L) };

    /**
     * Labels for the above time periods
     */
    static final String[] DURATION_UNITS = new String[] { "year", "month", "day", "hour", "minute",
            "second" };

    /**
     * Quick access fields for timeDimension and elevationDimension
     */
    DimensionInfo timeDimension;

    DimensionInfo elevationDimension;

    /**
     * Additional dimensions map
     */
    Map<String, DimensionInfo> additionalDimensions;

    ReaderDimensionsAccessor accessor;

    ISO8601Formatter formatter = new ISO8601Formatter();

    String elevationResolutionUnit;

    double elevationResolutionValue;

    String timeResolutionUnit;

    long timeResolutionValue;

    String coverageId;
   
    /**
     * Base constructor which only deals with timeDimension. It is used by WCS-EO classes which
     * deals with up to timeDimensions
     *
     * @param timeDimension
     * @param reader
     * @param coverageId
     * @throws IOException
     */
    public WCSDimensionsHelper(CoverageInfo ci) throws IOException {
        this.coverageId = NCNameResourceCodec.encode(ci);
        this.accessor = new ReaderDimensionsAccessor((GridCoverage2DReader) ci.getGridCoverageReader(null, null));

        Map<String, DimensionInfo> dimensions = new HashMap<String, DimensionInfo>();
        for (Map.Entry<String, Serializable> entry : ci.getMetadata().entrySet()) {
            if(entry.getValue() instanceof DimensionInfo) {
                dimensions.put(entry.getKey(), (DimensionInfo) entry.getValue());
            }
        }
        if (!dimensions.isEmpty()) {
            initDimensions(dimensions);
        }
    }

    /**
     * Base constructor which only deals with timeDimension. It is used by WCS-EO classes which
     * deals with up to timeDimensions
     *
     * @param timeDimension
     * @param reader
     * @param coverageId
     * @throws IOException
     */
    public WCSDimensionsHelper(final DimensionInfo timeDimension,
            final GridCoverage2DReader reader, final String coverageId) throws IOException {
        this(new HashMap<String, DimensionInfo>() {
            {
                put(ResourceInfo.TIME, timeDimension);
            }
        }, reader, coverageId);
    }

    public WCSDimensionsHelper(final Map<String, DimensionInfo> dimensions, final GridCoverage2DReader reader, final String coverageId) throws IOException {
        this.accessor = new ReaderDimensionsAccessor(reader);
        this.coverageId = coverageId;

        if (dimensions != null && !dimensions.isEmpty()) {
            initDimensions(dimensions);
        }
    }

    /**
     * Initialize dimensions
     *
     * @param updatedDimensions
     */
    private void initDimensions(Map<String, DimensionInfo> dimensions) {
        Utilities.ensureNonNull("dimensions", dimensions);
        Map<String, DimensionInfo> updatedDimensions = new HashMap<String, DimensionInfo>();
        updatedDimensions.putAll(dimensions);
       
        // Initialize Time dimensions
        if (updatedDimensions.containsKey(ResourceInfo.TIME)) {
            timeDimension = updatedDimensions.remove(ResourceInfo.TIME) ;
            if (timeDimension != null) {
                final BigDecimal resolution = timeDimension.getResolution();
                if (resolution != null) {
                    setupTimeResolution(resolution);
                }
            }
        }
       
        // Initialize Elevation Dimensions
        if (updatedDimensions.containsKey(ResourceInfo.ELEVATION)) {
            elevationDimension = updatedDimensions.remove(ResourceInfo.ELEVATION) ;
            final BigDecimal resolution = elevationDimension.getResolution();
            if (resolution != null) {
                elevationResolutionValue = resolution.doubleValue();
                elevationResolutionUnit = elevationDimension.getUnitSymbol();
            }
        }
       
        // Remaining dimensions are custom dimensions
        this.additionalDimensions = updatedDimensions;
    }

    private void setupTimeResolution(BigDecimal resolution) {
        for (int i = 0; i < DURATIONS.length; i++) {
            BigDecimal duration = DURATIONS[i];
            if (resolution.remainder(duration).longValue() == 0) {
                timeResolutionValue = resolution.divide(duration).longValue();
                timeResolutionUnit = DURATION_UNITS[i];
                return;
            }
        }
        // uh oh? it's a value in milliseconds?
        throw new WcsException(
                "Dimension's resolution requires milliseconds for full representation, "
                        + "but this cannot be represented in WCS 2.0 describe coverage output");
    }

    public DimensionInfo getTimeDimension() {
        return timeDimension;
    }

    public DimensionInfo getElevationDimension() {
        return elevationDimension;
    }

    public Map<String, DimensionInfo> getAdditionalDimensions() {
        return additionalDimensions;
    }

    public TreeSet<Object> getTimeDomain() throws IOException {
        return accessor.getTimeDomain();
    }

    public TreeSet<Object> getElevationDomain() throws IOException {
        return accessor.getElevationDomain();
    }

    public List<String> getDomain(final String domainName) throws IOException {
        return accessor.getDomain(domainName);
    }

    /**
     * Returns the minimum time, formatted according to ISO8601
     * @throws IOException
     */
    public String getBeginTime() throws IOException {
        Date minTime = accessor.getMinTime();
        return format(minTime);
    }

    /**
     * Returns the maximum time, formatted according to ISO8601
     * @throws IOException
     */
    public String getEndTime() throws IOException {
        Date maxTime = accessor.getMaxTime();
        return format(maxTime);
    }

    /**
     * Returns the minimum elevation
     * @throws IOException
     */
    public String getBeginElevation() throws IOException {
        Double minElevation = accessor.getMinElevation();
        return minElevation.toString();
    }

    /**
     * Returns the maximum elevation
     * @throws IOException
     */
    public String getEndElevation() throws IOException {
        Double maxElevation = accessor.getMaxElevation();
        return maxElevation.toString();
    }

    /**
     * Return the default value of the specified additional domain
     *
     * @param domainName
     * @return
     * @throws IOException
     */
    public String getDefaultValue(String domainName) throws IOException {
        if (additionalDimensions != null && !additionalDimensions.isEmpty() && additionalDimensions.containsKey(domainName)) {
            return accessor.getCustomDomainDefaultValue(domainName);
        }
        return null;
    }

    /**
     * Formats a Date into ISO86011
     * @param time
     * @return
     */
    public String format(Date time) {
        if (time != null) {
            return formatter.format(time);
        } else {
            return null;
        }
    }

    /**
     * Returns the time resolution unit, choosing among "year", "month", "day", "hour", "minute",
     * "second"
     *
     * @return
     */
    public String getTimeResolutionUnit() {
        return timeResolutionUnit;
    }

    /**
     * The time resolution value, expressed in the unit returned by {@link #getTimeResolutionUnit()}
     *
     * @return
     */
    public long getTimeResolutionValue() {
        return timeResolutionValue;
    }

    /**
     * Returns the elevation resolution unit
     *
     * @return
     */
    public String getElevationResolutionUnit() {
        return elevationResolutionUnit;
    }

    /**
     * The elevation resolution value
     * @return
     */
    public double getElevationResolutionValue() {
        return elevationResolutionValue;
    }

    /**
     * The coverage identifier
     * @return
     */
    public String getCoverageId() {
        return coverageId;
    }

    /**
     * Scan the metadataMap looking for resources related to {@link DimensionInfo} objects and
     * return a dimensions Map. Return an empty map if no dimensions are found.
     *
     * @param metadata
     * @return
     */
    public static Map<String, DimensionInfo> getDimensionsFromMetadata(MetadataMap metadata) {
        Map<String, DimensionInfo> dimensionsMap = new HashMap<String, DimensionInfo>();
        if (metadata != null && !metadata.isEmpty()) {
            final Set<String> metadataKeys = metadata.keySet();
            final Iterator<String> metadataIterator = metadataKeys.iterator();

            // loop over metadata keys
            while (metadataIterator.hasNext()) {
                String key = metadataIterator.next();
                if (isADimension(key)) {
                    // Check whether the specified metadata is related to an enabled Dimension
                    DimensionInfo dimension = metadata.get(key, DimensionInfo.class);
                    if (dimension != null && dimension.isEnabled()) {
                        if (key.startsWith(ResourceInfo.CUSTOM_DIMENSION_PREFIX)) {
                            key = key.substring(ResourceInfo.CUSTOM_DIMENSION_PREFIX.length());
                        }

                        dimensionsMap.put(key, dimension);
                    }
                }
            }
        }
        return dimensionsMap;
    }

    public static DimensionDescriptor getDimensionDescriptor(final StructuredGridCoverage2DReader reader, final String coverageName, final String dimensionName) {
        try {
            List<DimensionDescriptor> descriptors = reader.getDimensionDescriptors(coverageName);
            for (DimensionDescriptor dd : descriptors) {
                if (dd.getName().equalsIgnoreCase(dimensionName)) {
                    return dd;
                }
            }

            return null;
        } catch(IOException e) {
            throw new WCS20Exception("Failed to locate the reader's " + dimensionName + " dimension descriptor", e);
        }
    }
   
    /**
     * Return {@code true} in case the specified Key refers to a Dimension.
     * @param key
     * @return
     */
    private final static boolean isADimension(final String key) {
        return key != null && (key.equals(ResourceInfo.TIME) || key.equals(ResourceInfo.ELEVATION) || key
                        .startsWith(ResourceInfo.CUSTOM_DIMENSION_PREFIX));
    }

}
TOP

Related Classes of org.geoserver.wcs2_0.response.WCSDimensionsHelper

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.