blob: 70685d8ac42160628f810b6aaf7552ca30c80231 [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.atlas.query;
import org.apache.commons.lang.StringUtils;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
public class SelectClauseComposer {
private static final String COUNT_STR = "count";
private static final String MIN_STR = "min";
private static final String MAX_STR = "max";
private static final String SUM_STR = "sum";
private final String[] labels;
private final String[] attributes;
private final String[] items;
private final int countIdx;
private final int sumIdx;
private final int minIdx;
private final int maxIdx;
private final int aggCount;
private final Map<Integer, AggregatorFlag> aggregatorFlags = new HashMap();
private final Set<Integer> isNumericAggregator = new HashSet<>();
private final Set<Integer> isPrimitiveAttr = new HashSet<>();
private final Map<String, String> itemAssignmentExprs = new LinkedHashMap<>();
private boolean isSelectNoop = false;
private int introducedTypesCount = 0;
public SelectClauseComposer(String[] labels, String[] attributes, String[] items, int countIdx, int sumIdx, int minIdx, int maxIdx) {
this.labels = labels;
this.attributes = Arrays.copyOf(attributes, attributes.length);
this.items = Arrays.copyOf(items, items.length);
this.countIdx = countIdx;
this.sumIdx = sumIdx;
this.minIdx = minIdx;
this.maxIdx = maxIdx;
int aggCount = 0;
if (countIdx != -1) {
this.aggregatorFlags.put(countIdx, AggregatorFlag.COUNT);
aggCount++;
}
if (sumIdx != -1) {
this.aggregatorFlags.put(sumIdx, AggregatorFlag.SUM);
aggCount++;
}
if (maxIdx != -1) {
this.aggregatorFlags.put(maxIdx, AggregatorFlag.MAX);
aggCount++;
}
if (minIdx != -1) {
this.aggregatorFlags.put(minIdx, AggregatorFlag.MIN);
aggCount++;
}
this.aggCount = aggCount;
}
public static boolean isKeyword(String s) {
return COUNT_STR.equals(s) ||
MIN_STR.equals(s) ||
MAX_STR.equals(s) ||
SUM_STR.equals(s);
}
public String[] getItems() {
return items;
}
public boolean updateAsApplicable(int currentIndex, String propertyForClause, String qualifiedName) {
boolean ret = false;
if (currentIndex == getCountIdx()) {
ret = assign(currentIndex, COUNT_STR, GremlinClause.INLINE_COUNT.get(), GremlinClause.INLINE_ASSIGNMENT);
this.isNumericAggregator.add(currentIndex);
} else if (currentIndex == getMinIdx()) {
ret = assign(currentIndex, MIN_STR, propertyForClause, GremlinClause.INLINE_ASSIGNMENT, GremlinClause.INLINE_MIN);
this.isNumericAggregator.add(currentIndex);
} else if (currentIndex == getMaxIdx()) {
ret = assign(currentIndex, MAX_STR, propertyForClause, GremlinClause.INLINE_ASSIGNMENT, GremlinClause.INLINE_MAX);
this.isNumericAggregator.add(currentIndex);
} else if (currentIndex == getSumIdx()) {
ret = assign(currentIndex, SUM_STR, propertyForClause, GremlinClause.INLINE_ASSIGNMENT, GremlinClause.INLINE_SUM);
this.isNumericAggregator.add(currentIndex);
}
attributes[currentIndex] = qualifiedName;
return ret;
}
public String[] getAttributes() {
return attributes;
}
public boolean assign(int i, String qualifiedName, GremlinClause clause) {
items[i] = clause.get(qualifiedName, qualifiedName);
return true;
}
public String[] getLabels() {
return labels;
}
public boolean onlyAggregators() {
return hasAggregators() && aggCount == items.length;
}
public boolean hasAggregators() {
return aggCount > 0;
}
public String getLabelHeader() {
return getJoinedQuotedStr(getLabels());
}
public String getItemsString() {
return String.join(",", getItems());
}
public String getAssignmentExprString(){
return (!itemAssignmentExprs.isEmpty()) ? String.join(" ", itemAssignmentExprs.values()) : StringUtils.EMPTY;
}
public String getItem(int i) {
return items[i];
}
public String getAttribute(int i) {
return attributes[i];
}
public String getLabel(int i) {
return labels[i];
}
public int getAttrIndex(String attr) {
int ret = -1;
for (int i = 0; i < attributes.length; i++) {
if (attributes[i].equals(attr)) {
ret = i;
break;
}
}
return ret;
}
private boolean assign(String item, String assignExpr) {
itemAssignmentExprs.put(item, assignExpr);
return true;
}
private boolean assign(int i, String s, String p1, GremlinClause clause) {
items[i] = s;
return assign(items[i], clause.get(s, p1));
}
private boolean assign(int i, String s, String p1, GremlinClause inline, GremlinClause clause) {
items[i] = s;
return assign(items[i], inline.get(s, clause.get(p1, p1)));
}
public int getCountIdx() {
return countIdx;
}
public int getSumIdx() {
return sumIdx;
}
public int getMaxIdx() {
return maxIdx;
}
public int getMinIdx() {
return minIdx;
}
private String getJoinedQuotedStr(String[] elements) {
StringJoiner joiner = new StringJoiner(",");
Arrays.stream(elements)
.map(x -> x.contains("'") ? "\"" + x + "\"" : "'" + x + "'")
.forEach(joiner::add);
return joiner.toString();
}
public boolean isAggregatorWithArgument(int i) {
return i == getMaxIdx() || i == getMinIdx() || i == getSumIdx();
}
public void incrementTypesIntroduced() {
introducedTypesCount++;
}
public int getIntroducedTypesCount() {
return introducedTypesCount;
}
public boolean hasMultipleReferredTypes() {
return getIntroducedTypesCount() > 1;
}
public boolean hasMixedAttributes() {
return getIntroducedTypesCount() > 0 && getPrimitiveTypeCount() > 0;
}
private int getPrimitiveTypeCount() {
return isPrimitiveAttr.size();
}
public boolean getIsSelectNoop() {
return this.isSelectNoop;
}
public void setIsSelectNoop(boolean isSelectNoop) {
this.isSelectNoop = isSelectNoop;
}
public boolean isSumIdx(int idx) {
return aggregatorFlags.get(idx) == AggregatorFlag.SUM;
}
public boolean isMinIdx(int idx) {
return aggregatorFlags.get(idx) == AggregatorFlag.MIN;
}
public boolean isMaxIdx(int idx) {
return aggregatorFlags.get(idx) == AggregatorFlag.MAX;
}
public boolean isCountIdx(int idx) {
return aggregatorFlags.get(idx) == AggregatorFlag.COUNT;
}
public boolean isNumericAggregator(int idx) {
return isNumericAggregator.contains(idx);
}
public boolean isPrimitiveAttribute(int idx) {
return isPrimitiveAttr.contains(idx);
}
public void setIsPrimitiveAttr(int i) {
this.isPrimitiveAttr.add(i);
}
public enum AggregatorFlag {
NONE, COUNT, MIN, MAX, SUM
}
}