in repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala [405:631]
private def genQuery(parent: GroovyExpression, expr: Expression, inClosure: Boolean): GroovyExpression = expr match {
case ClassExpression(clsName) => typeTestExpression(parent, clsName)
case TraitExpression(clsName) => typeTestExpression(parent, clsName)
case fe@FieldExpression(fieldName, fInfo, child)
if fe.dataType.getTypeCategory == TypeCategory.PRIMITIVE || fe.dataType.getTypeCategory == TypeCategory.ARRAY => {
val fN = gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)
val childExpr = translateOptChild(parent, child, inClosure);
return GremlinExpressionFactory.INSTANCE.generateFieldExpression(childExpr, fInfo, fN, inClosure);
}
case fe@FieldExpression(fieldName, fInfo, child)
if fe.dataType.getTypeCategory == TypeCategory.CLASS || fe.dataType.getTypeCategory == TypeCategory.STRUCT => {
val childExpr = translateOptChild(parent, child, inClosure);
val direction = if (fInfo.isReverse) AtlasEdgeDirection.IN else AtlasEdgeDirection.OUT
val edgeLbl = gPersistenceBehavior.edgeLabel(fInfo)
return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction, edgeLbl)
}
case fe@FieldExpression(fieldName, fInfo, child) if fInfo.traitName != null => {
val childExpr = translateOptChild(parent, child, inClosure);
val direction = gPersistenceBehavior.instanceToTraitEdgeDirection
val edgeLbl = gPersistenceBehavior.edgeLabel(fInfo)
return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction, edgeLbl)
}
case c@ComparisonExpression(symb, f@FieldExpression(fieldName, fInfo, ch), l) => {
val qualifiedPropertyName = s"${gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)}"
val childExpr = translateOptChild(parent, ch, inClosure)
val persistentExprValue : GroovyExpression = if(l.isInstanceOf[Literal[_]]) {
translateLiteralValue(fInfo.attrInfo.dataType, l.asInstanceOf[Literal[_]]);
}
else {
genQuery(null, l, inClosure);
}
if (symb == "like") {
return GremlinExpressionFactory.INSTANCE.generateLikeExpressionUsingFilter(childExpr, qualifiedPropertyName, persistentExprValue);
}
return GremlinExpressionFactory.INSTANCE.generateHasExpression(gPersistenceBehavior, childExpr, qualifiedPropertyName, c.symbol, persistentExprValue, fInfo);
}
case fil@FilterExpression(child, condExpr) => {
var newParent = genQuery(parent, child, inClosure);
val alias = "a" + counter.next;
newParent = GremlinExpressionFactory.INSTANCE.generateAliasExpression(newParent, alias);
val translated = genQuery(newParent, condExpr, inClosure);
//we want the query to return instances of the class whose instances we are filtering out
//The act of filtering may traverse edges and have other side effects.
GremlinExpressionFactory.INSTANCE.generateBackReferenceExpression(translated, false, alias);
}
case l@LogicalExpression(symb, children) => {
val translatedChildren : java.util.List[GroovyExpression] = translateList(children, false);
return GremlinExpressionFactory.INSTANCE.generateLogicalExpression(parent, symb, translatedChildren);
}
case sel@SelectExpression(child, selList, forGroupBy) => {
val m = groupSelectExpressionsBySrc(sel)
var srcNamesList: java.util.List[LiteralExpression] = new ArrayList()
var srcExprsList: List[java.util.List[GroovyExpression]] = List()
val it = m.iterator
while (it.hasNext) {
val (src, selExprs) = it.next
srcNamesList.add(new LiteralExpression(src));
val translatedSelExprs : java.util.List[GroovyExpression] = translateList(selExprs, true);
srcExprsList = srcExprsList :+ translatedSelExprs
}
val srcExprsStringList : java.util.List[GroovyExpression] = new ArrayList();
srcExprsList.foreach { it =>
srcExprsStringList.add(new ListExpression(it));
}
val childExpr = genQuery(parent, child, inClosure)
return GremlinExpressionFactory.INSTANCE.generateSelectExpression(childExpr, srcNamesList, srcExprsStringList);
}
case loop@LoopExpression(input, loopExpr, t) => {
val times : Integer = if(t.isDefined) {
t.get.rawValue.asInstanceOf[Integer]
}
else {
null.asInstanceOf[Integer]
}
val alias = input.asInstanceOf[AliasExpression].alias;
val inputQry = genQuery(parent, input, inClosure)
val translatedLoopExpr = genQuery(GremlinExpressionFactory.INSTANCE.getLoopExpressionParent(inputQry), loopExpr, inClosure);
return GremlinExpressionFactory.INSTANCE.generateLoopExpression(inputQry, gPersistenceBehavior, input.dataType, translatedLoopExpr, alias, times);
}
case BackReference(alias, _, _) => {
return GremlinExpressionFactory.INSTANCE.generateBackReferenceExpression(parent, inClosure, alias);
}
case AliasExpression(child, alias) => {
var childExpr = genQuery(parent, child, inClosure);
return GremlinExpressionFactory.INSTANCE.generateAliasExpression(childExpr, alias);
}
case isTraitLeafExpression(traitName, Some(clsExp)) => {
val label = gPersistenceBehavior.traitLabel(clsExp.dataType, traitName);
return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(parent, AtlasEdgeDirection.OUT, label);
}
case isTraitUnaryExpression(traitName, child) => {
val label = gPersistenceBehavior.traitLabel(child.dataType, traitName);
return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(parent, AtlasEdgeDirection.OUT, label);
}
case hasFieldLeafExpression(fieldName, clsExp) => clsExp match {
case None => GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fieldName)
case Some(x) => {
val fi = TypeUtils.resolveReference(clsExp.get.dataType, fieldName);
if(! fi.isDefined) {
return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fieldName);
}
else {
val fName = gPersistenceBehavior.fieldNameInVertex(fi.get.dataType, fi.get.attrInfo)
return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fName);
}
}
}
case hasFieldUnaryExpression(fieldName, child) =>
val childExpr = genQuery(parent, child, inClosure);
return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(childExpr, fieldName);
case ArithmeticExpression(symb, left, right) => {
val leftExpr = genQuery(parent, left, inClosure);
val rightExpr = genQuery(parent, right, inClosure);
return GremlinExpressionFactory.INSTANCE.generateArithmeticExpression(leftExpr, symb, rightExpr);
}
case l: Literal[_] => {
if(parent != null) {
return new org.apache.atlas.groovy.FieldExpression(parent, cleanStringLiteral(l));
}
return translateLiteralValue(l.dataType, l);
}
case list: ListLiteral[_] => {
//Here, we are creating a Groovy list literal expression ([value1, value2, value3]). Because
//of this, any gremlin query expressions within the list must start with an anonymous traversal.
//We set 'inClosure' to true in this case to make that happen.
val values : java.util.List[GroovyExpression] = translateList(list.rawValue, true);
return new ListExpression(values);
}
case in@TraitInstanceExpression(child) => {
val childExpr = genQuery(parent, child, inClosure);
val direction = gPersistenceBehavior.traitToInstanceEdgeDirection;
return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction);
}
case in@InstanceExpression(child) => {
return genQuery(parent, child, inClosure);
}
case pe@PathExpression(child) => {
val childExpr = genQuery(parent, child, inClosure)
return GremlinExpressionFactory.INSTANCE.generatePathExpression(childExpr);
}
case order@OrderExpression(child, odr, asc) => {
var orderExpression = odr
if(odr.isInstanceOf[BackReference]) {
orderExpression = odr.asInstanceOf[BackReference].reference
}
else if (odr.isInstanceOf[AliasExpression]) {
orderExpression = odr.asInstanceOf[AliasExpression].child
}
val childExpr = genQuery(parent, child, inClosure);
var orderByParents : java.util.List[GroovyExpression] = GremlinExpressionFactory.INSTANCE.getOrderFieldParents();
val translatedParents : java.util.List[GroovyExpression] = new ArrayList[GroovyExpression]();
var translatedOrderParents = orderByParents.foreach { it =>
translatedParents.add(genQuery(it, orderExpression, true));
}
return GremlinExpressionFactory.INSTANCE.generateOrderByExpression(childExpr, translatedParents,asc);
}
case limitOffset@LimitExpression(child, limit, offset) => {
val childExpr = genQuery(parent, child, inClosure);
val totalResultRows = limit.value + offset.value;
return GremlinExpressionFactory.INSTANCE.generateRangeExpression(childExpr, offset.value, totalResultRows);
}
case count@CountExpression() => {
val listExpr = GremlinExpressionFactory.INSTANCE.getClosureArgumentValue();
GremlinExpressionFactory.INSTANCE.generateCountExpression(listExpr);
}
case max@MaxExpression(child) => {
//use "it" as the parent since the child will become
//part of a closure. Its value will be whatever vertex
//we are looking at in the collection.
val childExprParent = null;
val childExpr = genQuery(childExprParent, child, true);
val listExpr = GremlinExpressionFactory.INSTANCE.getClosureArgumentValue();
GremlinExpressionFactory.INSTANCE.generateMaxExpression(listExpr, childExpr);
}
case min@MinExpression(child) => {
//use "it" as the parent since the child will become
//part of a closure. Its value will be whatever vertex
//we are looking at in the collection.
val childExprParent = null;
val childExpr = genQuery(childExprParent, child, true);
val listExpr = GremlinExpressionFactory.INSTANCE.getClosureArgumentValue();
GremlinExpressionFactory.INSTANCE.generateMinExpression(listExpr, childExpr);
}
case sum@SumExpression(child) => {
//use "it" as the parent since the child will become
//part of a closure. Its value will be whatever vertex
//we are looking at in the collection.
val childExprParent = null;
val childExpr = genQuery(childExprParent, child, true);
val listExpr = GremlinExpressionFactory.INSTANCE.getClosureArgumentValue();
GremlinExpressionFactory.INSTANCE.generateSumExpression(listExpr, childExpr);
}
case groupByExpr@GroupByExpression(child, groupBy, selExpr) => {
//remove aliases
val groupByExprListToTranslate = (groupBy.asInstanceOf[SelectExpression]).selectListWithAlias.map {
x => x.child;
}
val grpByExprsList = translateList(groupByExprListToTranslate, true);
val groupByValue = new ListExpression(grpByExprsList);
//reduction only aggregate methods are supported here as of now.(Max, Min, Count)
//remove aliases
val srcExprListToTranslate = selExpr.selectListWithAlias.map {
x => x.child;
}
val srcExprsList = translateList(srcExprListToTranslate, true, true);
val srcExprsStringList = new ListExpression(srcExprsList)
val childExpr = genQuery(parent, child, inClosure);
return GremlinExpressionFactory.INSTANCE.generateGroupByExpression(childExpr, groupByValue, srcExprsStringList);
}
case x => throw new GremlinTranslationException(x, "expression not yet supported")
}