io.deephaven.engine.table.impl.RedefinableTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deephaven-engine-table Show documentation
Show all versions of deephaven-engine-table Show documentation
Engine Table: Implementation and closely-coupled utilities
/**
* Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
*/
package io.deephaven.engine.table.impl;
import io.deephaven.api.Selectable;
import io.deephaven.api.Pair;
import io.deephaven.engine.table.ColumnDefinition;
import io.deephaven.engine.table.Table;
import io.deephaven.engine.table.TableDefinition;
import io.deephaven.engine.table.impl.select.*;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* An uncoalesced table that may be redefined without triggering a {@link #coalesce()}.
*/
public abstract class RedefinableTable>
extends UncoalescedTable {
protected RedefinableTable(@NotNull final TableDefinition definition, @NotNull final String description) {
super(definition, description);
}
@Override
public Table view(Collection extends Selectable> selectables) {
return viewInternal(selectables, false);
}
@Override
public Table updateView(Collection extends Selectable> selectables) {
return viewInternal(selectables, true);
}
private Table viewInternal(Collection extends Selectable> selectables, boolean isUpdate) {
if (selectables == null || selectables.isEmpty()) {
return this;
}
final SelectColumn[] columns = Stream.concat(
isUpdate ? definition.getColumnStream().map(cd -> new SourceColumn(cd.getName())) : Stream.empty(),
selectables.stream().map(SelectColumn::of))
.toArray(SelectColumn[]::new);
final Set> resultColumnsInternal = new HashSet<>();
final Map> resultColumnsExternal = new LinkedHashMap<>();
final Map> allColumns = new HashMap<>(definition.getColumnNameMap());
boolean simpleRetain = true;
for (final SelectColumn selectColumn : columns) {
List usedColumnNames = selectColumn.initDef(allColumns);
usedColumnNames.addAll(selectColumn.getColumnArrays());
resultColumnsInternal.addAll(usedColumnNames.stream()
.filter(usedColumnName -> !resultColumnsExternal.containsKey(usedColumnName))
.map(definition::getColumn).collect(Collectors.toList()));
final ColumnDefinition> columnDef;
if (selectColumn.isRetain()) {
columnDef = definition.getColumn(selectColumn.getName());
} else {
simpleRetain = false;
columnDef = ColumnDefinition.fromGenericType(selectColumn.getName(), selectColumn.getReturnedType());
}
resultColumnsExternal.put(selectColumn.getName(), columnDef);
allColumns.put(selectColumn.getName(), columnDef);
}
TableDefinition newDefExternal = TableDefinition.of(
resultColumnsExternal.values().toArray(ColumnDefinition.ZERO_LENGTH_COLUMN_DEFINITION_ARRAY));
if (simpleRetain) {
// NB: We use the *external* TableDefinition because it's ordered appropriately.
return redefine(newDefExternal);
}
TableDefinition newDefInternal =
TableDefinition.of(
resultColumnsInternal.toArray(ColumnDefinition.ZERO_LENGTH_COLUMN_DEFINITION_ARRAY));
return redefine(newDefExternal, newDefInternal, columns);
}
@Override
public Table dropColumns(final String... columnNames) {
if (columnNames == null || columnNames.length == 0) {
return this;
}
final Set columnNamesToDrop = new HashSet<>(Arrays.asList(columnNames));
definition.checkHasColumns(columnNamesToDrop);
List> resultColumns = new ArrayList<>();
for (ColumnDefinition> cDef : definition.getColumns()) {
if (!columnNamesToDrop.contains(cDef.getName())) {
resultColumns.add(cDef);
}
}
return redefine(TableDefinition.of(resultColumns));
}
@Override
public Table renameColumns(Collection pairs) {
if (pairs == null || pairs.isEmpty()) {
return prepareReturnThis();
}
Map> columnDependency = new HashMap<>();
Map pairLookup = new HashMap<>();
for (Pair pair : pairs) {
ColumnDefinition> cDef = definition.getColumn(pair.input().name());
if (cDef == null) {
throw new IllegalArgumentException("Column \"" + pair.input().name() + "\" not found");
}
pairLookup.put(pair.input().name(), pair.output().name());
}
ColumnDefinition>[] columnDefinitions = definition.getColumnsArray();
ColumnDefinition>[] resultColumnsExternal = new ColumnDefinition[columnDefinitions.length];
SelectColumn[] viewColumns = new SelectColumn[columnDefinitions.length];
for (int ci = 0; ci < columnDefinitions.length; ++ci) {
ColumnDefinition> cDef = columnDefinitions[ci];
String newName = pairLookup.get(cDef.getName());
if (newName == null) {
resultColumnsExternal[ci] = cDef;
viewColumns[ci] = new SourceColumn(cDef.getName());
} else {
resultColumnsExternal[ci] = cDef.withName(newName);
viewColumns[ci] = new SourceColumn(cDef.getName(), newName);
}
}
return redefine(TableDefinition.of(resultColumnsExternal), definition, viewColumns);
}
/**
* Redefine this table with a subset of its current columns.
*
* @param newDefinition A TableDefinition with a subset of this RedefinableTable's ColumnDefinitions.
* @return
*/
protected abstract Table redefine(TableDefinition newDefinition);
/**
* Redefine this table with a subset of its current columns, with a potentially-differing definition to present to
* external interfaces and one or more select columns to apply.
*
* @param newDefinitionExternal A TableDefinition that represents the results of
* redefine(newDefinitionInternal).view(viewColumns).
* @param newDefinitionInternal A TableDefinition with a subset of this RedefinableTable's ColumnDefinitions.
* @param viewColumns A set of SelectColumns to apply in order to transform a table with newDefinitionInternal to a
* table with newDefinitionExternal.
* @return
*/
protected abstract Table redefine(TableDefinition newDefinitionExternal, TableDefinition newDefinitionInternal,
SelectColumn[] viewColumns);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy