Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* 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.metamodel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.metamodel.data.CachingDataSetHeader;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.data.DataSetHeader;
import org.apache.metamodel.data.DefaultRow;
import org.apache.metamodel.data.EmptyDataSet;
import org.apache.metamodel.data.FilteredDataSet;
import org.apache.metamodel.data.FirstRowDataSet;
import org.apache.metamodel.data.InMemoryDataSet;
import org.apache.metamodel.data.MaxRowsDataSet;
import org.apache.metamodel.data.Row;
import org.apache.metamodel.data.ScalarFunctionDataSet;
import org.apache.metamodel.data.SimpleDataSetHeader;
import org.apache.metamodel.data.SubSelectionDataSet;
import org.apache.metamodel.query.FilterItem;
import org.apache.metamodel.query.FromItem;
import org.apache.metamodel.query.GroupByItem;
import org.apache.metamodel.query.OrderByItem;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.query.ScalarFunction;
import org.apache.metamodel.query.SelectItem;
import org.apache.metamodel.query.parser.QueryParser;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.ColumnType;
import org.apache.metamodel.schema.Schema;
import org.apache.metamodel.schema.SuperColumnType;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.schema.WrappingSchema;
import org.apache.metamodel.schema.WrappingTable;
import org.apache.metamodel.util.AggregateBuilder;
import org.apache.metamodel.util.CollectionUtils;
import org.apache.metamodel.util.ObjectComparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class contains various helper functionality to common tasks in MetaModel, eg.:
*
*
*
Easy-access for traversing common schema items
*
Manipulate data in memory. These methods are primarily used to enable queries for non-queryable data sources like
* CSV files and spreadsheets.
*
Query rewriting, traversing and manipulation.
*
*
* The class is mainly intended for internal use within the framework operations, but is kept stable, so it can also be
* used by framework users.
*/
public final class MetaModelHelper {
private final static Logger logger = LoggerFactory.getLogger(MetaModelHelper.class);
private MetaModelHelper() {
// Prevent instantiation
}
/**
* Creates an array of tables where all occurrences of tables in the provided list of tables and columns are included
*/
public static Table[] getTables(Collection
tableList, Iterable columnList) {
HashSet
set = new HashSet
();
set.addAll(tableList);
for (Column column : columnList) {
set.add(column.getTable());
}
return set.toArray(new Table[set.size()]);
}
/**
* Determines if a schema is an information schema
*
* @param schema
* @return
*/
public static boolean isInformationSchema(Schema schema) {
String name = schema.getName();
return isInformationSchema(name);
}
/**
* Determines if a schema name is the name of an information schema
*
* @param name
* @return
*/
public static boolean isInformationSchema(String name) {
if (name == null) {
return false;
}
return QueryPostprocessDataContext.INFORMATION_SCHEMA_NAME.equals(name.toLowerCase());
}
/**
* Converts a list of columns to a corresponding array of tables
*
* @param columns the columns that the tables will be extracted from
* @return an array containing the tables of the provided columns.
*/
public static Table[] getTables(Iterable columns) {
ArrayList
result = new ArrayList
();
for (Column column : columns) {
Table table = column.getTable();
if (!result.contains(table)) {
result.add(table);
}
}
return result.toArray(new Table[result.size()]);
}
/**
* Creates a subset array of columns, where only columns that are contained within the specified table are included.
*
* @param table
* @param columns
* @return an array containing the columns that exist in the table
*/
public static Column[] getTableColumns(Table table, Iterable columns) {
if (table == null) {
return new Column[0];
}
final List result = new ArrayList();
for (Column column : columns) {
final boolean sameTable = table.equals(column.getTable());
if (sameTable) {
result.add(column);
}
}
return result.toArray(new Column[result.size()]);
}
/**
* Creates a subset array of columns, where only columns that are contained within the specified table are included.
*
* @param table
* @param columns
* @return an array containing the columns that exist in the table
*/
public static Column[] getTableColumns(Table table, Column[] columns) {
return getTableColumns(table, Arrays.asList(columns));
}
public static DataSet getCarthesianProduct(DataSet... fromDataSets) {
return getCarthesianProduct(fromDataSets, new FilterItem[0]);
}
public static DataSet getCarthesianProduct(DataSet[] fromDataSets, FilterItem... filterItems) {
return getCarthesianProduct(fromDataSets, Arrays.asList(filterItems));
}
public static DataSet getCarthesianProduct(DataSet[] fromDataSets, Iterable whereItems) {
assert (fromDataSets.length > 0);
// First check if carthesian product is even necessary
if (fromDataSets.length == 1) {
return getFiltered(fromDataSets[0], whereItems);
}
// do a nested loop join, no matter what
Iterator dsIter = Arrays.asList(fromDataSets).iterator();
DataSet joined = dsIter.next();
while (dsIter.hasNext()) {
joined = nestedLoopJoin(dsIter.next(), joined, (whereItems));
}
return joined;
}
/**
* Executes a simple nested loop join. The innerLoopDs will be copied in an in-memory dataset.
*
*/
public static InMemoryDataSet nestedLoopJoin(DataSet innerLoopDs, DataSet outerLoopDs,
Iterable filtersIterable) {
List filters = new ArrayList<>();
for (FilterItem fi : filtersIterable) {
filters.add(fi);
}
List innerRows = innerLoopDs.toRows();
List allItems = new ArrayList<>(outerLoopDs.getSelectItems());
allItems.addAll(innerLoopDs.getSelectItems());
Set applicableFilters = applicableFilters(filters, allItems);
DataSetHeader jointHeader = new CachingDataSetHeader(allItems);
List resultRows = new ArrayList<>();
for (Row outerRow : outerLoopDs) {
for (Row innerRow : innerRows) {
Object[] joinedRowObjects = new Object[outerRow.getValues().length + innerRow.getValues().length];
System.arraycopy(outerRow.getValues(), 0, joinedRowObjects, 0, outerRow.getValues().length);
System.arraycopy(innerRow.getValues(), 0, joinedRowObjects, outerRow.getValues().length,
innerRow.getValues().length);
Row joinedRow = new DefaultRow(jointHeader, joinedRowObjects);
if (applicableFilters.isEmpty() || applicableFilters.stream().allMatch(fi -> fi.accept(joinedRow))) {
resultRows.add(joinedRow);
}
}
}
return new InMemoryDataSet(jointHeader, resultRows);
}
/**
* Filters the FilterItems such that only the FilterItems are returned, which contain SelectItems that are contained
* in selectItemList
*
* @param filters
* @param selectItemList
* @return
*/
private static Set applicableFilters(Collection filters,
Collection selectItemList) {
final Set items = new HashSet<>(selectItemList);
return filters.stream().filter(fi -> items.containsAll(getSelectItems(fi))).collect(Collectors.toSet());
}
private static Set getSelectItems(final FilterItem filterItem) {
final Set itemsInFilter = new HashSet<>();
if (filterItem.getChildItemCount() == 0) {
itemsInFilter.add(filterItem.getSelectItem());
final Object operand = filterItem.getOperand();
if (operand instanceof SelectItem) {
itemsInFilter.add((SelectItem) operand);
}
} else {
for (FilterItem childFilterItem : filterItem.getChildItems()) {
itemsInFilter.addAll(getSelectItems(childFilterItem));
}
}
return itemsInFilter;
}
public static DataSet getFiltered(DataSet dataSet, Iterable filterItems) {
final FilterItem[] filterItemsArray =
StreamSupport.stream(filterItems.spliterator(), false).toArray(FilterItem[]::new);
return getFiltered(dataSet, filterItemsArray);
}
public static DataSet getFiltered(DataSet dataSet, FilterItem... filterItems) {
if (filterItems == null || filterItems.length == 0) {
return dataSet;
}
return getFiltered(dataSet, Arrays.asList(filterItems));
}
public static DataSet getFiltered(DataSet dataSet, Collection filterItems) {
if (filterItems == null || filterItems.isEmpty()) {
return dataSet;
}
final List selectItemsOnOutput = dataSet.getSelectItems();
final Iterable selectItems =
filterItems.stream().map(f -> f.getSelectItem()).filter(s -> s != null)::iterator;
final List scalarFunctionSelectItems =
getUnmaterializedScalarFunctionSelectItems(selectItems, dataSet);
final boolean calculateScalarFunctions = !scalarFunctionSelectItems.isEmpty();
if (calculateScalarFunctions) {
// scalar functions are needed in evaluation of the filters
dataSet = new ScalarFunctionDataSet(scalarFunctionSelectItems, dataSet);
}
final FilteredDataSet filteredDataSet = new FilteredDataSet(dataSet, filterItems);
if (calculateScalarFunctions) {
return getSelection(selectItemsOnOutput, filteredDataSet);
} else {
return filteredDataSet;
}
}
public static DataSet getSelection(final List selectItems, final DataSet dataSet) {
final List dataSetSelectItems = dataSet.getSelectItems();
// check if the selection is already the same
if (selectItems.equals(dataSetSelectItems)) {
// return the DataSet unmodified
return dataSet;
}
final List scalarFunctionSelectItemsToEvaluate = new ArrayList<>();
for (SelectItem selectItem : selectItems) {
if (selectItem.getScalarFunction() != null) {
if (!dataSetSelectItems.contains(selectItem)
&& dataSetSelectItems.contains(selectItem.replaceFunction(null))) {
scalarFunctionSelectItemsToEvaluate.add(selectItem);
}
}
}
if (scalarFunctionSelectItemsToEvaluate.isEmpty()) {
return new SubSelectionDataSet(selectItems, dataSet);
}
final ScalarFunctionDataSet scalaFunctionDataSet =
new ScalarFunctionDataSet(scalarFunctionSelectItemsToEvaluate, dataSet);
return new SubSelectionDataSet(selectItems, scalaFunctionDataSet);
}
public static DataSet getSelection(SelectItem[] selectItems, DataSet dataSet) {
return getSelection(Arrays.asList(selectItems), dataSet);
}
public static DataSet getGrouped(List selectItems, DataSet dataSet,
Collection groupByItems) {
DataSet result = dataSet;
if (groupByItems != null && groupByItems.size() > 0) {
Map>> uniqueRows = new HashMap>>();
final List groupBySelects =
groupByItems.stream().map(gbi -> gbi.getSelectItem()).collect(Collectors.toList());
final DataSetHeader groupByHeader = new CachingDataSetHeader(groupBySelects);
// Creates a list of SelectItems that have aggregate functions
List functionItems = getAggregateFunctionSelectItems(selectItems);
// Loop through the dataset and identify groups
while (dataSet.next()) {
Row row = dataSet.getRow();
// Subselect a row prototype with only the unique values that
// define the group
Row uniqueRow = row.getSubSelection(groupByHeader);
// function input is the values used for calculating aggregate
// functions in the group
Map> functionInput;
if (!uniqueRows.containsKey(uniqueRow)) {
// If this group already exist, use an existing function
// input
functionInput = new HashMap>();
for (SelectItem item : functionItems) {
functionInput.put(item, new ArrayList