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 }