/* XBN Java: Generically useful, non-GUI Java code. http://sourceforge.net/projects/xbnjava Copyright (C) 1997-2003, Jeff Epstein All rights reserved. Modifications: No Redistribution in binary form, with or without modifications, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * If modifications are made to source code then this license should indicate that fact in the "Modifications" section above. * Neither the author, nor the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [NOTE: This license contains NO advertising clause.] */ package xbn.named; import xbn.XBNObject; /**

A manual implementation of NamedArray. Where the heart of a NamedArray is an AOSLookup, the heart of ManualNamedArray is a plain array of Named objects.

Source code:  ManualNamedArray.java

Don't use this when speed and efficiency are critical. Do use this when you must not be dependent on the xbn.named (and other fundamental) classes. ManualNamedArray is intended for use in objects that cannot depend on NamedArray (to avoid circular dependencies), but need most of it's functionality.

@version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public class ManualNamedArray extends XBNObject { private Named[] aNamed = null; private static final String sRULE = "a_named must be non null, at least one element in length, no element may be null, and all names must be non-null and unique. "; /**

Create a ManualNamedArray.

Equal to ManualNamedArray(a_named, false)

**/ public ManualNamedArray(Named[] a_named) { this(a_named, false); } /**

Create a ManualNamedArray.

@param a_named The array of Named objects. May not be null, zero elements in length, and every element must be non null, and have unique names. @param b_lock Should direct access be allowed to a_named? If true, then yes. If false, no. See getAONamed, add, addOrReplace and replace. **/ public ManualNamedArray(Named[] a_named, boolean b_lock) { throwAXIfNull(a_named, "a_named", sCNSTR); if(a_named.length < 1) { throwAX("constructor: a_named may not be less than one element in length."); } //This is manually checked, instead of using UAString, //because CmdLineInts depends this class. Since we want //to use CmdLineInts in all the testing classes, we //don't want this to depend on much else...otherwise we'd //have to manually code in the testing classes for the //functionality CmdLineInts gives us. for(int i = 0; i < a_named.length; i++) { if(a_named[i] == null) { throwAX("constructor: a_named[" + i + "] is null."); } for(int j = (i + 1); j < a_named.length; j++) { if(a_named[j] == null) { throwAX("constructor: a_named[" + j + "] is null."); } if(a_named[i].getName().equals(a_named[j].getName())) { throwAX("constructor: " + sRULE + "a_named[" + i + "].getName() is equal to a_named[" + j + "].getName()"); } } } //a_named is completely valid. aNamed = a_named; } /**

Does the provided name exist in the Named array?

@return (getArrIdx(s_name, false) != -1) **/ public boolean doesExist(String s_name) { return (getArrIdx(s_name, false) != -1); } /**

Get the Named element having the provided name.

@return a_named[getArrIdx(s_name)] Where a_named is exactly as provided to the constructor. **/ public Named getNamed(String s_name) { return aNamed[getArrIdx(s_name)]; } /**

Get the Named element at the requested array index.

@return a_named[i_dx] Where a_named is exactly as provided to the constructor. **/ public Named getNamed(int i_dx) { try { return aNamed[i_dx]; } catch(ArrayIndexOutOfBoundsException aioobx) { throwAX("getNamed: i_dx (" + i_dx + ") is invalid. getLength()=" + getLength() + "."); } //Never reached. Required for compile. return null; } /**

How many Named elements exist in the array?

@return a_named.length Where a_named is exactly as provided to the constructor. **/ public int getLength() { return aNamed.length; } /**

Get the array of Named objects for direct manipulation.

@return a_named Where a_named is exactly as provided to the constructor. **/ public Named[] getAONamed() { return aNamed; } /**

Add a new or replace an existing Named object in the array.

@param n_amed The Named object to add or replace. May not be null. If n_amed.getName does exist in the array of Named objects, then that element is replaced by this. If the name does not exist, this n_amed is added to the end of the array. **/ public void addOrReplace(Named n_amed) { try { if(doesExist(n_amed.getName())) { replace(n_amed); } else { add(n_amed); } } catch(NullPointerException npx) { throwAX("addOrReplace: n_amed is null."); } } /**

Replace a Named object already existing in the array.

@param n_amed The Named object to add. May not be null and getName must exist. **/ public void replace(Named n_amed) { try { if(!doesExist(n_amed.getName())) { throwAX("add: s_name must equal the name of an existing Named object. Try add(). " + toString()); } } catch(NullPointerException npx) { throwAX("replace: n_amed is null."); } aNamed[getArrIdx(n_amed.getName())] = n_amed; } /**

Add a new Named object to the array.

@param n_amed The Named object to add. May not be null and getName may not exist. **/ public void add(Named n_amed) { if(n_amed == null) { throwAX("add: n_amed may not be null. " + toString()); } if(doesExist(n_amed.getName())) { throwAX("add: s_name must not equal the name of any existing Named object. Try replace(). " + toString()); } Named[] aNamedNew = new Named[aNamed.length + 1]; //Copy all elements from the current array to the new one. for(int i = 0; i < aNamed.length; i++) { aNamedNew[i] = aNamed[i]; } //All from the original are now in the new, and the //last element in the new is currently empty. aNamedNew[aNamedNew.length - 1] = n_amed; aNamed = aNamedNew; } /**

At which array index does the requested Named element exist?

@return getArrIdx(s_name, true) **/ public int getArrIdx(String s_name) { return getArrIdx(s_name, true); } /**

At which array index does the requested Named element exist?

@param s_name The name of the Named object. May not be null. @param b_crashIfNotFound If true and s_name does not exist, then an AssertException is thrown with an error message saying so. If false and s_name does not exist, then -1 is returned. @return The array index at which the Named having s_name as its name exists, or -1 if it does not. **/ protected int getArrIdx(String s_name, boolean b_crashIfNotFound) { try { for(int i = 0; i < aNamed.length; i++) { if(s_name.equals(aNamed[i].getName())) { return i; } } } catch(NullPointerException npx) { throwAX("getArrIdx: s_name is null."); } if(b_crashIfNotFound) { throw new NullPointerException("ERROR in ManualNamedArray.getIndex: s_name ('" + s_name + "') does not equal the name of any Named."); } return -1; } /**

Get some information about this ManualNamedArray.

**/ public String toString() { StringBuffer sbNames = new StringBuffer(sES); for(int i = 0; i < aNamed.length; i++) { sbNames.append(aNamed[i].getName() + " "); } return this.getClass().getName() + ": getLength()=" + getLength() + ", Names of all Named objects [" + sbNames.toString() + "]."; } }