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