/** * 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.lang.reflect.Constructor; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.hadoop.hive.ql.metadata.Table; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @Slf4j public class Dimension extends AbstractBaseTable { private final Set<CubeDimAttribute> attributes; private final Map<String, CubeDimAttribute> attributeMap; public Dimension(String name, Set<CubeDimAttribute> attributes) { this(name, attributes, new HashMap<String, String>(), 0L); } public Dimension(String name, Set<CubeDimAttribute> attributes, Map<String, String> properties, double weight) { this(name, attributes, null, null, properties, weight); } public Dimension(String name, Set<CubeDimAttribute> attributes, Set<ExprColumn> expressions, Set<JoinChain> joinChains, Map<String, String> properties, double weight) { super(name, expressions, joinChains, properties, weight); this.attributes = attributes; attributeMap = new HashMap<>(); for (CubeDimAttribute dim : attributes) { attributeMap.put(dim.getName().toLowerCase(), dim); } addProperties(); } public Dimension(Table tbl) { super(tbl); this.attributes = getAttributes(getName(), getProperties()); attributeMap = new HashMap<>(); for (CubeDimAttribute attr : attributes) { addAllAttributesToMap(attr); } } public Dimension(final String name, final Set<CubeDimAttribute> attributes, final Set<ExprColumn> exprs, final Map<String, String> dimProps, final long weight) { this(name, attributes, exprs, null, dimProps, weight); } private void addAllAttributesToMap(CubeDimAttribute attr) { attributeMap.put(attr.getName().toLowerCase(), attr); if (attr instanceof HierarchicalDimAttribute) { for (CubeDimAttribute d : ((HierarchicalDimAttribute) attr).getHierarchy()) { addAllAttributesToMap(d); } } } public Set<CubeDimAttribute> getAttributes() { return attributes; } @Override public CubeTableType getTableType() { return CubeTableType.DIMENSION; } @Override public Set<String> getStorages() { return null; } @Override public void addProperties() { super.addProperties(); MetastoreUtil.addNameStrings(getProperties(), MetastoreUtil.getDimAttributeListKey(getName()), attributes); setAttributedProperties(getProperties(), attributes); } private static void setAttributedProperties(Map<String, String> props, Set<CubeDimAttribute> attributes) { for (CubeDimAttribute attr : attributes) { attr.addProperties(props); } } public static Set<CubeDimAttribute> getAttributes(String name, Map<String, String> props) { Set<CubeDimAttribute> attributes = new HashSet<>(); String attrStr = MetastoreUtil.getNamedStringValue(props, MetastoreUtil.getDimAttributeListKey(name)); String[] names = attrStr.split(","); for (String attrName : names) { String className = props.get(MetastoreUtil.getDimensionClassPropertyKey(attrName)); CubeDimAttribute attr; try { Class<?> clazz = Class.forName(className); Constructor<?> constructor; constructor = clazz.getConstructor(String.class, Map.class); attr = (CubeDimAttribute) constructor.newInstance(new Object[]{attrName, props}); } catch (Exception e) { throw new IllegalArgumentException("Invalid dimension", e); } attributes.add(attr); } return attributes; } /** * @see org.apache.lens.cube.metadata.AbstractBaseTable */ @Override protected String getJoinChainListPropKey(String tblname) { return MetastoreUtil.getDimensionJoinChainListKey(tblname); } @Override public int hashCode() { return super.hashCode(); } @Override public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } Dimension other = (Dimension) obj; if (this.getAttributes() == null) { if (other.getAttributes() != null) { return false; } } else if (!this.getAttributes().equals(other.getAttributes())) { return false; } if (this.getJoinChains() == null) { if (other.getJoinChains() != null) { return false; } } else if (!this.getJoinChains().equals(other.getJoinChains())) { return false; } return true; } public CubeDimAttribute getAttributeByName(String attr) { return attributeMap.get(attr == null ? attr : attr.toLowerCase()); } public CubeColumn getColumnByName(String column) { CubeColumn cubeCol = super.getExpressionByName(column); if (cubeCol == null) { cubeCol = getAttributeByName(column); } return cubeCol; } /** * Alters the attribute if already existing or just adds if it is new attribute * * @param attribute */ public void alterAttribute(@NonNull CubeDimAttribute attribute) { // Replace dimension if already existing if (attributeMap.containsKey(attribute.getName().toLowerCase())) { attributes.remove(getAttributeByName(attribute.getName())); log.info("Replacing attribute {} with {}", getAttributeByName(attribute.getName()), attribute); } attributes.add(attribute); attributeMap.put(attribute.getName().toLowerCase(), attribute); MetastoreUtil.addNameStrings(getProperties(), MetastoreUtil.getDimAttributeListKey(getName()), attributes); attribute.addProperties(getProperties()); } /** * Remove the dimension with name specified * * @param attrName */ public void removeAttribute(String attrName) { if (attributeMap.containsKey(attrName.toLowerCase())) { log.info("Removing attribute {}", getAttributeByName(attrName)); attributes.remove(getAttributeByName(attrName)); attributeMap.remove(attrName.toLowerCase()); MetastoreUtil.addNameStrings(getProperties(), MetastoreUtil.getDimAttributeListKey(getName()), attributes); } } /** * @return the timedDimension */ public String getTimedDimension() { return getProperties().get(MetastoreUtil.getDimTimedDimensionKey(getName())); } public Set<String> getAttributeNames() { Set<String> dimNames = new HashSet<String>(); for (CubeDimAttribute f : getAttributes()) { MetastoreUtil.addColumnNames(f, dimNames); } return dimNames; } @Override public Set<String> getAllFieldNames() { Set<String> fieldNames = super.getAllFieldNames(); fieldNames.addAll(getAttributeNames()); return fieldNames; } }