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-2013 Pentaho and others 008// All Rights Reserved. 009*/ 010package mondrian.rolap.agg; 011 012import mondrian.rolap.CellKey; 013import mondrian.spi.SegmentBody; 014import mondrian.util.Pair; 015 016import java.util.*; 017 018/** 019 * Abstract implementation of a SegmentBody. 020 * 021 * @author LBoudreau 022 */ 023abstract class AbstractSegmentBody implements SegmentBody { 024 private static final long serialVersionUID = -7094121704771005640L; 025 026 protected final SortedSet<Comparable>[] axisValueSets; 027 private final boolean[] nullAxisFlags; 028 029 public AbstractSegmentBody( 030 List<Pair<SortedSet<Comparable>, Boolean>> axes) 031 { 032 super(); 033 //noinspection unchecked 034 this.axisValueSets = new SortedSet[axes.size()]; 035 this.nullAxisFlags = new boolean[axes.size()]; 036 for (int i = 0; i < axes.size(); i++) { 037 Pair<SortedSet<Comparable>, Boolean> pair = axes.get(i); 038 axisValueSets[i] = pair.left; 039 nullAxisFlags[i] = pair.right; 040 } 041 } 042 043 public SortedSet<Comparable>[] getAxisValueSets() { 044 return axisValueSets; 045 } 046 047 public boolean[] getNullAxisFlags() { 048 return nullAxisFlags; 049 } 050 051 public Map<CellKey, Object> getValueMap() { 052 return new AbstractMap<CellKey, Object>() { 053 public Set<Entry<CellKey, Object>> entrySet() { 054 return new AbstractSet<Entry<CellKey, Object>>() { 055 public Iterator<Entry<CellKey, Object>> iterator() { 056 return new SegmentBodyIterator(); 057 } 058 059 public int size() { 060 return getSize(); 061 } 062 }; 063 } 064 }; 065 } 066 067 public Object getValueArray() { 068 throw new UnsupportedOperationException( 069 "This method is only supported for dense segments"); 070 } 071 072 public BitSet getNullValueIndicators() { 073 throw new UnsupportedOperationException( 074 "This method is only supported for dense segments " 075 + "of native values"); 076 } 077 078 protected abstract int getSize(); 079 080 protected abstract Object getObject(int i); 081 082 /** 083 * Iterator over all (cellkey, value) pairs in this data set. 084 */ 085 private class SegmentBodyIterator 086 implements Iterator<Map.Entry<CellKey, Object>> 087 { 088 private int i = -1; 089 private final int[] ordinals; 090 private final int size = getSize(); 091 private boolean hasNext = true; 092 private Object next; 093 094 SegmentBodyIterator() { 095 ordinals = new int[axisValueSets.length]; 096 ordinals[ordinals.length - 1] = -1; 097 moveToNext(); 098 } 099 100 public boolean hasNext() { 101 return hasNext; 102 } 103 104 public Map.Entry<CellKey, Object> next() { 105 Pair<CellKey, Object> o = 106 Pair.of(CellKey.Generator.newCellKey(ordinals), next); 107 moveToNext(); 108 return o; 109 } 110 111 private void moveToNext() { 112 for (;;) { 113 ++i; 114 if (i >= size) { 115 hasNext = false; 116 return; 117 } 118 int k = ordinals.length - 1; 119 while (k >= 0) { 120 if (ordinals[k] < axisValueSets[k].size() - 1) { 121 ++ordinals[k]; 122 break; 123 } else { 124 ordinals[k] = 0; 125 --k; 126 } 127 } 128 next = getObject(i); 129 if (next != null) { 130 return; 131 } 132 } 133 } 134 135 public void remove() { 136 throw new UnsupportedOperationException(); 137 } 138 } 139} 140 141// End AbstractSegmentBody.java