001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004 Robert Grimm
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package xtc.util;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.NoSuchElementException;
025:
026: /**
027: * Implementation of a pair. Pairs are used to construct immutable
028: * singly-linked lists, not unlike cons cells in Scheme (with the
029: * differences that pairs are immutable and that the second pointer
030: * always references another pair).
031: *
032: * @author Robert Grimm
033: * @version $Revision: 1.1 $
034: */
035: public class Pair {
036:
037: /**
038: * The pair representing the empty list. This object serves as a
039: * sentinel to avoid special-casing <code>null</code>.
040: */
041: public static final Pair EMPTY = new Pair();
042:
043: /** The value. */
044: private final Object value;
045:
046: /** The next pair. */
047: private final Pair next;
048:
049: /** Create a new pair. */
050: private Pair() {
051: value = null;
052: next = null;
053: }
054:
055: /**
056: * Create a new pair. The newly created pair represents a singleton
057: * list.
058: *
059: * @param value The value.
060: */
061: public Pair(Object value) {
062: this (value, EMPTY);
063: }
064:
065: /**
066: * Create a new pair.
067: *
068: * @param value The value.
069: * @param next The next pair.
070: * @throws NullPointerException
071: * Signals that <code>next</code> is <code>null</code>.
072: */
073: public Pair(Object value, Pair next) {
074: if (null == next) {
075: throw new NullPointerException();
076: }
077:
078: this .value = value;
079: this .next = next;
080: }
081:
082: /**
083: * Determine whether the list starting at this pair is empty.
084: *
085: * @return <code>true</code> if the list is empty.
086: */
087: public boolean isEmpty() {
088: return (this == EMPTY);
089: }
090:
091: /**
092: * Get this pair's value.
093: *
094: * @return This pair's value.
095: * @throws IllegalStateException
096: * Signals that this pair represents the empty list.
097: */
098: public Object value() {
099: if (this == EMPTY) {
100: throw new IllegalStateException();
101: }
102:
103: return value;
104: }
105:
106: /**
107: * Get the next pair.
108: *
109: * @return The next pair.
110: * @throws IllegalStateException
111: * Signals that this pair represents the empty list.
112: */
113: public Pair next() {
114: if (this == EMPTY) {
115: throw new IllegalStateException();
116: }
117:
118: return next;
119: }
120:
121: /**
122: * Get the size of the list starting at this pair.
123: *
124: * @return The size.
125: */
126: public int size() {
127: Pair pair = this ;
128: int size = 0;
129:
130: while (pair != EMPTY) {
131: size++;
132: pair = pair.next;
133: }
134:
135: return size;
136: }
137:
138: /**
139: * Get an iterator over the values of the list starting at this
140: * pair.
141: *
142: * @return The iterator.
143: */
144: public Iterator iterator() {
145: return new Iterator() {
146: private Pair pair = Pair.this ;
147:
148: public boolean hasNext() {
149: return (EMPTY != pair);
150: }
151:
152: public Object next() {
153: if (EMPTY == pair) {
154: throw new NoSuchElementException();
155: } else {
156: Object v = pair.value;
157: pair = pair.next;
158: return v;
159: }
160: }
161:
162: public void remove() {
163: throw new UnsupportedOperationException();
164: }
165: };
166: }
167:
168: /**
169: * Get a Java Collections list with the values of the list starting
170: * at this pair.
171: *
172: * @return The Java Collections list.
173: */
174: public List list() {
175: ArrayList list = new ArrayList(size());
176: Pair pair = this;
177:
178: while (EMPTY != pair) {
179: list.add(pair.value);
180: pair = pair.next;
181: }
182:
183: return list;
184: }
185:
186: }
|