/**
* 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.hadoop.zebra.types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
import org.apache.hadoop.zebra.schema.Schema;
import org.apache.hadoop.zebra.parser.ParseException;
/**
* Projection for Table and Column Group
*/
public class Projection {
public static final String source_table_vcolumn_name = "source_table";
private Schema mProjection; // schema as needed by the projection
private int mNumColumns;
private String mProjStr;
//TODO: change name and comment - to yan
private Schema mSchema; // the logical schema literally from projection string
/* the maps from the column in projection to a set of map keys
* the projection is interested. If null, all keys in schema are interested
*/
private HashMap<Schema.ColumnSchema, HashSet<String>> mKeys;
/**
* ctor for full projection
*/
public Projection(Schema s) {
mProjection = s;
if (s != null)
{
mNumColumns = s.getNumColumns();
mProjStr = s.toString();
mSchema = s;
}
}
/**
* if a column name is on a virtual column
*/
public static boolean isVirtualColumn(String name)
{
if (name == null || name.isEmpty())
return false;
return name.trim().equalsIgnoreCase(source_table_vcolumn_name);
}
/**
* Get the indices of all virtual columns
*/
public static Integer[] getVirtualColumnIndices(String projection)
{
if (projection == null)
return null;
String[] colnames = projection.trim().split(Schema.COLUMN_DELIMITER);
int size = colnames.length, realsize = 0;
ArrayList<Integer> vcol = new ArrayList();
for (int i = 0; i < size; i++)
{
if (Projection.isVirtualColumn(colnames[i]))
{
vcol.add(i);
}
}
Integer[] result = null;
if (!vcol.isEmpty())
{
result = new Integer[vcol.size()];
vcol.toArray(result);
}
return result;
}
/**
* ctor for partial projection
*/
public Projection(Schema s, String projection) throws ParseException
{
String[] colnames = projection.trim().split(Schema.COLUMN_DELIMITER);
for (int nx = 0; nx < colnames.length; nx++)
{
colnames[nx] = colnames[nx].trim();
}
mKeys = new HashMap<Schema.ColumnSchema, HashSet<String>>();
mProjection = s.getProjectionSchema(colnames, mKeys);
mNumColumns = colnames.length;
mProjStr = projection;
mSchema = toSchema(projection);
}
/**
* accessor to the map keys
*/
HashMap<Schema.ColumnSchema, HashSet<String>> getKeys() {
return mKeys;
}
/**
* accessor to the projected schema including invalid columns
*/
public Schema getSchema() {
return mSchema;
}
/**
*
*/
public Schema getProjectionSchema()
{
return mProjection;
}
/**
* Get a particular projected column's schema
*/
public Schema.ColumnSchema getColumnSchema(int i)
{
return mProjection.getColumn(i);
}
/**
* Get the string representation
*/
public String toString() {
return mProjStr;
}
/**
* Get number of columns in the projection
*/
public int getNumColumns() {
return mNumColumns;
}
/**
* Get number of columns from a projection string
*/
public static int getNumColumns(String projection) {
return projection.trim().split(Schema.COLUMN_DELIMITER).length;
}
/**
* Get a projection string from a series of column names
*/
public static String getProjectionStr(String[] names) {
if (names == null)
return null;
String result = new String();
for (String name :names)
{
if (!result.isEmpty())
result += ",";
result += name;
}
return result;
}
/**
* Get schema from a projection string: all map keys are lost
*/
public static Schema toSchema(String projection) throws ParseException
{
String[] colnames = projection.trim().split(Schema.COLUMN_DELIMITER);
String schemaStr = new String();
int startidx, i = 0;
for (String name : colnames)
{
startidx = name.indexOf("#{");
if (startidx != -1)
{
if (!name.endsWith("}"))
throw new ParseException("Invalid projection");
startidx += 2;
if (name.substring(startidx, name.length()-1).indexOf("#") != -1 ||
name.substring(startidx, name.length()-1).indexOf("{") != -1 ||
name.substring(startidx, name.length()-1).indexOf("}") != -1)
throw new ParseException("Invalid projection");
name = name.substring(0, startidx-2);
} else {
if (name.indexOf("#") != -1 || name.indexOf("{") != -1 ||
name.indexOf("}") != -1)
throw new ParseException("Invalid projection");
}
if (i++ > 0)
schemaStr += ",";
schemaStr += name;
}
return new Schema(schemaStr, true);
}
/**
* Get a column's index in a projection.
* @param projection
* @param colname
* @return -1 if the column is not found in projection
*/
public static int getColumnIndex(String projection, String colname)
{
if (projection == null || colname == null)
return -1;
String[] colnames = projection.trim().split(Schema.COLUMN_DELIMITER);;
for (int i = 0; i < colnames.length; i++)
{
if (colnames[i].equals(colname))
return i;
}
return -1;
}
}