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-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.calc.impl; 011 012import mondrian.calc.TupleIterator; 013import mondrian.calc.TupleList; 014import mondrian.olap.Member; 015import mondrian.olap.Util; 016 017import java.util.*; 018 019/** 020 * Implementation of {@link mondrian.calc.TupleList} based on a list of 021 * {@code List<Member>} tuples. 022 * 023 * @author jhyde 024*/ 025public class DelegatingTupleList extends AbstractTupleList 026{ 027 private final List<List<Member>> list; 028 029 /** 030 * Creates a DelegatingTupleList. 031 * 032 * @param arity Arity 033 * @param list Backing list 034 */ 035 public DelegatingTupleList(int arity, List<List<Member>> list) { 036 super(arity); 037 this.list = list; 038 assert list.isEmpty() 039 || (list.get(0) instanceof List 040 && (list.get(0).isEmpty() 041 || list.get(0).get(0) == null 042 || list.get(0).get(0) instanceof Member)) 043 : "sanity check failed: " + list; 044 } 045 046 @Override 047 protected TupleIterator tupleIteratorInternal() { 048 return new AbstractTupleListIterator(); 049 } 050 051 @Override 052 public TupleList subList(int fromIndex, int toIndex) { 053 return new DelegatingTupleList(arity, list.subList(fromIndex, toIndex)); 054 } 055 056 @Override 057 public List<Member> get(int index) { 058 return list.get(index); 059 } 060 061 @Override 062 public int size() { 063 return list.size(); 064 } 065 066 public List<Member> slice(final int column) { 067 return new AbstractList<Member>() { 068 @Override 069 public Member get(int index) { 070 return list.get(index).get(column); 071 } 072 @Override 073 public int size() { 074 return list.size(); 075 } 076 public Member set(int index, Member element) { 077 List<Member> subList = list.get(index); 078 if (subList.size() == 1) { 079 // The sub list is probably a singleton list. 080 // calling set() on it will fail. We have to 081 // create a new singleton list. 082 return list.set(index, Collections.singletonList(element)) 083 .get(0); 084 } 085 return subList.set(column, element); 086 }; 087 }; 088 } 089 090 public TupleList cloneList(int capacity) { 091 return new DelegatingTupleList( 092 arity, 093 capacity < 0 094 ? new ArrayList<List<Member>>(list) 095 : new ArrayList<List<Member>>(capacity)); 096 } 097 098 @Override 099 public List<Member> set(int index, List<Member> element) { 100 return list.set(index, element); 101 } 102 103 @Override 104 public void add(int index, List<Member> element) { 105 list.add(index, element); 106 } 107 108 public void addTuple(Member... members) { 109 list.add(Util.flatList(members)); 110 } 111 112 public TupleList project(final int[] destIndices) { 113 return new DelegatingTupleList( 114 destIndices.length, 115 new AbstractList<List<Member>>() { 116 public List<Member> get(final int index) { 117 return new AbstractList<Member>() { 118 public Member get(int column) { 119 return list.get(index).get(destIndices[column]); 120 } 121 122 public int size() { 123 return destIndices.length; 124 } 125 126 public Member set(int column, Member element) { 127 return list.get(index).set(index, element); 128 }; 129 }; 130 } 131 132 public List<Member> set(int index, List<Member> element) { 133 return list.set(index, element); 134 }; 135 136 public int size() { 137 return list.size(); 138 } 139 } 140 ); 141 } 142 143 public TupleList withPositionCallback( 144 final PositionCallback positionCallback) 145 { 146 return new DelegatingTupleList( 147 arity, 148 new AbstractList<List<Member>>() { 149 @Override 150 public List<Member> get(int index) { 151 positionCallback.onPosition(index); 152 return list.get(index); 153 } 154 155 @Override 156 public int size() { 157 return list.size(); 158 } 159 160 @Override 161 public List<Member> set(int index, List<Member> element) { 162 positionCallback.onPosition(index); 163 return list.set(index, element); 164 } 165 166 @Override 167 public void add(int index, List<Member> element) { 168 positionCallback.onPosition(index); 169 list.add(index, element); 170 } 171 172 @Override 173 public List<Member> remove(int index) { 174 positionCallback.onPosition(index); 175 return list.remove(index); 176 } 177 } 178 ); 179 } 180} 181 182// End DelegatingTupleList.java