Rules builder using the Kotlin builder pattern

This commit is contained in:
Fedor Isakov 2015-11-22 22:35:54 +01:00
parent 77c827f8cd
commit ff71c6f990
4 changed files with 128 additions and 1 deletions

View File

@ -19,6 +19,9 @@ public abstract class RuleHandler {
public abstract void setRules(@NotNull Iterable<? extends Rule> rules);
@NotNull
public abstract Iterable<? extends Rule> rules();
/**
* SPI
*/

View File

@ -22,6 +22,10 @@ class RuleHandlerImpl : RuleHandler() {
}
}
override fun rules(): MutableIterable<Rule> {
return myRules
}
companion object {
fun init() {
setOurCompanion (object : RuleHandler.Companion {

View File

@ -0,0 +1,78 @@
import jetbrains.mps.logic.reactor.constraint.occurrence.AbstractConstraintOccurrence
import jetbrains.mps.logic.reactor.constraint.occurrence.ConstraintOccurrence
import jetbrains.mps.logic.reactor.rule.Rule
import jetbrains.mps.logic.reactor.rule.RuleBuilder
import java.util.*
import kotlin.reflect.KClass
/**
* @author Fedor Isakov
*/
fun rule(tag: String, vararg component:RB.() -> Unit): Rule {
val rb = RB(tag)
for (cmp in component) {
rb.cmp()
}
return rb.toRule()
}
fun headKept(vararg content : ConjBuilder.() -> Unit): RB.() -> Unit = {
appendHeadKept( * buildConjunction(ConstraintOccurrence::class.java, content).toArray())
}
fun headReplaced(vararg content : ConjBuilder.() -> Unit): RB.() -> Unit = {
appendHeadKept( * buildConjunction(ConstraintOccurrence::class.java, content).toArray())
}
fun guard(vararg content : ConjBuilder.() -> Unit): RB.() -> Unit = {
appendGuard( * buildConjunction(AbstractConstraintOccurrence::class.java, content).toArray())
}
fun body(vararg content : ConjBuilder.() -> Unit): RB.() -> Unit = {
appendBody( * buildConjunction(AbstractConstraintOccurrence::class.java, content).toArray())
}
fun constraint(id: String): ConjBuilder.() -> Unit = {
add(ConstraintOccurrence.singleton(id))
}
fun constraint(id: String, arg: Any): ConjBuilder.() -> Unit = {
add(ConstraintOccurrence.unitary(id, arg))
}
fun constraint(id: String, arg1: Any, arg2: Any): ConjBuilder.() -> Unit = {
add(ConstraintOccurrence.binary(id, arg1, arg2))
}
fun constraint(id: String, arg1: Any, arg2: Any, arg3: Any): ConjBuilder.() -> Unit = {
add(ConstraintOccurrence.ternary(id, arg1, arg2, arg3))
}
fun constraint(id: String, args: Array<out Any>): ConjBuilder.() -> Unit = {
add(ConstraintOccurrence.nary(id, * args))
}
class RB(tag: String) : RuleBuilder(tag) {}
class ConjBuilder (val type: Class<out AbstractConstraintOccurrence>) {
val constraints = ArrayList<AbstractConstraintOccurrence>()
fun add(constraint: AbstractConstraintOccurrence): Unit {
if (!type.isAssignableFrom(constraint.javaClass))
throw IllegalArgumentException("unexpected constraint class '${constraint.javaClass}'")
constraints.add(constraint)
}
fun <T : AbstractConstraintOccurrence> toArray(): Array<T> =
if (ConstraintOccurrence::class.java.isAssignableFrom(type))
Array<ConstraintOccurrence>(constraints.size) {
constraints.get(it) as ConstraintOccurrence
} as Array<T>
else
Array<AbstractConstraintOccurrence>(constraints.size) {
constraints.get(it)
} as Array<T>
}
private fun
buildConjunction(type: Class<out AbstractConstraintOccurrence>, content: Array<out ConjBuilder.() -> Unit>): ConjBuilder
{
var conjBuilder = ConjBuilder(type)
for (c in content) {
conjBuilder.c()
}
return conjBuilder
}

View File

@ -1,9 +1,13 @@
import jetbrains.mps.logic.reactor.handler.RuleHandler
import jetbrains.mps.logic.reactor.rule.InvalidRuleException
import jetbrains.mps.logicl.reactor.core.RuleHandlerImpl
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import java.util.*
import kotlin.reflect.KClass
import kotlin.test.assertEquals
import kotlin.test.expect
/**
* @author Fedor Isakov
@ -17,10 +21,48 @@ class Simple {
}
}
@Before fun beforeTest() {
handler = RuleHandler.with().newHandler()
}
lateinit var handler:RuleHandler
@Test fun empty() {
val handler = RuleHandler.with().newHandler()
handler.setRules(ArrayList())
}
@Test(expected = InvalidRuleException::class)
fun emptyBody() {
handler.setRules(arrayListOf(
rule("foo",
headKept(
constraint("bar")
))
))
}
@Test
fun replace() {
handler.setRules(arrayListOf(
rule("foo",
headReplaced(
constraint("bar")
),
body(
constraint("baz")
))
))
val sb = StringBuilder()
handler.rules().forEach {
sb.append(it.tag()).append(": ")
it.all().joinTo(sb, ", ")
sb.append(";")
}
assertEquals("foo", sb.toString())
}
}