//
// BaseQuantity.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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 visad;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
/**
* This class represents a base quantity (e.g. "length").
*
* This class is mutable but monotonic: new base quantities can be added but
* not removed.
*/
public final class BaseQuantity
implements Serializable
{
/**
* The name/quantity map-view of the database.
*/
private static final Map nameDB = new TreeMap();
/**
* The alias/quantity map-view of the database.
*/
private static final Map aliasDB = new TreeMap();
/**
* The index/quantity map-view of the database.
*/
private static final AbstractList indexDB = new Vector(8);
/**
* The name of this base quantity.
*/
private final String name;
/**
* The index of this base quantity.
*/
private final int index;
/*
* Initialize the database with standard base quantities.
*/
static
{
try
{
add("electric current",
new String[] {SI.ampere.quantityName(), "current"});
add("luminous intensity", SI.candela.quantityName());
add("thermodynamic temperature",
new String[] {SI.kelvin.quantityName(), "temperature"});
add("mass", SI.kilogram.quantityName());
add("length", SI.meter.quantityName());
add("time", SI.second.quantityName());
add("amount of substance", SI.mole.quantityName());
add("plane angle", new String[] {SI.radian.quantityName(), "angle"});
add("solid angle", SI.steradian.quantityName());
}
catch (VisADException e)
{
/*
* With our godlike powers of observation, we know that this
* VisADException can't occur -- so we ignore it.
*/
}
}
/**
* Construct a base quantity. Private to ensure use of the get...()
* methods.
*
* @param name The name of the base qantity.
*/
private BaseQuantity(String name, int index)
{
this.name = name;
this.index = index;
}
/**
* Add a base quantity to the database.
*
* @param name The name of the base quantity.
* @precondition <code>name</code> isn't already in the database.
* @exception VisADException Attempt to redefine an existing base quantity.
*/
public static synchronized BaseQuantity add(String name)
throws VisADException
{
String key = key(name);
if (nameDB.containsKey(key))
throw new VisADException("Attempt to redefine existing base quantity \"" +
name + "\"");
BaseQuantity q = new BaseQuantity(name, indexDB.size());
nameDB.put(key, q);
indexDB.add(q);
return q;
}
/**
* Add a base quantity with an alias to the database.
*
* @param name The name of the base quantity being added to
* the database (e.g. "plane angle", "foobility").
* @param alias An alias for the base quantity (e.g. "angle").
* @precondition Neither <code>name</code> nor <code>alias</code>
* is in the database.
* @return A reference to the new base quantity in the
* database.
* @exception VisADException Attempt to redefine an existing base quantity
* or alias. If thrown, then the database is
* unmodified.
*/
public static synchronized BaseQuantity add(String name, String alias)
throws VisADException
{
return add(name, new String[] {alias});
}
/**
* Add a base quantity with aliases to the database.
*
* @param name The name of the base quantity being added to
* the database (e.g. "plane angle", "foobility").
* @param aliases Aliases for the base quantity (e.g. "angle").
* @precondition Neither <code>name</code> nor any name in
* <code>aliases</code> is in the database.
* @postcondition <code>size()</code> will return one greater
* than on entry.
* @return A reference to the new base quantity in the
* database.
* @exception VisADException Attempt to redefine an existing base quantity
* or alias. If thrown, then the database is
* unmodified.
*/
public static synchronized BaseQuantity add(String name, String[] aliases)
throws VisADException
{
for (int i = 0; i < aliases.length; ++i)
{
if (aliasDB.containsKey(key(aliases[i])))
throw new VisADException(
"Attempt to redefine existing base quantity alias \"" +
aliases[i] + "\"");
}
BaseQuantity q = add(name);
for (int i = 0; i < aliases.length; ++i)
aliasDB.put(key(aliases[i]), q);
return q;
}
/**
* Convert the given name into a database key.
*
* @param name The name or alias of the base quantity.
* @return The database key.
*/
private static String key(String name)
{
return name.toLowerCase();
}
/**
* Return the number of base qantities in the database.
*
* @return The current number of base quantities in the
* database. This number is strictly monotonic:
* it will increase by one each time a new base
* quantity is added to the database.
*/
public static synchronized int size()
{
return indexDB.size();
}
/**
* Return the name of this base quantity.
*
* @return The name of this base quantity.
*/
public String getName()
{
return name;
}
/**
* Return the index of this base quantity.
*
* @return The index of this base quantity.
*/
public int getIndex()
{
return index;
}
/**
* Retrieve a base quantity from the database based on a
* match of the name.
*
* @param name The name of the base quantity to be retrieved.
* @return The base quantity in the database corresponding
* to <code>name</code> or <code>null</code> if
* no such quantity exists.
*/
public static synchronized BaseQuantity getByName(String name)
{
return (BaseQuantity)nameDB.get(key(name));
}
/**
* Retrieve a base quantity from the database based on a
* match of an alias.
*
* @param name An alias of the base quantity to be retrieved.
* @return The base quantity in the database corresponding
* to <code>name</code> or <code>null</code> if
* no such quantity exists.
*/
public static synchronized BaseQuantity getByAlias(String name)
{
return (BaseQuantity)aliasDB.get(key(name));
}
/**
* Retrieve a base quantity from the database based on a
* match of either the name or an alias. Try the name first.
*
* @param name The name or an alias of the base quantity to
* be retrieved.
* @return The base quantity in the database corresponding
* to <code>name</code> or <code>null</code> if
* no such quantity exists.
*/
public static synchronized BaseQuantity get(String name)
{
BaseQuantity q = getByName(name);
return q != null ? q : getByAlias(name);
}
/**
* Retrieve the base quantity associated with a given index.
*
* @param i The origin-0 index of the base quantity.
* @precondition <code>i >= 0 && i < size()</code>.
* @return The base quantity at index <code>i</code>.
*/
public static BaseQuantity get(int i)
{
return (BaseQuantity)indexDB.get(i);
}
}