<commit_before>package ingraph.cypher2relalg

import ingraph.cypher2relalg.factories.EdgeLabelFactory
import ingraph.cypher2relalg.factories.EdgeVariableFactory
import ingraph.cypher2relalg.factories.ExpressionVariableFactory
import ingraph.cypher2relalg.factories.VertexLabelFactory
import ingraph.cypher2relalg.factories.VertexVariableFactory
import ingraph.cypher2relalg.util.ElementVariableUtil
import ingraph.cypher2relalg.util.ExpressionNameInferencer
import ingraph.logger.IngraphLogger
import java.util.ArrayList
import java.util.Collection
import java.util.HashMap
import java.util.List
import java.util.Map
import org.eclipse.emf.common.util.EList
import org.slizaa.neo4j.opencypher.openCypher.ExpressionNodeLabelsAndPropertyLookup
import org.slizaa.neo4j.opencypher.openCypher.NodePattern
import org.slizaa.neo4j.opencypher.openCypher.RelationshipDetail
import org.slizaa.neo4j.opencypher.openCypher.VariableRef
import relalg.AttributeVariable
import relalg.EdgeLabel
import relalg.EdgeVariable
import relalg.ElementVariable
import relalg.Expression
import relalg.ExpressionVariable
import relalg.LabelSetStatus
import relalg.RelalgContainer
import relalg.RelalgFactory
import relalg.Variable
import relalg.VariableExpression
import relalg.VertexLabel
import relalg.VertexVariable

/**
 * This is the variable builder component of
 * the openCypher to relational algebra compiler.
 */
class VariableBuilder {
	extension RelalgFactory factory = RelalgFactory.eINSTANCE
	extension IngraphLogger logger = new IngraphLogger(VariableBuilder.name)

	val RelalgContainer topLevelContainer

	extension ElementVariableUtil elementVariableUtil

	val VertexVariableFactory vertexVariableFactory
	val EdgeVariableFactory edgeVariableFactory
	/**
	 * Chain means that these are chained from the previous return-items.
	 */
	val Map<String, ExpressionVariable> expressionVariableChain
	/**
	 * Extended below practically means they are created from the aliased return items
	 * or unwind item.
	 */
	val ExpressionVariableFactory expressionVariableFactoryExtended

	val VertexLabelFactory vertexLabelFactory
	val EdgeLabelFactory edgeLabelFactory

	/**
	 * Constructor that allows propagating the topLevelContainer,
	 * but creates new factories for variables and labels.
	 *
	 * Use this to create separate builder for each SingleQuery.
	 */
	new(RelalgContainer topLevelContainer, IngraphLogger logger) {
		this.logger=logger

		this.topLevelContainer = topLevelContainer

		this.vertexVariableFactory = new VertexVariableFactory(this.topLevelContainer)
		this.edgeVariableFactory = new EdgeVariableFactory(this.topLevelContainer)
		this.expressionVariableChain = new HashMap
		this.expressionVariableFactoryExtended = new ExpressionVariableFactory(this.topLevelContainer)
		this.vertexLabelFactory = new VertexLabelFactory(this.topLevelContainer)
		this.edgeLabelFactory = new EdgeLabelFactory(this.topLevelContainer)

		this.elementVariableUtil = new ElementVariableUtil(this.topLevelContainer)
	}

	/**
	 * Constructor that allows propagating the topLevelContainer
	 * and the label factories, but creates new factories for variables.
	 *
	 * This is used to create separate builder for each SingleQuery.
	 * Outside of this class, you should to use the public helper
	 * {@link #cloneBuilderWithNewVariableFactories cloneBuilderWithNewVariableFactories}
	 * call instead.
	 */
	protected new(RelalgContainer topLevelContainer, VertexLabelFactory vertexLabelFactory, EdgeLabelFactory edgeLabelFactory, Collection<ExpressionVariable> expressionVariableChain, IngraphLogger logger) {
		this.logger=logger

		this.topLevelContainer = topLevelContainer

		this.vertexVariableFactory = new VertexVariableFactory(this.topLevelContainer)
		this.edgeVariableFactory = new EdgeVariableFactory(this.topLevelContainer)
		this.expressionVariableChain = new HashMap
		expressionVariableChain.forEach[
			val f_it = it
			if (!f_it.hasInferredName) { // only those with actual name or alias can be re-used in the next context
				this.expressionVariableChain.put(f_it.name, f_it)
			}
		]
		this.expressionVariableFactoryExtended = new ExpressionVariableFactory(this.topLevelContainer)
		this.vertexLabelFactory = vertexLabelFactory
		this.edgeLabelFactory = edgeLabelFactory

		this.elementVariableUtil = new ElementVariableUtil(this.topLevelContainer)
	}

	/**
	 * Creates a new VariableBuilder instance that has new variable factory instances
	 * but retains label factories and the topLevelContainer.
	 */
	def cloneBuilderWithNewVariableFactories() {
		new VariableBuilder(topLevelContainer, vertexLabelFactory, edgeLabelFactory, expressionVariableFactoryExtended.elements.values,  logger)
	}

	protected def AttributeVariable buildPropertyLookupHelper(Variable ev, ExpressionNodeLabelsAndPropertyLookup e) {
		if (e.propertyLookups.length == 1) {
			val attributeName = e.propertyLookups.get(0).propertyKeyName

			if (ev instanceof ExpressionVariable) {
				val innerVariable = extractElementVariable(ev)<commit_msg>cypher2relalg: dirty hack to pass over un-aliased variable from a subquery<commit_after>package ingraph.cypher2relalg

import ingraph.cypher2relalg.factories.EdgeLabelFactory
import ingraph.cypher2relalg.factories.EdgeVariableFactory
import ingraph.cypher2relalg.factories.ExpressionVariableFactory
import ingraph.cypher2relalg.factories.VertexLabelFactory
import ingraph.cypher2relalg.factories.VertexVariableFactory
import ingraph.cypher2relalg.util.ElementVariableUtil
import ingraph.cypher2relalg.util.ExpressionNameInferencer
import ingraph.logger.IngraphLogger
import java.util.ArrayList
import java.util.Collection
import java.util.HashMap
import java.util.List
import java.util.Map
import org.eclipse.emf.common.util.EList
import org.slizaa.neo4j.opencypher.openCypher.ExpressionNodeLabelsAndPropertyLookup
import org.slizaa.neo4j.opencypher.openCypher.NodePattern
import org.slizaa.neo4j.opencypher.openCypher.RelationshipDetail
import org.slizaa.neo4j.opencypher.openCypher.VariableRef
import relalg.AttributeVariable
import relalg.EdgeLabel
import relalg.EdgeVariable
import relalg.ElementVariable
import relalg.Expression
import relalg.ExpressionVariable
import relalg.LabelSetStatus
import relalg.RelalgContainer
import relalg.RelalgFactory
import relalg.Variable
import relalg.VariableExpression
import relalg.VertexLabel
import relalg.VertexVariable

/**
 * This is the variable builder component of
 * the openCypher to relational algebra compiler.
 */
class VariableBuilder {
	extension RelalgFactory factory = RelalgFactory.eINSTANCE
	extension IngraphLogger logger = new IngraphLogger(VariableBuilder.name)

	val RelalgContainer topLevelContainer

	extension ElementVariableUtil elementVariableUtil

	val VertexVariableFactory vertexVariableFactory
	val EdgeVariableFactory edgeVariableFactory
	/**
	 * Chain means that these are chained from the previous return-items.
	 */
	val Map<String, ExpressionVariable> expressionVariableChain
	/**
	 * Extended below practically means they are created from the aliased return items
	 * or unwind item.
	 */
	val ExpressionVariableFactory expressionVariableFactoryExtended

	val VertexLabelFactory vertexLabelFactory
	val EdgeLabelFactory edgeLabelFactory

	/**
	 * Constructor that allows propagating the topLevelContainer,
	 * but creates new factories for variables and labels.
	 *
	 * Use this to create separate builder for each SingleQuery.
	 */
	new(RelalgContainer topLevelContainer, IngraphLogger logger) {
		this.logger=logger

		this.topLevelContainer = topLevelContainer

		this.vertexVariableFactory = new VertexVariableFactory(this.topLevelContainer)
		this.edgeVariableFactory = new EdgeVariableFactory(this.topLevelContainer)
		this.expressionVariableChain = new HashMap
		this.expressionVariableFactoryExtended = new ExpressionVariableFactory(this.topLevelContainer)
		this.vertexLabelFactory = new VertexLabelFactory(this.topLevelContainer)
		this.edgeLabelFactory = new EdgeLabelFactory(this.topLevelContainer)

		this.elementVariableUtil = new ElementVariableUtil(this.topLevelContainer)
	}

	/**
	 * Constructor that allows propagating the topLevelContainer
	 * and the label factories, but creates new factories for variables.
	 *
	 * This is used to create separate builder for each SingleQuery.
	 * Outside of this class, you should to use the public helper
	 * {@link #cloneBuilderWithNewVariableFactories cloneBuilderWithNewVariableFactories}
	 * call instead.
	 */
	protected new(RelalgContainer topLevelContainer, VertexLabelFactory vertexLabelFactory, EdgeLabelFactory edgeLabelFactory, Collection<ExpressionVariable> expressionVariableChain, IngraphLogger logger) {
		this.logger=logger

		this.topLevelContainer = topLevelContainer

		this.vertexVariableFactory = new VertexVariableFactory(this.topLevelContainer)
		this.edgeVariableFactory = new EdgeVariableFactory(this.topLevelContainer)
		this.expressionVariableChain = new HashMap
		expressionVariableChain.forEach[
			val f_it = it
			/**
			 * FIXME: deactivated if to add simple variable-wrapping ExpressionVariables regardless of having inferred name
			 *
			 * MATCH (segment:Segment)
			 * WHERE segment.length <= 0
			 * WITH segment
			 * RETURN DISTINCT segment, segment.length AS length
			 */
			//if (!f_it.hasInferredName) { // only those with actual name or alias can be re-used in the next context
				this.expressionVariableChain.put(f_it.name, f_it)
			//}
		]
		this.expressionVariableFactoryExtended = new ExpressionVariableFactory(this.topLevelContainer)
		this.vertexLabelFactory = vertexLabelFactory
		this.edgeLabelFactory = edgeLabelFactory

		this.elementVariableUtil = new ElementVariableUtil(this.topLevelContainer)
	}

	/**
	 * Creates a new VariableBuilder instance that has new variable factory instances
	 * but retains label factories and the topLevelContainer.
	 */
	def cloneBuilderWithNewVariableFactories() {
		new VariableBuilder(topLevelContainer, vertexLabelFactory, edgeLabelFactory, expressionVariableFactoryExtended.elements.values,  logger)
	}

	protected def AttributeVariable buildPropertyLookupHelper(Variable ev, ExpressionNodeLabelsAndPropertyLookup e) {
		if (e.propertyLookups.length == 1) {
			val attributeName = e.propertyLookups.get(0).propertyKeyName

			if (ev instanceof ExpressionVariable) {
				val innerVariable = extractElementVariable(ev)
{'fraction_non_alphanumeric': 0.05763104546770924, 'fraction_numerical': 0.0028960324355632784, 'mean_word_length': 6.08133971291866, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 7, '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': '4943293', 'n_tokens_mistral': 2859, 'n_tokens_neox': 2631, 'n_words': 699}