/*
* Copyright (C) Chaperon. All rights reserved.
* -------------------------------------------------------------------------
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package net.sourceforge.chaperon.model.symbol;
import java.io.Serializable;
/**
* This class represents a set of symbols, which means that this set dosn't contains duplett of
* symbols.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: SymbolSet.java,v 1.8 2003/12/09 19:55:53 benedikta Exp $
*/
public class SymbolSet implements SymbolCollection, Serializable, Cloneable
{
private int capacityIncrement = 100;
private int elementCount = 0;
private Symbol[] list = new Symbol[10];
/*
* Add a symbol to this set.
*
* @param symbol Symbol, which should added.
*
* @return Index of the symbol in this set.
*/
public boolean addSymbol(Symbol symbol)
{
int index = indexOf(symbol);
if (index==-1)
{
ensureCapacity(elementCount+1);
list[elementCount] = symbol;
elementCount++;
return true;
}
return false;
}
/*
* Add the symbols from an other list to this set
*
* @param collection Collection of symbols.
*/
public boolean addSymbol(SymbolCollection collection)
{
if (collection==null)
throw new NullPointerException("Symbol collection is null");
boolean changed = false;
for (int i = 0; i<collection.getSymbolCount(); i++)
changed |= addSymbol(collection.getSymbol(i));
return changed;
}
/**
* Removes a symbol by an index from this set.
*
* @param index Index of the symbol.
*/
public void removeSymbol(int index)
{
if (index>=elementCount)
throw new ArrayIndexOutOfBoundsException(index);
elementCount--;
if (index<elementCount)
System.arraycopy(list, index+1, list, index, elementCount-index);
}
/**
* Removes a symbol from this set.
*
* @param symbol Symbol, which should be removed.
*/
public void removeSymbol(Symbol symbol)
{
if (symbol==null)
throw new NullPointerException("Symbol is null");
for (int i = elementCount-1; i>=0; i--)
if (symbol.equals(list[i]))
removeSymbol(i);
}
/**
* Replace a symbol given by an index.
*
* @param index The index, at which the symbol be inserted.
* @param symbol Symbol.
*/
public void setSymbol(int index, Symbol symbol)
{
if (index>=elementCount)
throw new ArrayIndexOutOfBoundsException(index);
if (symbol==null)
throw new NullPointerException("Symbol is null");
list[index] = symbol;
if (contains(symbol) && (!getSymbol(index).equals(symbol)))
throw new IllegalArgumentException("Set already contains the symbol");
list[index] = symbol;
}
/**
* Return a symbol giving by an index.
*
* @param index Index of the symbol.
*
* @return Symbol.
*/
public Symbol getSymbol(int index)
{
if ((index<0) && (index>=elementCount))
throw new IndexOutOfBoundsException();
return list[index];
}
/**
* Returns a symbol from this set given by the name of the symbol.
*
* @param name Name of the symbol.
*
* @return Symbol.
*/
public Symbol getSymbol(String name)
{
int index = indexOf(name);
if (index>=0)
return list[index];
return null;
}
/**
* Returns the count of symbols in this set
*
* @return Count of symbols.
*/
public int getSymbolCount()
{
return elementCount;
}
/**
* If this set is empty.
*
* @return True, if the set is empty.
*/
public boolean isEmpty()
{
return elementCount==0;
}
/**
* Return the index of a symbol.
*
* @param symbol Symbol.
*
* @return Index of this symbol.
*/
public int indexOf(Symbol symbol)
{
if (symbol==null)
throw new NullPointerException("Symbol is null");
for (int i = 0; i<elementCount; i++)
if (list[i].equals(symbol))
return i;
return -1;
}
/**
* Return the index of a symbol, given by the name of the Symbol.
*
* @param name Name of symbol.
*
* @return Index of this symbol.
*/
public int indexOf(String name)
{
if (name==null)
throw new NullPointerException("Name is null");
for (int i = 0; i<elementCount; i++)
if (list[i].getName().equals(name))
return i;
return -1;
}
/**
* If the list contains a symbol
*
* @param symbol Symbol
*
* @return True, if the list contains the symbol
*/
public boolean contains(Symbol symbol)
{
if (symbol==null)
throw new NullPointerException("Symbol is null");
for (int i = 0; i<elementCount; i++)
if (list[i].equals(symbol))
return true;
return false;
}
/**
* If the list contains a symbol, given by the name of the symbol.
*
* @param name Name of the symbol.
*
* @return True, if the list contains the symbol.
*/
public boolean contains(String name)
{
if (name==null)
throw new NullPointerException("Name is null");
for (int i = 0; i<elementCount; i++)
if (list[i].getName().equals(name))
return true;
return false;
}
public boolean contains(SymbolCollection collection)
{
if (collection==null)
throw new NullPointerException("Set is null");
for (int i = 0; i<collection.getSymbolCount(); i++)
if (!contains(collection.getSymbol(i)))
return false;
return true;
}
/**
* Removes all symbols from this set.
*/
public void clear()
{
elementCount = 0;
}
/**
* Return all used terminal symbols in this set.
*
* @return List of terminal symbols.
*/
public SymbolSet getTerminals()
{
SymbolSet set = new SymbolSet();
Symbol symbol;
for (int i = 0; i<elementCount; i++)
if ((symbol = this.list[i]) instanceof Terminal)
set.addSymbol(symbol);
return set;
}
/**
* Return all used nonterminal symbols in this set.
*
* @return List of nonterminal symbols.
*/
public SymbolSet getNonterminals()
{
SymbolSet set = new SymbolSet();
Symbol symbol;
for (int i = 0; i<elementCount; i++)
if ((symbol = this.list[i]) instanceof Nonterminal)
set.addSymbol(symbol);
return set;
}
/**
* Compares to another set of symbols.
*
* @param o Another object.
*
* @return True, if both sets contains the same symbols.
*/
public boolean equals(Object o)
{
if (o==this)
return true;
if (o instanceof SymbolSet)
{
SymbolSet set = (SymbolSet)o;
if (getSymbolCount()!=set.getSymbolCount())
return false;
for (int i = 0; i<set.getSymbolCount(); i++)
if (!contains(set.getSymbol(i)))
return false;
return true;
}
return false;
}
/**
* Return a string representation of the set.
*
* @return String representation of the set.
*/
public String toString()
{
StringBuffer buffer = new StringBuffer();
for (int i = 0; i<elementCount; i++)
{
buffer.append(list[i].toString());
if (i<(elementCount-1))
buffer.append(" ");
}
return buffer.toString();
}
/**
* Create a clone of this set of symbols
*
* @return Clone of this set.
*
* @throws CloneNotSupportedException If a exception occurs during the cloning.
*/
public Object clone()
{
SymbolList clone = new SymbolList();
for (int i = 0; i<getSymbolCount(); i++)
clone.addSymbol(getSymbol(i));
return clone;
}
/**
* Ensure the capacity for adding values
*
* @param minCapacity
*/
private void ensureCapacity(int minCapacity)
{
if (list.length>=minCapacity)
return;
int newCapacity = list.length+capacityIncrement;
if (capacityIncrement<=0)
newCapacity = list.length*2;
Symbol[] newArray = new Symbol[Math.max(newCapacity, minCapacity)];
System.arraycopy(list, 0, newArray, 0, list.length);
list = newArray;
}
}
|