/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 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.image.io.text;
import org.geotools.image.io.metadata.GeographicMetadata;
import org.geotools.image.io.metadata.ImageGeometry;
import org.geotools.image.io.metadata.ImageReferencing;
import org.geotools.referencing.factory.ReferencingFactoryContainer;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
/**
* Default implementation of the {@link TextMetadataParser} class, providing a method
* to put all metadata read from a text into the tree model. This current implementation
* uses the tree structure which matches approximatively with the
* <a href="http://www.opengeospatial.org/standards/gmljp2">GML in JPEG 2000</a> standard.
*
* @since 2.5
* @source $URL$
* @version $Id$
* @author Cédric Briançon
*/
public class DefaultTextMetadataParser extends TextMetadataParser {
/**
* The unit for coordinate axes.
*/
private String unit;
/**
* The name for the {@link CoordinateReferenceSystem coordinate reference system}.
*/
private String crs_name;
/**
* The type for the {@link CoordinateReferenceSystem coordinate reference system}.
*/
private String crs_type;
/**
* The name for the {@link CoordinateSystem coordinate system}.
*/
private String cs_name;
/**
* The type for the {@link CoordinateSystem coordinate system}.
*/
private String cs_type;
/**
* The axis direction along the X axis.
*/
private String xdir;
/**
* The axis direction along the Y axis.
*/
private String ydir;
/**
* The axis direction along the Z axis.
*/
private String zdir;
/**
* The minimum value for the X ordinate.
*/
private double xmin;
/**
* The maximum value for the X ordinate.
*/
private double xmax;
/**
* The minimum value for the Y ordinate.
*/
private double ymin;
/**
* The maximum value for the Y ordinate.
*/
private double ymax;
/**
* The minimum value for the Z ordinate.
*/
private double zmin;
/**
* The maximum value for the Z ordinate.
*/
private double zmax;
/**
* The X resolution.
*/
private double xres;
/**
* The Y resolution.
*/
private double yres;
/**
* The Z resolution.
*/
private double zres;
/**
* Creates a new instance of {@link TextMetadataParser}, with default factories.
*/
public DefaultTextMetadataParser() {
super();
}
/**
* Creates a new instance of {@link TextMetadataParser}, with the factories specified.
*
* @param factories The factories to use.
*/
public DefaultTextMetadataParser(final ReferencingFactoryContainer factories) {
super(factories);
}
/**
* {@inheritDoc}
*/
protected void put(final Key key, final Object value) {
final ImageGeometry geometry = metadata.getGeometry();
final ImageReferencing referencing = metadata.getReferencing();
/* Verifies if a unit has already been specified, and if not, applied it
* to every axes already defined.
*/
if (key.equals(UNIT) && value instanceof String) {
unit = (String) value;
return;
}
/* Fills the matching variable for ordinates with values given.
*/
if (key.equals(X_MINIMUM)) {
xmin = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Y_MINIMUM)) {
ymin = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Z_MINIMUM)) {
zmin = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(X_MAXIMUM)) {
xmax = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Y_MAXIMUM)) {
ymax = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Z_MAXIMUM)) {
zmax = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
/*
*/
if (key.equals(WIDTH)) {
geometry.setGridRange(0, 0, Integer.parseInt((String) value));
return;
}
if (key.equals(HEIGHT)) {
geometry.setGridRange(1, 0, Integer.parseInt((String) value));
return;
}
if (key.equals(DEPTH)) {
geometry.setGridRange(2, 0, Integer.parseInt((String) value));
return;
}
/* Fills the matching varaible for the offset vector.
*/
if (key.equals(X_RESOLUTION)) {
xres = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Y_RESOLUTION)) {
yres = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
if (key.equals(Z_RESOLUTION)) {
zres = (value instanceof Double) ? (Double) value : Double.parseDouble((String) value);
return;
}
/**
* Fills the direction for the axes.
*/
if (key.equals(X_DIRECTION) && value instanceof String) {
xdir = (String) value;
return;
}
if (key.equals(Y_DIRECTION) && value instanceof String) {
ydir = (String) value;
return;
}
if (key.equals(Z_DIRECTION) && value instanceof String) {
zdir = (String) value;
return;
}
/* Specifies the projection and datum name.
*/
if (key.equals(PROJECTION) && value instanceof String) {
referencing.setProjectionName((String) value);
return;
}
if (key.equals(DATUM) && value instanceof String) {
/* @todo: handle the datum type, here one puts null for the type, but maybe a new key
* can contain this information.
*/
referencing.setDatum((String) value, null);
return;
}
if (key.equals(PRIME_MERIDIAN) && value instanceof String) {
referencing.setPrimeMeridianName((String) value);
return;
}
if (key.equals(GREENWICH_LONGITUDE)) {
referencing.setPrimeMeridianGreenwichLongitude((value instanceof Double) ?
(Double) value : Double.parseDouble((String) value));
return;
}
/* Specifies the ellipsoid value.
*/
if (key.equals(ELLIPSOID) && value instanceof String) {
referencing.setEllipsoidName((String) value);
return;
}
if (key.equals(ELLIPSOID_UNIT) && value instanceof String) {
referencing.setEllipsoidUnit((String) value);
return;
}
if (key.equals(SEMI_MAJOR)) {
if (value instanceof Double) {
referencing.setSemiMajorAxis((Double) value);
} else {
referencing.setSemiMajorAxis(Double.parseDouble((String) value));
}
return;
}
if (key.equals(SEMI_MINOR)) {
if (value instanceof Double) {
referencing.setSemiMinorAxis((Double) value);
} else {
referencing.setSemiMinorAxis(Double.parseDouble((String) value));
}
return;
}
if (key.equals(INVERSE_FLATTENING)) {
if (value instanceof Double) {
referencing.setInverseFlattening((Double) value);
} else {
referencing.setInverseFlattening(Double.parseDouble((String) value));
}
return;
}
/* CoordinateReferenceSystem value.
*/
if (key.equals(COORDINATE_REFERENCE_SYSTEM_TYPE) && value instanceof String) {
crs_type = (String) value;
return;
}
if (key.equals(COORDINATE_REFERENCE_SYSTEM) && value instanceof String) {
crs_name = (String) value;
return;
}
if (key.equals(COORDINATE_SYSTEM_TYPE) && value instanceof String) {
cs_type = (String) value;
return;
}
if (key.equals(COORDINATE_SYSTEM) && value instanceof String) {
cs_name = (String) value;
return;
}
/* Adds parameters using values found among these keys.
*/
if (key.equals(CENTRAL_MERIDIAN) || key.equals(FALSE_EASTING) ||
key.equals(FALSE_NORTHING) || key.equals(LATITUDE_OF_ORIGIN))
{
if (value instanceof Double) {
referencing.addParameter(key.toString(), (Double) value);
} else {
referencing.addParameter(key.toString(), Double.parseDouble((String) value));
}
return;
}
}
/**
* {@inheritDoc}
*/
protected void putDone() {
final ImageGeometry geometry = metadata.getGeometry();
final ImageReferencing referencing = metadata.getReferencing();
if (!Double.isNaN(xmin) && !Double.isNaN(xmax)) {
geometry.setOrdinateRange(0, xmin, xmax);
referencing.addAxis(null, xdir, unit);
}
if (!Double.isNaN(ymin) && !Double.isNaN(ymax)) {
geometry.setOrdinateRange(1, ymin, ymax);
referencing.addAxis(null, ydir, unit);
}
if (!Double.isNaN(zmin) && !Double.isNaN(zmax)) {
geometry.setOrdinateRange(2, zmin, zmax);
referencing.addAxis(null, zdir, unit);
}
final int dimension = referencing.getDimension();
/* Create an array of offset vectors with the value stored in the specified dimension.
* For example, if we are in a 2D system, offset vector will be like :
* offsetVector[0] : ||x|| 0
* offsetVector[1] : 0 ||y||
* This process assumes that the grid is straight, meaning the offset vector
* in the X ordinate have a value only in the X direction.
*/
final double[] offsetVector = new double[dimension];
if (!Double.isNaN(xres) && dimension > 0) {
offsetVector[0] = xres;
geometry.addOffsetVector(offsetVector);
offsetVector[0] = 0;
}
if (!Double.isNaN(yres) && dimension > 1) {
offsetVector[1] = yres;
geometry.addOffsetVector(offsetVector);
offsetVector[1] = 0;
}
if (!Double.isNaN(zres) && dimension > 2) {
offsetVector[2] = zres;
geometry.addOffsetVector(offsetVector);
offsetVector[2] = 0;
}
/* CoordinateReferenceSystem information.
*/
if (crs_name != null || crs_type != null) {
referencing.setCoordinateReferenceSystem(crs_name, crs_type);
}
if (cs_name != null || cs_type != null) {
referencing.setCoordinateSystem(cs_name, cs_type);
}
}
/**
* Sets the geographic metadata and put all other variables to their default value.
* This method should have been called before the {@link #put} and {@link #putDone}
* one.
*/
@Override
public void setGeographicMetadata(final GeographicMetadata metadata) {
super.setGeographicMetadata(metadata);
xmin = Double.NaN; xmax = Double.NaN; xres = Double.NaN; xdir = null;
ymin = Double.NaN; ymax = Double.NaN; yres = Double.NaN; ydir = null;
zmin = Double.NaN; zmax = Double.NaN; zres = Double.NaN; zdir = null;
unit = null; crs_type = null; crs_name = null;
cs_type = null; cs_name = null;
}
}