Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 11 additions & 18 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- uses: actions/setup-java@v3
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
java-version: '21'
cache: 'gradle'

- name: install gpg
Expand All @@ -24,7 +24,7 @@ jobs:
apt install -y gpg
fi

- uses: crazy-max/ghaction-import-gpg@v6
- uses: crazy-max/ghaction-import-gpg@v7
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
Expand All @@ -39,22 +39,15 @@ jobs:
-Psigning.gnupg.useLegacyGpg=true \
-Psigning.gnupg.keyName=${{ secrets.GPG_SIGN_KEY }} \
-Pversion=${GITHUB_REF_NAME} \
publishToSonatype
publish

- name: close staging
- name: finalize deployment
if: ${{ !endsWith(github.ref_name, '-SNAPSHOT') }}
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
run: |
./gradlew --no-daemon \
-Pversion=${GITHUB_REF_NAME} \
findSonatypeStagingRepository closeSonatypeStagingRepository

- name: release version
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
run: |
./gradlew --no-daemon \
-Pversion=${GITHUB_REF_NAME} \
findSonatypeStagingRepository releaseSonatypeStagingRepository
ENCODED=$(echo -n "${OSSRH_USERNAME}:${OSSRH_PASSWORD}" | base64)
curl --fail-with-body -X POST \
-H "Authorization: Bearer ${ENCODED}" \
"https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/com.rapatao.ruleset?publishing_type=automatic"
70 changes: 57 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# ruleset-engine

[![Maven Central](https://img.shields.io/maven-central/v/com.rapatao.ruleset/ruleset-engine.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:com.rapatao.ruleset%20AND%20a:ruleset-engine)
[![Sonatype OSS](https://img.shields.io/nexus/r/com.rapatao.ruleset/ruleset-engine?label=Sonatype%20OSS&server=https%3A%2F%2Foss.sonatype.org)](https://ossindex.sonatype.org/component/pkg:maven/com.rapatao.ruleset/ruleset-engine)

Simple yet powerful rules engine that offers the flexibility of using the built-in engine and creating a custom one.

Expand Down Expand Up @@ -109,10 +108,8 @@ printing the `result` in the default output.
### Code example

```kotlin

import com.rapatao.projects.ruleset.engine.Evaluator
import com.rapatao.projects.ruleset.engine.context.EvalEngine
import com.rapatao.projects.ruleset.engine.types.builder.equalsTo
import com.rapatao.projects.ruleset.engine.types.builder.extensions.equalsTo

val rule = "item.price" equalsTo 0
val input = mapOf("item" to mapOf("price" to 0))
Expand All @@ -127,7 +124,7 @@ data class Item(val price: Double)
data class Input(val item: Item)

val result2 = evaluator.evaluate(rule, Input(item = Item(price = 0.0)))
println(result) // true
println(result2) // true
```

## Expressions (Rule)
Expand Down Expand Up @@ -217,11 +214,11 @@ operator by one implemented by the user of this library.

## Supported group operations

A grouped operation is `true` when all inner operations result in:
A grouped operation is evaluated as follows:

* `anyMatch`: any operation must be evaluated as `true`
* `allMatch`: all operations must be evaluated as `true`
* `noneMatch`: all operations must be evaluated as `false`
* `anyMatch`: at least one inner expression must evaluate to `true`
* `allMatch`: all inner expressions must evaluate to `true`
* `noneMatch`: all inner expressions must evaluate to `false`

### Examples

Expand Down Expand Up @@ -257,21 +254,68 @@ Expression(
)
````

## Range (between) expressions

Range expressions can be composed using the `from`/`fromInclusive` extensions combined with `to`/`toInclusive`.

```kotlin
import com.rapatao.projects.ruleset.engine.types.builder.extensions.from
import com.rapatao.projects.ruleset.engine.types.builder.extensions.fromInclusive

// price > 10 AND price < 20
"price" from 10 to 20

// price >= 10 AND price <= 20
"price" fromInclusive 10 toInclusive 20
```

## Failure handling

Each `Expression` accepts an `onFailure` strategy that controls what happens when its evaluation throws (for example,
when a referenced field is missing from the input data).

| value | behavior |
|---------|-----------------------------------------------------------------------------|
| `THROW` | (default) re-throws the underlying exception |
| `TRUE` | swallows the exception and treats the expression as `true` |
| `FALSE` | swallows the exception and treats the expression as `false` |

The strategy can be set directly on the `Expression` constructor or applied to an existing expression via the
`ifFail` extension:

```kotlin
import com.rapatao.projects.ruleset.engine.types.OnFailure
import com.rapatao.projects.ruleset.engine.types.builder.extensions.equalsTo
import com.rapatao.projects.ruleset.engine.types.builder.extensions.ifFail

"item.optional.field" equalsTo 10 ifFail OnFailure.FALSE
```

## Expression serialization

### Jackson

All provided operations supports serialization using [Jackson](https://github.com/FasterXML/jackson) with the definition
of a Mixin.
All provided operations support serialization using [Jackson](https://github.com/FasterXML/jackson) with the definition
of a Mixin. The project currently targets Jackson 3.x (`tools.jackson` namespace).

Mixin interface: `com.rapatao.projects.ruleset.jackson.ExpressionMixin`

Example of usage:

```kotlin
val mapper = jacksonObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
import com.fasterxml.jackson.annotation.JsonInclude
import com.rapatao.projects.ruleset.engine.types.Expression
import com.rapatao.projects.ruleset.jackson.ExpressionMixin
import tools.jackson.databind.json.JsonMapper
import tools.jackson.module.kotlin.jacksonMapperBuilder
import tools.jackson.module.kotlin.readValue

val mapper: JsonMapper = jacksonMapperBuilder()
.changeDefaultPropertyInclusion { inclusion ->
inclusion.withValueInclusion(JsonInclude.Include.NON_NULL)
}
.addMixIn(Expression::class.java, ExpressionMixin::class.java)
.build()

val json = "{ serialized definition }"

Expand Down
22 changes: 12 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ plugins {
id "org.jetbrains.kotlin.jvm" version "${kotlinVersion}"
id "io.gitlab.arturbosch.detekt" version "${detektVersion}"
id "org.jetbrains.kotlinx.kover" version "${koverVersion}"
id "io.github.gradle-nexus.publish-plugin" version "${publishPluginVersion}"
id "com.github.ben-manes.versions" version "${benManerVersionsVersion}"
}

Expand Down Expand Up @@ -88,6 +87,18 @@ allprojects {
}

publishing {
repositories {
maven {
name = "mavenCentral"
url = version.endsWith("SNAPSHOT")
? "https://central.sonatype.com/repository/maven-snapshots/"
: "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"
credentials {
username = System.getenv('OSSRH_USERNAME')
password = System.getenv('OSSRH_PASSWORD')
}
}
}
publications {
maven(MavenPublication) {
from components.java
Expand Down Expand Up @@ -131,15 +142,6 @@ allprojects {
}
}

nexusPublishing {
repositories {
sonatype {
username = System.getenv('OSSRH_USERNAME')
password = System.getenv('OSSRH_PASSWORD')
}
}
}

def isNonStable = { String version ->
def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) }
def regex = /^[0-9,.v-]+(-r)?$/
Expand Down
16 changes: 8 additions & 8 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
benManerVersionsVersion=0.51.0
benManerVersionsVersion=0.52.0
credentialsVersion=3.0
detektVersion=1.23.6
graalvmPolyglotVersion=24.1.0
hamcrestVersion=3.0
jacksonVersion=2.17.2
jacksonVersion=3.1.3
jacocoVersion=0.8.7
javaVersion=17
javaVersion=21
junitPlatformVersion=1.11.2
junitVersion=5.11.2
kotlinVersion=2.0.20
koverVersion=0.8.3
publishPluginVersion=2.0.0
rhinoVersion=1.7.15
graalvmPolyglotVersion=24.1.0
kotlinVersion=2.3.21
koverVersion=0.9.1
rhinoVersion=1.8.1
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
14 changes: 5 additions & 9 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading