ucar.units.UnitDBImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.units;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* Provides most of a concrete implementation of a database of units.
*
* @author Steven R. Emmerson
*/
public class UnitDBImpl implements UnitDB, Serializable {
private static final long serialVersionUID = 1L;
/**
* The set of units.
*
* @serial
*/
private final Set unitSet;
/**
* The name-to-unit map.
*
* @serial
*/
private final Map nameMap;
/**
* The symbol-to-unit map.
*
* @serial
*/
private final Map symbolMap;
/**
* Constructs from the expected number of names and symbols. The sizes will
* be used to construct the initial database but will not limit its growth.
*
* @param nameCount
* The expected number of names (including plurals and aliases).
* @param symbolCount
* The expected number of symbols.
*/
protected UnitDBImpl(final int nameCount, final int symbolCount) {
unitSet = new TreeSet<>((obj1, obj2) -> (obj1).getName().compareTo((obj2).getName()));
nameMap = new Hashtable<>(nameCount + 1);
symbolMap = new Hashtable<>(symbolCount + 1);
}
/**
* Adds all the entries in another UnitDBImpl to this database.
*
* @param that
* The other UnitDBImpl.
* @throws UnitExistsException
* Attempt to redefine an existing entry.
*/
public void add(final UnitDBImpl that) throws UnitExistsException {
unitSet.addAll(that.unitSet);
nameMap.putAll(that.nameMap);
symbolMap.putAll(that.symbolMap);
}
/**
* Return the number of names in this database
*
* @return The total number of names, plurals, and aliases.
*/
public int nameCount() {
return nameMap.size();
}
/**
* Return the number of symbols in this database.
*
* @return The number of symbols in this database.
*/
public int symbolCount() {
return symbolMap.size();
}
/**
* Adds a unit to the database.
*
* @param unit
* The unit to be added.
* @throws UnitExistsException
* Another unit with the same name or symbol already exists in
* the database.
* @throws NameException
* Bad unit name.
*/
public void addUnit(final Unit unit) throws UnitExistsException, NameException {
if (unit.getName() == null) {
throw new NameException("Unit name can't be null");
}
addByName(unit.getName(), unit);
addByName(unit.getPlural(), unit);
addBySymbol(unit.getSymbol(), unit);
unitSet.add(unit);
}
/**
* Adds an alias for a unit already in the database.
*
* @param alias
* An alias for the unit.
* @param name
* The name of the unit already in the database.
* @throws UnitExistsException
* Another unit with the same name or symbol already exists in
* the database.
* @throws NoSuchUnitException
* The unit isn't in the database.
*/
public final void addAlias(final String alias, final String name) throws NoSuchUnitException, UnitExistsException {
addAlias(alias, name, null);
}
/**
* Adds an alias for a unit already in the database.
*
* @param alias
* An alias for the unit.
* @param name
* The name of the unit already in the database.
* @param symbol
* The symbol for the unit.
* @throws UnitExistsException
* Another unit with the same name or symbol already exists in
* the database.
* @throws NoSuchUnitException
* The unit isn't in the database.
*/
public final void addAlias(final String alias, final String name, final String symbol)
throws NoSuchUnitException, UnitExistsException {
addAlias(alias, name, symbol, null);
}
/**
* Adds a symbol for a unit already in the database.
*
* @param symbol
* The symbol for the unit.
* @param name
* The name of the unit already in the database.
* @throws UnitExistsException
* Another unit with the same name or symbol already exists in
* the database.
* @throws NoSuchUnitException
* The unit isn't in the database.
*/
public final void addSymbol(final String symbol, final String name) throws NoSuchUnitException, UnitExistsException {
addAlias(null, name, symbol, null);
}
/**
* Adds an alias for a unit already in the database.
*
* @param alias
* The alias to be added to the database. May be null.
* @param name
* The name of the unit to have an alias added to the database.
* @param symbol
* The symbol to be added. May be null.
* @param plural
* The plural form of the alias. If null
*
, then regular
* plural-forming rules are followed.
* @throws NoSuchUnitException
* The unit is not in the database.
* @throws UnitExistsException
* Another unit with the same alias is already in the database.
*/
public final void addAlias(final String alias, final String name, final String symbol, final String plural)
throws NoSuchUnitException, UnitExistsException {
addAlias(UnitID.newUnitID(alias, plural, symbol), name);
}
/**
* Adds an alias for a unit already in the database.
*
* @param alias
* The alias to be added to the database.
* @param name
* The name of the unit to have an alias added to the database.
* @throws NoSuchUnitException
* The unit is not in the database.
* @throws UnitExistsException
* Another unit with the same alias is already in the database.
*/
public final void addAlias(final UnitID alias, final String name) throws NoSuchUnitException, UnitExistsException {
final Unit unit = getByName(name);
if (unit == null) {
throw new NoSuchUnitException(name);
}
addByName(alias.getName(), unit);
addByName(alias.getPlural(), unit);
addBySymbol(alias.getSymbol(), unit);
}
/**
* Gets a unit by either name, plural, or symbol. Retrieving the unit by
* symbol is attempted before retrieving the unit by name because symbol
* comparisons are case sensitive and, hence, should be more robust.
*
* @param id
* The id to be matched.
* @return The unit whose name, plural, or symbol matches or
* null
if no such unit was found.
*/
public Unit get(final String id) {
Unit unit = getBySymbol(id);
if (unit == null) {
unit = getByName(id);
}
return unit;
}
/**
* Gets a unit by name.
*
* @param name
* The name to be matched.
* @return The unit whose name, plural, or alias matches or
* null
if no such unit was found.
*/
public Unit getByName(final String name) {
return nameMap.get(canonicalize(name));
}
/**
* Returns the canonical form of a unit name.
*
* @param name
* A unit name.
* @return The canonical form of the name.
*/
private static String canonicalize(final String name) {
return name.toLowerCase().replace(' ', '_');
}
/**
* Gets a unit by symbol.
*
* @param symbol
* The symbol to be matched.
* @return The unit whose symbol matches or null
*
if no such unit was
* found.
*/
public Unit getBySymbol(final String symbol) {
return symbolMap.get(symbol);
}
/**
* Returns the string representation of this database.
*
* @return The string representation of this database.
*/
@Override
public String toString() {
return unitSet.toString();
}
/**
* Gets an iterator over the units in the database.
*
* @return An iterator over the units in the database. The iterator's
* next()
method returns objects of type
* Unit
.
*/
public final Iterator getIterator() {
return unitSet.iterator();
}
/**
* Adds a unit to the database by name.
*
* @param name
* The name of the unit. If null
then the unit is
* not added.
* @param newUnit
* The unit to be added.
* @throws UnitExistsException
* Attempt to redefine an existing unit.
*/
private void addByName(final String name, final Unit newUnit) throws UnitExistsException {
if (name != null) {
addUnique(nameMap, canonicalize(name), newUnit);
}
}
/**
* Adds a unit to the database by symbol.
*
* @param symbol
* The symbol for the unit. If null
then the unit is
* not added.
* @param newUnit
* The unit to be added.
* @throws UnitExistsException
* Attempt to redefine an existing unit.
*/
private void addBySymbol(final String symbol, final Unit newUnit) throws UnitExistsException {
if (symbol != null) {
addUnique(symbolMap, symbol, newUnit);
}
}
/**
* Adds a unique unit to a map..
*
* @param map
* The map to be added to.
* @param key
* The key for the unit entry.
* @param newUnit
* The unit to be added.
* @throws UnitExistsException
* Attempt to redefine an existing unit.
*/
private static void addUnique(final Map map, final String key, final Unit newUnit)
throws UnitExistsException {
final Unit oldUnit = map.put(key, newUnit);
if (oldUnit != null && !oldUnit.equals(newUnit)) {
throw new UnitExistsException(oldUnit, newUnit);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy