001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2011-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.calc.impl; 011 012import mondrian.calc.*; 013import mondrian.olap.Evaluator; 014import mondrian.olap.Member; 015 016import java.util.*; 017 018/** 019 * Abstract implementation of {@link TupleList}. 020 * 021 * @author jhyde 022 */ 023public abstract class AbstractTupleList 024 extends AbstractList<List<Member>> 025 implements RandomAccess, Cloneable, TupleList 026{ 027 protected final int arity; 028 protected boolean mutable = true; 029 030 public AbstractTupleList(int arity) { 031 this.arity = arity; 032 } 033 034 public int getArity() { 035 return arity; 036 } 037 038 protected abstract TupleIterator tupleIteratorInternal(); 039 040 @Override 041 public abstract TupleList subList(int fromIndex, int toIndex); 042 043 public TupleList fix() { 044 return new DelegatingTupleList( 045 arity, 046 new ArrayList<List<Member>>(this)); 047 } 048 049 @Override 050 public final Iterator<List<Member>> iterator() { 051 return tupleIteratorInternal(); 052 } 053 054 public final TupleIterator tupleIterator() { 055 return tupleIteratorInternal(); 056 } 057 058 /** 059 * Creates a {@link TupleCursor} over this list. 060 * 061 * <p>Any implementation of {@link TupleList} must implement all three 062 * methods {@link #iterator()}, {@link #tupleIterator()} and 063 * {@code tupleCursor}. The default implementation returns the same 064 * for all three, but a derived classes can override this method to create a 065 * more efficient implementation that implements cursor but not iterator. 066 * 067 * @return A cursor over this list 068 */ 069 public TupleCursor tupleCursor() { 070 return tupleIteratorInternal(); 071 } 072 073 public void addCurrent(TupleCursor tupleIter) { 074 add(tupleIter.current()); 075 } 076 077 public Member get(int slice, int index) { 078 return get(index).get(slice); 079 } 080 081 /** 082 * Implementation of {@link mondrian.calc.TupleIterator} for 083 * {@link ArrayTupleList}. 084 * Based upon AbstractList.Itr, but with concurrent modification checking 085 * removed. 086 */ 087 protected class AbstractTupleListIterator 088 implements TupleIterator 089 { 090 /** 091 * Index of element to be returned by subsequent call to next. 092 */ 093 int cursor = 0; 094 095 /** 096 * Index of element returned by most recent call to next or 097 * previous. Reset to -1 if this element is deleted by a call 098 * to remove. 099 */ 100 int lastRet = -1; 101 102 public boolean hasNext() { 103 return cursor != size(); 104 } 105 106 public List<Member> next() { 107 try { 108 List<Member> next = get(cursor); 109 lastRet = cursor++; 110 return next; 111 } catch (IndexOutOfBoundsException e) { 112 throw new NoSuchElementException(); 113 } 114 } 115 116 public boolean forward() { 117 if (cursor == size()) { 118 return false; 119 } 120 lastRet = cursor++; 121 return true; 122 } 123 124 public List<Member> current() { 125 return get(lastRet); 126 } 127 128 public void currentToArray(Member[] members, int offset) { 129 final List<Member> current = current(); 130 if (offset == 0) { 131 current.toArray(members); 132 } else { 133 //noinspection SuspiciousSystemArraycopy 134 System.arraycopy(current.toArray(), 0, members, offset, arity); 135 } 136 } 137 138 public int getArity() { 139 return AbstractTupleList.this.getArity(); 140 } 141 142 public void remove() { 143 assert mutable; 144 if (lastRet == -1) { 145 throw new IllegalStateException(); 146 } 147 try { 148 AbstractTupleList.this.remove(lastRet); 149 if (lastRet < cursor) { 150 cursor--; 151 } 152 lastRet = -1; 153 } catch (IndexOutOfBoundsException e) { 154 throw new ConcurrentModificationException(); 155 } 156 } 157 158 public void setContext(Evaluator evaluator) { 159 evaluator.setContext(current()); 160 } 161 162 public Member member(int column) { 163 return get(lastRet).get(column); 164 } 165 } 166} 167 168// End AbstractTupleList.java