/*
* Geotools 2 - OpenSource mapping toolkit
* (C) 2003, Geotools Project Management Committee (PMC)
* (C) 2002, Institut de Recherche pour le Développement
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.geotools.cv;
// J2SE dependencies
import java.awt.Color;
import java.lang.ref.Reference;
import java.rmi.RemoteException;
import java.util.Locale;
import javax.media.jai.PropertySource;
import org.geotools.pt.CoordinatePoint;
import org.geotools.pt.Envelope;
import org.geotools.resources.RemoteProxy;
import org.geotools.resources.i18n.ErrorKeys;
import org.geotools.resources.i18n.Errors;
import org.geotools.units.Unit;
import org.opengis.coverage.CannotEvaluateException;
import org.opengis.cv.CV_ColorInterpretation;
import org.opengis.cv.CV_Coverage;
import org.opengis.cv.CV_PaletteInterpretation;
import org.opengis.cv.CV_SampleDimension;
import org.opengis.cv.CV_SampleDimensionType;
/**
* Provide methods for interoperability with OpenGIS CV package.
* All methods accept null argument. This class has no default instance, since the
* {@link org.geotools.gp.Adapters org.geotools.gp.Adapters}
* implementation cover this case.
*
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux
*
* @see org.geotools.gp.Adapters#getDefault()
*
* @deprecated The legacy OpenGIS CV package is deprecated.
* There is no replacement at this time for RMI objects.
*/
public class Adapters {
/**
* The adapters from Coordinate Transformation Services
* (package org.geotools.ct
).
*/
public final org.geotools.ct.Adapters CTS;
/**
* Default constructor. A shared instance of Adapters
can
* be obtained with {@link org.geotools.gp.Adapters#getDefault()}.
*
* @param CTS The adapters from Coordinate Transformation Services
* (package org.geotools.ct
).
*/
protected Adapters(final org.geotools.ct.Adapters CTS) {
this.CTS = CTS;
}
/**
* Returns an OpenGIS enumeration for a color interpretation.
*
* @param colors The Geotools object.
* @return The OpenGIS object.
*/
public CV_ColorInterpretation export(final ColorInterpretation colors) {
if (colors == null) {
return null;
}
return new CV_ColorInterpretation(colors.getValue());
}
/**
* Returns an OpenGIS enumeration for a color interpretation.
*
* @param type The Geotools object.
* @return The OpenGIS object.
*/
public CV_SampleDimensionType export(final SampleDimensionType type) {
if (type == null) {
return null;
}
return new CV_SampleDimensionType(type.getValue());
}
/**
* Returns an OpenGIS interface for a sample dimension.
*
* @param dimension The Geotools object.
* @return The OpenGIS object.
* @throws RemoteException if the OpenGIS object can't be exported.
*/
public CV_SampleDimension export(final SampleDimension dimension) throws RemoteException {
if (dimension == null) {
return null;
}
return (CV_SampleDimension) dimension.toOpenGIS(this);
}
/**
* Returns an OpenGIS interface for a coverage.
*
* @param coverage The Geotools object.
* @return The OpenGIS object.
* @throws RemoteException if the OpenGIS object can't be exported.
*/
public CV_Coverage export(final Coverage coverage) throws RemoteException {
if (coverage == null) {
return null;
}
Object proxy = coverage.proxy;
if (proxy instanceof Reference) {
proxy = ((Reference) proxy).get();
}
if (proxy != null) {
return (CV_Coverage) proxy;
}
return doExport(coverage);
}
/**
* Performs the wrapping of a Geotools object. This method is invoked by
* {@link #export(Coverage)} if an OpenGIS object is not already presents
* in the cache. Subclasses should override this method instead of
* {@link #export(Coverage)}.
*
* @param coverage The Geotools object.
* @return The OpenGIS object.
* @throws RemoteException if the OpenGIS object can't be exported.
*/
protected CV_Coverage doExport(final Coverage coverage) throws RemoteException {
return coverage.new Export(this);
}
/**
* Returns a color interpretation from an OpenGIS's enumeration.
*
* @param colors The OpenGIS object.
* @return The Geotools object.
*/
public ColorInterpretation wrap(final CV_ColorInterpretation colors) {
return (colors!=null) ? ColorInterpretation.getEnum(colors.value) : null;
}
/**
* Returns a sample type from an OpenGIS's enumeration.
*
* @param type The OpenGIS object.
* @return The Geotools object.
*/
public SampleDimensionType wrap(final CV_SampleDimensionType type) {
return (type!=null) ? SampleDimensionType.getEnum(type.value) : null;
}
/**
* Returns a sample dimension from an OpenGIS's interface.
*
* @param sd The OpenGIS object.
* @return The Geotools object.
* @throws RemoteException if an operation failed while querying the OpenGIS object.
*/
public SampleDimension wrap(final CV_SampleDimension sd) throws RemoteException {
if (sd == null) {
return null;
}
if (sd instanceof RemoteProxy) {
return (SampleDimension) ((RemoteProxy) sd).getImplementation();
}
return doWrap(sd);
}
/**
* Returns a sample dimension from an OpenGIS's interface. This implementation is made
* available separatly from {@link #wrap(CV_SampleDimension)} in order to allow tests
* with JUnit.
*
* @param sd The OpenGIS object.
* @return The Geotools object.
* @throws RemoteException if an operation failed while querying the OpenGIS object.
*/
final SampleDimension doWrap(final CV_SampleDimension sd) throws RemoteException {
if (sd.getPaletteInterpretation().value != CV_PaletteInterpretation.CV_RGB) {
throw new UnsupportedOperationException("Not yet implemented");
}
String description = sd.getDescription();
SampleDimensionType type = SampleDimensionType.getEnum(sd.getSampleDimensionType().value);
ColorInterpretation color = ColorInterpretation.getEnum(sd.getColorInterpretation().value);
int[][] palette = sd.getPalette();
String[] categories = sd.getCategoryNames();
double[] nodata = sd.getNoDataValue();
double minimum = sd.getMinimumValue();
double maximum = sd.getMaximumValue();
double scale = sd.getScale();
double offset = sd.getOffset();
Unit units = CTS.wrap(sd.getUnits());
Color[] colors = null;
if (palette != null) {
colors = new Color[palette.length];
for (int i=0; iand this
* Adapters
is an instance of the {@link org.geotools.gc.Adapters
* org.geotools.gc.Adapters} class, then the returned coverage
* implementation will be an instance of {@link org.geotools.gc.GridCoverage}.
*
* @param coverage The OpenGIS object.
* @return The Geotools object.
* @throws RemoteException if an operation failed while querying the OpenGIS object.
*/
public Coverage wrap(final CV_Coverage coverage) throws RemoteException {
if (coverage == null) {
return null;
}
if (coverage instanceof Coverage.Export) {
return ((Coverage.Export) coverage).getImplementation();
}
final Coverage wrapped = doWrap(coverage);
wrapped.proxy = coverage;
return wrapped;
}
/**
* Performs the wrapping of an OpenGIS's interface. This method is invoked by
* {@link #wrap(CV_Coverage)} if a Geotools object is not already presents in
* the cache. Subclasses should override this method instead of
* {@link #wrap(CV_Coverage)}.
*
* @param coverage The OpenGIS object.
* @return The Geotools object.
* @throws RemoteException if an operation failed while querying the OpenGIS object.
*/
protected Coverage doWrap(final CV_Coverage coverage) throws RemoteException {
try {
return new CoverageProxy(coverage);
} catch (RuntimeException exception) {
final Throwable cause = exception.getCause();
if (cause instanceof RemoteException) {
// May occurs when the PropertySourceImpl constructor
// fetch values from the CoverageProperties adapter.
throw (RemoteException) cause;
}
throw exception;
}
}
/**
* Returns the {@link PropertySource} for the specified OpenGIS's coverage. If the
* specified coverage already implements {@link PropertySource}, then it is returned.
* Otherwise, the coverage is wrapped in an object with the following behaviour:
*
* - {@link PropertySource#getPropertyNames()} delegates to
* {@link CV_Coverage#getMetadataNames()}.
* - {@link PropertySource#getProperty(String)} delegates to
* {@link CV_Coverage#getMetadataValue(String)}.
* - If a checked {@link RemoteException} is thrown, it is
* wrapped in an unchecked {@link CannotEvaluateException}.
*
*
* @param coverage The OpenGIS coverage.
* @return The property source for the specified coverage.
*/
protected PropertySource getPropertySource(final CV_Coverage coverage) {
if (coverage == null) {
return null;
}
if (coverage instanceof PropertySource) {
return (PropertySource) coverage;
}
return new CoverageProperties(coverage);
}
/**
* An adapter class for {@link CV_Coverage}. Every call to an evaluate
* method is delegates to the underlying {@link CV_Coverage}, which may be executed
* on a remote machine. {@link RemoteException} are catched and rethrown as a
* {@link CannotEvaluateException}.
*
* @version $Id$
* @author Martin Desruisseaux
*/
private final class CoverageProxy extends Coverage {
/**
* The wrapped OpenGIS coverage. This reference
* must be the same than {@link Coverage#proxy}.
*/
private final CV_Coverage coverage;
/**
* The bounding box for the coverage domain in coordinate system coordinates.
*/
private final Envelope envelope;
/**
* The names of each dimension in this coverage.
*/
private final String[] dimensionNames;
/**
* The sample dimensions for this coverage.
* Will be fetch only when first requested.
*/
private SampleDimension[] dimensions;
/**
* Construct a new coverage wrapping the specified OpenGIS object.
*
* @param coverage The OpenGIS coverage.
* @throws RemoteException if a remote call failed.
* @throws CannotEvaluateException if the construction failed for some other reason.
* The cause for this exception may be a {@link RemoteException}. Callers
* should check the cause and throw the underlying {@link RemoteException}
* if applicable.
*/
CoverageProxy(CV_Coverage coverage) throws RemoteException {
super(null, CTS.wrap(coverage.getCoordinateSystem()), getPropertySource(coverage), null);
this.coverage = coverage;
this.proxy = coverage;
this.envelope = CTS.wrap(coverage.getEnvelope());
dimensionNames = coverage.getDimensionNames();
}
/**
* Returns the bounding box for the coverage domain in coordinate system coordinates.
*/
public Envelope getEnvelope() {
return (Envelope) envelope.clone();
}
/**
* Returns the names of each dimension in this coverage.
*/
public String[] getDimensionNames(final Locale locale) {
return (String[]) dimensionNames.clone();
}
/**
* Retrieve sample dimension information for the coverage.
*/
public synchronized SampleDimension[] getSampleDimensions() {
if (dimensions == null) try {
dimensions = new SampleDimension[coverage.getNumSampleDimensions()];
for (int i=0; i