diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..8b337dd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Shell script files must always be normalized
+*.sh text eol=lf
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6120ac7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+#Maven
+target/
+
+#IntelliJ
+/.idea
+*.iml
+*.ipr
+*.iws
+gradle-wrapper.jar
+
+#Eclipse
+/.classpath
+/.settings/
+/.project
+/bin/
+
+#Misc
+*.log
+.gradle
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..8078268
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,276 @@
+
+
+ 4.0.0
+
+ io.github.avegera
+ predicate4j
+ 0.1.0
+ jar
+
+ ${project.groupId}:${project.artifactId}
+ Human readable fluent API for predicates in Java
+ https://github.com/avegera/predicate4j
+
+
+ UTF-8
+
+
+ 5.10.2
+ 3.26.0
+
+
+ 3.13.0
+ 3.2.5
+ 3.3.1
+ 3.7.0
+ 3.2.4
+ 1.7.0
+ 0.8.12
+
+
+
+
+ The Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ avegera
+ Artem Vegera
+ https://github.com/avegera
+
+
+
+
+ scm:git:git://github.com/avegera/predicate4j.git
+ scm:git:ssh://github.com:avegera/predicate4j.git
+ https://github.com/avegera/predicate4j/tree/main
+
+
+
+
+ ossrh
+ https://s01.oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit-jupiter.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${asserj.version}
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven-source-plugin.version}
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven-javadoc-plugin.version}
+
+
+
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+
+ prepare-agent
+
+
+
+ jacoco-check
+
+ check
+
+
+
+
+ CLASS
+
+
+ LINE
+ COVEREDRATIO
+ 0.9
+
+
+ METHOD
+ COVEREDRATIO
+ 0.9
+
+
+ INSTRUCTION
+ COVEREDRATIO
+ 0.9
+
+
+ BRANCH
+ COVEREDRATIO
+ 0.9
+
+
+ COMPLEXITY
+ COVEREDRATIO
+ 0.9
+
+
+
+
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ ${maven-gpg-plugin.version}
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ ${nexus-staging-maven-plugin.version}
+ true
+
+ ossrh
+ https://s01.oss.sonatype.org/
+ true
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+
+
+
+ java-code-coverage
+
+ true
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+
+
+ sign
+
+ false
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+
+
+
+
+
+ release
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/Predicates.java b/src/main/java/io/github/avegera/predicate4j/Predicates.java
new file mode 100644
index 0000000..857e62a
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/Predicates.java
@@ -0,0 +1,46 @@
+package io.github.avegera.predicate4j;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * This class contains library of common java predicates.
+ */
+public class Predicates {
+
+ private Predicates() {
+ //private constructor
+ }
+
+ public static Predicate isEqualTo(T object) {
+ return it -> Objects.equals(it, object);
+ }
+
+ public static Predicate notEqualTo(T object) {
+ return it -> !Objects.equals(it, object);
+ }
+
+ public static Predicate isNull() {
+ return Objects::isNull;
+ }
+
+ public static Predicate notNull() {
+ return Objects::nonNull;
+ }
+
+ public static Predicate isInstanceOf(Class> clazz) {
+ return obj -> clazz != null && clazz.isInstance(obj);
+ }
+
+ public static Predicate notInstanceOf(Class> clazz) {
+ return obj -> clazz == null || !clazz.isInstance(obj);
+ }
+
+ public static Predicate alwaysTrue() {
+ return it -> true;
+ }
+
+ public static Predicate alwaysFalse() {
+ return it -> false;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/Where.java b/src/main/java/io/github/avegera/predicate4j/Where.java
new file mode 100644
index 0000000..0e6d7af
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/Where.java
@@ -0,0 +1,17 @@
+package io.github.avegera.predicate4j;
+
+import io.github.avegera.predicate4j.api.WhereObject;
+import io.github.avegera.predicate4j.impl.WhereObjectImpl;
+
+import java.util.function.Function;
+
+public class Where {
+
+ private Where() {
+ //private constructor
+ }
+
+ public static WhereObject where(Function mapper) {
+ return new WhereObjectImpl<>(mapper);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/api/RichPredicate.java b/src/main/java/io/github/avegera/predicate4j/api/RichPredicate.java
new file mode 100644
index 0000000..3311fb4
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/api/RichPredicate.java
@@ -0,0 +1,6 @@
+package io.github.avegera.predicate4j.api;
+
+import java.util.function.Predicate;
+
+public interface RichPredicate extends Predicate {
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/api/WhereObject.java b/src/main/java/io/github/avegera/predicate4j/api/WhereObject.java
new file mode 100644
index 0000000..8d87d45
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/api/WhereObject.java
@@ -0,0 +1,16 @@
+package io.github.avegera.predicate4j.api;
+
+public interface WhereObject {
+
+ RichPredicate isEqualTo(R value);
+
+ RichPredicate isInstanceOf(Class> clazz);
+
+ RichPredicate isNull();
+
+ RichPredicate notEqualTo(R value);
+
+ RichPredicate notInstanceOf(Class> clazz);
+
+ RichPredicate notNull();
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/impl/RichPredicateImpl.java b/src/main/java/io/github/avegera/predicate4j/impl/RichPredicateImpl.java
new file mode 100644
index 0000000..a19d517
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/impl/RichPredicateImpl.java
@@ -0,0 +1,23 @@
+package io.github.avegera.predicate4j.impl;
+
+import io.github.avegera.predicate4j.api.RichPredicate;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class RichPredicateImpl implements RichPredicate {
+
+ private final Function mapper;
+
+ private final Predicate predicate;
+
+ public RichPredicateImpl(Function mapper, Predicate predicate) {
+ this.mapper = mapper;
+ this.predicate = predicate;
+ }
+
+ @Override
+ public boolean test(T object) {
+ return predicate.test(mapper.apply(object));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/avegera/predicate4j/impl/WhereObjectImpl.java b/src/main/java/io/github/avegera/predicate4j/impl/WhereObjectImpl.java
new file mode 100644
index 0000000..19e7f0f
--- /dev/null
+++ b/src/main/java/io/github/avegera/predicate4j/impl/WhereObjectImpl.java
@@ -0,0 +1,51 @@
+package io.github.avegera.predicate4j.impl;
+
+import io.github.avegera.predicate4j.Predicates;
+import io.github.avegera.predicate4j.api.RichPredicate;
+import io.github.avegera.predicate4j.api.WhereObject;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class WhereObjectImpl implements WhereObject {
+
+ private final Function mapper;
+
+ public WhereObjectImpl(Function mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public RichPredicate isEqualTo(R value) {
+ return getPredicate(Predicates.isEqualTo(value));
+ }
+
+ @Override
+ public RichPredicate isInstanceOf(Class> clazz) {
+ return getPredicate(Predicates.isInstanceOf(clazz));
+ }
+
+ @Override
+ public RichPredicate isNull() {
+ return getPredicate(Predicates.isNull());
+ }
+
+ @Override
+ public RichPredicate notEqualTo(R value) {
+ return getPredicate(Predicates.notEqualTo(value));
+ }
+
+ @Override
+ public RichPredicate notInstanceOf(Class> clazz) {
+ return getPredicate(Predicates.notInstanceOf(clazz));
+ }
+
+ @Override
+ public RichPredicate notNull() {
+ return getPredicate(Predicates.notNull());
+ }
+
+ protected RichPredicate getPredicate(Predicate predicate) {
+ return new RichPredicateImpl<>(mapper, predicate);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/github/avegera/predicate4j/PredicatesTest.java b/src/test/java/io/github/avegera/predicate4j/PredicatesTest.java
new file mode 100644
index 0000000..cc6daf8
--- /dev/null
+++ b/src/test/java/io/github/avegera/predicate4j/PredicatesTest.java
@@ -0,0 +1,328 @@
+package io.github.avegera.predicate4j;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import java.util.function.Predicate;
+
+import static io.github.avegera.predicate4j.Predicates.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+class PredicatesTest {
+
+ @Nested
+ @DisplayName("Object predicate")
+ class ObjectPredicate {
+
+ @Nested
+ @DisplayName("isEqualTo()")
+ class IsEqualTo {
+
+ @Nested
+ @DisplayName("returns true when")
+ class ReturnsTrue {
+
+ @Test
+ @DisplayName("object is equal to provided object")
+ void objectIsEqualToProvidedObject() {
+ Object object = new Object();
+ Predicate