Skip to content

Commit c2d013c

Browse files
authored
Merge pull request #8 from sidhant92/develop
ANTLR Based Boolean Expression Parser
2 parents 31da181 + b1ffb69 commit c2d013c

File tree

63 files changed

+4603
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4603
-0
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Build Job
2+
3+
on:
4+
pull_request:
5+
branches: ['master', 'develop']
6+
7+
jobs:
8+
build:
9+
name: Compile and Test code
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up JDK 8
15+
uses: actions/setup-java@v3
16+
with:
17+
java-version: '8'
18+
distribution: 'temurin'
19+
cache: 'gradle'
20+
21+
- name: Validate Gradle wrapper
22+
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
23+
- name: Build with Gradle
24+
run: ./gradlew build --no-daemon

.github/workflows/release.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Snapshot Release
2+
3+
on:
4+
push:
5+
branches: ['master']
6+
7+
jobs:
8+
build:
9+
name: Compile and Test code
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up JDK 8
15+
uses: actions/setup-java@v3
16+
with:
17+
java-version: '8'
18+
distribution: 'temurin'
19+
cache: 'gradle'
20+
21+
- name: Validate Gradle wrapper
22+
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
23+
- name: Build with Gradle
24+
run: ./gradlew build --no-daemon
25+
26+
publish:
27+
name: Publish Artifacts
28+
needs: [build]
29+
runs-on: ubuntu-latest
30+
31+
steps:
32+
- uses: actions/checkout@v3
33+
- name: Set up JDK 8
34+
uses: actions/setup-java@v3
35+
with:
36+
java-version: '8'
37+
distribution: 'temurin'
38+
cache: 'gradle'
39+
40+
- name: Validate Gradle wrapper
41+
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
42+
43+
- name: Publish with Gradle
44+
env:
45+
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
46+
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
47+
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET }}
48+
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }}
49+
run: ./gradlew -Psnapshot=false publishToSonatype --no-daemon
50+
51+
increment:
52+
name: Increment Version
53+
needs: [publish]
54+
runs-on: ubuntu-latest
55+
steps:
56+
- uses: actions/checkout@v3
57+
- name: Increment Version
58+
run: ./gradlew incrementVersion --versionIncrementType=PATCH --versionIncrementBranch=master

.github/workflows/snapshot.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Java CI
2+
3+
on:
4+
push:
5+
branches: ['develop', 'master']
6+
7+
jobs:
8+
build:
9+
name: Compile and Test code
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up JDK 8
15+
uses: actions/setup-java@v3
16+
with:
17+
java-version: '8'
18+
distribution: 'temurin'
19+
cache: 'gradle'
20+
21+
- name: Validate Gradle wrapper
22+
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
23+
- name: Build with Gradle
24+
run: ./gradlew build --no-daemon
25+
26+
publish:
27+
name: Publish Artifacts
28+
needs: [build]
29+
if: github.event_name != 'pull_request'
30+
runs-on: ubuntu-latest
31+
32+
steps:
33+
- uses: actions/checkout@v3
34+
- name: Set up JDK 8
35+
uses: actions/setup-java@v3
36+
with:
37+
java-version: '8'
38+
distribution: 'temurin'
39+
cache: 'gradle'
40+
41+
- name: Validate Gradle wrapper
42+
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
43+
44+
- name: Publish with Gradle
45+
env:
46+
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
47+
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
48+
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET }}
49+
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }}
50+
run: ./gradlew publishToSonatype --no-daemon

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
HELP.md
2+
.gradle
3+
build/
4+
5+
### STS ###
6+
.apt_generated
7+
.classpath
8+
.factorypath
9+
.project
10+
.settings
11+
.springBeans
12+
.sts4-cache
13+
14+
### IntelliJ IDEA ###
15+
.idea
16+
*.iws
17+
*.iml
18+
*.ipr
19+
out/
20+
21+
### NetBeans ###
22+
/nbproject/private/
23+
/nbbuild/
24+
/dist/
25+
/nbdist/
26+
/.nb-gradle/
27+
28+
### VS Code ###
29+
.vscode/
30+
`
31+
32+
gradle.properties

README.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# bool-parser-java
2+
A Boolean Expression Parser for Java
3+
4+
The library can help parse complex and nested boolean expressions.
5+
The expressions are in SQL-like syntax, where you can use boolean operators and parentheses to combine individual expressions.
6+
7+
An expression can be as simple as `name = Sidhant`.
8+
A Complex expression is formed by combining these small expressions by logical operators and giving precedence using parenthesis
9+
10+
### Examples
11+
#### Textual Equality
12+
13+
Format: `${attributeName} = ${value}`
14+
15+
Example: `name = john`
16+
17+
#### Numeric Comparisons
18+
19+
Format: `${attributeName} ${operator} ${value}`
20+
21+
Example: `price > 12.99`
22+
23+
The ${value} must be numeric. Supported operators are `<`, `<=`, `=`, `!=`, `>=` and `>`, with the same semantics as in virtually all programming languages.
24+
25+
#### Numeric Range
26+
27+
Format: `${attributeName} ${lowerBound} TO ${upperBound}`
28+
29+
Example: `price 5.99 TO 100`
30+
31+
`${lowerBound}` and `${upperBound}` must be numeric. Both are inclusive.
32+
33+
#### Boolean operators
34+
35+
Example:
36+
37+
`price < 10 AND (category:Book OR NOT category:Ebook)`
38+
39+
Individual filters can be combined via boolean operators. The following operators are supported:
40+
41+
* `OR`: must match any of the combined conditions (disjunction)
42+
* `AND`: must match all of the combined conditions (conjunction)
43+
* `NOT`: negate a filter
44+
45+
Parentheses, `(` and `)`, can be used for grouping.
46+
47+
#### Usage Notes
48+
* Phrases that includes quotes, like `content = "It's a wonderful day"`
49+
* Phrases that includes quotes, like `attribute = 'She said "Hello World"'`
50+
* For nested keys in data map you can use the dot notation, like `person.age`
51+
52+
## Usage
53+
POM
54+
```xml
55+
<dependencies>
56+
<dependency>
57+
<groupId>com.github.sidhant92</groupId>
58+
<artifactId>bool-parser-java</artifactId>
59+
<version>1.0.0</version>
60+
</dependency>
61+
</dependencies>
62+
```
63+
Gradle
64+
```
65+
dependencies {
66+
implementation "com.github.sidhant92:bool-parser-java:1.0.0"
67+
}
68+
```
69+
70+
71+
Code
72+
```
73+
final BoolParser boolParser = new BoolParser();
74+
final Try<Node> nodeOptional = boolParser.parseExpression("name = test");
75+
```
76+
77+
### Node Types Post Parsing
78+
####
79+
NumericNode
80+
```
81+
private final String field;
82+
83+
private final Object value;
84+
85+
private final Operator operator;
86+
87+
private final DataType dataType;
88+
```
89+
90+
####
91+
NumericRangeNode
92+
```
93+
private final String field;
94+
95+
private final Object fromValue;
96+
97+
private final Object toValue;
98+
99+
private final DataType fromDataType;
100+
101+
private final DataType toDataType;
102+
```
103+
104+
####
105+
BooleanNode
106+
```
107+
private Node left;
108+
109+
private Node right;
110+
111+
private LogicalOperationType operator;
112+
```
113+
114+
####
115+
UnaryNode
116+
```
117+
private final DataType dataType;
118+
119+
private final Object value;
120+
```
121+
122+
####
123+
InNode
124+
```
125+
private final String field;
126+
127+
private final List<Pair<DataType, Object>> items;
128+
```
129+
130+
131+
## Applications
132+
133+
### Boolean Expression Evaluator
134+
135+
The library can be used to evaluate a boolean expression.
136+
137+
The following Data Types are supported:
138+
1. String
139+
2. Integer
140+
3. Long
141+
4. Decimal
142+
5. Boolean
143+
6. Semantic Version
144+
145+
Usage examples:
146+
147+
Simple Numerical Comparison
148+
```
149+
final BooleanExpressionEvaluator booleanExpressionEvaluator = new BooleanExpressionEvaluator();
150+
final Map<String, Object> data = new HashMap<>();
151+
data.put("age", 26);
152+
final Try<Boolean> result = booleanExpressionEvaluator.evaluate("age >= 27", data);
153+
assertTrue(booleanOptional.isPresent());
154+
assertFalse(booleanOptional.get());
155+
```
156+
Boolean Comparison
157+
```
158+
final BooleanExpressionEvaluator booleanExpressionEvaluator = new BooleanExpressionEvaluator();
159+
final Map<String, Object> data = new HashMap<>();
160+
data.put("age", 25);
161+
data.put("name", "sid");
162+
final Try<Boolean> result = booleanExpressionEvaluator.evaluate("name = sid AND age = 25", data);
163+
assertTrue(booleanOptional.isPresent());
164+
assertTrue(booleanOptional.get());
165+
```
166+
Nested Boolean Comparison
167+
```
168+
final BooleanExpressionEvaluator booleanExpressionEvaluator = new BooleanExpressionEvaluator();
169+
final Map<String, Object> data = new HashMap<>();
170+
data.put("age", 25);
171+
data.put("name", "sid");
172+
data.put("num", 45);
173+
final Try<Boolean> result = booleanExpressionEvaluator.evaluate("name:sid AND (age = 25 OR num = 44)", data);
174+
assertTrue(booleanOptional.isPresent());
175+
assertTrue(booleanOptional.get());
176+
```
177+
App Version Comparison
178+
```
179+
final BooleanExpressionEvaluator booleanExpressionEvaluator = new BooleanExpressionEvaluator();
180+
final Map<String, Object> data = new HashMap<>();
181+
data.put("app_version", "1.5.9");
182+
final Try<Boolean> result = booleanExpressionEvaluator.evaluate("app_version < 1.5.10", data);
183+
assertTrue(booleanOptional.isPresent());
184+
assertTrue(booleanOptional.get());
185+
```
186+
187+
The return type is `Try<Boolean>`. Failure means that parsing has failed and any fallback can be used.
188+
189+
190+
[For a complete list of examples please check out the test file](src/test/java/com/github/sidhant92/boolparser/application/BooleanExpressionEvaluatorTest.java)

0 commit comments

Comments
 (0)