/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.cassandra.cql3.selection;

import java.util.*;
import java.util.stream.Collectors;

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
/** * 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() { return columnMappings.asMap() .entrySet() .stream() .map(entry -> entry.getValue() .stream() .map(colDef -> colDef.name.toString()) .collect(Collectors.joining(", ", entry.getKey().name.toString() + ":[", "]"))) .collect(Collectors.joining(", ", columnSpecifications.stream() .map(colSpec -> colSpec.name.toString()) .collect(Collectors.joining(", ", "{ Columns:[", "], Mappings:{")), "} }")); } }