<commit_before>package ingraph.compiler.cypher2gplan.builders

import java.util

import ingraph.compiler.cypher2gplan.util.BuilderUtil
import ingraph.compiler.exceptions.{CompilerException, PatternNotAllowedException, UnexpectedTypeException, UnsupportedException}
import ingraph.model.misc.Function
import ingraph.model.{expr, gplan}
import org.apache.spark.sql.catalyst.analysis.UnresolvedFunction
import org.apache.spark.sql.catalyst.expressions.Expression
import org.apache.spark.sql.catalyst.{expressions => cExpr}
import org.slizaa.neo4j.opencypher.{openCypher => oc}

import scala.collection.JavaConverters._
import scala.collection.mutable.ListBuffer

object ExpressionBuilder {

  def buildExpression(expression: oc.Expression, joins: ListBuffer[gplan.GNode]): cExpr.Expression = {
    expression match {
      case e: oc.ComparisonExpression => buildExpressionComparision(e, joins)
      case e: oc.AndExpression => cExpr.And(buildExpression(e.getLeft, joins), buildExpression(e.getRight, joins))
      case e: oc.OrExpression => cExpr.Or(buildExpression(e.getLeft, joins), buildExpression(e.getRight, joins))
      case e: oc.XorExpression => buildExpressionXor(e, joins)
      case e: oc.NotExpression => cExpr.Not(buildExpression(e.getLeft, joins))
      case e: oc.IsNotNullExpression => cExpr.IsNotNull(buildExpressionNoJoinAllowed(e.getLeft))
      case e: oc.IsNullExpression => cExpr.IsNull(buildExpressionNoJoinAllowed(e.getLeft))
      case e: oc.ParenthesizedExpression => buildExpression(e.getExpression, joins)
      case e: oc.RelationshipsPattern => buildExpressionPattern(e, joins)
      case e: oc.PropertyLookupExpression => AttributeBuilder.buildAttribute(e)
      case e: oc.NodeLabelsExpression => UnresolvedFunction(Function.NODE_HAS_LABELS.getPrettyName, Seq[cExpr.Expression](buildExpressionNoJoinAllowed(e.getLeft), BuilderUtil.parseToVertexLabelSet(e.getNodeLabels)), false)
      case e: oc.AddOrSubtractExpression => buildExpressionArithmetic(e, joins)
      case e: oc.UnaryAddOrSubtractExpression => buildExpressionArithmetic(e, joins)
      case e: oc.MultiplyDivideModuloExpression => buildExpressionArithmetic(e, joins)
      case e: oc.PowerOfExpression => buildExpressionArithmetic(e, joins)
      //FIXME#206: this should pass function name unresolved
      case e: oc.FunctionInvocation => UnresolvedFunction(e.getFunctionName, e.getParameter.asScala.map( e => buildExpression(e, joins) ), e.isDistinct)
      case _: oc.Count => UnresolvedFunction(Function.COUNT_ALL.getPrettyName, Seq[cExpr.Expression](), false)
      case e: oc.IndexRangeExpression => buildExpressionIndexRange(e) // foo[a..b], should return list, even for foo[1..2]
      case e: oc.IndexLookupExpression => buildExpressionIndexLookup(e) // foo[a], should return scalar
      case e: oc.InCollectionExpression => UnresolvedFunction(Function.IN_COLLECTION.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false)
      // String predicates
      case e: oc.ContainsExpression => UnresolvedFunction(Function.CONTAINS.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.Contains
      case e: oc.StartsWithExpression => UnresolvedFunction(Function.STARTS_WITH.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.StartsWith
      case e: oc.EndsWithExpression => UnresolvedFunction(Function.ENDS_WITH.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.EndsWith
      case e: oc.RegExpMatchingExpression => UnresolvedFunction(Function.REGEX_LIKE.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false)
      // End string predicates
      case e: oc.NumberLiteral => LiteralBuilder.buildNumberLiteral(e)
      case e: oc.Parameter => buildParameter(e)
      case e: oc.StringLiteral => LiteralBuilder.buildStringLiteral(e)
      case e: oc.VariableRef => AttributeBuilder.buildAttribute(e)
      case e: oc.CaseExpression => buildExpressionCase(e)
      case e: oc.ListLiteral => expr.ListExpression( e.getExpressions.asScala.map( buildExpressionNoJoinAllowed(_) ) )
      case e: oc.NULL => cExpr.Literal(null)
      case e: oc.BooleanLiteral => LiteralBuilder.buildBoolLiteral(e)

      case e => throw new CompilerException("TODO: " + s"Unhandled parameter types: ${util.Arrays.asList[Object](e)}")
    }
  }

  /**<commit_msg>Remove stale comment. Ref. #206<commit_after>package ingraph.compiler.cypher2gplan.builders

import java.util

import ingraph.compiler.cypher2gplan.util.BuilderUtil
import ingraph.compiler.exceptions.{CompilerException, PatternNotAllowedException, UnexpectedTypeException, UnsupportedException}
import ingraph.model.misc.Function
import ingraph.model.{expr, gplan}
import org.apache.spark.sql.catalyst.analysis.UnresolvedFunction
import org.apache.spark.sql.catalyst.expressions.Expression
import org.apache.spark.sql.catalyst.{expressions => cExpr}
import org.slizaa.neo4j.opencypher.{openCypher => oc}

import scala.collection.JavaConverters._
import scala.collection.mutable.ListBuffer

object ExpressionBuilder {

  def buildExpression(expression: oc.Expression, joins: ListBuffer[gplan.GNode]): cExpr.Expression = {
    expression match {
      case e: oc.ComparisonExpression => buildExpressionComparision(e, joins)
      case e: oc.AndExpression => cExpr.And(buildExpression(e.getLeft, joins), buildExpression(e.getRight, joins))
      case e: oc.OrExpression => cExpr.Or(buildExpression(e.getLeft, joins), buildExpression(e.getRight, joins))
      case e: oc.XorExpression => buildExpressionXor(e, joins)
      case e: oc.NotExpression => cExpr.Not(buildExpression(e.getLeft, joins))
      case e: oc.IsNotNullExpression => cExpr.IsNotNull(buildExpressionNoJoinAllowed(e.getLeft))
      case e: oc.IsNullExpression => cExpr.IsNull(buildExpressionNoJoinAllowed(e.getLeft))
      case e: oc.ParenthesizedExpression => buildExpression(e.getExpression, joins)
      case e: oc.RelationshipsPattern => buildExpressionPattern(e, joins)
      case e: oc.PropertyLookupExpression => AttributeBuilder.buildAttribute(e)
      case e: oc.NodeLabelsExpression => UnresolvedFunction(Function.NODE_HAS_LABELS.getPrettyName, Seq[cExpr.Expression](buildExpressionNoJoinAllowed(e.getLeft), BuilderUtil.parseToVertexLabelSet(e.getNodeLabels)), false)
      case e: oc.AddOrSubtractExpression => buildExpressionArithmetic(e, joins)
      case e: oc.UnaryAddOrSubtractExpression => buildExpressionArithmetic(e, joins)
      case e: oc.MultiplyDivideModuloExpression => buildExpressionArithmetic(e, joins)
      case e: oc.PowerOfExpression => buildExpressionArithmetic(e, joins)
      case e: oc.FunctionInvocation => UnresolvedFunction(e.getFunctionName, e.getParameter.asScala.map( e => buildExpression(e, joins) ), e.isDistinct)
      case _: oc.Count => UnresolvedFunction(Function.COUNT_ALL.getPrettyName, Seq[cExpr.Expression](), false)
      case e: oc.IndexRangeExpression => buildExpressionIndexRange(e) // foo[a..b], should return list, even for foo[1..2]
      case e: oc.IndexLookupExpression => buildExpressionIndexLookup(e) // foo[a], should return scalar
      case e: oc.InCollectionExpression => UnresolvedFunction(Function.IN_COLLECTION.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false)
      // String predicates
      case e: oc.ContainsExpression => UnresolvedFunction(Function.CONTAINS.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.Contains
      case e: oc.StartsWithExpression => UnresolvedFunction(Function.STARTS_WITH.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.StartsWith
      case e: oc.EndsWithExpression => UnresolvedFunction(Function.ENDS_WITH.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false) //cExpr.EndsWith
      case e: oc.RegExpMatchingExpression => UnresolvedFunction(Function.REGEX_LIKE.getPrettyName, Seq[Expression]( buildExpressionNoJoinAllowed(e.getLeft), buildExpressionNoJoinAllowed(e.getRight)), isDistinct=false)
      // End string predicates
      case e: oc.NumberLiteral => LiteralBuilder.buildNumberLiteral(e)
      case e: oc.Parameter => buildParameter(e)
      case e: oc.StringLiteral => LiteralBuilder.buildStringLiteral(e)
      case e: oc.VariableRef => AttributeBuilder.buildAttribute(e)
      case e: oc.CaseExpression => buildExpressionCase(e)
      case e: oc.ListLiteral => expr.ListExpression( e.getExpressions.asScala.map( buildExpressionNoJoinAllowed(_) ) )
      case e: oc.NULL => cExpr.Literal(null)
      case e: oc.BooleanLiteral => LiteralBuilder.buildBoolLiteral(e)

      case e => throw new CompilerException("TODO: " + s"Unhandled parameter types: ${util.Arrays.asList[Object](e)}")
    }
  }

  /**
{'fraction_non_alphanumeric': 0.10831451005700764, 'fraction_numerical': 0.0017209852640636765, 'mean_word_length': 5.689208633093525, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6545215', 'n_tokens_mistral': 2750, 'n_tokens_neox': 2705, 'n_words': 495}