/*
* Copyright 1998, University Corporation for Atmospheric Research
* All Rights Reserved.
* See file LICENSE for copying and redistribution conditions.
*
* $Id: NetcdfAdapter.java,v 1.30 2002-10-21 20:07:46 donm Exp $
*/
package visad.data.netcdf.in;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.IOException;
import java.rmi.RemoteException;
import ucar.netcdf.Netcdf;
import ucar.netcdf.NetcdfFile;
import visad.*;
import visad.data.BadFormException;
import visad.data.netcdf.*;
/**
* <p>A class for importing a netCDF dataset.</p>
*
* <p>This implementation uses a {@link Strategy} for importing netCDF datasets.
* The initial strategy is determined from the Java (not JavaBean) property
* <em>visad.data.netcdf.in.Strategy</em>. If that property is set, then its
* values is used as the name of the initial {@link Strategy} class to use.
* If that property is not set, then the initial strategy is {@link
* Strategy#DEFAULT}. See, however, {@link #setDefaultStrategy(Strategy)}.</p>
*
* @author Steven R. Emmerson
*/
public class
NetcdfAdapter
{
/**
* The name of the import-strategy Java property. (NOTE: A Java property is
* not a JavaBean property.)
*/
public static final String IMPORT_STRATEGY_PROPERTY =
"visad.data.netcdf.in.Strategy";
/**
* The default strategy to use for importing a netCDF dataset.
*/
private static Strategy strategy;
/**
* The view of the netCDF datset.
*/
private View view;
/**
* The top-level VisAD data object corresponding to the netCDF datset.
*/
private DataImpl data;
static {
String strategyName =
System.getProperty(IMPORT_STRATEGY_PROPERTY);
try
{
strategy =
strategyName == null
? Strategy.DEFAULT
: (Strategy)Class.forName(strategyName).getMethod(
"instance", new Class[0])
.invoke(null, new Object[0]);
}
catch (NoSuchMethodException e)
{
throw new Error(
"Import strategy \"" + strategyName + "\" doesn't have an "
+ "\"instance()\" method");
}
catch (ClassNotFoundException e)
{
throw new Error(
"Import strategy \"" + strategyName + "\" not found");
}
catch (IllegalAccessException e)
{
throw new Error(
"Permission to access import strategy \"" + strategyName +
"\" denied");
}
catch (java.lang.reflect.InvocationTargetException e)
{
throw new Error(
"Import strategy's \"" +
strategyName + "\" \"instance()\" method threw exception: "
+ e.getMessage());
}
}
/**
* Constructs from a netCDF dataset.
*
* @param netcdf The netCDF dataset to be adapted.
* @param quantityDB A quantity database to be used to map netCDF
* variables to VisAD {@link Quantity}s.
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws RemoteException Remote data access failure.
* @throws IOException Data access I/O failure.
* @throws BadFormException Non-conforming netCDF dataset.
*/
public
NetcdfAdapter(Netcdf netcdf, QuantityDB quantityDB)
throws VisADException, RemoteException, IOException, BadFormException
{
this(netcdf, quantityDB, false);
}
/**
* Constructs from a netCDF dataset.
*
* @param netcdf The netCDF dataset to be adapted.
* @param quantityDB A quantity database to be used to map netCDF
* variables to VisAD {@link Quantity}s.
* @param charToText Specifies whether the NetcdfAdapter should
* map char variables to VisAD Text objects
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws RemoteException Remote data access failure.
* @throws IOException Data access I/O failure.
* @throws BadFormException Non-conforming netCDF dataset.
*/
public
NetcdfAdapter(Netcdf netcdf, QuantityDB quantityDB, boolean charToText)
throws VisADException, RemoteException, IOException, BadFormException
{
this(View.getInstance(netcdf, quantityDB, charToText));
}
/**
* Constructs from a view of a netCDF dataset.
*
* @param view The view of the netCDF dataset to be adapted.
*/
public
NetcdfAdapter(View view)
{
this.view = view;
}
/**
* Sets the default strategy used to import a netCDF dataset. Subsequent
* use of the {@link #getData()} method will use the given strategy.
*
* @param strategy The default strategy to use.
* @return The previous strategy.
* @throws NullPointerException if the strategy is <code>null</code>.
*/
public static synchronized Strategy setDefaultStrategy(Strategy strategy) {
if (strategy == null)
throw new NullPointerException();
Strategy prev = NetcdfAdapter.strategy;
NetcdfAdapter.strategy = strategy;
return prev;
}
/**
* Returns the default strategy used to import a netCDF dataset.
*
* @return The default strategy.
*/
public static synchronized Strategy getDefaultStrategy() {
return strategy;
}
/**
* <p>Gets the VisAD data object corresponding to the netCDF dataset. This
* is a potentially expensive method in either time or space.</p>
*
* <p>This implementation invokes method {@link #getData(Strategy)} with the
* default {@link Strategy}.</p>
*
* @return The top-level, VisAD data object in the netCDF
* dataset.
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws IOException Data access I/O failure.
* @throws BadFormException netCDF dataset doesn't conform to conventions
* implicit in the View that was passed to the
* constructor.
* @throws OutOfMemoryError Couldn't read netCDF dataset into memory.
* @throws RemoteException if a Java RMI failure occurs.
* @see #getData(Strategy)
*/
public synchronized DataImpl getData()
throws IOException, VisADException, RemoteException, BadFormException,
OutOfMemoryError
{
synchronized(getClass()) {
return getData(strategy);
}
}
/**
* Gets the VisAD data object corresponding to the netCDF dataset using a
* given strategy. This is a potentially expensive method in either time or
* space.</p>
*
* @param strategy The strategy to use for importing the data.
* @return The top-level, VisAD data object in the netCDF
* dataset.
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws IOException Data access I/O failure.
* @throws BadFormException netCDF dataset doesn't conform to conventions
* implicit in the View that was passed to the
* constructor.
* @throws OutOfMemoryError Couldn't read netCDF dataset into memory.
* @throws RemoteException if a Java RMI failure occurs.
*/
public synchronized DataImpl getData(Strategy strategy)
throws IOException, VisADException, RemoteException, BadFormException,
OutOfMemoryError
{
if (data == null)
{
synchronized(getClass()) {
data = strategy.getData(this);
}
}
return data;
}
/**
* Returns a proxy for the VisAD data object corresponding to the netCDF
* dataset. Because of the way import strategies are used, this just
* invokes the <em>getData()</em> method.
*
* @return A proxy for the top-level, VisAD data object in
* the netCDF dataset.
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws IOException Data access I/O failure.
* @throws BadFormException netCDF dataset doesn't conform to conventions
* implicit in constructing View.
* @throws OutOfMemoryError Couldn't read netCDF dataset into memory.
* @throws RemoteException if a Java RMI failure occurs.
* @see Strategy#getData
*/
public DataImpl
getProxy()
throws IOException, VisADException, RemoteException, BadFormException,
OutOfMemoryError
{
return getData();
}
/**
* Returns the VisAD data object corresponding to the netCDF dataset. This
* is a potentially expensive method in either time or space. This method
* is designed to be used by a <em>Strategy</em>.
*
* @param view The view of the netCDF dataset.
* @param merger The object that merges the data objects in the
* netCDF dataset.
* @param dataFactory The factory that creates VisAD data objects from
* virtual data objects.
* @return The VisAD data object corresponding to the
* netCDF dataset.
* @throws VisADException Problem in core VisAD. Probably some VisAD
* object couldn't be created.
* @throws IOException Data access I/O failure.
* @throws BadFormException netCDF dataset doesn't conform to conventions
* implicit in constructing View.
* @throws OutOfMemoryError Couldn't read netCDF dataset into memory.
* @throws RemoteException if a Java RMI failure occurs.
* @see Strategy
*/
protected static DataImpl
importData(View view, Merger merger, DataFactory dataFactory)
throws IOException, VisADException, RemoteException, BadFormException,
OutOfMemoryError
{
VirtualTuple topTuple = new VirtualTuple();
for (VirtualDataIterator iter = view.getVirtualDataIterator();
iter.hasNext(); )
{
merger.merge(topTuple, iter.next());
}
topTuple.setDataFactory(dataFactory);
return topTuple.getData();
}
/**
* Gets the view of the netCDF dataset.
*
* @return The view of the netCDF dataset.
*/
protected View
getView()
{
return view;
}
/**
* Tests this class.
*
* @param args File pathnames.
* @throws Exception Something went wrong.
*/
public static void
main(String[] args)
throws Exception
{
String[] pathnames;
if (args.length == 0)
pathnames = new String[] {"test.nc"};
else
pathnames = args;
for (int i = 0; i < pathnames.length; ++i)
{
NetcdfFile file;
try
{
URL url = new URL(pathnames[i]);
file = new NetcdfFile(url);
}
catch (MalformedURLException e)
{
file = new NetcdfFile(pathnames[i], /*readonly=*/true);
}
NetcdfAdapter adapter =
new NetcdfAdapter(file, QuantityDBManager.instance());
DataImpl data = adapter.getData();
System.out.println("data.getClass().getName() = " +
data.getClass().getName());
System.out.println("data.getType().prettyString():\n" +
data.getType().prettyString());
// System.out.println("Domain set:\n" +
// ((FieldImpl)data).getDomainSet());
// System.out.println("Data:\n" + data);
}
}
}