001 /*
002 * LAPIS lightweight structured text processing system
003 *
004 * Copyright (C) 1998-2002 Carnegie Mellon University,
005 * Copyright (C) 2003 Massachusetts Institute of Technology.
006 * All rights reserved.
007 *
008 * This library is free software; you can redistribute it
009 * and/or modify it under the terms of the GNU General
010 * Public License as published by the Free Software
011 * Foundation, version 2.
012 *
013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/
014 */
015
016
017 package lapisx.enum;
018 import java.util.Enumeration;
019 import java.util.NoSuchElementException;
020 import java.util.Vector;
021
022 /**
023 * Enumeration which transforms the elements of another enumeration.
024 */
025 public abstract class PairEnumeration implements Enumeration {
026 Enumeration e1;
027 Enumeration e2;
028
029 PairEnumeration history;
030 Vector e1History = new Vector (); // all objects returned by e1
031 Vector e2History = new Vector (); // all objects returned by e2
032
033 Object r; // last object returned by e1
034 Enumeration e; // enumeration of e2's history
035 boolean swapped = false;
036
037 Object o; // first object yielded by transform ()
038 Vector v; // other objects yielded by transform ()
039 int i; // next object to return from v
040
041 int state = INIT;
042 static final int INIT = 0;
043 static final int RUNNING = 1;
044 static final int DONE = 2;
045
046 public PairEnumeration (Enumeration e1, Enumeration e2) {
047 this.e1 = e1;
048 this.e2 = e2;
049 }
050
051 public PairEnumeration (Enumeration e1, Enumeration e2, PairEnumeration history) {
052 this.e1 = e1;
053 this.e2 = e2;
054 this.history = history;
055 }
056
057 public boolean hasMoreElements () {
058 next ();
059 return o != null;
060 }
061
062 public Object nextElement () {
063 next ();
064 if (o == null)
065 throw new NoSuchElementException ();
066 Object result = o;
067 o = null;
068 return result;
069 }
070
071 void next () {
072 if (state == INIT) {
073 if (history != null) {
074 if (swapped == history.swapped) {
075 e1History = (Vector) history.e1History.clone ();
076 e2History = (Vector) history.e2History.clone ();
077 } else {
078 e2History = (Vector) history.e1History.clone ();
079 e1History = (Vector) history.e2History.clone ();
080 }
081 }
082
083 if (!e1.hasMoreElements ())
084 swap ();
085
086 if (e1.hasMoreElements ()) {
087 r = e1.nextElement ();
088 e = e2History.elements ();
089 state = RUNNING;
090 } else
091 state = DONE;
092 }
093
094 // check if yielded element is waiting to be returned
095 if (o != null)
096 return;
097
098 // check in v for other yielded elements
099 if (v != null) {
100 if (i < v.size ()) {
101 o = v.elementAt (i);
102 v.setElementAt (null, i);
103 ++i;
104 } else {
105 v.setSize (0);
106 i = 0;
107 }
108 }
109
110 // transform more pairs of elements until at least one
111 // output element is yielded
112 while (o == null && state != DONE) {
113 while (o == null && e.hasMoreElements ()) {
114 Object s = e.nextElement ();
115 if (swapped)
116 transform (s, r);
117 else
118 transform (r, s);
119 }
120 if (o != null)
121 return;
122
123 e1History.addElement (r);
124 if (e2.hasMoreElements ())
125 swap ();
126
127 if (e1.hasMoreElements ()) {
128 r = e1.nextElement ();
129 e = e2History.elements ();
130 } else
131 state = DONE;
132 }
133 }
134
135 void swap () {
136 Enumeration te;
137 Vector tv;
138
139 te = e1;
140 e1 = e2;
141 e2 = te;
142
143 tv = e1History;
144 e1History = e2History;
145 e2History = tv;
146
147 swapped = !swapped;
148 }
149
150 public void yield (Object obj) {
151 if (o == null)
152 o = obj;
153 else {
154 if (v == null)
155 v = new Vector ();
156 v.addElement (obj);
157 }
158 }
159
160 public abstract void transform (Object o1, Object o2);
161 }