001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/DenseSegmentDataset.java#9 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2002-2002 Kana Software, Inc. 007 // Copyright (C) 2002-2007 Julian Hyde and others 008 // All Rights Reserved. 009 // You must accept the terms of that agreement to use this software. 010 // 011 // jhyde, 21 March, 2002 012 */ 013 package mondrian.rolap.agg; 014 015 import mondrian.rolap.CellKey; 016 017 import java.util.Map; 018 import java.util.Iterator; 019 020 /** 021 * A <code>DenseSegmentDataset</code> is a means of storing segment values 022 * which is suitable when most of the combinations of keys have a value 023 * present. 024 * 025 * <p>The storage requirements are as follows. Table requires 1 word per 026 * cell.</p> 027 * 028 * @author jhyde 029 * @since 21 March, 2002 030 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/DenseSegmentDataset.java#9 $ 031 */ 032 class DenseSegmentDataset implements SegmentDataset { 033 private final Segment segment; 034 private final Object[] values; // length == m[0] * ... * m[axes.length-1] 035 036 DenseSegmentDataset(Segment segment, Object[] values) { 037 this.segment = segment; 038 this.values = values; 039 } 040 041 public Object get(CellKey key) { 042 int offset = getOffset(key.getOrdinals()); 043 return values[offset]; 044 } 045 046 public double getBytes() { 047 // assume a slot, key, and value are each 4 bytes 048 return values.length * 12; 049 } 050 051 public void put(CellKey key, Object value) { 052 int offset = getOffset(key.getOrdinals()); 053 values[offset] = value; 054 } 055 056 public Iterator<Map.Entry<CellKey, Object>> iterator() { 057 return new Itr(); 058 } 059 060 boolean contains(Object[] keys) { 061 return getOffset(keys) >= 0; 062 } 063 064 Object get(Object[] keys) { 065 int offset = getOffset(keys); 066 return keys[offset]; 067 } 068 069 void put(Object[] keys, Object value) { 070 int offset = getOffset(keys); 071 keys[offset] = value; 072 } 073 074 private int getOffset(int[] keys) { 075 int offset = 0; 076 for (int i = 0; i < keys.length; i++) { 077 Aggregation.Axis axis = segment.axes[i]; 078 Object[] ks = axis.getKeys(); 079 offset *= ks.length; 080 offset += keys[i]; 081 } 082 return offset; 083 } 084 085 private int getOffset(Object[] keys) { 086 int offset = 0; 087 outer: 088 for (int i = 0; i < keys.length; i++) { 089 Aggregation.Axis axis = segment.axes[i]; 090 Object[] ks = axis.getKeys(); 091 offset *= ks.length; 092 Object value = keys[i]; 093 for (int j = 0, axisLength = ks.length; j < axisLength; j++) { 094 if (ks[j].equals(value)) { 095 offset += j; 096 continue outer; 097 } 098 } 099 return -1; // not found 100 } 101 return offset; 102 } 103 104 void set(int k, Object o) { 105 values[k] = o; 106 } 107 108 /** 109 * Iterator over a DenseSegmentDataset. 110 * 111 * <p>This is a 'cheap' implementation 112 * which doesn't allocate a new Entry every step: it just returns itself. 113 * The Entry must therefore be used immediately, before calling 114 * {@link #next()} again. 115 */ 116 private class Itr implements 117 Iterator<Map.Entry<CellKey, Object>>, 118 Map.Entry<CellKey, Object> 119 { 120 private int i = -1; 121 private final int[] ordinals; 122 private final CellKey key; 123 124 Itr() { 125 ordinals = new int[segment.axes.length]; 126 ordinals[ordinals.length - 1] = -1; 127 key = CellKey.Generator.newRefCellKey(ordinals); 128 } 129 130 public boolean hasNext() { 131 return i < values.length - 1; 132 } 133 134 public Map.Entry<CellKey, Object> next() { 135 ++i; 136 int k = ordinals.length - 1; 137 while (k >= 0) { 138 if (ordinals[k] < segment.axes[k].getKeys().length - 1) { 139 ++ordinals[k]; 140 break; 141 } else { 142 ordinals[k] = 0; 143 --k; 144 } 145 } 146 return this; 147 } 148 149 // implement Iterator 150 public void remove() { 151 throw new UnsupportedOperationException(); 152 } 153 154 // implement Entry 155 public CellKey getKey() { 156 return key; 157 } 158 159 // implement Entry 160 public Object getValue() { 161 return values[i]; 162 } 163 164 // implement Entry 165 public Object setValue(Object value) { 166 throw new UnsupportedOperationException(); 167 } 168 } 169 } 170 171 // End DenseSegmentDataset.java