001: /*
002: * Copyright (C) Chaperon. All rights reserved.
003: * -------------------------------------------------------------------------
004: * This software is published under the terms of the Apache Software License
005: * version 1.1, a copy of which has been included with this distribution in
006: * the LICENSE file.
007: */
008:
009: package net.sourceforge.chaperon.model.symbol;
010:
011: import java.io.Serializable;
012:
013: /**
014: * This class represents a set of symbols, which means that this set dosn't contains duplett of
015: * symbols.
016: *
017: * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
018: * @version CVS $Id: SymbolSet.java,v 1.8 2003/12/09 19:55:53 benedikta Exp $
019: */
020: public class SymbolSet implements SymbolCollection, Serializable,
021: Cloneable {
022: private int capacityIncrement = 100;
023: private int elementCount = 0;
024: private Symbol[] list = new Symbol[10];
025:
026: /*
027: * Add a symbol to this set.
028: *
029: * @param symbol Symbol, which should added.
030: *
031: * @return Index of the symbol in this set.
032: */
033: public boolean addSymbol(Symbol symbol) {
034: int index = indexOf(symbol);
035:
036: if (index == -1) {
037: ensureCapacity(elementCount + 1);
038: list[elementCount] = symbol;
039: elementCount++;
040: return true;
041: }
042:
043: return false;
044: }
045:
046: /*
047: * Add the symbols from an other list to this set
048: *
049: * @param collection Collection of symbols.
050: */
051: public boolean addSymbol(SymbolCollection collection) {
052: if (collection == null)
053: throw new NullPointerException("Symbol collection is null");
054:
055: boolean changed = false;
056: for (int i = 0; i < collection.getSymbolCount(); i++)
057: changed |= addSymbol(collection.getSymbol(i));
058:
059: return changed;
060: }
061:
062: /**
063: * Removes a symbol by an index from this set.
064: *
065: * @param index Index of the symbol.
066: */
067: public void removeSymbol(int index) {
068: if (index >= elementCount)
069: throw new ArrayIndexOutOfBoundsException(index);
070:
071: elementCount--;
072: if (index < elementCount)
073: System.arraycopy(list, index + 1, list, index, elementCount
074: - index);
075: }
076:
077: /**
078: * Removes a symbol from this set.
079: *
080: * @param symbol Symbol, which should be removed.
081: */
082: public void removeSymbol(Symbol symbol) {
083: if (symbol == null)
084: throw new NullPointerException("Symbol is null");
085:
086: for (int i = elementCount - 1; i >= 0; i--)
087: if (symbol.equals(list[i]))
088: removeSymbol(i);
089: }
090:
091: /**
092: * Replace a symbol given by an index.
093: *
094: * @param index The index, at which the symbol be inserted.
095: * @param symbol Symbol.
096: */
097: public void setSymbol(int index, Symbol symbol) {
098: if (index >= elementCount)
099: throw new ArrayIndexOutOfBoundsException(index);
100:
101: if (symbol == null)
102: throw new NullPointerException("Symbol is null");
103:
104: list[index] = symbol;
105:
106: if (contains(symbol) && (!getSymbol(index).equals(symbol)))
107: throw new IllegalArgumentException(
108: "Set already contains the symbol");
109:
110: list[index] = symbol;
111: }
112:
113: /**
114: * Return a symbol giving by an index.
115: *
116: * @param index Index of the symbol.
117: *
118: * @return Symbol.
119: */
120: public Symbol getSymbol(int index) {
121: if ((index < 0) && (index >= elementCount))
122: throw new IndexOutOfBoundsException();
123:
124: return list[index];
125: }
126:
127: /**
128: * Returns a symbol from this set given by the name of the symbol.
129: *
130: * @param name Name of the symbol.
131: *
132: * @return Symbol.
133: */
134: public Symbol getSymbol(String name) {
135: int index = indexOf(name);
136:
137: if (index >= 0)
138: return list[index];
139:
140: return null;
141: }
142:
143: /**
144: * Returns the count of symbols in this set
145: *
146: * @return Count of symbols.
147: */
148: public int getSymbolCount() {
149: return elementCount;
150: }
151:
152: /**
153: * If this set is empty.
154: *
155: * @return True, if the set is empty.
156: */
157: public boolean isEmpty() {
158: return elementCount == 0;
159: }
160:
161: /**
162: * Return the index of a symbol.
163: *
164: * @param symbol Symbol.
165: *
166: * @return Index of this symbol.
167: */
168: public int indexOf(Symbol symbol) {
169: if (symbol == null)
170: throw new NullPointerException("Symbol is null");
171:
172: for (int i = 0; i < elementCount; i++)
173: if (list[i].equals(symbol))
174: return i;
175:
176: return -1;
177: }
178:
179: /**
180: * Return the index of a symbol, given by the name of the Symbol.
181: *
182: * @param name Name of symbol.
183: *
184: * @return Index of this symbol.
185: */
186: public int indexOf(String name) {
187: if (name == null)
188: throw new NullPointerException("Name is null");
189:
190: for (int i = 0; i < elementCount; i++)
191: if (list[i].getName().equals(name))
192: return i;
193:
194: return -1;
195: }
196:
197: /**
198: * If the list contains a symbol
199: *
200: * @param symbol Symbol
201: *
202: * @return True, if the list contains the symbol
203: */
204: public boolean contains(Symbol symbol) {
205: if (symbol == null)
206: throw new NullPointerException("Symbol is null");
207:
208: for (int i = 0; i < elementCount; i++)
209: if (list[i].equals(symbol))
210: return true;
211:
212: return false;
213: }
214:
215: /**
216: * If the list contains a symbol, given by the name of the symbol.
217: *
218: * @param name Name of the symbol.
219: *
220: * @return True, if the list contains the symbol.
221: */
222: public boolean contains(String name) {
223: if (name == null)
224: throw new NullPointerException("Name is null");
225:
226: for (int i = 0; i < elementCount; i++)
227: if (list[i].getName().equals(name))
228: return true;
229:
230: return false;
231: }
232:
233: public boolean contains(SymbolCollection collection) {
234: if (collection == null)
235: throw new NullPointerException("Set is null");
236:
237: for (int i = 0; i < collection.getSymbolCount(); i++)
238: if (!contains(collection.getSymbol(i)))
239: return false;
240:
241: return true;
242: }
243:
244: /**
245: * Removes all symbols from this set.
246: */
247: public void clear() {
248: elementCount = 0;
249: }
250:
251: /**
252: * Return all used terminal symbols in this set.
253: *
254: * @return List of terminal symbols.
255: */
256: public SymbolSet getTerminals() {
257: SymbolSet set = new SymbolSet();
258:
259: Symbol symbol;
260:
261: for (int i = 0; i < elementCount; i++)
262: if ((symbol = this .list[i]) instanceof Terminal)
263: set.addSymbol(symbol);
264:
265: return set;
266: }
267:
268: /**
269: * Return all used nonterminal symbols in this set.
270: *
271: * @return List of nonterminal symbols.
272: */
273: public SymbolSet getNonterminals() {
274: SymbolSet set = new SymbolSet();
275:
276: Symbol symbol;
277:
278: for (int i = 0; i < elementCount; i++)
279: if ((symbol = this .list[i]) instanceof Nonterminal)
280: set.addSymbol(symbol);
281:
282: return set;
283: }
284:
285: /**
286: * Compares to another set of symbols.
287: *
288: * @param o Another object.
289: *
290: * @return True, if both sets contains the same symbols.
291: */
292: public boolean equals(Object o) {
293: if (o == this )
294: return true;
295:
296: if (o instanceof SymbolSet) {
297: SymbolSet set = (SymbolSet) o;
298:
299: if (getSymbolCount() != set.getSymbolCount())
300: return false;
301:
302: for (int i = 0; i < set.getSymbolCount(); i++)
303: if (!contains(set.getSymbol(i)))
304: return false;
305:
306: return true;
307: }
308:
309: return false;
310: }
311:
312: /**
313: * Return a string representation of the set.
314: *
315: * @return String representation of the set.
316: */
317: public String toString() {
318: StringBuffer buffer = new StringBuffer();
319:
320: for (int i = 0; i < elementCount; i++) {
321: buffer.append(list[i].toString());
322: if (i < (elementCount - 1))
323: buffer.append(" ");
324: }
325:
326: return buffer.toString();
327: }
328:
329: /**
330: * Create a clone of this set of symbols
331: *
332: * @return Clone of this set.
333: *
334: * @throws CloneNotSupportedException If a exception occurs during the cloning.
335: */
336: public Object clone() {
337: SymbolList clone = new SymbolList();
338:
339: for (int i = 0; i < getSymbolCount(); i++)
340: clone.addSymbol(getSymbol(i));
341:
342: return clone;
343: }
344:
345: /**
346: * Ensure the capacity for adding values
347: *
348: * @param minCapacity
349: */
350: private void ensureCapacity(int minCapacity) {
351: if (list.length >= minCapacity)
352: return;
353:
354: int newCapacity = list.length + capacityIncrement;
355:
356: if (capacityIncrement <= 0)
357: newCapacity = list.length * 2;
358:
359: Symbol[] newArray = new Symbol[Math.max(newCapacity,
360: minCapacity)];
361:
362: System.arraycopy(list, 0, newArray, 0, list.length);
363: list = newArray;
364: }
365: }
|