Add Kotlin extensions aliasing reserved keywords and operators.

This adds extensions for `as` and `in` and closes #37.
This commit is contained in:
Michael Simons
2019-09-16 18:35:58 +02:00
parent ad545fc490
commit 0fc7dde2c7
10 changed files with 281 additions and 18 deletions

View File

@@ -61,7 +61,7 @@
<property name="illegalPkgs"
value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|lang|lang3|logging|pool2).*, ^com\.google\.common.*, ^org\.flywaydb\.core\.internal.*, ^org\.testcontainers\.shaded.*, ^org\.neo4j\.driver\.internal\.shaded.*, ^org\.slf4j.*" />
<property name="illegalClasses"
value="^reactor\.core\.support\.Assert, ^org\.junit\.rules\.ExpectedException" />
value="^reactor\.core\.support\.Assert, ^org\.junit\.rules\.ExpectedException, ^org\.junit\.Test" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.RedundantImportCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">

View File

@@ -133,6 +133,12 @@
<artifactId>kotlin-reflect</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.mockk</groupId>
<artifactId>mockk</artifactId>
<version>${mockk}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>

View File

@@ -188,19 +188,6 @@ public final class Conditions {
return Comparison.create(Operator.IS_NOT_NULL, expression);
}
/**
* Creates a condition that checkts whether the expression {@code searchFor} is in the expression {@code in}.
* {@code in} is supposed to represent a list object.
*
* @param searchFor The expression to search for.
* @param in The expression to search in.
* @return A new condition.
*/
static Condition in(Expression searchFor, Expression in) {
return Comparison.create(searchFor, Operator.IN, in);
}
/**
* A condition that evaluates to true if a list or a string represented by {@code expression} is empty or has the length of 0.
*
@@ -223,7 +210,6 @@ public final class Conditions {
return new BooleanFunctionCondition(Functions.exists(expression));
}
/**
* Not to be instantiated.
*/

View File

@@ -171,11 +171,11 @@ public interface Expression extends Visitable {
* Creates a {@code IN} operation for this expression and that {@code expression}.
* The expression does not track the condition created here.
*
* @param expression The expression to search for this expression
* @param haystack The expression to search for this expression
* @return A new condition.
*/
default Condition in(Expression expression) {
return Conditions.in(this, expression);
default Condition in(Expression haystack) {
return Comparison.create(this, Operator.IN, haystack);
}
/**

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core
/**
* Extension for [Neo4jClient.RunnableSpec.in] providing an `inDatabase` alias since `in` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun Neo4jClient.RunnableSpec.inDatabase(targetDatabase: String): Neo4jClient.RunnableSpecTightToDatabase = `in`(targetDatabase)
/**
* Extension for [Neo4jClient.OngoingDelegation.in] providing an `inDatabase` alias since `in` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun <T : Any?> Neo4jClient.OngoingDelegation<T>.inDatabase(targetDatabase: String): Neo4jClient.RunnableDelegation<T> = `in`(targetDatabase)

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core
/**
* Extension for [ReactiveNeo4jClient.ReactiveRunnableSpec.in] providing an `inDatabase` alias since `in` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun ReactiveNeo4jClient.ReactiveRunnableSpec.inDatabase(targetDatabase: String): ReactiveNeo4jClient.ReactiveRunnableSpecTightToDatabase = `in`(targetDatabase)
/**
* Extension for [ReactiveNeo4jClient.OngoingReactiveDelegation.in] providing an `inDatabase` alias since `in` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun <T : Any?> ReactiveNeo4jClient.OngoingReactiveDelegation<T>.inDatabase(targetDatabase: String): ReactiveNeo4jClient.ReactiveRunnableDelegation<T> = `in`(targetDatabase)

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core.cypher
/**
* Extension for [Expression.in] providing an `inValues` alias since `in` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun Expression.inValues(inHaystack: Expression): Condition = `in`(inHaystack)
/**
* Extension for [Expression.as] providing an `withAlias` alias since `as` is a reserved keyword in Kotlin.
*
* @author Michael J. Simons
* @since 1.0
*/
fun Expression.asAlias(alias: String): AliasedExpression = `as`(alias)
fun StatementBuilder.OngoingUnwind.asAlias(alias: String): StatementBuilder.OngoingReading = `as`(alias)

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test
/**
* @author Michael J. Simons
*/
class Neo4jClientExtensionsTest {
@Test
fun `RunnableSpec#inDatabase(targetDatabase) extension should call its Java counterpart`() {
val runnableSpec = mockk<Neo4jClient.RunnableSpec>(relaxed = true)
runnableSpec.inDatabase("foobar");
verify(exactly = 1) { runnableSpec.`in`("foobar") }
}
@Test
fun `OngoingDelegation#inDatabase(targetDatabase) extension should call its Java counterpart`() {
val ongoingDelegation = mockk<Neo4jClient.OngoingDelegation<Any>>(relaxed = true)
ongoingDelegation.inDatabase("foobar");
verify(exactly = 1) { ongoingDelegation.`in`("foobar") }
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test
/**
* @author Michael J. Simons
*/
class ReactiveNeo4jClientExtensionsTest {
@Test
fun `RunnableSpec#inDatabase(targetDatabase) extension should call its Java counterpart`() {
val runnableSpec = mockk<ReactiveNeo4jClient.ReactiveRunnableSpec>(relaxed = true)
runnableSpec.inDatabase("foobar");
verify(exactly = 1) { runnableSpec.`in`("foobar") }
}
@Test
fun `OngoingDelegation#inDatabase(targetDatabase) extension should call its Java counterpart`() {
val ongoingDelegation = mockk<ReactiveNeo4jClient.OngoingReactiveDelegation<Any>>(relaxed = true)
ongoingDelegation.inDatabase("foobar");
verify(exactly = 1) { ongoingDelegation.`in`("foobar") }
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2019 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.springframework.data.core.cypher
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.neo4j.springframework.data.core.cypher.Cypher.listOf
import org.neo4j.springframework.data.core.cypher.Cypher.literalFalse
/**
* @author Michael J. Simons
*/
class CypherExtensionsTest {
@Nested
inner class ExpressionExtensions {
val expression = mockk<Expression>(relaxed = true)
@Test
fun `inValues(expression) extension should call its Java counterpart`() {
expression.inValues(listOf(literalFalse()));
verify(exactly = 1) { expression.`in`(any()) }
}
@Test
fun `asAlias(alias) extension should call its Java counterpart`() {
expression.asAlias("foo")
verify(exactly = 1) { expression.`as`("foo") }
}
}
@Nested
inner class StatementBuilderExtensions {
@Test
fun `asAlias(alias) extension should call its Java counterpart`() {
val ongoingUnwind = mockk<StatementBuilder.OngoingUnwind>(relaxed = true)
ongoingUnwind.asAlias("foo")
verify(exactly = 1) { ongoingUnwind.`as`("foo") }
}
}
}