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.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} that stores tuples
021 * end-to-end in a backing list.
022 *
023 * <pre>
024 * l1: {A,B,C},{D,E,F}
025 * l2: {a,b},{c,d},{e,f}
026 *
027 * externally looks like:
028 *  [] <- {A,B,C,a,b}
029 *  [] <- {A,B,C,c,d}
030 *  [] <- {A,B,C,e,f}
031 *  [] <- {D,E,F,a,b}
032 *  [] <- {D,E,F,c,d}
033 *  [] <- {D,E,F,e,d}
034 *
035 * but internally is:
036 *  A,B,C,a,b,A,B,C,c,d,A,B,C,e,f,D,E,F,a,b,D,E,F,c,d,D,E,F,e,d
037 * </pre>
038 *
039 * @author jhyde
040 */
041public class ListTupleList extends AbstractEndToEndTupleList
042{
043    private final List<Member> list;
044
045    /**
046     * Creates a ListTupleList.
047     *
048     * @param arity Arity
049     * @param list Backing list
050     */
051    public ListTupleList(int arity, List<Member> list) {
052        super(arity);
053        this.list = list;
054    }
055
056    protected List<Member> backingList() {
057        return list;
058    }
059
060    public Member get(int slice, int index) {
061        return list.get(index * arity + slice);
062    }
063
064    public List<Member> get(int index) {
065        final int startIndex = index * arity;
066        final List<Member> list1 =
067            new AbstractList<Member>() {
068                public Member get(int index) {
069                    return list.get(startIndex + index);
070                }
071
072                public int size() {
073                    return arity;
074                }
075            };
076        if (mutable) {
077            return Util.flatList(list1);
078        }
079        return list1;
080    }
081
082    public void add(int index, List<Member> element) {
083        assert mutable;
084        list.addAll(index * arity, element);
085    }
086
087    public void addTuple(Member... members) {
088        assert mutable;
089        list.addAll(Arrays.asList(members));
090    }
091
092    @Override
093    public void clear() {
094        assert mutable;
095        list.clear();
096    }
097
098    @Override
099    public List<Member> remove(int index) {
100        assert mutable;
101        for (int i = 0, n = index * arity; i < arity; i++) {
102            list.remove(n);
103        }
104        return null; // breach of List contract
105    }
106
107    @Override
108    protected void removeRange(int fromIndex, int toIndex) {
109        assert mutable;
110        list.subList(fromIndex * arity, toIndex * arity).clear();
111    }
112
113    public int size() {
114        return list.size() / arity;
115    }
116
117    public List<Member> slice(final int column) {
118        if (column < 0 || column >= arity) {
119            throw new IllegalArgumentException();
120        }
121        return new AbstractList<Member>() {
122            @Override
123            public Member get(int index) {
124                return ListTupleList.this.get(column, index);
125            }
126
127            @Override
128            public int size() {
129                return ListTupleList.this.size();
130            }
131        };
132    }
133
134    public TupleList cloneList(int capacity) {
135        return new ListTupleList(
136            arity,
137            capacity < 0
138                ? new ArrayList<Member>(list)
139                : new ArrayList<Member>(capacity * arity));
140    }
141
142    public TupleIterator tupleIteratorInternal() {
143        return new AbstractTupleListIterator();
144    }
145}
146
147// End ListTupleList.java