//
// QuantityDB.java
//
/*
* Copyright 1998, University Corporation for Atmospheric Research
* See file LICENSE for copying and redistribution conditions.
*
* $Id: QuantityDB.java,v 1.12 2002-09-20 18:15:29 steve Exp $
*/
package visad.data.netcdf;
import java.util.Iterator;
import java.util.NoSuchElementException;
import visad.Unit;
import visad.UnitException;
import visad.VisADException;
import visad.data.units.NoSuchUnitException;
import visad.data.units.ParseException;
import visad.data.units.Parser;
/**
* Provides support for a database of quantities.
*
* @author Steven R. Emmerson
*/
public abstract class
QuantityDB
{
/**
* The empty quantity database. This is useful if, for example, you do
* not want the netCDF import package to map incoming netCDF variables to
* canonical ones by, effectively, altering their names and units. This
* database cannot be altered.
*/
public static final QuantityDB emptyDB;
static {
try {
emptyDB =
new QuantityDB() {
public Quantity get(String name) {
return null;
}
public Quantity[] get(Unit unit) {
return null;
}
public void add(String name, Quantity quantity) {
throw new UnsupportedOperationException();
}
public Iterator quantityIterator() {
return NilIterator.INSTANCE;
}
public Iterator nameIterator() {
return NilIterator.INSTANCE;
}
};
}
catch (Exception ex) {
throw new ExceptionInInitializerError();
}
}
/**
* Returns the quantity in the database whose name matches a
* given name.
*
* @param name The name of the quantity.
* @return The quantity in the loal database that matches
* <code>name</code>. Note that
* RETURN_VALUE<code>.getName().equals(name)</code> can
* be <code>false</code> due to aliasing.
*/
public abstract Quantity
get(String name);
/**
* Returns all quantities in the database whose default unit is
* convertible with a given unit.
*
* @param unit The unit of the quantity.
* @return The quantities in the database whose unit is
* convertible with <code>unit</code>.
*/
public abstract Quantity[]
get(Unit unit);
/**
* Returns the quantity that matches the given name and unit. If
* necessary, it creates the quantity and adds it to the database.
*
* @param name The name of the quantity.
* @param unitSpec The unit of the quantity.
* @return The quantity in the database that matches
* <code>name</code> and <code>unit</code>. Note
* that RETURN_VALUE<code>.getName().equals(name)
* </code> can be <code>false</code> due to
* aliasing and RETURN_VALUE<code>.
* getDefaultUnit().equals(unit)</code> can be
* <code>false</code> due to allowable unit
* conversion.
* @throws ParseException Couldn't decode <code>unitSpec</code>.
* @throws NoSuchUnitException
* <code>unitSpec</code> not in unit database.
* @throws UnitException The quantity already exists with an
* incompatible unit.
* @throws VisADException Couldn't create necessary VisAD object.
*/
public synchronized Quantity
get(String name, String unitSpec)
throws ParseException, NoSuchUnitException, UnitException,
VisADException
{
Quantity quantity = get(name);
if (quantity == null)
{
quantity = new Quantity(name, unitSpec);
add(quantity);
}
else
{
Unit quantityUnit = quantity.getDefaultUnit();
if (!Unit.canConvert(Parser.parse(unitSpec), quantityUnit))
throw new UnitException(
"Quantity " + name + " already exists; its unit " +
quantity.getDefaultUnitString() +
" is inconvertible with " + unitSpec);
}
return quantity;
}
/**
* Adds a given Quantity to the database under a given name.
*
* @param name The name under which the quantity is to be
* added. May be an alias.
* @param quantity The quantity to be added.
* @throws VisADException Couldn't create necessary VisAD object.
*/
public abstract void
add(String name, Quantity quantity)
throws VisADException;
/**
* Adds a given Quantity to the database.
*
* @param quantity The quantity to be added. The quantity will
* be added under it own name.
* @throws VisADException Couldn't create necessary VisAD object.
*/
public void add(Quantity quantity) throws VisADException
{
add(quantity.getName(), quantity);
}
/**
* Returns an iterator of the quantities in the database.
*/
public abstract Iterator
quantityIterator();
/**
* Returns an iterator of the names in the database.
*/
public abstract Iterator
nameIterator();
/**
* A nil {@link Iterator}. Such an {@link Iterator} iterates over nothing.
*/
static class NilIterator implements Iterator {
static final NilIterator INSTANCE;
static {
INSTANCE = new NilIterator();
}
private NilIterator() {
}
/**
* Indicates if another element exists. This implementation always
* returns <code>false</code>.
*
* @return <code>false</code>.
*/
public boolean hasNext() {
return false;
}
/**
* Returns the next element. This implementation always throws a
* {@link NoSuchElementException}.
*
* @throws NoSuchElementException if this method is invoked.
*/
public Object next() {
throw new NoSuchElementException();
}
/**
* Removes the current element. This implementation always throws an
* {@link UnsupportedOperationException}.
*
* @throws UnsupportedOperationException if this method is invoked.
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
}