blob: 33ef0af17f63969465bf39f3246697d65b48b588 [file] [log] [blame]
package org.apache.cassandra.cql3.selection;
import java.util.*;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.*;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.ColumnSpecification;
/**
* Separately maintains the ColumnSpecifications and their mappings to underlying
* columns as we may receive null mappings. This occurs where a query result
* includes a column specification which does not map to any particular real
* column, e.g. COUNT queries or where no-arg functions like now() are used
*/
public class SelectionColumnMapping implements SelectionColumns
{
private final ArrayList<ColumnSpecification> columnSpecifications;
private final HashMultimap<ColumnSpecification, ColumnDefinition> columnMappings;
private SelectionColumnMapping()
{
this.columnSpecifications = new ArrayList<>();
this.columnMappings = HashMultimap.create();
}
protected static SelectionColumnMapping newMapping()
{
return new SelectionColumnMapping();
}
protected static SelectionColumnMapping simpleMapping(Iterable<ColumnDefinition> columnDefinitions)
{
SelectionColumnMapping mapping = new SelectionColumnMapping();
for (ColumnDefinition def: columnDefinitions)
mapping.addMapping(def, def);
return mapping;
}
protected SelectionColumnMapping addMapping(ColumnSpecification colSpec, ColumnDefinition column)
{
columnSpecifications.add(colSpec);
// functions without arguments do not map to any column, so don't
// record any mapping in that case
if (column != null)
columnMappings.put(colSpec, column);
return this;
}
protected SelectionColumnMapping addMapping(ColumnSpecification colSpec, Iterable<ColumnDefinition> columns)
{
columnSpecifications.add(colSpec);
columnMappings.putAll(colSpec, columns);
return this;
}
public List<ColumnSpecification> getColumnSpecifications()
{
// return a mutable copy as we may add extra columns
// for ordering (CASSANDRA-4911 & CASSANDRA-8286)
return Lists.newArrayList(columnSpecifications);
}
public Multimap<ColumnSpecification, ColumnDefinition> getMappings()
{
return Multimaps.unmodifiableMultimap(columnMappings);
}
public boolean equals(Object obj)
{
if (obj == null)
return false;
if (!(obj instanceof SelectionColumnMapping))
return false;
SelectionColumns other = (SelectionColumns)obj;
return Objects.equal(columnMappings, other.getMappings())
&& Objects.equal(columnSpecifications, other.getColumnSpecifications());
}
public int hashCode()
{
return Objects.hashCode(columnMappings);
}
public String toString()
{
final Function<ColumnDefinition, String> getDefName = new Function<ColumnDefinition, String>()
{
public String apply(ColumnDefinition def)
{
return def.name.toString();
}
};
Function<Map.Entry<ColumnSpecification, Collection<ColumnDefinition>>, String> mappingEntryToString =
new Function<Map.Entry<ColumnSpecification, Collection<ColumnDefinition>>, String>(){
public String apply(Map.Entry<ColumnSpecification, Collection<ColumnDefinition>> entry)
{
StringBuilder builder = new StringBuilder();
builder.append(entry.getKey().name.toString());
builder.append(":[");
builder.append(Joiner.on(',').join(Iterables.transform(entry.getValue(), getDefName)));
builder.append("]");
return builder.toString();
}
};
Function<ColumnSpecification, String> colSpecToString = new Function<ColumnSpecification, String>()
{
public String apply(ColumnSpecification columnSpecification)
{
return columnSpecification.name.toString();
}
};
StringBuilder builder = new StringBuilder();
builder.append("{ Columns:[");
builder.append(Joiner.on(",")
.join(Iterables.transform(columnSpecifications, colSpecToString)));
builder.append("], Mappings:[");
builder.append(Joiner.on(", ")
.join(Iterables.transform(columnMappings.asMap().entrySet(),
mappingEntryToString)));
builder.append("] }");
return builder.toString();
}
}