From 06b041029920ff197497dacc49bfd54b189b31fd Mon Sep 17 00:00:00 2001
From: Kieran van Gaalen <kieran.van.gaalen@casema.nl>
Date: Fri, 12 Nov 2021 14:55:36 +0100
Subject: [PATCH] Replaced old convertQuery with new convertQuery, fixed parent
 -1 giving index out of range

---
 aql/convertQuery.go  | 185 +++++++++++++++++++++++++++++++++++++++--
 aql/convertQuery2.go | 192 -------------------------------------------
 realtest.json        |   2 +-
 3 files changed, 177 insertions(+), 202 deletions(-)
 delete mode 100644 aql/convertQuery2.go

diff --git a/aql/convertQuery.go b/aql/convertQuery.go
index dfdcbc1..e6d5368 100644
--- a/aql/convertQuery.go
+++ b/aql/convertQuery.go
@@ -6,6 +6,7 @@ This program has been developed by students from the bachelor Computer Science a
 package aql
 
 import (
+	"errors"
 	"fmt"
 	"strconv"
 
@@ -22,19 +23,185 @@ ConvertQuery converts an IncomingQueryJSON object into AQL
 func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, error) {
 	// Check to make sure all indexes exist
 	// The largest possible id for an entity
-	shitlist, _ := createHierarchy(JSONQuery)
-	for i, tree := range shitlist {
-		fmt.Println("I am triple(from,rel,to): " + strconv.Itoa(tree.Self.FromNode.ID) + "," + strconv.Itoa(tree.Self.Rel.ID) + "," + strconv.Itoa(tree.Self.ToNode.ID))
-		fmt.Println("My relation contains the following nodes(from,to): " + strconv.Itoa(tree.Self.Rel.FromID) + "," + strconv.Itoa(tree.Self.Rel.ToID))
+	largestEntityID := len(JSONQuery.Entities) - 1
+	// The largest possible id for a relation
+	largestRelationID := len(JSONQuery.Relations) - 1
+
+	// Make sure no entity should be returned that is outside the range of that list
+	for _, e := range JSONQuery.Return.Entities {
+		// If this entity references an entity that is outside the range
+		if e > largestEntityID || e < 0 {
+			return nil, errors.New("non-existing entity referenced in return")
+		}
+	}
+
+	// Make sure that no relation mentions a non-existing entity
+	for _, r := range JSONQuery.Relations {
+		if r.FromID > largestEntityID && r.FromType == "entity" || r.ToID > largestEntityID && r.ToType == "entity" {
+			return nil, errors.New("non-exisiting entity referenced in relation")
+		}
+	}
+
+	// Make sure no non-existing relation is tried to be returned
+	for _, r := range JSONQuery.Return.Relations {
+		if r > largestRelationID || r < 0 {
+			return nil, errors.New("non-existing relation referenced in return")
+		}
+	}
+	// Don't run search if we are getting empty queries from unit tests
+	var tree []entity.Tree
+	var topNode entity.QueryEntityStruct
+	if len(JSONQuery.Entities) != 0 && len(JSONQuery.Relations) != 0 {
+		tree, topNode = createHierarchy(JSONQuery)
+	}
+
+	for i, treeElement := range tree {
+		fmt.Println("I am triple(from,rel,to): " + strconv.Itoa(treeElement.Self.FromNode.ID) + "," + strconv.Itoa(treeElement.Self.Rel.ID) + "," + strconv.Itoa(treeElement.Self.ToNode.ID))
+		fmt.Println("My relation contains the following nodes(from,to): " + strconv.Itoa(treeElement.Self.Rel.FromID) + "," + strconv.Itoa(treeElement.Self.Rel.ToID))
 		fmt.Println("My index is: " + strconv.Itoa(i))
-		fmt.Println("My parent index is: " + strconv.Itoa(tree.Parent))
+		fmt.Println("My parent index is: " + strconv.Itoa(treeElement.Parent))
 		fmt.Println("My children's indices are: ")
-		for j := range tree.Children {
-			fmt.Println(tree.Children[j])
+		for j := range treeElement.Children {
+			fmt.Println(treeElement.Children[j])
 		}
 		fmt.Println("Next please!")
 	}
-	result := ""
-	return &result, nil
+	result := createQuery(JSONQuery, tree, topNode)
+	return result, nil
+}
+
+/*
+createQuery generates a query based on the json file provided
+	JSONQuery: *entity.IncomingQueryJSON, this is a parsedJSON struct holding all the data needed to form a query,
+	Return: *string, a string containing the corresponding AQL query and an error
+*/
+func createQuery(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, topNode entity.QueryEntityStruct) *string {
+	output := createLetFor("result", fmt.Sprintf("e_%v", topNode.ID), topNode.Name)
+	for constraint := range topNode.Constraints {
+		output += createFilter(topNode.Constraints[constraint], fmt.Sprintf("e_%v", topNode.ID))
+	}
+	subQuery, subName := createQueryRecurse(JSONQuery, tree, 0, topNode)
+	subNames := []string{subName}
+	output += subQuery
+	output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", topNode.ID)))
+	output += createReturn(fmt.Sprintf("e_%v", topNode.ID), "", subNames)
+	output += "let nodes = union_distinct(flatten(result[**].nodes),[])\nlet edges = union_distinct(flatten(result[**].rel),[])\nreturn {\"vertices\":nodes,\"edges\":edges}"
+	return &output
+}
+
+func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, currentindex int, topNode entity.QueryEntityStruct) (string, string) {
+	currentTree := tree[currentindex]
+	newNode := getTreeNewNode(currentTree, tree, topNode)
+	output := createLetFor(fmt.Sprintf("e%v", newNode.ID), fmt.Sprintf("e_%v", newNode.ID), newNode.Name)
+	output += fmt.Sprintf("FOR r%v IN %v", currentTree.Self.Rel.ID, currentTree.Self.Rel.Name)
+	for constraint := range newNode.Constraints {
+		output += createFilter(newNode.Constraints[constraint], fmt.Sprintf("e_%v", newNode.ID))
+	}
+	for constraint := range currentTree.Self.Rel.QueryConstraintStruct {
+		output += createFilter(currentTree.Self.Rel.QueryConstraintStruct[constraint], fmt.Sprintf("r%v", currentTree.Self.Rel.ID))
+	}
+	output += fmt.Sprintf("FILTER r%v._from == e_%v._id AND r%v._to == e_%v._id", currentTree.Self.Rel.ID, currentTree.Self.FromNode.ID, currentTree.Self.Rel.ID, currentTree.Self.ToNode.ID)
+	var subNames []string
+	for i := range currentTree.Children {
+		subQuery, subName := createQueryRecurse(JSONQuery, tree, currentTree.Children[i], topNode)
+		output += subQuery
+		subNames = append(subNames, subName)
+	}
+	output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID)))
+	output += createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), subNames)
+	return output, fmt.Sprintf("e%v", newNode.ID)
+}
+
+func getTreeNewNode(currentTree entity.Tree, tree []entity.Tree, topNode entity.QueryEntityStruct) entity.QueryEntityStruct {
+	if currentTree.Parent < 0 {
+		if currentTree.Self.FromNode.ID == topNode.ID {
+			return currentTree.Self.ToNode
+		} else {
+			return currentTree.Self.FromNode
+		}
+	} else if currentTree.Self.FromNode.ID == tree[currentTree.Parent].Self.FromNode.ID || currentTree.Self.FromNode.ID == tree[currentTree.Parent].Self.ToNode.ID {
+		return currentTree.Self.ToNode
+	} else {
+		return currentTree.Self.FromNode
+	}
+}
+
+func createLetFor(variableName string, forName string, enumerableName string) string {
+	return "LET " + variableName + " = (\n\tFOR " + forName + " IN " + enumerableName + "\n"
+}
+
+func createFilter(constraint entity.QueryConstraintStruct, filtered string) string {
+	return "\tFILTER + " + filtered + constraint.Attribute + " " + wordsToLogicalSign(constraint) + " " + constraint.Value + " \n"
+}
+
+func createZeroFilter(subNames []string) string {
+	output := "FILTER"
+	for i := range subNames {
+		output += fmt.Sprintf(" length(%v) != 0", subNames[i])
+		if i < len(subNames)-1 {
+			output += " AND"
+		}
+	}
+	return output
+}
 
+func createReturn(nodeName string, relName string, subNames []string) string {
+	output := "RETURN {\"nodes\":union_distinct("
+	for i := range subNames {
+		output += fmt.Sprintf("flatten(%v[**].nodes), ", subNames[i])
+	}
+	output += "[" + nodeName + "]"
+	if len(subNames) == 0 {
+		output += ", []"
+	}
+	output += "), \"rel\": union_distinct("
+	for i := range subNames {
+		output += fmt.Sprintf("flatten(%v[**].rel), ", subNames[i])
+	}
+	output += "[" + relName + "]"
+	if len(subNames) == 0 {
+		output += ", []"
+	}
+	output += ")}\n)\n"
+	return output
+}
+
+func wordsToLogicalSign(element entity.QueryConstraintStruct) string {
+	var match string
+	switch element.DataType {
+	case "string":
+		switch element.MatchType {
+		case "NEQ":
+			match = "!="
+		case "contains":
+			match = "LIKE"
+		case "excludes":
+			match = "NOT LIKE"
+		default: //EQ
+			match = "=="
+		}
+	case "int":
+		switch element.MatchType {
+		case "NEQ":
+			match = "!="
+		case "GT":
+			match = ">"
+		case "LT":
+			match = "<"
+		case "GET":
+			match = ">="
+		case "LET":
+			match = "<="
+		default: //EQ
+			match = "=="
+		}
+	default: /*bool*/
+		switch element.MatchType {
+		case "NEQ":
+			match = "!="
+		default: //EQ
+			match = "=="
+		}
+	}
+	return match
 }
diff --git a/aql/convertQuery2.go b/aql/convertQuery2.go
deleted file mode 100644
index 2170b4c..0000000
--- a/aql/convertQuery2.go
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
-This program has been developed by students from the bachelor Computer Science at Utrecht University within the Software Project course.
-© Copyright Utrecht University (Department of Information and Computing Sciences)
-*/
-
-package aql
-
-import (
-	"errors"
-	"fmt"
-
-	"git.science.uu.nl/graphpolaris/query-conversion/entity"
-)
-
-// Version 1.13
-
-/*
-ConvertQuery converts an IncomingQueryJSON object into AQL
-	JSONQuery: *entity.IncomingQueryJSON, the query to be converted to AQL
-	Returns: *string, the AQL query and a possible error
-*/
-func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, error) {
-	// Check to make sure all indexes exist
-	// The largest possible id for an entity
-	largestEntityID := len(JSONQuery.Entities) - 1
-	// The largest possible id for a relation
-	largestRelationID := len(JSONQuery.Relations) - 1
-
-	// Make sure no entity should be returned that is outside the range of that list
-	for _, e := range JSONQuery.Return.Entities {
-		// If this entity references an entity that is outside the range
-		if e > largestEntityID || e < 0 {
-			return nil, errors.New("non-existing entity referenced in return")
-		}
-	}
-
-	// Make sure that no relation mentions a non-existing entity
-	for _, r := range JSONQuery.Relations {
-		if r.FromID > largestEntityID && r.FromType == "entity" || r.ToID > largestEntityID && r.ToType == "entity" {
-			return nil, errors.New("non-exisiting entity referenced in relation")
-		}
-	}
-
-	// Make sure no non-existing relation is tried to be returned
-	for _, r := range JSONQuery.Return.Relations {
-		if r > largestRelationID || r < 0 {
-			return nil, errors.New("non-existing relation referenced in return")
-		}
-	}
-	// Don't run search if we are getting empty queries from unit tests
-	var tree []entity.Tree
-	var topNode entity.QueryEntityStruct
-	if len(JSONQuery.Entities) != 0 && len(JSONQuery.Relations) != 0 {
-		tree, topNode = search(JSONQuery, 0)
-	}
-	result := createQuery(JSONQuery, tree, topNode)
-	return result, nil
-}
-
-/*
-createQuery generates a query based on the json file provided
-	JSONQuery: *entity.IncomingQueryJSON, this is a parsedJSON struct holding all the data needed to form a query,
-	Return: *string, a string containing the corresponding AQL query and an error
-*/
-func createQuery(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, topNode entity.QueryEntityStruct) *string {
-	output := createLetFor("result", fmt.Sprintf("e_%v", topNode.ID), topNode.Name)
-	for constraint := range topNode.Constraints {
-		output += createFilter(topNode.Constraints[constraint], fmt.Sprintf("e_%v", topNode.ID))
-	}
-	subQuery, subName := createQueryRecurse(JSONQuery, tree, 0)
-	subNames := []string{subName}
-	output += subQuery
-	output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", topNode.ID)))
-	output += createReturn(fmt.Sprintf("e_%v", topNode.ID), "", subNames)
-	output += "let nodes = union_distinct(flatten(result[**].nodes),[])\nlet edges = union_distinct(flatten(result[**].rel),[])\nreturn {\"vertices\":nodes,\"edges\":edges}"
-	return &output
-}
-
-func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, currentindex int) (string, string) {
-	currentTree := tree[currentindex]
-	newNode, oldNode := getTreeNewAndOldNode(currentTree, tree)
-	output := createLetFor(fmt.Sprintf("e%v", newNode.ID), fmt.Sprintf("e_%v", newNode.ID), newNode.Name)
-	output += fmt.Sprintf("FOR r%v IN %v", currentTree.Self.Rel.ID, currentTree.Self.Rel.Name)
-	for constraint := range newNode.Constraints {
-		output += createFilter(newNode.Constraints[constraint], fmt.Sprintf("e_%v", newNode.ID))
-	}
-	for constraint := range currentTree.Self.Rel.QueryConstraintStruct {
-		output += createFilter(currentTree.Self.Rel.QueryConstraintStruct[constraint], fmt.Sprintf("r%v", currentTree.Self.Rel.ID))
-	}
-	if currentTree.Self.Rel.FromID == newNode.ID {
-		output += fmt.Sprintf("FILTER r%v._from == e_%v._id AND r%v._to == e_%v._id", currentTree.Self.Rel.ID, newNode.ID, currentTree.Self.Rel.ID, oldNode.ID)
-	} else {
-		output += fmt.Sprintf("FILTER r%v._from == e_%v._id AND r%v._to == e_%v._id", currentTree.Self.Rel.ID, oldNode.ID, currentTree.Self.Rel.ID, newNode.ID)
-	}
-	var subNames []string
-	for i := range currentTree.Children {
-		subQuery, subName := createQueryRecurse(JSONQuery, tree, currentTree.Children[i])
-		output += subQuery
-		subNames = append(subNames, subName)
-	}
-	output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID)))
-	output += createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), subNames)
-	return output, fmt.Sprintf("e%v", newNode.ID)
-}
-
-func getTreeNewAndOldNode(currentTree entity.Tree, tree []entity.Tree) (entity.QueryEntityStruct, entity.QueryEntityStruct) {
-	if currentTree.Self.FromNode.ID == tree[currentTree.Parent].Self.FromNode.ID || currentTree.Self.FromNode.ID == tree[currentTree.Parent].Self.ToNode.ID {
-		return currentTree.Self.ToNode, currentTree.Self.FromNode
-	} else {
-		return currentTree.Self.FromNode, currentTree.Self.ToNode
-	}
-}
-
-func createLetFor(variableName string, forName string, enumerableName string) string {
-	return "LET " + variableName + " = (\n\tFOR " + forName + " IN " + enumerableName + "\n"
-}
-
-func createFilter(constraint entity.QueryConstraintStruct, filtered string) string {
-	return "\tFILTER + " + filtered + constraint.Attribute + " " + wordsToLogicalSign(constraint) + " " + constraint.Value + " \n"
-}
-
-func createZeroFilter(subNames []string) string {
-	output := "FILTER"
-	for i := range subNames {
-		output += fmt.Sprintf(" length(%v) != 0", subNames[i])
-		if i < len(subNames)-1 {
-			output += " AND"
-		}
-	}
-	return output
-}
-
-func createReturn(nodeName string, relName string, subNames []string) string {
-	output := "RETURN {\"nodes\":union_distinct("
-	for i := range subNames {
-		output += fmt.Sprintf("flatten(%v[**].nodes), ", subNames[i])
-	}
-	output += "[" + nodeName + "]"
-	if len(subNames) == 0 {
-		output += ", []"
-	}
-	output += "), \"rel\": union_distinct("
-	for i := range subNames {
-		output += fmt.Sprintf("flatten(%v[**].rel), ", subNames[i])
-	}
-	output += "[" + relName + "]"
-	if len(subNames) == 0 {
-		output += ", []"
-	}
-	output += ")}\n)\n"
-	return output
-}
-
-func wordsToLogicalSign(element entity.QueryConstraintStruct) string {
-	var match string
-	switch element.DataType {
-	case "string":
-		switch element.MatchType {
-		case "NEQ":
-			match = "!="
-		case "contains":
-			match = "LIKE"
-		case "excludes":
-			match = "NOT LIKE"
-		default: //EQ
-			match = "=="
-		}
-	case "int":
-		switch element.MatchType {
-		case "NEQ":
-			match = "!="
-		case "GT":
-			match = ">"
-		case "LT":
-			match = "<"
-		case "GET":
-			match = ">="
-		case "LET":
-			match = "<="
-		default: //EQ
-			match = "=="
-		}
-	default: /*bool*/
-		switch element.MatchType {
-		case "NEQ":
-			match = "!="
-		default: //EQ
-			match = "=="
-		}
-	}
-	return match
-}
diff --git a/realtest.json b/realtest.json
index c007bf0..5b928f0 100644
--- a/realtest.json
+++ b/realtest.json
@@ -12,7 +12,7 @@
             "constraints": []
         },
         {
-            "name": "commission",
+            "name": "commissions",
             "ID": 1,
             "constraints": []
         },
-- 
GitLab