/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.dashbuilder.dataset.engine.index; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dashbuilder.dataset.impl.MemSizeEstimator; import org.dashbuilder.dataset.engine.index.visitor.DataSetIndexVisitor; import org.dashbuilder.dataset.filter.ColumnFilter; import org.dashbuilder.dataset.group.AggregateFunctionType; import org.dashbuilder.dataset.group.ColumnGroup; import org.dashbuilder.dataset.sort.DataSetSort; /** * A DataSet index node */ public abstract class DataSetIndexNode extends DataSetIndexElement { DataSetIndexNode parent = null; List<Integer> rows = null; List<DataSetGroupIndex> groupIndexes = null; List<DataSetSortIndex> sortIndexes = null; List<DataSetFilterIndex> filterIndexes = null; Map<String, Map<AggregateFunctionType, DataSetFunctionIndex>> functionIndexes = null; public DataSetIndexNode() { this(null, null, 0); } public DataSetIndexNode(DataSetIndexNode parent, List<Integer> rows, long buildTime) { super(buildTime); this.parent = parent; this.rows = rows; } public DataSetIndexNode getParent() { return parent; } public void setParent(DataSetIndexNode parent) { this.parent = parent; } public List<Integer> getRows() { return rows; } public long getEstimatedSize() { long result = super.getEstimatedSize(); if (rows != null) { result += rows.size() * MemSizeEstimator.sizeOfInteger; } return result; } public void acceptVisitor(DataSetIndexVisitor visitor) { super.acceptVisitor(visitor); if (groupIndexes != null) { for (DataSetGroupIndex index : groupIndexes) { index.acceptVisitor(visitor); } } if (filterIndexes != null) { for (DataSetFilterIndex index : filterIndexes) { index.acceptVisitor(visitor); } } if (sortIndexes != null) { for (DataSetSortIndex index : sortIndexes) { index.acceptVisitor(visitor); } } if (functionIndexes != null) { for (Map<AggregateFunctionType, DataSetFunctionIndex> indexMap : functionIndexes.values()) { for (DataSetFunctionIndex index : indexMap.values()) { index.acceptVisitor(visitor); } } } } // Aggregate function indexes public DataSetFunctionIndex indexAggValue(String columnId, AggregateFunctionType type, Double value, long buildTime) { if (functionIndexes == null) functionIndexes = new HashMap<String, Map<AggregateFunctionType, DataSetFunctionIndex>>(); Map<AggregateFunctionType,DataSetFunctionIndex> columnAggFunctions = functionIndexes.get(columnId); if (columnAggFunctions == null) { functionIndexes.put(columnId, columnAggFunctions = new EnumMap<AggregateFunctionType, DataSetFunctionIndex>(AggregateFunctionType.class)); } DataSetFunctionIndex index = new DataSetFunctionIndex(value, buildTime); columnAggFunctions.put(type, index); return index; } public Double getAggValue(String columnId, AggregateFunctionType type) { if (functionIndexes == null) return null; Map<AggregateFunctionType,DataSetFunctionIndex> columnAggFunctions = functionIndexes.get(columnId); if (columnAggFunctions == null) return null; DataSetFunctionIndex functionIndex = columnAggFunctions.get(type); if (functionIndex == null) return null; functionIndex.reuseHit(); return functionIndex.getValue(); } // TODO: coordinate concurrent index modifications // Group indexes public DataSetGroupIndex indexGroup(DataSetGroupIndex index) { if (groupIndexes == null) groupIndexes = new ArrayList<DataSetGroupIndex>(); index.setParent(this); index.setBuildTime(buildTime); groupIndexes.add(index); return index; } public DataSetGroupIndex getGroupIndex(ColumnGroup gc) { if (groupIndexes == null) return null; String key = getGroupKey(gc); for (DataSetGroupIndex groupIndex : groupIndexes) { ColumnGroup c = groupIndex.columnGroup; if (key.equals(getGroupKey(c))) { groupIndex.reuseHit(); return groupIndex; } } return null; } public String getGroupKey(ColumnGroup columnGroup) { return columnGroup.getSourceId() + "_" + columnGroup.getStrategy().toString() + "_" + columnGroup.getIntervalSize() + "_" + columnGroup.getMaxIntervals() + "_" + columnGroup.areEmptyIntervalsAllowed() + "_" + columnGroup.isAscendingOrder() + (columnGroup.getFirstMonthOfYear() != null ? "_" + columnGroup.getFirstMonthOfYear() : "") + (columnGroup.getFirstDayOfWeek() != null ? "_" + columnGroup.getFirstDayOfWeek() : ""); } // Filter indexes public DataSetFilterIndex indexFilter(ColumnFilter filter, List<Integer> rows, long buildTime) { if (filterIndexes == null) filterIndexes = new ArrayList<DataSetFilterIndex>(); DataSetFilterIndex index = new DataSetFilterIndex(filter, rows); index.setParent(this); index.setBuildTime(buildTime); filterIndexes.add(index); return index; } public DataSetFilterIndex getFilterIndex(ColumnFilter filter) { if (filterIndexes == null) return null; for (DataSetFilterIndex index: filterIndexes) { if (filter.equals(index.getColumnFilter())) { index.reuseHit(); return index; } } return null; } // Sort indexes public DataSetSortIndex indexSort(DataSetSort sortOp, List<Integer> sortedRows, long buildTime) { if (sortIndexes == null) sortIndexes = new ArrayList<DataSetSortIndex>(); DataSetSortIndex index = new DataSetSortIndex(sortOp, sortedRows); index.setParent(this); index.setBuildTime(buildTime); sortIndexes.add(index); // Also create an index for the inverted sort. DataSetSort invertedSortOp = sortOp.cloneInstance().invertOrder(); List<Integer> invertedRows = new ArrayList<Integer>(sortedRows); Collections.reverse(invertedRows); DataSetSortIndex invertedIndex = new DataSetSortIndex(invertedSortOp, invertedRows); invertedIndex.setParent(this); sortIndexes.add(invertedIndex); return index; } public DataSetSortIndex getSortIndex(DataSetSort sortOp) { if (sortIndexes == null) return null; for (DataSetSortIndex sortIndex : sortIndexes) { if (sortOp.equals(sortIndex.getSortOp())) { sortIndex.reuseHit(); return sortIndex; } } return null; } }