Package org.geoserver.wcs.responses

Source Code of org.geoserver.wcs.responses.NetCDFDimensionManager$DimensionValues

/* (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.wcs.responses;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.geoserver.wcs2_0.response.DimensionBean;
import org.geoserver.wcs2_0.response.DimensionBean.DimensionType;
import org.geotools.util.DateRange;
import org.geotools.util.NumberRange;

import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.Index;
import ucar.nc2.Dimension;

/**
* A DimensionManager class to associate to a dimension:
* - the input coverageDimension,
* - the output netCDFDimension,
* - the available values for the coordinate variable of that dimension
*/
class NetCDFDimensionManager {
    public NetCDFDimensionManager(String name) {
        super();
        this.name = name;
    }

    /**
     * The available (sorted) values for a Dimension
     */
    private DimensionValues dimensionValues;

    /**
     * The input coverage Dimension (a {@link DimensionBean} instance)
     */
    private DimensionBean coverageDimension;

    /**
     * The output netCDF dimension (a {@link Dimension} instance)
     */
    private Dimension netCDFDimension;

    /**
     * the name of this dimension manager
     */
    private String name;

    @Override
    public String toString() {
        return "NetCDFDimensionManager [name=" + name + " coverageDimension=" + coverageDimension
                + ", netCDFDimension=" + netCDFDimension + "]";
    }

    public DimensionValues getDimensionValues() {
        return dimensionValues;
    }

    public void setDimensionValues(DimensionValues dimensionValues) {
        this.dimensionValues = dimensionValues;
    }

    public DimensionBean getCoverageDimension() {
        return coverageDimension;
    }

    public void setCoverageDimension(DimensionBean coverageDimension) {
        this.coverageDimension = coverageDimension;
    }

    public Dimension getNetCDFDimension() {
        return netCDFDimension;
    }

    public void setNetCDFDimension(Dimension netCDFDimension) {
        this.netCDFDimension = netCDFDimension;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * A simple interface to deal with the values of a Dimension
     */
    interface DimensionValues {

        abstract Object getValues();

        abstract void addValue(Object object);

        abstract int getSize();
    }

    /**
     * A DimensionValues based on Set of objects
     *
     */
    static class DimensionValuesSet implements DimensionValues {
        Set<Object> values;

        public DimensionValuesSet(Set<Object> set) {
            values = set;
        }

        @Override
        public Set getValues() {
            return values;
        }

        @Override
        public void addValue(Object object) {
            values.add(object);
        }

        @Override
        public int getSize() {
            return values.size();
        }
    }

    /**
     * A DimensionValues based on Array
     */
    static class DimensionValuesArray implements DimensionValues {
        Array values;

        public DimensionValuesArray(Array data) {
            values = data;
        }

        @Override
        public Array getValues() {
            return (Array) values;
        }

        @Override
        public void addValue(Object object) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getSize() {
            return (int) values.getSize();
        }
    }

    public void dispose() {
        dimensionValues = null;
        netCDFDimension = null;
//        coverageDimension = null;
    }
   
    /**
     * Get the values for a Dimension wrapped by its specific DimensionManager and return them as
     * a NetCDF Array object
     *
     * @param rangeValues specify whether the data should be returned as a 1D array or a 2D array
     * (the latter for dimensions having ranges)
     * @return
     */
    public Array getDimensionData(final boolean rangeValues) {
        final String dimensionName = getName();
       
        // Special management for latitude and logitude
        if (dimensionName.equalsIgnoreCase(NCUtilities.LAT)) {
            return (Array) getDimensionValues().getValues();
        } else if (dimensionName.equalsIgnoreCase(NCUtilities.LON)) {
            return (Array) getDimensionValues().getValues();
        } else {

            // Get Dimension information
            DimensionBean bean = getCoverageDimension();
            DimensionType type = bean.getDimensionType();
            final String dataType = bean.getDatatype();
            boolean isTime = false;
            if (type == DimensionType.TIME || NCUtilities.isATime(dataType)) {
                isTime = true;
            }

            // Get Dimension values
            final DimensionValues dimensionValues = getDimensionValues();
            final Set<Object> values = (Set<Object>) dimensionValues.getValues();
            final int numElements = values.size();

            final String dimensionDataType = getCoverageDimension().getDatatype();
            final DataType netCDFDataType = NCUtilities.getNetCDFDataType(dimensionDataType);

            // Get a proper array to contain the dimension values
            final int[] dimensionSize = rangeValues ? new int[] { numElements, 2 } : new int[] {numElements};
            final Array data = NCUtilities.getArray(dimensionSize, netCDFDataType);

            final Index index = data.getIndex();
            final Iterator<Object> valuesIterator = values.iterator();
            final int indexing[] = new int[rangeValues ? 2: 1];

            // Setting array values
            for (int pos = 0; pos < numElements; pos++) {
                indexing[0] = pos;
                Object value = valuesIterator.next();
                data.setObject(index.set(indexing), getValue(value, isTime, false));
                if (rangeValues) {
                    indexing[1] = 1;
                    data.setObject(index.set(indexing), getValue(value, isTime, rangeValues));
                    indexing[1] = 0;
                }
            }
            return data;
        }
    }
   
    /**
     * Get the value from the input object. Take care of time elements since they need
     * to be referred to the time origin
     *
     * @param input
     * @param isTime does this object represents a temporal entity?
     * @param endValue specify whether it needs to return the second value of a range
     * @return
     */
    private Object getValue(Object input, boolean isTime, boolean endValue) {
        if (isTime) {
            return getTime(input, endValue);
        } else if (input instanceof NumberRange) {
            NumberRange range = (NumberRange) input;
            return endValue ? range.getMaxValue() : range.getMinValue();
        }
        //Simply return back the value
        return input;
    }

    /**
     * Return the time value for this object. Note that times are referred with respect to
     * an origin {@link NCUtilities#START_TIME}.
     * @param input
     * @param endTime specify whether it needs to return the second value of a time range
     * @return
     */
    private Double getTime(Object input, boolean endTime) {
        long time = 0;
        if (input instanceof Timestamp) {
            time = ((Timestamp) input).getTime();
        } else if (input instanceof DateRange) {
            if (!endTime) {
                time = ((DateRange) input).getMinValue().getTime();
            } else {
                time = ((DateRange) input).getMaxValue().getTime();
            }
        } else if (input instanceof Date){
            time = ((Date)input).getTime();
        } else {
            throw new IllegalArgumentException("Unsupported time");
        }
        // Convert to seconds since START_TIME
        return ((double)(time - NCUtilities.START_TIME))/1000d;
    }
}
TOP

Related Classes of org.geoserver.wcs.responses.NetCDFDimensionManager$DimensionValues

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.