/* * 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 com.google.common.collect.Lists; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.functions.Function; import org.apache.cassandra.cql3.selection.Selector.Factory; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.exceptions.InvalidRequestException; /** * A set of <code>Selector</code> factories. */ final class SelectorFactories implements Iterable<Selector.Factory> { /** * The <code>Selector</code> factories. */ private final List<Selector.Factory> factories; /** * <code>true</code> if one of the factory creates writetime selectors. */ private boolean containsWritetimeFactory; /** * <code>true</code> if one of the factory creates TTL selectors. */ private boolean containsTTLFactory; /** * The number of factories creating aggregates. */ private int numberOfAggregateFactories; /** * Creates a new <code>SelectorFactories</code> instance and collect the column definitions. * * @param selectables the <code>Selectable</code>s for which the factories must be created * @param cfm the Column Family Definition * @param defs the collector parameter for the column definitions * @return a new <code>SelectorFactories</code> instance * @throws InvalidRequestException if a problem occurs while creating the factories */ public static SelectorFactories createFactoriesAndCollectColumnDefinitions(List<Selectable> selectables, CFMetaData cfm, List<ColumnDefinition> defs) throws InvalidRequestException { return new SelectorFactories(selectables, cfm, defs); } private SelectorFactories(List<Selectable> selectables, CFMetaData cfm, List<ColumnDefinition> defs) throws InvalidRequestException { factories = new ArrayList<>(selectables.size()); for (Selectable selectable : selectables) { Factory factory = selectable.newSelectorFactory(cfm, defs); containsWritetimeFactory |= factory.isWritetimeSelectorFactory(); containsTTLFactory |= factory.isTTLSelectorFactory(); if (factory.isAggregateSelectorFactory()) ++numberOfAggregateFactories; factories.add(factory); } } public void addFunctionsTo(List<Function> functions) { factories.forEach(p -> p.addFunctionsTo(functions)); } /** * Returns the factory with the specified index. * * @param i the factory index * @return the factory with the specified index */ public Selector.Factory get(int i) { return factories.get(i); } /** * Adds a new <code>Selector.Factory</code> for a column that is needed only for ORDER BY purposes. * @param def the column that is needed for ordering * @param index the index of the column definition in the Selection's list of columns */ public void addSelectorForOrdering(ColumnDefinition def, int index) { factories.add(SimpleSelector.newFactory(def, index)); } /** * Whether the selector built by this factory does aggregation or not (either directly or in a sub-selector). * * @return <code>true</code> if the selector built by this factor does aggregation, <code>false</code> otherwise. */ public boolean doesAggregation() { return numberOfAggregateFactories > 0; } /** * Checks if this <code>SelectorFactories</code> contains at least one factory for writetime selectors. * * @return <code>true</code> if this <code>SelectorFactories</code> contains at least one factory for writetime * selectors, <code>false</code> otherwise. */ public boolean containsWritetimeSelectorFactory() { return containsWritetimeFactory; } /** * Checks if this <code>SelectorFactories</code> contains at least one factory for TTL selectors. * * @return <code>true</code> if this <code>SelectorFactories</code> contains at least one factory for TTL * selectors, <code>false</code> otherwise. */ public boolean containsTTLSelectorFactory() { return containsTTLFactory; } /** * Creates a list of new <code>Selector</code> instances. * @return a list of new <code>Selector</code> instances. */ public List<Selector> newInstances() throws InvalidRequestException { List<Selector> selectors = new ArrayList<>(factories.size()); for (Selector.Factory factory : factories) { selectors.add(factory.newInstance()); } return selectors; } public Iterator<Factory> iterator() { return factories.iterator(); } /** * Returns the names of the columns corresponding to the output values of the selector instances created by * these factories. * * @return a list of column names */ public List<String> getColumnNames() { return Lists.transform(factories, new com.google.common.base.Function<Selector.Factory, String>() { public String apply(Selector.Factory factory) { return factory.getColumnName(); } }); } /** * Returns a list of the return types of the selector instances created by these factories. * * @return a list of types */ public List<AbstractType<?>> getReturnTypes() { return Lists.transform(factories, new com.google.common.base.Function<Selector.Factory, AbstractType<?>>() { public AbstractType<?> apply(Selector.Factory factory) { return factory.getReturnType(); } }); } /** * Returns the number of factories. * @return the number of factories */ public int size() { return factories.size(); } }