// $Id: NamedDictionary.java,v 1.4 2002-05-29 18:31:34 steve Exp $ /* * Copyright 1997-2000 Unidata Program Center/University Corporation for * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, * support@unidata.ucar.edu. * * 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 ucar.netcdf; import java.io.Serializable; import java.util.Vector; import java.util.Enumeration; import java.util.Hashtable; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; /** * NamedDictionary is a collection of Named things. * This is used in the implementation of the other netcdf collections. * Note: no public methods, all are package scope or more private. * <p> * It turns out that people think that the order of these things is * important. So, we implement as a Vector, with an aux Hashtable for * lookup by name. * <p> * For serialization, we only put the Vector part over the wire. * The Hashtable is reconstructed at the other end. * In fact, we encode the vector as an array for transport, saving * a few more bytes. * * @author $Author: steve $ * @version $Revision: 1.4 $ */ class NamedDictionary implements Serializable { private void init(Named [] na) { if(na == null) { vector = new Vector(0); } else synchronized (na) { vector = new Vector(na.length); for(int ii = 0; ii < na.length; ii++) { vector.addElement(na[ii]); } } // TODO: Dont use Hashtable unless size is worth it? int size = vector.size(); if(size < 3) size = 3; size *= 4; size /= 3; table = new Hashtable(size, .75f + Float.MIN_VALUE); Enumeration ee = vector.elements(); while ( ee.hasMoreElements() ) { final Named value = (Named) ee.nextElement(); table.put(value.getName(), value); } } NamedDictionary(Named [] na) { init(na); } NamedDictionary(int size, Enumeration ee) { vector = new Vector(size); table = new Hashtable(((size < 3 ? 3 : size) * 4)/3, .75f + Float.MIN_VALUE); while ( ee.hasMoreElements() ) { final Named value = (Named) ee.nextElement(); this.put(value); } } /** */ NamedDictionary(int size) { vector = new Vector(size); table = new Hashtable(((size < 3 ? 3 : size) * 4)/3, .75f + Float.MIN_VALUE); } /** * Returns the number of elements contained within the Dictionary. */ int size() { return vector.size(); } /** * Returns an enumeration of the elements. Use the Enumeration methods * on the returned object to fetch the elements sequentially. * @see java.util.Enumeration */ Enumeration elements() { return vector.elements(); } /** * Gets the object associated with the specified name. * @param name the name of the dimension * @return the dimension, or null if not found * @see NamedDictionary#put */ Named get(String name) { return (Named) table.get(name); } /** * Puts the specified element into the Dictionary, using the its name as * key. The element may be retrieved by doing a get() with the same * name. The element cannot be null. * @param value the specified element * @return the old value of the key, or null if it did not have one. * @exception NullPointerException If the value of the specified * element is null. * @see NamedDictionary#get */ synchronized Named put(Named value) { String name = value.getName(); Named prev = get(name); if (prev != null) vector.remove(prev); vector.addElement(value); return (Named) table.put(name, value); } /** * Removes the element corresponding to the key. Does nothing if the * key is not present. * @param name the name of the Named that needs to be removed * @return the Named, or null if no match. * */ synchronized Named remove(String name) { vector.removeElement(get(name)); return (Named) table.remove(name); } /** * Searches for the specified object, starting from the first position * and returns an index to it. Only used by DimensionDictionary. * @param elem the desired element * @return the index of the element, or -1 if it was not found. */ int indexOf(Named elem) { return vector.indexOf(elem); } /** * Tests if the Named identified by <code>name</code> * is in this set. * @param name String which identifies the desired object * @return <code>true</code> if and only if this set contains * the Named */ boolean contains(String name) { return table.containsKey(name); } /** * Tests if the argument is in this set. * @param oo some Object * @return <code>true</code> if and only if this set contains * <code>oo</code> * TODO? typecheck? */ boolean contains(Object oo) { return table.contains(oo); } private void writeObject(ObjectOutputStream out) throws IOException { final int sz = size(); final Named [] na = new Named[sz]; int ii = 0; Enumeration ee = vector.elements(); while ( ee.hasMoreElements() ) { na[ii++] = (Named) ee.nextElement(); } out.writeObject(na); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { Named [] na = (Named []) in.readObject(); init(na); } private Vector vector; // encoded over the wire as an array. private transient Hashtable table; }