Package org.geotools.coverage.io.hdf4

Source Code of org.geotools.coverage.io.hdf4.HDF4Access

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2007-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.coverage.io.hdf4;

import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.measure.unit.Unit;

import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.io.CoverageAccess;
import org.geotools.coverage.io.CoverageSource;
import org.geotools.coverage.io.CoverageStore;
import org.geotools.coverage.io.Driver;
import org.geotools.coverage.io.hdf4.HDF4ProductFieldType.Product;
import org.geotools.coverage.io.impl.DefaultCoverageAccess;
import org.geotools.coverage.io.impl.DefaultFileDriver;
import org.geotools.coverage.io.range.FieldType;
import org.geotools.coverage.io.range.RangeType;
import org.geotools.coverage.io.range.impl.DefaultRangeType;
import org.geotools.coverage.io.util.Utilities;
import org.geotools.data.DefaultServiceInfo;
import org.geotools.data.Parameter;
import org.geotools.data.ServiceInfo;
import org.geotools.factory.Hints;
import org.geotools.feature.NameImpl;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.imageio.SliceDescriptor;
import org.geotools.imageio.SpatioTemporalImageReader;
import org.geotools.imageio.hdf4.HDF4ImageReader;
import org.geotools.imageio.metadataold.Band;
import org.geotools.imageio.metadataold.RectifiedGrid;
import org.geotools.imageio.metadataold.SpatioTemporalMetadata;
import org.geotools.referencing.operation.transform.ProjectiveTransform;
import org.geotools.resources.coverage.CoverageUtilities;
import org.geotools.util.NullProgressListener;
import org.geotools.util.SimpleInternationalString;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.feature.type.Name;
import org.opengis.geometry.BoundingBox;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.temporal.TemporalGeometricPrimitive;
import org.opengis.util.InternationalString;
import org.opengis.util.ProgressListener;

/**
* {@link CoverageAccess} implementation for HDF4 Data format.
*
* @author Romagnoli Daniele, GeoSolutions
*
*
*
*
* @source $URL$
*/
public class HDF4Access extends DefaultCoverageAccess {
   
    private final static Set<AccessType> allowedAccessTypes;

    private final static Map<String, Parameter<?>> accessParameters;

    private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(HDF4Access.class.toString());

    private int numberOfCoverages;

    Map<Integer, SliceDescriptor> sliceDescriptorsMap = new HashMap<Integer, SliceDescriptor>();

    Map<Integer, SpatioTemporalMetadata> spatioTemporalMetadataMap = new HashMap<Integer, SpatioTemporalMetadata>();

    /**
     * Name of this coverage data product.
     */
    ArrayList<Name> coverageNames = new ArrayList<Name>();

    private Map<String, Serializable> connectionParameters;

    HashMap<Name, GeneralEnvelope> envelopesMap = new HashMap<Name, GeneralEnvelope>();

    HashMap<Name, GeneralEnvelope> coverageEnvelope2DMap = new HashMap<Name, GeneralEnvelope>();
   
    HashMap<BoundingBox, Name> coverages2DMap = new HashMap<BoundingBox, Name>();

    HashMap<Name, CoordinateReferenceSystem> crsMap = new HashMap<Name, CoordinateReferenceSystem>();

    HashMap<Name, MathTransform> raster2ModelMap = new HashMap<Name, MathTransform>();

    HashMap<Name, Set<TemporalGeometricPrimitive>> temporalExtentMap = new HashMap<Name, Set<TemporalGeometricPrimitive>>();

//    HashMap<Name, Set<NumberRange<Double>>> verticalExtentMap = new HashMap<Name, Set<NumberRange<Double>>>();
//   
//    HashMap <String, Name> verticalCRSMap = new HashMap <String, Name>();

    /** Highest resolution available. */
    HashMap<Name, double[]> highestResMap = new HashMap<Name, double[]>();

    /** The base envelope 2D */
    HashMap<Name, Envelope2D> baseEnvelope2DMap = new HashMap<Name, Envelope2D>();

    HashMap<Name, BoundingBox> boundingBoxesMap = new HashMap<Name, BoundingBox>();

    /** WGS84 envelope 2D for this coverage */
    HashMap<Name, Envelope2D> wgs84BaseEnvelope2DMap = new HashMap<Name, Envelope2D>();

    /** The CRS related to the base envelope 2D */
    HashMap<Name, CoordinateReferenceSystem> spatialReferenceSystem2DMap = new HashMap<Name, CoordinateReferenceSystem>();

    private URL input;

    HashMap<Name, RangeType> rangeMap = new HashMap<Name, RangeType>();

    HashMap<Name, GridGeometry2D> gridGeometry2DMap = new HashMap<Name, GridGeometry2D>();

    static {
        final Set<AccessType> types = new HashSet<AccessType>();
        types.add(AccessType.READ_ONLY);
        allowedAccessTypes = Collections.unmodifiableSet(types);
        final Map<String, Parameter<?>> parameters = new HashMap<String, Parameter<?>>();
        parameters.put(DefaultFileDriver.URL.key, DefaultFileDriver.URL);
        accessParameters = Collections.unmodifiableMap(parameters);
    }

    HDF4Access(Driver driver, URL source, Map<String, Serializable> additionalParameters, Hints hints,
            ProgressListener listener) throws IOException {
        super(driver);

        if (source == null) {
            if (additionalParameters.containsKey(DefaultFileDriver.URL.key)) {
                source = (URL) additionalParameters.get(DefaultFileDriver.URL.key);
            }
        }
        if (source == null)
            throw new IllegalArgumentException();
        connectionParameters = new HashMap<String, Serializable>();
        if (additionalParameters != null) {
            connectionParameters.putAll(additionalParameters);
        }
        connectionParameters.put(DefaultFileDriver.URL.key, source);

        // get the protocol
        final String protocol = source.getProtocol();

        // file
        if (protocol.equalsIgnoreCase("file")) {
            // convert to file
            final File sourceFile = DefaultFileDriver.urlToFile(source);

            // check that it is a file,exists and can be at least read
            if (!sourceFile.exists() || !sourceFile.isFile() || !sourceFile.canRead())
                throw new IllegalArgumentException("Invalid input");

            // set the class type
            // this.inputClass = File.class;
            this.input = source;

            // initialize
            this.init();

            return;
        }
    }

    private void init() {
        // get the needed info from them to set the extent
        try {
            final HDF4ImageReader reader = (HDF4ImageReader) HDF4Driver.spi.createReaderInstance(this.input);
            reader.setInput(this.input);

            int numCoverages = 0;

            // Setting the name
            final Name mainCoverageName = Utilities.buildCoverageName(input);
            Name coverageName = mainCoverageName;

            // TODO: Add more checks on Vertical/Temporal dimension availability
            final int numImages = reader.getNumImages(false);

            // //
            //
            // Setting Envelope and Extents
            //
            // //
            Map<Name, Map<String, HDF4ProductFieldType>> fieldsMap = new HashMap<Name, Map<String, HDF4ProductFieldType>>();
            for (int imageIndex = 0; imageIndex < numImages; imageIndex++) {
                final SpatioTemporalMetadata metadata = reader.getSpatioTemporalMetadata(imageIndex);
                final SliceDescriptor sd = reader.getSliceDescriptor(imageIndex);
                if (sd == null)
                    throw new IllegalStateException("unable to get the required sliceDescriptor");

                // //
                //
                // Getting slice extent
                //
                // //
//                VerticalExtent ve = sd.getVerticalExtent();
//                CoordinateReferenceSystem crs = sd.getCoordinateReferenceSystem();
                TemporalGeometricPrimitive time = sd.getTemporalExtent();
               
                BoundingBox boundingBox = sd.getHorizontalExtent();
//                String referenceID = "";
//                if (crs instanceof CompoundCRS){
//                    List<CoordinateReferenceSystem> list = ((CompoundCRS) crs).getCoordinateReferenceSystems();
//                    if (list!=null && !list.isEmpty()){
//                        for (CoordinateReferenceSystem crsElement : list){
//                            if (crsElement instanceof VerticalCRS){
//                                referenceID = crsElement.getName().getCode();
//                                break;
//                            }
//                        }
//                    }
//                }

                Band band = metadata.getBand(0);
                Set<TemporalGeometricPrimitive> temporalExtent;
//                Set<NumberRange<Double>> verticalExtent;
                Map<String, HDF4ProductFieldType> fields;

                // //
                //
                // Firstly, group coverages having the same bounding Box.
                // Some datasources may contain data coming from acquisitions
                // on different areas. We divide them in different groups.
                //
                // //

//                if (!verticalCRSMap.containsKey(referenceID)) {
                if (!coverages2DMap.containsKey(boundingBox)) {
                    // //
                    //
                    // This is the first occurrence. Setting coverageName,
                    // as well as the extents.
                    //
                    // //
                    coverageName = new NameImpl(mainCoverageName.getLocalPart() + "_" + Integer.toString(numCoverages++));
                    coverageNames.add(coverageName);
//                    verticalCRSMap.put(referenceID, coverageName);
                    coverages2DMap.put(boundingBox, coverageName);
                    temporalExtent = new LinkedHashSet<TemporalGeometricPrimitive>();
//                    verticalExtent = new LinkedHashSet<NumberRange<Double>>();
                    fields = new LinkedHashMap<String, HDF4ProductFieldType>();
                    temporalExtentMap.put(coverageName, temporalExtent);
//                    verticalExtentMap.put(coverageName, verticalExtent);
                    fieldsMap.put(coverageName, fields);
                } else {
//                    coverageName = verticalCRSMap.get(referenceID);
                  coverageName = coverages2DMap.get(boundingBox);
                }

                if (!envelopesMap.containsKey(coverageName)) {
                    // //
                    //
                    // In case this coverage's properties haven't been
                    // initialized yet, init them.
                    //
                    // //
                    initOriginalEnvelopeAndCRS(coverageName, sd);
                    final GridGeometry2D gridGeometry2D = buildGridGeometry2D(coverageName, metadata);
                    gridGeometry2DMap.put(coverageName, gridGeometry2D);
                } else {
                    GeneralEnvelope envelope = envelopesMap.get(coverageName);
                    envelope.add(sd.getGeneralEnvelope());
                    envelopesMap.put(coverageName, envelope);
                }

                // //
                //
                // Update the temporal, vertical extent for this coverage
                //
                // //
                temporalExtent = (LinkedHashSet<TemporalGeometricPrimitive>) temporalExtentMap.get(coverageName);
//                verticalExtent = (LinkedHashSet<NumberRange<Double>>) verticalExtentMap.get(coverageName);
//                if (ve != null) {
//                  NumberRange<Double> verticalEnvelope = NumberRange.create(ve.getMinimumValue().doubleValue(), ve.getMaximumValue().doubleValue());
//                    if (!verticalExtent.contains(verticalEnvelope))
//                        verticalExtent.add(verticalEnvelope);
//                }

                if (time != null) {
                    if (!temporalExtent.contains(time))
                        temporalExtent.add(time);
                }

                // //
                //
                // Update the fields for this coverage
                //
                // //
                fields = (LinkedHashMap<String, HDF4ProductFieldType>) fieldsMap.get(coverageName);

                String elementName = band.getName();
                if (!fields.containsKey(elementName)) {

                    Product product = HDF4ProductFieldType.getProduct(elementName);
                    Unit unit = Unit.ONE;
                    if (product != null) {
                        unit = product.getUoM();
                    } else {
                        String uOm = band.getUoM();
                        if(uOm == null)
                           unit = Unit.ONE.alternate(uOm);
                        else
                          try {
                            unit = Unit.valueOf(uOm);
                          } catch (IllegalArgumentException iae) {
                              try {
                                  unit = Unit.ONE.alternate(uOm);
                              } catch (IllegalArgumentException iae2) {
                                  if (LOGGER.isLoggable(Level.FINE)) {
                                      LOGGER.log(Level.FINE, "Unable to parse the provided unit " + uOm, iae2);
                                  }
                              } catch (UnsupportedOperationException uoe) {
                                  if (LOGGER.isLoggable(Level.FINE)) {
                                      LOGGER.log(Level.FINE,
                                              "Unable to parse the provided unit "
                                                      + uOm, uoe);
                                  }
                              }
                          }
                    }
                    final Name nameImpl = new NameImpl(coverageName.getLocalPart(), elementName);
                    final InternationalString description = new SimpleInternationalString(product!=null?product.getDescription():elementName);

                    // setting bands names.
                    final GridSampleDimension gridBand = Utilities.buildBands(band, elementName, unit);
                    final HDF4ProductFieldType fd = new HDF4ProductFieldType(nameImpl, description, gridBand);
                    fields.put(elementName, fd);
                }

                // //
                //
                // Updating the sliceDescriptor Map
                //
                // //
                sliceDescriptorsMap.put(imageIndex, sd);
                spatioTemporalMetadataMap.put(imageIndex, metadata);
            }

            // //
            //
            // Checking sets
            //
            // //
            for (Name covName : coverageNames) {
//            for (Name covName : verticalExtentMap.keySet()) {
//                Set<NumberRange<Double>> verticalExtent = verticalExtentMap.get(covName);
//                if (verticalExtent.size() == 0) {
//                    verticalExtent = Collections.emptySet();
//                    verticalExtentMap.put(covName, verticalExtent);
//                }
                Set<TemporalGeometricPrimitive> temporalExtent = temporalExtentMap.get(covName);
                if (temporalExtent.size() == 0) {
                    temporalExtent = Collections.emptySet();
                    temporalExtentMap.put(covName, temporalExtent);
                }

                // //
                //
                // Setting a proper RangeType using the FieldTypes found
                //
                // //
                Map<String, HDF4ProductFieldType> fields = (LinkedHashMap<String, HDF4ProductFieldType>) fieldsMap.get(covName);
                if (fields != null && !fields.isEmpty()) {
                    final Set<FieldType> fieldTypes = new LinkedHashSet<FieldType>(fields.size());
                    final StringBuilder sb = new StringBuilder();
                    for (HDF4ProductFieldType fd : fields.values()) {
                        fieldTypes.add(fd);
                        final InternationalString description = fd.getDescription();
                        sb.append(description != null ? description.toString()+ "," : "");
                    }
                    String description = sb.toString();
                    int pos = -1;
                    if (description.length() > 0 && (pos = description.lastIndexOf(",")) != -1) {
                        description = description.substring(0, pos);
                    }
                    DefaultRangeType range = new DefaultRangeType(covName,new SimpleInternationalString(description),fieldTypes);
                    rangeMap.put(covName, range);
                }
            }

            numberOfCoverages = numCoverages;
            // dispose the reader
            reader.dispose();
        } catch (IOException e) {
            this.numberOfCoverages = 1;

        } catch (FactoryException fe) {
            this.numberOfCoverages = 1;

        } catch (TransformException fe) {
            this.numberOfCoverages = 1;
        }

    }

    public CoverageSource access(Name name, Map<String, Serializable> params,
            AccessType accessType, Hints hints, ProgressListener listener)
            throws IOException {
        if (listener == null)
            listener = new NullProgressListener();
        listener.started();
        try {
            return new HDF4Source(this, name);
        } finally {
            listener.complete();
        }
    }

    public boolean canCreate(Name name, Map<String, Serializable> params,
            Hints hints, ProgressListener listener) throws IOException {
        return false;
    }

    public boolean canDelete(Name name, Map<String, Serializable> params,
            Hints hints) throws IOException {
        return false;
    }

    public CoverageStore create(Name name, Map<String, Serializable> params,
            Hints hints, ProgressListener listener) throws IOException {
        throw new UnsupportedOperationException("HDF4Access only provides read access from a Coverage Source");
    }

    public boolean delete(Name name, Map<String, Serializable> params, Hints hints) throws IOException {
        return false;
    }

    public void dispose() {
        input = null;
    }

    public Map<String, Parameter<?>> getAccessParameterInfo(AccessType accessType) {
        return accessParameters;
    }

    public Map<String, Serializable> getConnectParameters() {
        return Collections.unmodifiableMap(connectionParameters);
    }

    public Driver getDriver() {
        return new HDF4Driver();
    }

    public ServiceInfo getInfo(ProgressListener listener) {
        if (listener == null)
            listener = new NullProgressListener();
        listener.started();
        final DefaultServiceInfo info = new DefaultServiceInfo();

        info.setTitle(coverageNames.get(0).toString());
        try {

            info.setSource(input.toURI());
        } catch (URISyntaxException e1) {

        } finally {
            listener.complete();
        }
        return info;
    }

    public Envelope getExtent(Name coverageName, ProgressListener listener) {
        if (listener == null)
            listener = new NullProgressListener();
        listener.started();
        try {
            return envelopesMap.get(coverageName).clone();
        } finally {
            listener.complete();
        }
    }

    public List<Name> getNames(ProgressListener listener) {
        if (listener == null)
            listener = new NullProgressListener();
        listener.started();
        try {
            return Collections.unmodifiableList(this.coverageNames);
        } finally {
            listener.complete();
        }
    }

    public int getNumCoverages(ProgressListener listener) {
        if (listener == null)
            listener = new NullProgressListener();
        listener.started();
        try {
            return numberOfCoverages;
        } finally {
            listener.complete();
        }
    }

    public Set<AccessType> getSupportedAccessTypes() {
        return allowedAccessTypes;
    }

    public boolean isCreateSupported() {
        return false;
    }

    public boolean isDeleteSupported() {
        return false;
    }

    private GridGeometry2D buildGridGeometry2D(Name coverageName, SpatioTemporalMetadata metadata) {
        GridGeometry2D g2d = null;
        if (metadata != null) {
            // //
            //
            // Getting the rectifiedGrid node
            //
            // //
            final RectifiedGrid rg = metadata.getRectifiedGrid();
            final AffineTransform at = Utilities.getAffineTransform(rg);
            final GridEnvelope gridRange = Utilities.getGridRange(rg);
            final MathTransform raster2Model = ProjectiveTransform.create(at);
            raster2ModelMap.put(coverageName, raster2Model);
            final double[] highestRes = CoverageUtilities.getResolution((AffineTransform) raster2Model);
            highestResMap.put(coverageName, highestRes);
            g2d = new GridGeometry2D(gridRange, raster2Model,spatialReferenceSystem2DMap.get(coverageName));
        }
        return g2d;
    }

    private void initOriginalEnvelopeAndCRS(Name coverageName,
            SliceDescriptor sd) throws FactoryException, TransformException {
        if (sd == null)
            throw new IllegalArgumentException("Provided Slice Descriptor is null");
        final GeneralEnvelope envelope = sd.getGeneralEnvelope().clone();
        envelopesMap.put(coverageName, envelope);
        crsMap.put(coverageName, sd.getCoordinateReferenceSystem());
        final BoundingBox bb = sd.getHorizontalExtent();
        boundingBoxesMap.put(coverageName, bb);
        final GeneralEnvelope coverageEnvelope2D = new GeneralEnvelope(bb);
        coverageEnvelope2DMap.put(coverageName, coverageEnvelope2D);
        spatialReferenceSystem2DMap.put(coverageName, coverageEnvelope2D.getCoordinateReferenceSystem());
        final Envelope2D wgs84BaseEnvelope2D = (Envelope2D) Utilities.getEnvelopeAsWGS84(coverageEnvelope2D, true);
        wgs84BaseEnvelope2DMap.put(coverageName, wgs84BaseEnvelope2D);
        baseEnvelope2DMap.put(coverageName, new Envelope2D(coverageEnvelope2D));
    }

    public URL getInput() {
        return input;
    }

}
TOP

Related Classes of org.geotools.coverage.io.hdf4.HDF4Access

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.