diff --git a/core/src/main/scala/erules/Rule.scala b/core/src/main/scala/erules/Rule.scala index bf5c95c..929d6af 100644 --- a/core/src/main/scala/erules/Rule.scala +++ b/core/src/main/scala/erules/Rule.scala @@ -176,10 +176,12 @@ object Rule extends RuleInstances { class RuleBuilder[F[_], T] private[erules] (name: String) { $this => - def apply(f: Function[T, F[RuleVerdict]]): Rule[F, T] = + def apply(f: T => F[RuleVerdict]): Rule[F, T] = RuleImpl(f, RuleInfo($this.name)) - def partially(f: PartialFunction[T, F[RuleVerdict]])(implicit F: Applicative[F]): Rule[F, T] = + def matchOrIgnore(f: PartialFunction[T, F[RuleVerdict]])(implicit + F: Applicative[F] + ): Rule[F, T] = apply(f.lift.andThen(_.getOrElse(F.pure(Ignore.noMatch)))) def failed(ex: Throwable)(implicit F: ApplicativeThrow[F]): Rule[F, T] = @@ -189,7 +191,7 @@ object Rule extends RuleInstances { apply(_ => F.pure(v)) // assertions - def assert(f: Function[T, F[Boolean]])(implicit + def assert(f: T => F[Boolean])(implicit F: Applicative[F] ): Rule[F, T] = fromBooleanF(f)( @@ -197,7 +199,7 @@ object Rule extends RuleInstances { ifFalse = Deny.withoutReasons ) - def assert(ifFalse: String)(f: Function[T, F[Boolean]])(implicit + def assert(ifFalse: String)(f: T => F[Boolean])(implicit F: Applicative[F] ): Rule[F, T] = fromBooleanF(f)( @@ -205,15 +207,15 @@ object Rule extends RuleInstances { ifFalse = Deny.because(ifFalse) ) - def assertNot(f: Function[T, F[Boolean]])(implicit F: Applicative[F]): Rule[F, T] = + def assertNot(f: T => F[Boolean])(implicit F: Applicative[F]): Rule[F, T] = assert(f.andThen(_.map(!_))) - def assertNot(ifTrue: String)(f: Function[T, F[Boolean]])(implicit + def assertNot(ifTrue: String)(f: T => F[Boolean])(implicit F: Applicative[F] ): Rule[F, T] = assert(ifTrue)(f.andThen(_.map(!_))) def fromBooleanF( - f: Function[T, F[Boolean]] + f: T => F[Boolean] )(ifTrue: => RuleVerdict, ifFalse: => RuleVerdict)(implicit F: Applicative[F] ): Rule[F, T] = apply(f.andThen(_.ifF(ifTrue, ifFalse))) diff --git a/core/src/main/scala/erules/RuleVerdict.scala b/core/src/main/scala/erules/RuleVerdict.scala index d15ad24..b1fb588 100644 --- a/core/src/main/scala/erules/RuleVerdict.scala +++ b/core/src/main/scala/erules/RuleVerdict.scala @@ -57,7 +57,7 @@ private[erules] trait RuleVerdictBecauseSupport[+T <: RuleVerdict] { object RuleVerdict extends RuleVerdictInstances { // noinspection ScalaWeakerAccess - val noReasons: List[EvalReason] = Nil + lazy val noReasons: List[EvalReason] = Nil // TODO: add test def whenNot(b: Boolean)(ifTrue: => RuleVerdict, ifFalse: => RuleVerdict): RuleVerdict = @@ -71,7 +71,7 @@ object RuleVerdict extends RuleVerdictInstances { sealed trait Allow extends RuleVerdict with RuleVerdictBecauseSupport[Allow] object Allow extends RuleVerdictBecauseSupport[Allow] { - val allNotExplicitlyDenied: Allow = Allow.because("Allow All Not Explicitly Denied") + lazy val allNotExplicitlyDenied: Allow = Allow.because("Allow All Not Explicitly Denied") // TODO: add test def when(b: Boolean)(ifFalse: => RuleVerdict): RuleVerdict = @@ -107,7 +107,7 @@ object RuleVerdict extends RuleVerdictInstances { sealed trait Deny extends RuleVerdict with RuleVerdictBecauseSupport[Deny] object Deny extends RuleVerdictBecauseSupport[Deny] { - val allNotExplicitlyAllowed: Deny = Deny.because("Deny All Not Explicitly Allowed") + lazy val allNotExplicitlyAllowed: Deny = Deny.because("Deny All Not Explicitly Allowed") // TODO: add test def when(b: Boolean)(ifFalse: => RuleVerdict): RuleVerdict = @@ -143,7 +143,7 @@ object RuleVerdict extends RuleVerdictInstances { sealed trait Ignore extends RuleVerdict with RuleVerdictBecauseSupport[Ignore] object Ignore extends RuleVerdictBecauseSupport[Ignore] { - val noMatch: Ignore = Ignore.because("No match") + lazy val noMatch: Ignore = Ignore.because("No match") // TODO: add test def when(b: Boolean)(ifFalse: => RuleVerdict): RuleVerdict = diff --git a/core/src/test/scala/erules/EngineResultSpec.scala b/core/src/test/scala/erules/EngineResultSpec.scala index 2fd89b6..f5b78f4 100644 --- a/core/src/test/scala/erules/EngineResultSpec.scala +++ b/core/src/test/scala/erules/EngineResultSpec.scala @@ -14,12 +14,12 @@ class EngineResultSpec extends AnyWordSpec with Matchers with EitherValues { case class Foo(value: String) - val rule1: PureRule[Foo] = Rule("Check Foo").partially { + val rule1: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } - val rule2: PureRule[Foo] = Rule("Check Foo").partially { + val rule2: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } @@ -57,12 +57,12 @@ class EngineResultSpec extends AnyWordSpec with Matchers with EitherValues { case class Foo(value: String) - val rule1: PureRule[Foo] = Rule("Check Foo").partially { + val rule1: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } - val rule2: PureRule[Foo] = Rule("Check Foo").partially { + val rule2: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Deny.withoutReasons } @@ -99,12 +99,12 @@ class EngineResultSpec extends AnyWordSpec with Matchers with EitherValues { case class Foo(value: String) - val rule1: PureRule[Foo] = Rule("Check Foo").partially { + val rule1: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Deny.withoutReasons } - val rule2: PureRule[Foo] = Rule("Check Foo").partially { + val rule2: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } @@ -141,12 +141,12 @@ class EngineResultSpec extends AnyWordSpec with Matchers with EitherValues { case class Foo(value: String) - val rule1: PureRule[Foo] = Rule("Check Foo").partially { + val rule1: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Deny.withoutReasons } - val rule2: PureRule[Foo] = Rule("Check Foo").partially { + val rule2: PureRule[Foo] = Rule("Check Foo").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Deny.withoutReasons } @@ -187,17 +187,17 @@ class EngineResultSpec extends AnyWordSpec with Matchers with EitherValues { case class Foo(value: String) - val rule1: PureRule[Foo] = Rule("Check Foo 1").partially { + val rule1: PureRule[Foo] = Rule("Check Foo 1").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } - val rule2: PureRule[Foo] = Rule("Check Foo 2").partially { + val rule2: PureRule[Foo] = Rule("Check Foo 2").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } - val rule3: PureRule[Foo] = Rule("Check Foo 3").partially { + val rule3: PureRule[Foo] = Rule("Check Foo 3").matchOrIgnore { case Foo("") => Deny.because("Empty Value") case Foo("TEST") => Allow.withoutReasons } diff --git a/core/src/test/scala/erules/RuleSpec.scala b/core/src/test/scala/erules/RuleSpec.scala index c5f9b99..cec1347 100644 --- a/core/src/test/scala/erules/RuleSpec.scala +++ b/core/src/test/scala/erules/RuleSpec.scala @@ -130,7 +130,7 @@ class RuleSpec "return the right result once evaluated" in { case class Foo(@unused x: String, @unused y: Int) - val rule: RuleIO[Foo] = Rule("Check Y value").partially { + val rule: RuleIO[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => IO.pure(Allow.withoutReasons) case Foo(_, 1) => IO.pure(Deny.withoutReasons) } @@ -153,7 +153,7 @@ class RuleSpec case class Foo(@unused x: String, @unused y: Int) val ex = new RuntimeException("BOOM") - val rule: RuleIO[Foo] = Rule("Check Y value").partially { + val rule: RuleIO[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => IO.raiseError(ex) case Foo(_, 1) => IO.pure(Deny.withoutReasons) } @@ -173,7 +173,7 @@ class RuleSpec "return the right result once evaluated in defined domain" in { case class Foo(@unused x: String, @unused y: Int) - val rule: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val rule: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -186,7 +186,7 @@ class RuleSpec "return the Ignore once evaluated out of the defined domain" in { case class Foo(@unused x: String, @unused y: Int) - val rule: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val rule: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -298,7 +298,7 @@ class RuleSpec "return the right result once evaluated" in { case class Foo(@unused x: String, @unused y: Int) - val rule: Rule[IO, Foo] = Rule("Check Y value").partially { + val rule: Rule[IO, Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => IO.pure(Allow.withoutReasons) case Foo(_, 1) => IO.pure(Deny.withoutReasons) } @@ -312,7 +312,7 @@ class RuleSpec "return an exception when a case fail" in { case class Foo(@unused x: String, @unused y: Int) - val rule: RuleIO[Foo] = Rule("Check Y value").partially { + val rule: RuleIO[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => IO.raiseError(new RuntimeException("BOOM")) case Foo(_, 1) => IO.pure(Deny.withoutReasons) } @@ -327,7 +327,7 @@ class RuleSpec case class Foo(@unused x: String, @unused y: Int) val rule: PureRule[Foo] = - Rule("Check Y value").partially { case Foo(_, 0) => + Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -338,7 +338,7 @@ class RuleSpec case class Foo(@unused x: String, @unused y: Int) val rule: PureRule[Foo] = - Rule("Check Y value").partially { case Foo(_, 0) => + Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -353,10 +353,10 @@ class RuleSpec val duplicated: List[PureRule[Foo]] = Rule.findDuplicated( NonEmptyList.of( - Rule("Check Y value").partially { case Foo(_, 0) => + Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons }, - Rule("Check Y value").partially { case Foo(_, 1) => + Rule("Check Y value").matchOrIgnore { case Foo(_, 1) => Allow.withoutReasons } ) @@ -370,10 +370,10 @@ class RuleSpec val duplicated: Seq[PureRule[Foo]] = Rule.findDuplicated( NonEmptyList.of( - Rule("Check Y value").partially { case Foo(_, 0) => + Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons }, - Rule("Check X value").partially { case Foo("Foo", _) => + Rule("Check X value").matchOrIgnore { case Foo("Foo", _) => Allow.withoutReasons } ) diff --git a/core/src/test/scala/erules/RulesEngineSpec.scala b/core/src/test/scala/erules/RulesEngineSpec.scala index 191dcd7..d2c013d 100644 --- a/core/src/test/scala/erules/RulesEngineSpec.scala +++ b/core/src/test/scala/erules/RulesEngineSpec.scala @@ -23,11 +23,11 @@ class RulesEngineSpec "RulesEngine" should { "Return a DuplicatedRulesException with duplicated rules" in { - val allowYEqZero1: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero1: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } - val allowYEqZero2: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero2: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -50,7 +50,7 @@ class RulesEngineSpec "Respond with DENIED when there are no rules for the target" in { - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -76,11 +76,11 @@ class RulesEngineSpec "Respond with DENIED when a rule Deny the target" in { - val denyXEqTest: PureRule[Foo] = Rule("Check X value").partially { case Foo("TEST", _) => + val denyXEqTest: PureRule[Foo] = Rule("Check X value").matchOrIgnore { case Foo("TEST", _) => Deny.withoutReasons } - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -112,7 +112,7 @@ class RulesEngineSpec "Respond with ALLOWED when a ALL rules allow the target" in { - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -174,7 +174,7 @@ class RulesEngineSpec "Respond with ALLOWED when there are no rules for the target" in { - val denyYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val denyYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Deny.withoutReasons } @@ -200,11 +200,11 @@ class RulesEngineSpec "Respond with DENIED when a rule Deny the target" in { - val denyXEqTest: PureRule[Foo] = Rule("Check X value").partially { case Foo("TEST", _) => + val denyXEqTest: PureRule[Foo] = Rule("Check X value").matchOrIgnore { case Foo("TEST", _) => Deny.withoutReasons } - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } @@ -233,7 +233,7 @@ class RulesEngineSpec "Respond with ALLOWED when a ALL rules allow the target" in { - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } diff --git a/core/src/test/scala/erules/report/StringReportEncoderSpec.scala b/core/src/test/scala/erules/report/StringReportEncoderSpec.scala index dd8d33a..560f58c 100644 --- a/core/src/test/scala/erules/report/StringReportEncoderSpec.scala +++ b/core/src/test/scala/erules/report/StringReportEncoderSpec.scala @@ -17,7 +17,7 @@ class StringReportEncoderSpec extends AsyncWordSpec with AsyncIOSpec with Matche case class Foo(x: String, y: Int) - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.withoutReasons } diff --git a/modules/cats-xml/src/test/scala/erules/cats/xml/report/XmlReportEncoderSpec.scala b/modules/cats-xml/src/test/scala/erules/cats/xml/report/XmlReportEncoderSpec.scala index 305cc93..6ffdef3 100644 --- a/modules/cats-xml/src/test/scala/erules/cats/xml/report/XmlReportEncoderSpec.scala +++ b/modules/cats-xml/src/test/scala/erules/cats/xml/report/XmlReportEncoderSpec.scala @@ -24,7 +24,7 @@ class XmlReportEncoderSpec extends munit.CatsEffectSuite { ) } - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.because("because yes!") } diff --git a/modules/circe/src/test/scala/erules/circe/report/JsonReportEncoderSpec.scala b/modules/circe/src/test/scala/erules/circe/report/JsonReportEncoderSpec.scala index 6c61c4a..e9b2d9b 100644 --- a/modules/circe/src/test/scala/erules/circe/report/JsonReportEncoderSpec.scala +++ b/modules/circe/src/test/scala/erules/circe/report/JsonReportEncoderSpec.scala @@ -14,7 +14,7 @@ class JsonReportEncoderSpec extends munit.CatsEffectSuite { test("EngineResult.asJsonReport return a well-formatted JSON report") { case class Foo(x: String, y: Int) - val allowYEqZero: PureRule[Foo] = Rule("Check Y value").partially { case Foo(_, 0) => + val allowYEqZero: PureRule[Foo] = Rule("Check Y value").matchOrIgnore { case Foo(_, 0) => Allow.because("reason") }