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.TupleList; 013import mondrian.olap.Member; 014 015import java.util.*; 016 017/** 018 * Abstract implementation of a {@link mondrian.calc.TupleList} that stores 019 * tuples in end-to-end format. 020 * 021 * <p>For example, if the arity is 3, the tuples {(A1, B1, C1), (A1, B2, C2)} 022 * will be stored as {A1, B1, C1, A2, B2, C2}. This is memory-efficient (only 023 * one array, compared to 3 arrays or one array per tuple in other 024 * representations), has good locality of reference, and typical operations 025 * require few indirections. 026 * 027 * <p>Concrete subclasses can store the data in various backing lists. 028 * 029 * @author jhyde 030*/ 031abstract class AbstractEndToEndTupleList extends AbstractTupleList { 032 033 AbstractEndToEndTupleList(int arity) { 034 super(arity); 035 } 036 037 public TupleList project(final int[] destIndices) { 038 final List<Member> backingList = backingList(); 039 final int originalArity = getArity(); 040 return new DelegatingTupleList( 041 destIndices.length, 042 new AbstractList<List<Member>>() { 043 public List<Member> get(int index) { 044 final int n = index * originalArity; 045 return new AbstractList<Member>() { 046 public Member get(int index) { 047 return backingList.get(n + destIndices[index]); 048 } 049 050 public int size() { 051 return destIndices.length; 052 } 053 }; 054 } 055 056 public int size() { 057 return backingList.size() / originalArity; 058 } 059 }); 060 } 061 062 protected abstract List<Member> backingList(); 063 064 @Override 065 public List<Member> set(int index, List<Member> element) { 066 assert mutable; 067 final List<Member> list = backingList(); 068 for (int i = 0, startIndex = index * arity; i < arity; i++) { 069 list.set(startIndex + i, element.get(i)); 070 } 071 return null; // not compliant with List contract 072 } 073 074 @Override 075 public boolean addAll(Collection<? extends List<Member>> c) { 076 return addAll(size(), c); 077 } 078 079 @Override 080 public boolean addAll(int i, Collection<? extends List<Member>> c) { 081 assert mutable; 082 if (c instanceof AbstractEndToEndTupleList) { 083 return backingList().addAll( 084 i * arity, 085 ((AbstractEndToEndTupleList) c).backingList()); 086 } 087 return super.addAll(i, c); 088 } 089 090 @Override 091 public TupleList subList(int fromIndex, int toIndex) { 092 return new ListTupleList( 093 arity, 094 backingList().subList(fromIndex * arity, toIndex * arity)); 095 } 096 097 public TupleList withPositionCallback( 098 final PositionCallback positionCallback) 099 { 100 assert !(backingList() instanceof PositionSensingList); 101 return new ListTupleList( 102 arity, new PositionSensingList(positionCallback)); 103 } 104 105 private class PositionSensingList extends AbstractList<Member> { 106 private final PositionCallback positionCallback; 107 private final List<Member> backingList = backingList(); 108 109 public PositionSensingList( 110 PositionCallback positionCallback) 111 { 112 this.positionCallback = positionCallback; 113 } 114 115 @Override 116 public Member get(int index) { 117 positionCallback.onPosition(index / arity); 118 return backingList.get(index); 119 } 120 121 @Override 122 public int size() { 123 return backingList.size(); 124 } 125 126 @Override 127 public Member set(int index, Member element) { 128 assert mutable; 129 positionCallback.onPosition(index / arity); 130 return backingList.set(index, element); 131 } 132 133 @Override 134 public void add(int index, Member element) { 135 assert mutable; 136 positionCallback.onPosition(index); 137 backingList.add(index, element); 138 } 139 140 @Override 141 public Member remove(int index) { 142 assert mutable; 143 positionCallback.onPosition(index); 144 return backingList.remove(index); 145 } 146 } 147} 148 149// End AbstractEndToEndTupleList.java