Skip to content

Commit

Permalink
Allow Translator to return multiple Cypher objects
Browse files Browse the repository at this point in the history
resolves #265
  • Loading branch information
Andy2003 committed Feb 2, 2022
1 parent 6eac42f commit cba4780
Show file tree
Hide file tree
Showing 46 changed files with 904 additions and 115 deletions.
2 changes: 1 addition & 1 deletion .run/Run All tests including integration tests.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run All tests including integration tests" type="JUnit" factoryName="JUnit">
<module name="neo4j-graphql-java" />
<module name="neo4j-graphql-java (1)" />
<option name="PACKAGE_NAME" value="org.neo4j.graphql" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/kotlin/org/neo4j/graphql/Translator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import graphql.schema.GraphQLSchema

class Translator(val schema: GraphQLSchema) {

class CypherHolder(var cypher: Cypher?)
class CypherHolder(val cyphers :MutableList<Cypher> = mutableListOf())

private val gql: GraphQL = GraphQL.newGraphQL(schema).build()

@JvmOverloads
@Throws(OptimizedQueryException::class)
fun translate(query: String, params: Map<String, Any?> = emptyMap(), ctx: QueryContext = QueryContext()): List<Cypher> {
val cypherHolder = CypherHolder(null)
val cypherHolder = CypherHolder()
val executionInput = ExecutionInput.newExecutionInput()
.query(query)
.variables(params)
Expand All @@ -36,6 +36,6 @@ class Translator(val schema: GraphQLSchema) {
}
}

return listOf(requireNotNull(cypherHolder.cypher))
return cypherHolder.cyphers
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ abstract class BaseDataFetcher(schemaConfig: SchemaConfig) : ProjectionBase(sche
}
return Cypher(query, params, env.fieldDefinition.type, variable = field.aliasOrName())
.also {
(env.getLocalContext() as? Translator.CypherHolder)?.apply { this.cypher = it }
(env.getLocalContext() as? Translator.CypherHolder)?.apply { this.cyphers += it }
}
}

Expand Down
57 changes: 32 additions & 25 deletions core/src/test/kotlin/org/neo4j/graphql/utils/AsciiDocTestSuite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,12 @@ open class AsciiDocTestSuite(
private var currentDocumentLevel: DocumentLevel? = null
private var currentDepth = 0

private val globalCodeBlocks = mutableMapOf<String, ParsedBlock>()
private var codeBlocksOfTest = mutableMapOf<String, ParsedBlock>()
private val globalCodeBlocks = mutableMapOf<String, MutableList<ParsedBlock>>()
private var codeBlocksOfTest = mutableMapOf<String, MutableList<ParsedBlock>>()

fun parse(): Stream<DynamicNode> {
val file = File(AsciiDocTestSuite::class.java.getResource("/$fileName").toURI())
val file = File(AsciiDocTestSuite::class.java.getResource("/$fileName")?.toURI()!!)
val lines = file.readLines()
val terminatorElement = testCaseMarkers.lastOrNull()

var title: String? = null
var currentBlock: ParsedBlock? = null
Expand All @@ -92,11 +91,17 @@ open class AsciiDocTestSuite(
val headlineMatcher = HEADLINE_PATTERN.matcher(line)

when {
!globalDone && globalMarkers.contains(line) -> currentBlock = startBlock(line, lineNr, globalCodeBlocks)
!globalDone && globalMarkers.contains(line) -> currentBlock =
startBlock(line, lineNr, globalCodeBlocks)
testCaseMarkers.contains(line) -> {
globalDone = true
currentBlock = startBlock(line, lineNr, codeBlocksOfTest)
}
line == "'''" -> {
createTests(title, lineNr, ignore)
currentBlock = null
ignore = false
}
line == "----" -> {
inside = !inside
if (inside) {
Expand All @@ -111,16 +116,10 @@ open class AsciiDocTestSuite(
SCHEMA_MARKER -> {
val schemaTests = schemaTestFactory(currentBlock.code())
currentDocumentLevel?.tests?.add(schemaTests)
if (terminatorElement == null) {
if (testCaseMarkers.isEmpty()){
break@loop
}
}

terminatorElement -> {
createTests(title, lineNr, ignore)
currentBlock = null
ignore = false
}
}

}
Expand All @@ -143,15 +142,22 @@ open class AsciiDocTestSuite(

if (UPDATE_TEST_FILE) {
// this test prints out the adjusted test file
root?.afterTests?.add(DynamicTest.dynamicTest("Write updated Testfile", srcLocation, this@AsciiDocTestSuite::writeAdjustedTestFile))
root?.afterTests?.add(
DynamicTest.dynamicTest("Write updated Testfile", srcLocation, this@AsciiDocTestSuite::writeAdjustedTestFile)
)
} else if (GENERATE_TEST_FILE_DIFF) {
// this test prints out the adjusted test file
root?.afterTests?.add(DynamicTest.dynamicTest("Adjusted Tests", srcLocation, this@AsciiDocTestSuite::printAdjustedTestFile))
root?.afterTests?.add(
DynamicTest.dynamicTest("Adjusted Tests", srcLocation, this@AsciiDocTestSuite::printAdjustedTestFile)
)
}
return root?.generateTests() ?: Stream.empty()
}

private fun createTests(title: String?, lineNr: Int, ignore: Boolean) {
if (codeBlocksOfTest.isEmpty()) {
throw IllegalStateException("no code blocks for tests (line $lineNr)")
}
val tests = testFactory(
title ?: throw IllegalStateException("Title should be defined (line $lineNr)"),
globalCodeBlocks,
Expand Down Expand Up @@ -211,33 +217,34 @@ open class AsciiDocTestSuite(
return rebuildTest.toString()
}

fun startBlock(marker: String, lineIndex: Int, blocks: MutableMap<String, ParsedBlock>): ParsedBlock {
fun startBlock(marker: String, lineIndex: Int, blocks: MutableMap<String, MutableList<ParsedBlock>>): ParsedBlock {
val uri = UriBuilder.fromUri(srcLocation).queryParam("line", lineIndex + 1).build()
val block = ParsedBlock(marker, uri)
knownBlocks += block
blocks[marker] = block
blocks.computeIfAbsent(marker) { mutableListOf() }.add(block)
return block
}

protected open fun testFactory(title: String, globalBlocks: Map<String, ParsedBlock>, codeBlocks: Map<String, ParsedBlock>, ignore: Boolean): List<DynamicNode> {
protected open fun testFactory(title: String, globalBlocks: Map<String, List<ParsedBlock>>, codeBlocks: Map<String, List<ParsedBlock>>, ignore: Boolean): List<DynamicNode> {
return emptyList()
}

protected open fun schemaTestFactory(schema: String): List<DynamicNode> {
return emptyList()
}

protected fun getOrCreateBlock(codeBlocks: Map<String, ParsedBlock>, marker: String, headline: String): ParsedBlock? {
var block = codeBlocks[marker]
if (block == null && (GENERATE_TEST_FILE_DIFF || UPDATE_TEST_FILE)) {
protected fun getOrCreateBlocks(codeBlocks: Map<String, List<ParsedBlock>>, marker: String, headline: String): List<ParsedBlock> {
val blocks = codeBlocks[marker]?.toMutableList() ?: mutableListOf()
if (blocks.isEmpty() && (GENERATE_TEST_FILE_DIFF || UPDATE_TEST_FILE)) {
val insertPoints = testCaseMarkers.indexOf(marker).let { testCaseMarkers.subList(0, it).asReversed() }
val insertPoint = insertPoints.mapNotNull { codeBlocks[it] }.firstOrNull()
?: throw IllegalArgumentException("none of the insert points $insertPoints found")
block = ParsedBlock(marker, insertPoint.uri, headline)
val insertPoint = insertPoints.mapNotNull { codeBlocks[it]?.firstOrNull() }.firstOrNull()
?: throw IllegalArgumentException("none of the insert points $insertPoints found in $fileName")
val block = ParsedBlock(marker, insertPoint.uri, headline)
block.start = (insertPoint.end ?: throw IllegalStateException("no start for block defined")) + 6
knownBlocks += block
knownBlocks += blocks
blocks += block
}
return block
return blocks
}

companion object {
Expand Down
Loading

0 comments on commit cba4780

Please sign in to comment.