/* 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.array.VectorWrapper; import xbn.array.BinarySearchData; import java.util.Vector; import java.util.Vector; /**

A VectorWrapper for Named objects. See Named.

Source code:  VWNamed.java.  Example code  See the similar example code for VWInt.

@since 0.8.2b @version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public class VWNamed extends VectorWrapper implements Cloneable { private BinarySearchData bsd = null; /**

Create a VWNamed with default settings.

Equal to VectorWrapper()

**/ public VWNamed() { super(); } /**

Create a VWNamed.

Equal to VectorWrapper(v_ector)

Note: It is expected that this Vector contain only Named objects.

**/ public VWNamed(Vector v_ector) { super(v_ector); } /**

Create a VWNamed.

Equal to VectorWrapper(b_orderDirAscDesc)

**/ public VWNamed(boolean b_orderDirAscDesc) { super(b_orderDirAscDesc); } /**

Create a VWNamed.

Equal to VectorWrapper(v_ector, b_orderDirAscDesc)

Note: It is expected that this Vector contain only Named objects.

**/ public VWNamed(Vector v_ector, boolean b_orderDirAscDesc) { super(v_ector, b_orderDirAscDesc); } /**

Create a VWNamed.

Equal to VectorWrapper(b_addInOrder, b_orderDirAscDesc)

**/ public VWNamed(boolean b_addInOrder, boolean b_orderDirAscDesc) { super(b_addInOrder, b_orderDirAscDesc); } /**

Create a VWNamed.

Equal to VectorWrapper(v_ector, b_addInOrder, b_orderDisAscDesc)

Note: It is expected that this Vector contain only Named objects.

**/ public VWNamed(Vector v_ector, boolean b_addInOrder, boolean b_orderDirAscDesc) { super(v_ector, b_addInOrder, b_orderDirAscDesc); } /**

Add a Named object.

@param n_amed The string to add. May not be null, nor may the name be null. If not adding in order, then the name may not be less than zero characters in length. If adding in order, the name may not be less than one character in length. **/ public final void add(Named n_amed) { if(!doAddInOrder()) { throwAXIfNull(n_amed, "n_amed", "add"); throwAXIfNull(n_amed.getName(), "n_amed.getName()", "add"); getVector().addElement(n_amed); return; } //DO add in order. try { getVector().insertElementAt(n_amed, getInsertAddIdx(n_amed.getName())); } catch(NullPointerException npx) { throwAX("add: n_amed is null."); } //We've just changed the size of the "array", so the bsd //is no longer valid. This will be recreated in //getArrIdx(). bsd = null; } /**

Get the index at which to insert the provided string. This function is only meaningful when doAddInOrder() equals true. See doAddInOrder.

@param s_name The name of the Named you wish to add. May not be null. @return If... **/ public final int getInsertAddIdx(String s_name) { return getArrIdx("getInsertAddIdx", s_name, false); } /**

Get the index at which the string actually exists.

@param n_amed The string that may already exist in this VWNamed. May not be null. @return -1 If no Named object whose name equals s_name exists.
The array index at which the Named object exists. **/ public final int getFoundIdx(String s_name) { return getArrIdx("getFoundIdx", s_name, true); } /**

Was a Named object with the provided name already added?

@param s_name The name who's existence (of the Named object having that name) you want to test for. May not be null. @return true If a Named object whose name equals s_name exists.
false if no added Named object has the name s_name. **/ public final boolean doesExist(String s_name) { return (getFoundIdx(s_name) != -1); } /**

Add an array of strings.

For each element in a_named, this calls, in order: add(a_named[X])

@param a_named The Named array to add. May not be null, nor may any element be null. **/ public final void addArray(Named[] a_named) { try { for(int i = 0; i < a_named.length; i++) { add(a_named[i]); } } catch(NullPointerException npx) { throwAX("addArray: a_named is null."); } } /**

Alias for getNamed(i_dx).getName().

@return getNamed(i_dx).getName() **/ public final String getString(int i_dx) { return getNamed(i_dx).getName(); } /**

Get a string from the vector, at the required array index.

@param i_dx The array index. Must range 0..[size() - 1], inclusive. **/ public final Named getNamed(int i_dx) { try { return (Named)getVector().elementAt(i_dx); } catch(ClassCastException ccx) { throwAX("getNamed: Element i_dx (" + i_dx + ") is not a Named object, which it must be. It is actually a " + getVector().elementAt(i_dx).getClass().getName() + ". It seems you provided an inaccurate Vector to the constructor."); } catch(ArrayIndexOutOfBoundsException aioobx) { throwAX("getNamed: i_dx (" + i_dx + ") is invalid. size()=" + size() + "."); } //Never reached. Required for compile. return null; } public final boolean isNull(int i_dx) { return (getNamed(i_dx) == null); } /**

Get the array of strings. This array is composed of all those strings added since this object was created, or since the last time this function was called.

@return An array containing all strings added, in the same order as originally added (if not ordered when added), or in order (if ordered when added). **/ public final Named[] getAONamed() { Named an[] = new Named[getVector().size()]; if(an.length == 0) { return an; } //The array is at least one element in length. getVector().copyInto(an); return an; } //Cloning...START /**

Get a full (deep) copy of this VWNamed.

@return (VWNamed)clone() **/ public final VWNamed getVWSClone() { try { return (VWNamed)clone(); } catch(CloneNotSupportedException cnsx) { throwAX("getVWSClone [SHOULD NEVER HAPPEN!]: " + cnsx.toString()); } //Never reached. Required for compile. return null; } /**

Get a full (deep) copy of this VWNamed as an Object.

**/ protected final Object clone() throws CloneNotSupportedException { VWNamed vwnClone = new VWNamed(); for(int i = 0; i < size(); i++) { vwnClone.add(getNamed(i)); } return vwnClone; } //Cloning...END private final int getArrIdx(String s_callingFunc, String s_name, boolean b_onlyIfFound) { if(s_name == null || s_name.length() < 1) { throwAX(s_callingFunc + ": s_name ('" + s_name + "') is null or zero characters in length."); } if(size() == 0) { //There are no elements yet return b_onlyIfFound ? -1 : 0; } //There is at least one element. if(!doAddInOrder()) { //Adding is not done in order. Binary searching is //pointless. if(b_onlyIfFound) { //We only want to know the index at which c_har is //found. for(int i = 0; i < size(); i++) { if(s_name.equals(getNamed(i).getName())) { return i; } } } //ELSE: We only want the array index at which to // *insert*. Since it's not ordered, just // return zero. return b_onlyIfFound ? -1 : 0; } //Adding IS done in order. Binary searching is //useful. if(bsd == null) { //This is either (1) the first time using this //function, or this is (2) the first time using //this function since adding something. bsd = new BinarySearchData(size(), getOrderDirAscDesc()); } bsd.reset(); int iPrevMidIdx = -1; while(bsd.getIdxMiddle() != -1) { int iMiddleIdx = bsd.getIdxMiddle(); String sAtMiddle = getNamed(bsd.getIdxMiddle()).getName(); //Used only after the end of this while block. iPrevMidIdx = iMiddleIdx; if(s_name.equals(sAtMiddle)) { //Found. Duplicates (which are okay) are added at //the same point, pushing the duplicate to the right. return iMiddleIdx; } bsd.prepareForNextSearch(s_name.compareTo(sAtMiddle) < 0); } //The char to be inserted does not currently exist in the //array. if(s_name.compareTo(getNamed(iPrevMidIdx).getName()) < 0) { if(!getOrderDirAscDesc()) { //Insert n_amed at the index right *after* the //element it is just-less than. iPrevMidIdx++; } //ELSE: The order is ascending, so insert it *at* // the element n_amed's name is just-less than. This // pushes the existing element one to the // right. } else { //s_name is greater than the existing "middle" element. if(getOrderDirAscDesc()) { //Insert n_amed at the index right *after* the //element it is just-greater than. iPrevMidIdx++; } //ELSE: The order is descending, so insert it *at* // the element n_amed is just-less than. This // pushes the existing element one to the // right. } return b_onlyIfFound ? -1 : iPrevMidIdx; } }