001: /*
002: * $Id: AbstractJoinedRowIterator.java,v 1.7 2005/03/31 00:07:07 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2005 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.engine.rowiterators;
042:
043: import java.util.NoSuchElementException;
044:
045: import org.axiondb.AxionException;
046: import org.axiondb.Row;
047: import org.axiondb.RowDecorator;
048: import org.axiondb.RowIterator;
049: import org.axiondb.Selectable;
050: import org.axiondb.engine.rows.JoinedRow;
051: import org.axiondb.engine.rows.SimpleRow;
052: import org.axiondb.util.ExceptionConverter;
053:
054: /**
055: * @version $Revision: 1.7 $ $Date: 2005/03/31 00:07:07 $
056: * @author Rodney Waldhoff
057: * @author Ahimanikya Satapathy
058: */
059: public abstract class AbstractJoinedRowIterator extends BaseRowIterator {
060:
061: public AbstractJoinedRowIterator() {
062: }
063:
064: public Row current() throws NoSuchElementException {
065: if (_currentSet) {
066: return _current;
067: } else {
068: throw new NoSuchElementException();
069: }
070: }
071:
072: public int currentIndex() throws NoSuchElementException {
073: return _currentIndex;
074: }
075:
076: public boolean hasCurrent() {
077: return _currentSet;
078: }
079:
080: public boolean hasNext() {
081: if (_nextSet) {
082: return true;
083: } else {
084: try {
085: return setNext();
086: } catch (AxionException e) {
087: throw ExceptionConverter.convertToRuntimeException(e);
088: }
089: }
090: }
091:
092: public boolean hasPrevious() {
093: return nextIndex() > 0;
094: }
095:
096: public Row next() throws NoSuchElementException, AxionException {
097: if (!hasNext()) {
098: throw new NoSuchElementException();
099: } else {
100: _current = _next;
101: _currentSet = true;
102: _currentIndex = _nextIndex;
103: _nextIndex++;
104: clearNext();
105: return _current;
106: }
107: }
108:
109: public int nextIndex() {
110: return _nextIndex;
111: }
112:
113: public Row previous() throws NoSuchElementException, AxionException {
114: if (!hasPrevious()) {
115: throw new NoSuchElementException();
116: } else {
117: setPrevious();
118: _current = _previous;
119: _currentSet = true;
120: _currentIndex = (_nextIndex - 1);
121: _nextIndex--;
122: clearPrevious();
123: return _current;
124: }
125: }
126:
127: public int previousIndex() {
128: return _nextIndex - 1;
129: }
130:
131: public void reset() throws AxionException {
132: _currentIterator = null;
133: _left.reset();
134: _nextIndex = 0;
135: _nextSet = false;
136: _previousSet = false;
137: _currentSet = false;
138: _currentIndex = -1;
139: _next = null;
140: _previous = null;
141: _current = null;
142: }
143:
144: public void setJoinCondition(Selectable joinCondition,
145: RowDecorator decorator) {
146: setJoinCondition(joinCondition);
147: setRowDecorator(decorator);
148: }
149:
150: public String toString() {
151: String joinType = isSwapLeftAndRight() ? "right" : "left";
152: joinType = isRightOuter() ? joinType + "-outer" : "inner";
153: String condition = getJoinCondition() != null ? getJoinCondition()
154: .toString()
155: : "";
156: return "type=" + joinType + ";condition=" + condition;
157: }
158:
159: protected abstract RowIterator generateRightRowIterator()
160: throws AxionException;
161:
162: protected Selectable getJoinCondition() {
163: return _joinCondition;
164: }
165:
166: protected RowIterator getLeftRowIterator() {
167: return _left;
168: }
169:
170: protected int getRightSideColumnCount() {
171: return _rightColumnCount;
172: }
173:
174: protected RowDecorator getRowDecorator() {
175: return _rowDecorator;
176: }
177:
178: protected boolean isRightOuter() {
179: return _rightOuter;
180: }
181:
182: protected boolean isSwapLeftAndRight() {
183: return _swapLeftAndRight;
184: }
185:
186: protected void setLeftRowIterator(RowIterator left) {
187: _left = left;
188: }
189:
190: protected void setRightOuter(boolean b) {
191: _rightOuter = b;
192: }
193:
194: protected void setRightSideColumnCount(int rightColumnCount) {
195: _rightColumnCount = rightColumnCount;
196: }
197:
198: protected void setSwapLeftAndRight(boolean b) {
199: _swapLeftAndRight = b;
200: }
201:
202: private void clearNext() {
203: _next = null;
204: _nextSet = false;
205: }
206:
207: private void clearPrevious() {
208: _previous = null;
209: _previousSet = false;
210: }
211:
212: private RowIterator generateCurrentRowIterator()
213: throws AxionException {
214: RowIterator iter = new JoinRowIterator(_left.current(),
215: generateRightRowIterator(), isSwapLeftAndRight());
216: if (null != getJoinCondition()) {
217: iter = new FilteringRowIterator(iter, getRowDecorator(),
218: getJoinCondition());
219: }
220: if (iter.isEmpty() && isRightOuter()) {
221: JoinedRow row = new JoinedRow();
222: if (isSwapLeftAndRight()) {
223: row.addRow(new SimpleRow(getRightSideColumnCount()));
224: row.addRow(_left.current());
225: } else {
226: row.addRow(_left.current());
227: row.addRow(new SimpleRow(getRightSideColumnCount()));
228: }
229: iter = new SingleRowIterator(row);
230: }
231: return iter;
232: }
233:
234: private void setJoinCondition(Selectable joinCondition) {
235: _joinCondition = joinCondition;
236: }
237:
238: private boolean setNext() throws AxionException {
239: if (!_left.hasCurrent()) {
240: if (_left.hasNext()) {
241: _left.next();
242: _currentIterator = generateCurrentRowIterator();
243: } else {
244: return false;
245: }
246: }
247: if (_left.currentIndex() == _left.nextIndex()) {
248: _left.next();
249: }
250: for (;;) {
251: if (_currentIterator.hasNext()) {
252: setNext(_currentIterator.next());
253: break;
254: } else if (!_left.hasNext()) {
255: clearNext();
256: break;
257: } else {
258: _left.next();
259: _currentIterator = generateCurrentRowIterator();
260: }
261: }
262: return _nextSet;
263: }
264:
265: private void setNext(Row next) {
266: _next = next;
267: _nextSet = true;
268: }
269:
270: private boolean setPrevious() throws AxionException {
271: if (_nextSet) {
272: clearNext();
273: setPrevious();
274: }
275: if (_left.currentIndex() == _left.previousIndex()) {
276: _left.previous();
277: }
278: for (;;) {
279: if (_currentIterator.hasPrevious()) {
280: setPrevious(_currentIterator.previous());
281: break;
282: } else {
283: _left.previous();
284: _currentIterator = generateCurrentRowIterator();
285: if (!_currentIterator.isEmpty()) {
286: _currentIterator.last();
287: }
288: }
289: }
290: return _previousSet;
291: }
292:
293: private void setPrevious(Row previous) {
294: _previous = previous;
295: _previousSet = true;
296: }
297:
298: private void setRowDecorator(RowDecorator rowDecorator) {
299: _rowDecorator = rowDecorator;
300: }
301:
302: private Row _current = null;
303: private int _currentIndex = -1;
304: private RowIterator _currentIterator = null;
305: private boolean _currentSet = false;
306: private Selectable _joinCondition = null;
307: private RowIterator _left = null;
308: private Row _next = null;
309: private int _nextIndex = 0;
310: private boolean _nextSet = false;
311: private Row _previous = null;
312: private boolean _previousSet = false;
313:
314: private int _rightColumnCount;
315: private boolean _rightOuter = false;
316: private RowDecorator _rowDecorator = null;
317: private boolean _swapLeftAndRight = false;
318: }
|