Skip to content

Commit d4c0fcd

Browse files
committed
First version
0 parents  commit d4c0fcd

26 files changed

+1019
-0
lines changed

.gitignore

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Java template
3+
*.class
4+
5+
# Mobile Tools for Java (J2ME)
6+
.mtj.tmp/
7+
8+
# Package Files #
9+
*.jar
10+
*.war
11+
*.ear
12+
13+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
14+
hs_err_pid*
15+
### JetBrains template
16+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
17+
18+
*.iml
19+
20+
## Directory-based project format:
21+
.idea/
22+
# if you remove the above rule, at least ignore the following:
23+
24+
# User-specific stuff:
25+
# .idea/workspace.xml
26+
# .idea/tasks.xml
27+
# .idea/dictionaries
28+
29+
# Sensitive or high-churn files:
30+
# .idea/dataSources.ids
31+
# .idea/dataSources.xml
32+
# .idea/sqlDataSources.xml
33+
# .idea/dynamic.xml
34+
# .idea/uiDesigner.xml
35+
36+
# Gradle:
37+
# .idea/gradle.xml
38+
# .idea/libraries
39+
40+
# Mongo Explorer plugin:
41+
# .idea/mongoSettings.xml
42+
43+
## File-based project format:
44+
*.ipr
45+
*.iws
46+
47+
## Plugin-specific files:
48+
49+
# IntelliJ
50+
/out/
51+
52+
# mpeltonen/sbt-idea plugin
53+
.idea_modules/
54+
55+
# JIRA plugin
56+
atlassian-ide-plugin.xml
57+
58+
# Crashlytics plugin (for Android Studio and IntelliJ)
59+
com_crashlytics_export_strings.xml
60+
crashlytics.properties
61+
crashlytics-build.properties
62+
63+
target

pom.xml

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>io.appform.rules</groupId>
8+
<artifactId>json-rules</artifactId>
9+
<version>0.1-SNAPSHOT</version>
10+
<build>
11+
<plugins>
12+
<plugin>
13+
<groupId>org.apache.maven.plugins</groupId>
14+
<artifactId>maven-compiler-plugin</artifactId>
15+
<configuration>
16+
<source>1.8</source>
17+
<target>1.8</target>
18+
</configuration>
19+
</plugin>
20+
</plugins>
21+
</build>
22+
23+
<properties>
24+
<jackson.version>2.7.4</jackson.version>
25+
<lombok.version>1.16.6</lombok.version>
26+
<junit.version>4.12</junit.version>
27+
</properties>
28+
29+
30+
<dependencies>
31+
<dependency>
32+
<groupId>org.projectlombok</groupId>
33+
<artifactId>lombok</artifactId>
34+
<version>${lombok.version}</version>
35+
<scope>provided</scope>
36+
</dependency>
37+
<dependency>
38+
<groupId>com.fasterxml.jackson.core</groupId>
39+
<artifactId>jackson-core</artifactId>
40+
<version>${jackson.version}</version>
41+
</dependency>
42+
<dependency>
43+
<groupId>com.fasterxml.jackson.core</groupId>
44+
<artifactId>jackson-databind</artifactId>
45+
<version>${jackson.version}</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>com.fasterxml.jackson.datatype</groupId>
49+
<artifactId>jackson-datatype-jsr310</artifactId>
50+
<version>${jackson.version}</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>com.fasterxml.jackson.datatype</groupId>
54+
<artifactId>jackson-datatype-jdk8</artifactId>
55+
<version>${jackson.version}</version>
56+
</dependency>
57+
<dependency>
58+
<groupId>junit</groupId>
59+
<artifactId>junit</artifactId>
60+
<version>${junit.version}</version>
61+
<scope>test</scope>
62+
</dependency>
63+
</dependencies>
64+
65+
<profiles>
66+
<profile>
67+
<id>lombok-needs-tools-jar</id>
68+
<activation>
69+
<file>
70+
<exists>${java.home}/../lib/tools.jar</exists>
71+
</file>
72+
</activation>
73+
<build>
74+
<plugins>
75+
<plugin>
76+
<groupId>org.projectlombok</groupId>
77+
<artifactId>lombok-maven-plugin</artifactId>
78+
<version>1.16.4.1</version>
79+
<dependencies>
80+
<dependency>
81+
<groupId>sun.jdk</groupId>
82+
<artifactId>tools</artifactId>
83+
<version>1.6</version>
84+
<scope>system</scope>
85+
<systemPath>${java.home}/../lib/tools.jar</systemPath>
86+
</dependency>
87+
</dependencies>
88+
</plugin>
89+
</plugins>
90+
</build>
91+
</profile>
92+
</profiles>
93+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.appform.jsonrules;
2+
3+
import com.fasterxml.jackson.annotation.JsonSubTypes;
4+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
5+
import io.appform.jsonrules.expressions.composite.AndExpression;
6+
import io.appform.jsonrules.expressions.composite.NotExpression;
7+
import io.appform.jsonrules.expressions.composite.OrExpression;
8+
import io.appform.jsonrules.expressions.equality.EqualsExpression;
9+
import io.appform.jsonrules.expressions.equality.InExpression;
10+
import io.appform.jsonrules.expressions.equality.NotEqualsExpression;
11+
import io.appform.jsonrules.expressions.equality.NotInExpression;
12+
import io.appform.jsonrules.expressions.numeric.GreaterThanEqualsExpression;
13+
import io.appform.jsonrules.expressions.numeric.GreaterThanExpression;
14+
import io.appform.jsonrules.expressions.numeric.LessThanEqualsExpression;
15+
import io.appform.jsonrules.expressions.numeric.LessThanExpression;
16+
import lombok.Data;
17+
import lombok.EqualsAndHashCode;
18+
import lombok.ToString;
19+
20+
/**
21+
* A base expression
22+
*/
23+
@Data
24+
@EqualsAndHashCode
25+
@ToString
26+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
27+
@JsonSubTypes({
28+
@JsonSubTypes.Type(name = "equals", value = EqualsExpression.class),
29+
@JsonSubTypes.Type(name = "not_equals", value = NotEqualsExpression.class),
30+
@JsonSubTypes.Type(name = "in", value = InExpression.class),
31+
@JsonSubTypes.Type(name = "not_in", value = NotInExpression.class),
32+
33+
@JsonSubTypes.Type(name = "greater_than", value = GreaterThanExpression.class),
34+
@JsonSubTypes.Type(name = "greater_than_equals", value = GreaterThanEqualsExpression.class),
35+
@JsonSubTypes.Type(name = "less_than", value = LessThanExpression.class),
36+
@JsonSubTypes.Type(name = "less_than_equals", value = LessThanEqualsExpression.class),
37+
38+
@JsonSubTypes.Type(name = "and", value = AndExpression.class),
39+
@JsonSubTypes.Type(name = "or", value = OrExpression.class),
40+
@JsonSubTypes.Type(name = "not", value = NotExpression.class),
41+
})
42+
public abstract class Expression {
43+
private final ExpressionType type;
44+
45+
protected Expression(ExpressionType type) {
46+
this.type = type;
47+
}
48+
49+
abstract public boolean evaluate(ExpressionEvaluationContext context);
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.appform.jsonrules;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
8+
/**
9+
* Context passed to expression evaluator
10+
*/
11+
@Data
12+
@AllArgsConstructor
13+
@Builder
14+
public class ExpressionEvaluationContext {
15+
private byte json[];
16+
private JsonNode node;
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.appform.jsonrules;
2+
3+
/**
4+
* Types of expression
5+
*/
6+
public enum ExpressionType {
7+
8+
//Equality
9+
equals,
10+
not_equals,
11+
in,
12+
not_in,
13+
14+
//Numeric
15+
greater_than,
16+
less_than,
17+
greater_than_equals,
18+
less_than_equals,
19+
20+
//Joiner
21+
and,
22+
or,
23+
not
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.appform.jsonrules;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
6+
/**
7+
* A basic rule
8+
*/
9+
public class Rule {
10+
private final Expression expression;
11+
12+
public Rule(Expression expression) {
13+
this.expression = expression;
14+
}
15+
16+
public static Rule create(final String json, final ObjectMapper mapper) throws Exception {
17+
return new Rule(mapper.readValue(json, Expression.class));
18+
}
19+
20+
public boolean matches(JsonNode node) {
21+
return expression.evaluate(
22+
ExpressionEvaluationContext.builder()
23+
.node(node)
24+
.build());
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.appform.jsonrules;
2+
3+
/**
4+
* Top level rule evaluator
5+
*/
6+
public class RuleEngine {
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.appform.jsonrules.expressions;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import io.appform.jsonrules.ExpressionEvaluationContext;
5+
import io.appform.jsonrules.Expression;
6+
import io.appform.jsonrules.ExpressionType;
7+
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.ToString;
10+
11+
/**
12+
* All expressions that evaluate a json path uses this.
13+
*/
14+
@Data
15+
@EqualsAndHashCode(callSuper = true)
16+
@ToString(callSuper = true)
17+
public abstract class JsonPathBasedExpression extends Expression {
18+
private String path;
19+
20+
protected JsonPathBasedExpression(ExpressionType type) {
21+
super(type);
22+
}
23+
24+
protected JsonPathBasedExpression(ExpressionType type, String path) {
25+
this(type);
26+
this.path = path;
27+
}
28+
29+
@Override
30+
public final boolean evaluate(ExpressionEvaluationContext context) {
31+
//T value = context.getParsedContext().read(path, clazz);
32+
final JsonNode evaluatedNode = context.getNode().at(path);
33+
return evaluate(context, path, evaluatedNode);
34+
}
35+
36+
abstract protected boolean evaluate(ExpressionEvaluationContext context, final String path, JsonNode evaluatedNode);
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.appform.jsonrules.expressions.composite;
2+
3+
import io.appform.jsonrules.ExpressionEvaluationContext;
4+
import io.appform.jsonrules.Expression;
5+
import io.appform.jsonrules.ExpressionType;
6+
import lombok.*;
7+
8+
import java.util.List;
9+
import java.util.function.Predicate;
10+
11+
/**
12+
* And operator
13+
*/
14+
@Data
15+
@EqualsAndHashCode(callSuper = true)
16+
@ToString(callSuper = true)
17+
public class AndExpression extends CompositeExpression {
18+
public AndExpression() {
19+
super(ExpressionType.and);
20+
}
21+
22+
@Builder
23+
public AndExpression(ExpressionType type, @Singular List<Expression> children) {
24+
super(type, children);
25+
}
26+
27+
@Override
28+
protected boolean evaluate(ExpressionEvaluationContext context, List<Expression> children) {
29+
return children.stream()
30+
.map(expression -> expression.evaluate(context))
31+
.allMatch(Predicate.isEqual(true));
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.appform.jsonrules.expressions.composite;
2+
3+
import io.appform.jsonrules.ExpressionEvaluationContext;
4+
import io.appform.jsonrules.Expression;
5+
import io.appform.jsonrules.ExpressionType;
6+
import lombok.Data;
7+
import lombok.EqualsAndHashCode;
8+
import lombok.ToString;
9+
10+
import java.util.List;
11+
12+
/**
13+
* Expression that accepts another expression
14+
*/
15+
@Data
16+
@EqualsAndHashCode(callSuper = true)
17+
@ToString(callSuper = true)
18+
public abstract class CompositeExpression extends Expression {
19+
private List<Expression> children;
20+
21+
protected CompositeExpression(ExpressionType type) {
22+
super(type);
23+
}
24+
25+
protected CompositeExpression(ExpressionType type, List<Expression> children) {
26+
this(type);
27+
this.children = children;
28+
}
29+
30+
@Override
31+
public final boolean evaluate(ExpressionEvaluationContext context) {
32+
return null != children
33+
&& evaluate(context, children);
34+
}
35+
36+
protected abstract boolean evaluate(ExpressionEvaluationContext context, List<Expression> children);
37+
}

0 commit comments

Comments
 (0)