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    }