/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.qp.util; import com.foundationdb.qp.operator.BindingsAwareCursor; import com.foundationdb.qp.operator.QueryBindings; import com.foundationdb.qp.operator.RowCursor; import com.foundationdb.qp.operator.RowCursorImpl; import com.foundationdb.qp.row.Row; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class MultiCursor extends RowCursorImpl implements BindingsAwareCursor { // Cursor interface @Override public void open() { super.open(); sealed = true; if (openAll) { for (RowCursor cursor : cursors) { cursor.open(); } } cursorIterator = cursors.iterator(); startNextCursor(); } @Override public Row next() { Row next; do { next = current != null ? current.next() : null; if (next == null) { startNextCursor(); } } while (next == null && current != null); return next; } @Override public void close() { try { if (current != null) { current.close(); } if (openAll) { while (cursorIterator.hasNext()) { current = cursorIterator.next(); current.close(); } } } finally { current = null; super.close(); } } @Override public void rebind(QueryBindings bindings) { for (RowCursor cursor : cursors) { if (cursor instanceof BindingsAwareCursor) { ((BindingsAwareCursor)cursor).rebind(bindings); } } } // MultiCursor interface public MultiCursor() { this(false); } public MultiCursor(boolean openAll) { this.openAll = openAll; } public void addCursor(RowCursor cursor) { if (sealed) { throw new IllegalStateException(); } cursors.add(cursor); } // For use by this class private void startNextCursor() { if (cursorIterator.hasNext()) { // closing last cursor if (current != null) { try { current.close(); } finally { current = null; } } current = cursorIterator.next(); if (!openAll) { current.open(); } } else { current = null; setIdle(); } } // Object state private final List<RowCursor> cursors = new ArrayList<>(); private final boolean openAll; private boolean sealed = false; private Iterator<RowCursor> cursorIterator; private RowCursor current; }