/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.flatten;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.UUID;
import javax.inject.Inject;
import org.diqube.context.AutoInstatiate;
import org.diqube.data.column.AdjustableStandardColumnShard;
import org.diqube.data.column.ColumnPage;
import org.diqube.data.column.ColumnPageFactory;
import org.diqube.data.column.ColumnShardFactory;
import org.diqube.data.column.StandardColumnShard;
import org.diqube.data.flatten.FlattenDataFactory;
import org.diqube.data.flatten.FlattenedTable;
import org.diqube.data.table.TableFactory;
import org.diqube.data.table.TableShard;
import org.diqube.data.types.dbl.DoubleStandardColumnShard;
import org.diqube.data.types.lng.LongStandardColumnShard;
import org.diqube.data.types.str.StringStandardColumnShard;
import org.diqube.name.FlattenedTableNameUtil;
/**
* Util for {@link FlattenedTable}s.
*
* @author Bastian Gloeckle
*/
@AutoInstatiate
public class FlattenedTableUtil {
@Inject
private FlattenDataFactory factory;
@Inject
private FlattenedTableNameUtil flattenedTableNameGenerator;
@Inject
private ColumnPageFactory columnPageFactory;
@Inject
private ColumnShardFactory columnShardFactory;
@Inject
private TableFactory tableFactory;
/**
* Will facade the given table, so in the returned table, the
* {@link AdjustableStandardColumnShard#adjustToFirstRowId(long)} can be safely executed without changing the source
* table.
*
* <p>
* The returned table will have those firstRowIds of the table that the flattening was originally based on.
*
* @param inputTable
* The table to be facaded.
* @param Name
* of the original (not-flattened) table.
* @param flattenBy
* The field which was flattened by.
* @param flattenId
* The new ID of the flattening (will be used on returned table).
* @return New table object which re-uses as much as possible from input table, but its firstRowIds can be adjusted
* without changing the inputTable. The returned FlattenedTables firstRowIds (of all col shards and
* distributed validly across all colPages) basically is in the same state as
* {@link Flattener#flattenTable(org.diqube.data.table.Table, java.util.Collection, String, java.util.UUID)}
* would return.
*/
public FlattenedTable facadeWithDefaultRowIds(FlattenedTable inputTable, String origTableName, String flattenBy,
UUID flattenId) {
String newTableName = flattenedTableNameGenerator.createFlattenedTableName(origTableName, flattenBy, flattenId);
Collection<TableShard> newTableShards = new ArrayList<>();
List<TableShard> inputTableShardsSorted = new ArrayList<>(inputTable.getShards());
inputTableShardsSorted.sort((s1, s2) -> Long.compare(s1.getLowestRowId(), s2.getLowestRowId()));
Iterator<Long> origTableShardFirstRowIdIt =
inputTable.getOriginalFirstRowIdsOfShards().stream().sorted().iterator();
for (TableShard inputTableShard : inputTableShardsSorted) {
long origFirstRowId = origTableShardFirstRowIdIt.next();
Collection<StandardColumnShard> newColShards = new ArrayList<>();
for (StandardColumnShard inputColumnShard : inputTableShard.getColumns().values()) {
NavigableMap<Long, ColumnPage> newPages = new TreeMap<>();
long nextFirstRowId = origFirstRowId;
for (ColumnPage inputPage : inputColumnShard.getPages().values()) {
ColumnPage newPage;
// Use the original dict and values, but provide a different firstRowId.
newPage = columnPageFactory.createDefaultColumnPage(inputPage.getColumnPageDict(), inputPage.getValues(),
nextFirstRowId, inputColumnShard.getName() + "#" + nextFirstRowId);
nextFirstRowId += newPage.size();
newPages.put(newPage.getFirstRowId(), newPage);
}
StandardColumnShard newColShard = null;
switch (inputColumnShard.getColumnType()) {
case STRING:
newColShard = columnShardFactory.createStandardStringColumnShard(inputColumnShard.getName(), newPages,
((StringStandardColumnShard) inputColumnShard).getColumnShardDictionary());
break;
case LONG:
newColShard = columnShardFactory.createStandardLongColumnShard(inputColumnShard.getName(), newPages,
((LongStandardColumnShard) inputColumnShard).getColumnShardDictionary());
break;
case DOUBLE:
newColShard = columnShardFactory.createStandardDoubleColumnShard(inputColumnShard.getName(), newPages,
((DoubleStandardColumnShard) inputColumnShard).getColumnShardDictionary());
break;
}
newColShards.add(newColShard);
}
newTableShards.add(tableFactory.createDefaultTableShard(newTableName, newColShards));
}
return factory.createFlattenedTable(newTableName, newTableShards, inputTable.getOriginalFirstRowIdsOfShards());
}
}