blob: 2ff4ab14f7b8dcc5da7afd39f5fae7b963c3049b [file] [log] [blame]
/**
* 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.cube.error.LensCubeErrorCode;
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 com.google.common.collect.Lists;
public class DerivedCube extends AbstractCubeTable implements CubeInterface {
private static final List<FieldSchema> COLUMNS = new ArrayList<>();
static {
COLUMNS.add(new FieldSchema("dummy", "string", "dummy column"));
}
private final Cube parent;
private final Set<String> measures = new HashSet<>();
private final Set<String> dimensions = new HashSet<>();
public DerivedCube(String name, Set<String> measures, Set<String> dimensions, Cube parent) throws LensException {
this(name, measures, dimensions, new HashMap<String, String>(), 0L, parent);
}
public DerivedCube(String name, Set<String> measures, Set<String> dimensions, Map<String, String> properties,
double weight, Cube parent) throws LensException {
super(name, COLUMNS, properties, weight);
for (String msr : measures) {
this.measures.add(msr.toLowerCase());
}
for (String dim : dimensions) {
this.dimensions.add(dim.toLowerCase());
}
this.parent = parent;
validate();
addProperties();
}
public void validate() throws LensException {
List<String> measuresNotInParentCube = Lists.newArrayList();
List<String> dimAttributesNotInParentCube = Lists.newArrayList();
for (String msr : measures) {
if (parent.getMeasureByName(msr) == null) {
measuresNotInParentCube.add(msr);
}
}
for (String dim : dimensions) {
if (parent.getDimAttributeByName(dim) == null) {
dimAttributesNotInParentCube.add(dim);
}
}
StringBuilder validationErrorStringBuilder = new StringBuilder();
String sep = "";
boolean invalid = false;
if (!measuresNotInParentCube.isEmpty()) {
validationErrorStringBuilder.append(sep).append("Measures ").append(measuresNotInParentCube);
sep = " and ";
invalid = true;
}
if (!dimAttributesNotInParentCube.isEmpty()) {
validationErrorStringBuilder.append(sep).append("Dim Attributes ").append(dimAttributesNotInParentCube);
invalid = true;
}
if (invalid) {
throw new LensException(LensCubeErrorCode.ERROR_IN_ENTITY_DEFINITION.getLensErrorInfo(),
"Derived cube invalid: " + validationErrorStringBuilder.append(" were not present in " + "parent cube ")
.append(parent));
}
}
public DerivedCube(Table tbl, Cube parent) {
super(tbl);
this.measures.addAll(getMeasures(getName(), getProperties()));
this.dimensions.addAll(getDimensions(getName(), getProperties()));
this.parent = parent;
}
private Set<CubeMeasure> cachedMeasures = new HashSet<>();
private Set<CubeDimAttribute> cachedDims = new HashSet<>();
public Set<CubeMeasure> getMeasures() {
synchronized (measures) {
if (cachedMeasures.isEmpty()) {
for (String msr : measures) {
cachedMeasures.add(parent.getMeasureByName(msr));
}
}
}
return cachedMeasures;
}
public Set<CubeDimAttribute> getDimAttributes() {
synchronized (dimensions) {
if (cachedDims.isEmpty()) {
for (String dim : dimensions) {
cachedDims.add(parent.getDimAttributeByName(dim));
}
}
}
return cachedDims;
}
@Override
public CubeTableType getTableType() {
return CubeTableType.CUBE;
}
@Override
public Set<String> getStorages() {
return null;
}
@Override
public void addProperties() {
super.addProperties();
updateMeasureProperties();
updateDimAttributeProperties();
getProperties().put(MetastoreUtil.getParentCubeNameKey(getName()), parent.getName().toLowerCase());
getProperties().put(MetastoreUtil.getParentCubeNameKey(getName()), parent.getName().toLowerCase());
}
public void updateDimAttributeProperties() {
MetastoreUtil.addNameStrings(getProperties(), MetastoreUtil.getCubeDimensionListKey(getName()),
MetastoreUtil.getNamedSetFromStringSet(dimensions));
}
public void updateMeasureProperties() {
MetastoreUtil.addNameStrings(getProperties(), MetastoreUtil.getCubeMeasureListKey(getName()),
MetastoreUtil.getNamedSetFromStringSet(measures));
}
public static Set<String> getMeasures(String name, Map<String, String> props) {
Set<String> measures = new HashSet<>();
String measureStr = MetastoreUtil.getNamedStringValue(props, MetastoreUtil.getCubeMeasureListKey(name));
measures.addAll(Arrays.asList(StringUtils.split(measureStr, ',')));
return measures;
}
public Set<String> getTimedDimensions() {
String str = getProperties().get(MetastoreUtil.getCubeTimedDimensionListKey(getName()));
if (str != null) {
Set<String> timedDimensions = new HashSet<>();
timedDimensions.addAll(Arrays.asList(StringUtils.split(str, ',')));
return timedDimensions;
} else {
return parent.getTimedDimensions();
}
}
public static Set<String> getDimensions(String name, Map<String, String> props) {
Set<String> dimensions = new HashSet<>();
String dimStr = MetastoreUtil.getNamedStringValue(props, MetastoreUtil.getCubeDimensionListKey(name));
dimensions.addAll(Arrays.asList(StringUtils.split(dimStr, ',')));
return dimensions;
}
public Cube getParent() {
return parent;
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
DerivedCube other = (DerivedCube) obj;
if (!this.getParent().equals(other.getParent())) {
return false;
}
if (this.getMeasureNames() == null) {
if (other.getMeasureNames() != null) {
return false;
}
} else if (!this.getMeasureNames().equals(other.getMeasureNames())) {
return false;
}
if (this.getDimAttributeNames() == null) {
if (other.getDimAttributeNames() != null) {
return false;
}
} else if (!this.getDimAttributeNames().equals(other.getDimAttributeNames())) {
return false;
}
return true;
}
public CubeDimAttribute getDimAttributeByName(String dimension) {
if (dimensions.contains(dimension.toLowerCase())) {
return parent.getDimAttributeByName(dimension);
}
return null;
}
public CubeMeasure getMeasureByName(String measure) {
if (measures.contains(measure.toLowerCase())) {
return parent.getMeasureByName(measure);
}
return null;
}
public CubeColumn getColumnByName(String column) {
CubeColumn cubeCol = (CubeColumn) getMeasureByName(column);
if (cubeCol == null) {
cubeCol = (CubeColumn) getDimAttributeByName(column);
}
return cubeCol;
}
/**
* Add a new measure
*
* @param measure measure name
*/
public void addMeasure(String measure) {
measures.add(measure.toLowerCase());
updateMeasureProperties();
}
/**
* Add a new dimension
*
* @param dimension attribute name
*/
public void addDimension(String dimension) {
dimensions.add(dimension.toLowerCase());
updateDimAttributeProperties();
}
/**
* Remove the dimension with name specified
*
* @param dimName
*/
public void removeDimension(String dimName) {
dimensions.remove(dimName.toLowerCase());
updateDimAttributeProperties();
}
/**
* Remove the measure with name specified
*
* @param msrName
*/
public void removeMeasure(String msrName) {
measures.remove(msrName.toLowerCase());
updateMeasureProperties();
}
@Override
public boolean isDerivedCube() {
return true;
}
@Override
public Set<String> getMeasureNames() {
return measures;
}
@Override
public Set<String> getDimAttributeNames() {
Set<String> dimNames = new HashSet<>();
for (CubeDimAttribute f : getDimAttributes()) {
MetastoreUtil.addColumnNames(f, dimNames);
}
return dimNames;
}
@Override
public boolean allFieldsQueriable() {
return true;
}
@Override
public Set<ExprColumn> getExpressions() {
return null;
}
@Override
public ExprColumn getExpressionByName(String exprName) {
return null;
}
@Override
public Set<String> getAllFieldNames() {
Set<String> fieldNames = new HashSet<>();
fieldNames.addAll(getMeasureNames());
fieldNames.addAll(getDimAttributeNames());
fieldNames.addAll(getTimedDimensions());
return fieldNames;
}
@Override
public Set<String> getExpressionNames() {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<JoinChain> getJoinChains() {
// TODO Auto-generated method stub
return null;
}
@Override
public JoinChain getChainByName(String chainName) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<String> getJoinChainNames() {
// TODO Auto-generated method stub
return null;
}
@Override
public Date getAbsoluteStartTime() {
return parent.getAbsoluteStartTime();
}
@Override
public Date getRelativeStartTime() {
return parent.getRelativeStartTime();
}
@Override
public Date getStartTime() {
return parent.getStartTime();
}
@Override
public Date getAbsoluteEndTime() {
return parent.getAbsoluteEndTime();
}
@Override
public Date getRelativeEndTime() {
return parent.getRelativeEndTime();
}
@Override
public Date getEndTime() {
return parent.getEndTime();
}
}