/* * 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.imageio.metadata; import it.geosolutions.imageio.ndplugin.BaseImageMetadata; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import org.geotools.imageio.SpatioTemporalImageReader; import org.opengis.temporal.Instant; import org.opengis.temporal.Period; import org.opengis.temporal.TemporalObject; import org.w3c.dom.Node; public abstract class SpatioTemporalMetadata extends IIOMetadata { private final static Logger LOGGER = Logger.getLogger(SpatioTemporalMetadata.class.toString()); /** the imageIndex referring this specific metadata instance */ private int imageIndex; public SpatioTemporalMetadata(final SpatioTemporalImageReader reader,final int imageIndex) { this.imageIndex = imageIndex; setCoordinateReferenceSystemElement(reader); setBoundedByElement(reader); setRectifiedGridElement(reader); setBandsElement(reader); } @Override public boolean isReadOnly() { return false; } @Override public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { } @Override public void reset() { } public int getImageIndex() { return imageIndex; } /** * The root node to be returned by {@link #getAsTree}. */ private Node root; /** * The spatial coordinate reference system node. Will be created only when * first needed. */ private CoordinateReferenceSystem crs; /** * The vertical coordinate reference system node. Will be created only when * first needed. */ private VerticalCRS verticalCRS; /** {@code true} if a VerticalCRS is available */ private boolean hasVerticalCRS = false; /** * The temporal coordinate reference system node. Will be created only when * first needed. */ private TemporalCRS temporalCRS; /** {@code true} if a TemporalCRS is available */ private boolean hasTemporalCRS = false; /** * The rectified grid node. Will be created only when first needed. */ private RectifiedGrid rectifiedGrid; /** * The boundedBy node. Will be created only when first needed. */ private BoundedBy boundedBy; /** * The list of {@linkplain Band bands}. Will be created only * when first needed. */ private ChildList<Band> bands; private void checkFormatName(final String formatName) throws IllegalArgumentException { if (!SpatioTemporalMetadataFormat.FORMAT_NAME.equals(formatName)) { throw new IllegalArgumentException("Illegal formatName:"+ formatName); } } /** * Returns the root of a tree of metadata contained within this object * according to the conventions defined by a given metadata format. * * @param formatName * the desired metadata format. * @return The node forming the root of metadata tree. * @throws IllegalArgumentException * if the format name is {@code null} or is not one of the * names returned by {@link #getMetadataFormatNames() * getMetadataFormatNames()}. */ public Node getAsTree(final String formatName) throws IllegalArgumentException { checkFormatName(formatName); return getRootNode(); } public boolean isHasVerticalCRS() { return hasVerticalCRS; } /** * Call this method before setting a VerticalCRS node * * @param hasVerticalCRS */ public void setHasVerticalCRS(boolean hasVerticalCRS) { this.hasVerticalCRS = hasVerticalCRS; } public boolean isHasTemporalCRS() { return hasTemporalCRS; } /** * Call this method before setting a TemporalCRS node * * @param hasTemporalCRS */ public void setHasTemporalCRS(boolean hasTemporalCRS) { this.hasTemporalCRS = hasTemporalCRS; } /** * Returns the root of a tree of metadata contained within this object * according to the conventions defined by a given metadata format. */ final Node getRootNode() { if (root == null) { root = new IIOMetadataNode(SpatioTemporalMetadataFormat.FORMAT_NAME); } return root; } /** * Returns the list of all {@linkplain Band bands}. */ final ChildList<Band> getSampleDimensions() { if (bands == null) { bands = new ChildList.Bands(this); } return bands; } /** * Returns a {@linkplain Band band}. */ public Band getBand(int dimensionIndex) { return getSampleDimensions().getChild(dimensionIndex); } /** * Add a Sample Dimension to the Sample Dimensions node. */ public Band addBand() { if (bands == null) { bands = new ChildList.Bands(this); } Band candidate = bands.addChild(); return candidate; } /** * Returns the CoordinateReferenceSystem. */ public CoordinateReferenceSystem getCRS(final String crsType) { if (crs == null) { crs = new CoordinateReferenceSystem(this, crsType); } return crs; } /** * Returns the CoordinateReferenceSystem. */ public CoordinateReferenceSystem getCRS() { return getCRS(null); } /** * Returns the Vertical CoordinateReferenceSystem node. */ public VerticalCRS getVerticalCRS() { if (verticalCRS == null && hasVerticalCRS) { verticalCRS = new VerticalCRS(this); } return verticalCRS; } /** * Returns the Temporal CoordinateReferenceSystem node. */ public TemporalCRS getTemporalCRS() { if (temporalCRS == null && hasTemporalCRS) { temporalCRS = new TemporalCRS(this); } return temporalCRS; } /** * Returns the rectified grid. */ public RectifiedGrid getRectifiedGrid() { if (rectifiedGrid == null) { rectifiedGrid = new RectifiedGrid(this); } return rectifiedGrid; } /** * Returns the Bounded by domain. */ public BoundedBy getBoundedBy() { if (boundedBy == null) { boundedBy = new BoundedBy(this); } return boundedBy; } /** * Set the {@code coordinateReferenceSystem} metadata element. * * @param reader * the {@link SpatioTemporalImageReader} to be used to set * this metadata element. */ protected abstract void setCoordinateReferenceSystemElement(SpatioTemporalImageReader reader); /** * Set the {@code boundedBy} metadata element. * * @param reader * the {@link SpatioTemporalImageReader} to be used to set * this metadata element. */ protected abstract void setBoundedByElement(SpatioTemporalImageReader reader); /** * Set the {@code rectifiedGrid} metadata element. * * @param reader * the {@link SpatioTemporalImageReader} to be used to set * this metadata element. */ protected abstract void setRectifiedGridElement(SpatioTemporalImageReader reader); /** * Set the {@code bands} metadata element. * * @param reader * the {@link SpatioTemporalImageReader} to be used to set * this metadata element. */ protected abstract void setBandsElement(SpatioTemporalImageReader reader); /** * Utility method which allows to fill Bands attributes using a * {@link BaseImageMetadata} instance obtained from the underlying flat * reader. * * @param band * the {@link Band} metadata object to be set. * @param baseMetadata * a {@link BaseImageMetadata} instance containing the * required values. */ protected static void setBandFromCommonMetadata(Band band, BaseImageMetadata baseMetadata) { if (band == null) throw new IllegalArgumentException("Provided sample dimension to be set is null"); if (baseMetadata != null) { String name = ""; double scale = 1.0; double offset = 0.0; double[] validRange = null; double[] noDataValues = null; try { scale = baseMetadata.getScale(0); offset = baseMetadata.getOffset(0); } catch (IllegalArgumentException iae) { // TODO: no scale and offset are available if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Using default scale and offset values"); } } band.setScale(scale); band.setOffset(offset); try { double max = baseMetadata.getMaximum(0); double min = baseMetadata.getMinimum(0); validRange = new double[] { min, max }; } catch (IllegalArgumentException iae) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("ValidRange values not found"); } } if (validRange != null) { band.setValidRange(validRange[0], validRange[1]); } try { double noData = baseMetadata.getNoDataValue(0); noDataValues = new double[] { noData }; } catch (IllegalArgumentException iae) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("NoData values not found"); } } if (noDataValues != null) { band.setNoDataValues(noDataValues); } name = baseMetadata.getDatasetName(); band.setName(name); } else throw new IllegalArgumentException("Provided metadata object is null"); } /** * Set the TimeExtent sub node of a BoundedBy metadata node * * @param bb * @param timeExtent */ protected static void setTimeExtentNode(final BoundedBy bb, final TemporalObject timeExtent) { if (bb == null) throw new IllegalArgumentException("Provided BoundedBy element is null"); if (timeExtent != null) { if (timeExtent instanceof Period) { Period p = (Period) timeExtent; p.getBeginning().getPosition().getDateTime().toString(); bb.setTemporalExtent(new String[] {p.getBeginning().getPosition().getDateTime().toString(), p.getEnding().getPosition().getDateTime().toString()}); } else if (timeExtent instanceof Instant) { bb.setTemporalExtent(((Instant) timeExtent).getPosition().getDateTime().toString()); } else throw new IllegalArgumentException("Unhandled temporal object: " + timeExtent.getClass().getName()); } else { throw new IllegalArgumentException("Provided TemporalObject is null"); } } }