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) 2010-2012 Pentaho and others
008// All Rights Reserved.
009*/
010package mondrian.rolap.agg;
011
012import mondrian.rolap.CellKey;
013import mondrian.rolap.SqlStatement;
014import mondrian.spi.SegmentBody;
015import mondrian.util.Pair;
016
017import java.util.*;
018
019/**
020 * A <code>SparseSegmentDataset</code> is a means of storing segment values
021 * which is suitable when few of the combinations of keys have a value present.
022 *
023 * <p>The storage requirements are as follows. Key is 1 word for each
024 * dimension. Hashtable entry is 3 words. Value is 1 word. Total space is (4 +
025 * d) * v. (May also need hash table to ensure that values are only stored
026 * once.)</p>
027 *
028 * <p>NOTE: This class is not synchronized.</p>
029 *
030 * @author jhyde
031 * @since 21 March, 2002
032 */
033class SparseSegmentDataset implements SegmentDataset {
034    private final Map<CellKey, Object> values;
035
036    /**
037     * Creates an empty SparseSegmentDataset.
038     */
039    SparseSegmentDataset() {
040        this(new HashMap<CellKey, Object>());
041    }
042
043    /**
044     * Creates a SparseSegmentDataset with a given value map. The map is not
045     * copied; a reference to the map is retained inside the dataset, and
046     * therefore the contents of the dataset will change if the map is modified.
047     *
048     * @param values Value map
049     */
050    SparseSegmentDataset(Map<CellKey, Object> values) {
051        this.values = values;
052    }
053
054    public Object getObject(CellKey pos) {
055        return values.get(pos);
056    }
057
058    public boolean isNull(CellKey pos) {
059        // cf exists -- calls values.containsKey
060        return values.get(pos) == null;
061    }
062
063    public int getInt(CellKey pos) {
064        throw new UnsupportedOperationException();
065    }
066
067    public double getDouble(CellKey pos) {
068        throw new UnsupportedOperationException();
069    }
070
071    public boolean exists(CellKey pos) {
072        return values.containsKey(pos);
073    }
074
075    public void put(CellKey key, Object value) {
076        values.put(key, value);
077    }
078
079    public Iterator<Map.Entry<CellKey, Object>> iterator() {
080        return values.entrySet().iterator();
081    }
082
083    public double getBytes() {
084        // assume a slot, key, and value are each 4 bytes
085        return values.size() * 12;
086    }
087
088    public void populateFrom(int[] pos, SegmentDataset data, CellKey key) {
089        values.put(CellKey.Generator.newCellKey(pos), data.getObject(key));
090    }
091
092    public void populateFrom(
093        int[] pos, SegmentLoader.RowList rowList, int column)
094    {
095        final Object o = rowList.getObject(column);
096        put(CellKey.Generator.newCellKey(pos), o);
097    }
098
099    public SqlStatement.Type getType() {
100        return SqlStatement.Type.OBJECT;
101    }
102
103    public SegmentBody createSegmentBody(
104        List<Pair<SortedSet<Comparable>, Boolean>> axes)
105    {
106        return new SparseSegmentBody(
107            values,
108            axes);
109    }
110}
111
112// End SparseSegmentDataset.java