/**
* 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.lens.cube.metadata;
import java.util.*;
import org.apache.lens.server.api.error.LensException;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.ql.metadata.Table;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractCubeTable implements Named {
private final String name;
private final List<FieldSchema> columns;
private final Map<String, String> properties = new HashMap<>();
private double weight;
protected AbstractCubeTable(String name, List<FieldSchema> columns, Map<String, String> props, double weight) {
this.name = name.toLowerCase();
this.columns = columns;
this.weight = weight;
if (props != null) {
this.properties.putAll(props);
}
}
protected AbstractCubeTable(Table hiveTable) {
this.name = hiveTable.getTableName().toLowerCase();
this.columns = hiveTable.getCols();
this.properties.putAll(hiveTable.getParameters());
this.weight = getWeight(getProperties(), getName());
}
public abstract CubeTableType getTableType();
public abstract Set<String> getStorages();
public Map<String, String> getProperties() {
return properties;
}
public static double getWeight(Map<String, String> properties, String name) {
String wtStr = properties.get(MetastoreUtil.getCubeTableWeightKey(name));
return wtStr == null ? 0L : Double.parseDouble(wtStr);
}
protected void addProperties() {
properties.put(MetastoreConstants.TABLE_TYPE_KEY, getTableType().name());
properties.put(MetastoreUtil.getCubeTableWeightKey(name), String.valueOf(weight));
}
public String getName() {
return name;
}
public List<FieldSchema> getColumns() {
return columns;
}
public double weight() {
return weight;
}
/**
* Alters the weight of table
*
* @param weight Weight of the table.
*/
public void alterWeight(double weight) {
this.weight = weight;
this.addProperties();
}
/**
* Add more table properties
*
* @param props properties
*/
public void addProperties(Map<String, String> props) {
this.properties.putAll(props);
addProperties();
}
/**
* Remove property specified by the key
*
* @param propKey property key
*/
public void removeProperty(String propKey) {
properties.remove(propKey);
}
/**
* Alters the column if already existing or just adds it if it is new column
*
* @param column The column spec as FieldSchema - name, type and a comment
*/
protected void alterColumn(@NonNull FieldSchema column) {
Iterator<FieldSchema> columnItr = columns.iterator();
int alterPos = -1;
int i = 0;
FieldSchema toReplace = null;
while (columnItr.hasNext()) {
FieldSchema c = columnItr.next();
// Replace column if already existing
if (column.getName().equalsIgnoreCase(c.getName())) {
toReplace = c;
columnItr.remove();
alterPos = i;
}
i++;
}
if (alterPos != -1) {
log.info("In {} replacing column {}:{} to {}:{}", getName(), toReplace.getName(), toReplace.getType(),
column.getName(), column.getType());
columns.add(alterPos, column);
} else {
columns.add(column);
}
}
/**
* Adds or alters the columns passed
*
* @param columns The collection of columns
*/
protected void addColumns(@NonNull Collection<FieldSchema> columns) {
for (FieldSchema column : columns) {
alterColumn(column);
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
AbstractCubeTable other = (AbstractCubeTable) obj;
if (!this.getName().equalsIgnoreCase(other.getName())) {
return false;
}
if (this.getColumns() == null) {
if (other.getColumns() != null) {
return false;
}
} else {
if (!this.getColumns().equals(other.getColumns())) {
return false;
}
}
if (this.weight() != other.weight()) {
return false;
}
return true;
}
public Date getDateFromProperty(String propKey, boolean relative, boolean start) {
String prop = getProperties().get(propKey);
try {
if (StringUtils.isNotBlank(prop)) {
if (relative) {
return DateUtil.resolveRelativeDate(prop, now());
} else {
return DateUtil.resolveAbsoluteDate(prop);
}
}
} catch (LensException e) {
log.error("unable to parse {} {} date: {}", relative ? "relative" : "absolute", start ? "start" : "end", prop);
}
return start ? DateUtil.MIN_DATE : DateUtil.MAX_DATE;
}
@Override
public String toString() {
return getName();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
return result;
}
public Set<String> getAllFieldNames() {
List<FieldSchema> fields = getColumns();
Set<String> columns = new HashSet<>(fields.size());
for (FieldSchema f : fields) {
columns.add(f.getName().toLowerCase());
}
return columns;
}
public Date now() {
return new Date();
}
}