From 2480902c1b66689234bbc2555e63d5d9ca3f0d0a Mon Sep 17 00:00:00 2001
From: Evgenii Plugatar <54626653+evpl@users.noreply.github.com>
Date: Sun, 11 Feb 2024 17:55:36 +0300
Subject: [PATCH] Initial commit
---
.gitignore | 6 +
.idea/codeStyles/Project.xml | 64 +++
.idea/codeStyles/codeStyleConfig.xml | 5 +
CHANGELOG.md | 5 +
LICENSE | 201 +++++++++
README.md | 140 ++++++
pom.xml | 189 ++++++++
.../java/com/plugatar/jkscope/JKScope.java | 406 ++++++++++++++++++
.../java/com/plugatar/jkscope/JKScopeOpt.java | 177 ++++++++
.../com/plugatar/jkscope/SafeJKScope.java | 58 +++
.../jkscope/function/ThBiConsumer.java | 47 ++
.../jkscope/function/ThBiFunction.java | 49 +++
.../plugatar/jkscope/function/ThConsumer.java | 45 ++
.../plugatar/jkscope/function/ThFunction.java | 47 ++
.../jkscope/function/ThPredicate.java | 46 ++
.../plugatar/jkscope/function/ThRunnable.java | 43 ++
.../plugatar/jkscope/function/ThSupplier.java | 45 ++
.../jkscope/function/ThTriConsumer.java | 48 +++
.../jkscope/function/ThTriFunction.java | 50 +++
.../jkscope/function/package-info.java | 19 +
.../com/plugatar/jkscope/package-info.java | 21 +
.../com/plugatar/jkscope/JKScopeOptTest.java | 47 ++
.../com/plugatar/jkscope/JKScopeTest.java | 349 +++++++++++++++
.../jkscope/function/ThBiConsumerTest.java | 51 +++
.../jkscope/function/ThBiFunctionTest.java | 63 +++
.../jkscope/function/ThConsumerTest.java | 46 ++
.../jkscope/function/ThFunctionTest.java | 57 +++
.../jkscope/function/ThPredicateTest.java | 57 +++
.../jkscope/function/ThRunnableTest.java | 45 ++
.../jkscope/function/ThSupplierTest.java | 47 ++
.../jkscope/function/ThTriConsumerTest.java | 56 +++
.../jkscope/function/ThTriFunctionTest.java | 71 +++
.../jkscope/function/package-info.java | 19 +
.../com/plugatar/jkscope/package-info.java | 19 +
34 files changed, 2638 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/codeStyles/Project.xml
create mode 100644 .idea/codeStyles/codeStyleConfig.xml
create mode 100644 CHANGELOG.md
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 pom.xml
create mode 100644 src/main/java/com/plugatar/jkscope/JKScope.java
create mode 100644 src/main/java/com/plugatar/jkscope/JKScopeOpt.java
create mode 100644 src/main/java/com/plugatar/jkscope/SafeJKScope.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThBiConsumer.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThBiFunction.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThConsumer.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThFunction.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThPredicate.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThRunnable.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThSupplier.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThTriConsumer.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/ThTriFunction.java
create mode 100644 src/main/java/com/plugatar/jkscope/function/package-info.java
create mode 100644 src/main/java/com/plugatar/jkscope/package-info.java
create mode 100644 src/test/java/com/plugatar/jkscope/JKScopeOptTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/JKScopeTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThBiConsumerTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThBiFunctionTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThConsumerTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThFunctionTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThPredicateTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThRunnableTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThSupplierTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThTriConsumerTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/ThTriFunctionTest.java
create mode 100644 src/test/java/com/plugatar/jkscope/function/package-info.java
create mode 100644 src/test/java/com/plugatar/jkscope/package-info.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..90b9b44
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.idea/
+!.idea/codeStyles/
+*.iml
+*.iws
+target/
+build/
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..da679c4
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..127f806
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..22afcac
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changelog
+
+## 1.0 (released 11.02.2024)
+
+First release
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9436c43
--- /dev/null
+++ b/README.md
@@ -0,0 +1,140 @@
+# JKScope
+
+Java scope functions in style of Kotlin
+
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.plugatar.jkscope/jkscope/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.plugatar.jkscope/jkscope)
+[![Javadoc](https://javadoc.io/badge2/com.plugatar.jkscope/jkscope/javadoc.svg)](https://javadoc.io/doc/com.plugatar.jkscope/jkscope)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+
+## Table of Contents
+
+* [How to use](#How-to-use)
+* [Example](#Examples)
+
+## How to use
+
+Requires Java 8+ version.
+
+Maven:
+
+```xml
+
+
+ com.plugatar.jkscope
+ jkscope
+ 1.0
+
+```
+
+Gradle:
+
+```groovy
+dependencies {
+ implementation 'com.plugatar.jkscope:jkscope:1.0'
+}
+```
+
+## Examples
+
+### Static methods
+
+```java
+import static com.plugatar.jkscope.JKScope.let;
+import static com.plugatar.jkscope.JKScope.run;
+import static com.plugatar.jkscope.JKScope.with;
+import static com.plugatar.jkscope.JKScope.withNonNull;
+
+class ExampleTest {
+
+ @Test
+ void letMethod() {
+ let(() -> {
+ System.out.println("ok");
+ });
+ }
+
+ @Test
+ void runMethod() {
+ int result = run(() -> {
+ System.out.println("ok");
+ return 12;
+ });
+ }
+
+ @Test
+ void withMethod() {
+ String value1 = "a";
+ String value2 = "b";
+ String value3 = "c";
+
+ with(value2, it -> {
+ System.out.println(it);
+ });
+
+ String result = with(value1, value2, (it1, it2) -> it1 + it2);
+
+ with(value1, value2, value3, (it1, it2, it3) -> {
+ System.out.println(it1 + it2 + it3);
+ });
+
+ with(value2).takeNonNull().takeIf(it -> it.length() > 3).let(it -> System.out.println(it));
+ }
+
+ @Test
+ void withNonNullMethod() {
+ String value1 = "a";
+ String value2 = null;
+ String value3 = "c";
+
+ withNonNull(value2, it -> {
+ System.out.println(it);
+ });
+
+ withNonNull(value1, value2, (it1, it2) -> it1 + it2).let(it -> System.out.println(it));
+
+ withNonNull(value1, value2, value3, (it1, it2, it3) -> {
+ System.out.println(it1 + it2 + it3);
+ });
+
+ withNonNull(value2).takeNonNull().takeUnless(it -> it.length() < 3).let(it -> System.out.println(it));
+ }
+}
+```
+
+### Instance methods
+
+```java
+public class MyClass implements JKScope {
+
+ public MyClass() {
+ }
+
+ public void method1() {
+ }
+
+ public String method2() {
+ return "abc";
+ }
+}
+
+class ExampleTest {
+
+ @Test
+ void instance() {
+ MyClass myClass = new MyClass().also(it -> it.method1());
+
+ myClass.apply(it -> it.method1()).apply(it -> it.method2());
+
+ myClass.let(it -> {
+ it.method1();
+ it.method2();
+ });
+
+ String result = myClass.run(it -> it.method2());
+
+ myClass.takeIf(it -> it.method2().length() > 3).let(it -> {
+ System.out.println("ok");
+ });
+ }
+}
+```
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d722c9c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,189 @@
+
+
+
+ 4.0.0
+
+ com.plugatar.jkscope
+ jkscope
+ 0.0-SNAPSHOT
+ jar
+
+ JKScope
+ Java scope functions in style of Kotlin
+ https://github.com/evpl/jkscope
+
+
+
+ evpl
+ Evgenii Plugatar
+ evpl.dev@gmail.com
+ https://plugatar.com
+
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+ Github
+ https://github.com/evpl/jkscope/issues
+
+
+
+ scm:git:git@github.com:evpl/jkscope.git
+ scm:git:git@github.com:evpl/jkscope.git
+ https://github.com/evpl/jkscope
+
+
+
+ 1.8
+ UTF-8
+ UTF-8
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.10.2
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.25.3
+ test
+
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.10.1
+
+
+ ${java.version}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M7
+
+
+ org.codehaus.mojo
+ flatten-maven-plugin
+ 1.3.0
+
+ true
+ resolveCiFriendliesOnly
+
+
+
+ flatten
+ process-resources
+
+ flatten
+
+
+
+ flatten.clean
+ clean
+
+ clean
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.13
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.4.1
+
+
+ package
+
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 3.0.1
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/plugatar/jkscope/JKScope.java b/src/main/java/com/plugatar/jkscope/JKScope.java
new file mode 100644
index 0000000..801a05c
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/JKScope.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope;
+
+import com.plugatar.jkscope.function.ThBiConsumer;
+import com.plugatar.jkscope.function.ThBiFunction;
+import com.plugatar.jkscope.function.ThConsumer;
+import com.plugatar.jkscope.function.ThFunction;
+import com.plugatar.jkscope.function.ThPredicate;
+import com.plugatar.jkscope.function.ThRunnable;
+import com.plugatar.jkscope.function.ThSupplier;
+import com.plugatar.jkscope.function.ThTriConsumer;
+import com.plugatar.jkscope.function.ThTriFunction;
+
+/**
+ * This interface contains scope functions.
+ *
+ *
+ * @param the type of the class implementing JKScope
+ */
+public interface JKScope> extends SafeJKScope {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ default void let(final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept((T) this);
+ }
+
+ /**
+ * Performs given function on the value.
+ *
+ * @param block the function
+ * @param the type of function result
+ * @return function result
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ @SuppressWarnings("unchecked")
+ default R run(final ThFunction super T, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().apply((T) this);
+ }
+
+ /**
+ * Performs given consumer on the value. Similar to the {@link #apply(ThConsumer)} method.
+ *
+ * @param block the consumer
+ * @return this
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ @SuppressWarnings("unchecked")
+ default T also(final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept((T) this);
+ return (T) this;
+ }
+
+ /**
+ * Performs given consumer on the value. Similar to the {@link #also(ThConsumer)} method.
+ *
+ * @param block the consumer
+ * @return this
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ @SuppressWarnings("unchecked")
+ default T apply(final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept((T) this);
+ return (T) this;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ default JKScopeOpt takeIf(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().test((T) this)
+ ? JKScopeOpt.of((T) this)
+ : JKScopeOpt.empty();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ default JKScopeOpt takeUnless(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().test((T) this)
+ ? JKScopeOpt.empty()
+ : JKScopeOpt.of((T) this);
+ }
+
+ /**
+ * Performs given runnable.
+ *
+ * @param block the runnable
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void let(final ThRunnable> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().run();
+ }
+
+ /**
+ * Performs given supplier.
+ *
+ * @param block the supplier
+ * @param the type of supplier result
+ * @return supplier result
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static R run(final ThSupplier extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().get();
+ }
+
+ /**
+ * Returns JKScopeOpt instance with given value.
+ *
+ * @param t the value
+ * @param the type of the value
+ * @return JKScopeOpt instance with given value
+ */
+ static JKScopeOpt with(final T t) {
+ return JKScopeOpt.of(t);
+ }
+
+ /**
+ * Performs given consumer on the given value.
+ *
+ * @param t the value
+ * @param block the consumer
+ * @param type of the value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void with(final T t,
+ final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept(t);
+ }
+
+ /**
+ * Performs given consumer on the given values.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param block the consumer
+ * @param type of the first value
+ * @param type of the second value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void with(final T t,
+ final U u,
+ final ThBiConsumer super T, ? super U, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept(t, u);
+ }
+
+ /**
+ * Performs given consumer on the given values.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param v the third value
+ * @param block the consumer
+ * @param type of the first value
+ * @param type of the second value
+ * @param type of the third value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void with(final T t,
+ final U u,
+ final V v,
+ final ThTriConsumer super T, ? super U, ? super V, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept(t, u, v);
+ }
+
+ /**
+ * Performs given function on the given value.
+ *
+ * @param t the value
+ * @param block the function
+ * @param type of the value
+ * @param the type of function result
+ * @return function result
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static R with(final T t,
+ final ThFunction super T, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().apply(t);
+ }
+
+ /**
+ * Performs given function on the given values.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param block the function
+ * @param the type of the first value
+ * @param the type of the second value
+ * @param the type of function result
+ * @return function result
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static R with(final T t,
+ final U u,
+ final ThBiFunction super T, ? super U, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().apply(t, u);
+ }
+
+ /**
+ * Performs given function on the given values.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param v the third value
+ * @param block the function
+ * @param the type of the first value
+ * @param the type of the second value
+ * @param the type of the third value
+ * @param the type of function result
+ * @return function result
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static R with(final T t,
+ final U u,
+ final V v,
+ final ThTriFunction super T, ? super U, ? super V, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().apply(t, u, v);
+ }
+
+ /**
+ * Returns JKScopeOpt instance with given value or empty JKScopeOpt instance if value is null.
+ *
+ * @param t the value
+ * @param the type of the value
+ * @return JKScopeOpt instance with given value or empty JKScopeOpt instance
+ */
+ static JKScopeOpt withNonNull(final T t) {
+ return t == null
+ ? JKScopeOpt.empty()
+ : JKScopeOpt.of(t);
+ }
+
+ /**
+ * Performs given consumer on the given value if value is non-null.
+ *
+ * @param t the value
+ * @param block the consumer
+ * @param the type of the value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void withNonNull(final T t,
+ final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ if (t != null) {
+ block.asUnchecked().accept(t);
+ }
+ }
+
+ /**
+ * Performs given consumer on the given values if all values are non-null.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param block the consumer
+ * @param the type of the first value
+ * @param the type of the second value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void withNonNull(final T t,
+ final U u,
+ final ThBiConsumer super T, ? super U, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ if (t != null && u != null) {
+ block.asUnchecked().accept(t, u);
+ }
+ }
+
+ /**
+ * Performs given consumer on the given values if all values are non-null.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param v the third value
+ * @param block the consumer
+ * @param the type of the first value
+ * @param the type of the second value
+ * @param the type of the third value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static void withNonNull(final T t,
+ final U u,
+ final V v,
+ final ThTriConsumer super T, ? super U, ? super V, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ if (t != null && u != null && v != null) {
+ block.asUnchecked().accept(t, u, v);
+ }
+ }
+
+ /**
+ * Performs given function on the given value if value is non-null.
+ *
+ * @param t the value
+ * @param block the function
+ * @param the type of the value
+ * @param the type of the function result
+ * @return JKScopeOpt instance
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static JKScopeOpt withNonNull(final T t,
+ final ThFunction super T, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return t != null
+ ? JKScopeOpt.of(block.asUnchecked().apply(t))
+ : JKScopeOpt.empty();
+ }
+
+ /**
+ * Performs given function on the given values if all values are non-null.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param block the function
+ * @param the type of the first value
+ * @param the type of the second value
+ * @param the type of the function result
+ * @return JKScopeOpt instance
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static JKScopeOpt withNonNull(final T t,
+ final U u,
+ final ThBiFunction super T, ? super U, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return t != null && u != null
+ ? JKScopeOpt.of(block.asUnchecked().apply(t, u))
+ : JKScopeOpt.empty();
+ }
+
+ /**
+ * Performs given function on the given values if all values are non-null.
+ *
+ * @param t the first value
+ * @param u the second value
+ * @param v the third value
+ * @param block the function
+ * @param the type of the first value
+ * @param the type of the second value
+ * @param the type of the third value
+ * @param the type of the function result
+ * @return JKScopeOpt instance
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ static JKScopeOpt withNonNull(final T t,
+ final U u,
+ final V v,
+ final ThTriFunction super T, ? super U, ? super V, ? extends R, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return t != null && u != null && v != null
+ ? JKScopeOpt.of(block.asUnchecked().apply(t, u, v))
+ : JKScopeOpt.empty();
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/JKScopeOpt.java b/src/main/java/com/plugatar/jkscope/JKScopeOpt.java
new file mode 100644
index 0000000..eb3a9eb
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/JKScopeOpt.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope;
+
+import com.plugatar.jkscope.function.ThConsumer;
+import com.plugatar.jkscope.function.ThPredicate;
+
+import java.util.Optional;
+
+/**
+ * This interface contains instance methods:
+ *
+ *
{@link #let(ThConsumer)}
+ *
{@link #takeIf(ThPredicate)}
+ *
{@link #takeUnless(ThPredicate)}
+ *
{@link #takeNonNull()}
+ *
{@link #asOptional()}
+ *
+ * And static methods:
+ *
+ *
{@link #empty()}
+ *
{@link #of(Object)}
+ *
+ *
+ * @param the type of the value
+ */
+public interface JKScopeOpt extends SafeJKScope {
+
+ @Override
+ JKScopeOpt takeIf(ThPredicate super T, ?> block);
+
+ @Override
+ JKScopeOpt takeUnless(ThPredicate super T, ?> block);
+
+ /**
+ * Filters the value.
+ *
+ * @return filtered value
+ */
+ JKScopeOpt takeNonNull();
+
+ /**
+ * Returns the value as an Optional instance.
+ *
+ * @return Optional instance
+ */
+ Optional asOptional();
+
+ /**
+ * Returns an empty JKScopeOpt instance.
+ *
+ * @param the type of the value
+ * @return empty JKScopeOpt instance
+ */
+ @SuppressWarnings("unchecked")
+ static JKScopeOpt empty() {
+ return (JKScopeOpt) Empty.INSTANCE;
+ }
+
+ /**
+ * Returns a non-empty JKScopeOpt instance (null value considered a value too).
+ *
+ * @param value the value
+ * @param the type of value
+ * @return non-empty JKScopeOpt instance
+ */
+ static JKScopeOpt of(final T value) {
+ return new OfValue<>(value);
+ }
+
+ /**
+ * Non-empty JKScopeOpt implementation.
+ *
+ * @param the type of the value
+ */
+ final class OfValue implements JKScopeOpt {
+ private final T value;
+
+ /**
+ * Ctor
+ *
+ * @param value the value
+ */
+ private OfValue(final T value) {
+ this.value = value;
+ }
+
+ @Override
+ public void let(final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ block.asUnchecked().accept(this.value);
+ }
+
+ @Override
+ public JKScopeOpt takeIf(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().test(this.value)
+ ? this
+ : JKScopeOpt.empty();
+ }
+
+ @Override
+ public JKScopeOpt takeUnless(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return block.asUnchecked().test(this.value)
+ ? JKScopeOpt.empty()
+ : this;
+ }
+
+ @Override
+ public JKScopeOpt takeNonNull() {
+ return this.value == null
+ ? JKScopeOpt.empty()
+ : this;
+ }
+
+ @Override
+ public Optional asOptional() {
+ return Optional.ofNullable(this.value);
+ }
+ }
+
+ /**
+ * Empty JKScopeOpt implementation.
+ *
+ * @param the type of the value
+ */
+ final class Empty implements JKScopeOpt {
+ private static final Empty> INSTANCE = new Empty<>();
+
+ /**
+ * Ctor.
+ */
+ private Empty() {
+ }
+
+ @Override
+ public void let(final ThConsumer super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ }
+
+ @Override
+ public JKScopeOpt takeIf(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return this;
+ }
+
+ @Override
+ public JKScopeOpt takeUnless(final ThPredicate super T, ?> block) {
+ if (block == null) { throw new NullPointerException("block arg is null"); }
+ return this;
+ }
+
+ @Override
+ public JKScopeOpt takeNonNull() {
+ return this;
+ }
+
+ @Override
+ public Optional asOptional() {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/SafeJKScope.java b/src/main/java/com/plugatar/jkscope/SafeJKScope.java
new file mode 100644
index 0000000..d820fa4
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/SafeJKScope.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope;
+
+import com.plugatar.jkscope.function.ThConsumer;
+import com.plugatar.jkscope.function.ThPredicate;
+
+/**
+ * This interface contains instance methods:
+ *
+ *
{@link #let(ThConsumer)}
+ *
{@link #takeIf(ThPredicate)}
+ *
{@link #takeUnless(ThPredicate)}
+ *
+ *
+ * @param the type of the value
+ */
+public interface SafeJKScope {
+
+ /**
+ * Performs given consumer on the value.
+ *
+ * @param block the consumer
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ void let(ThConsumer super T, ?> block);
+
+ /**
+ * Filters the value using given predicate.
+ *
+ * @param block the predicate
+ * @return filtered value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ SafeJKScope takeIf(ThPredicate super T, ?> block);
+
+ /**
+ * Filters the value using given predicate.
+ *
+ * @param block the predicate
+ * @return filtered value
+ * @throws NullPointerException if {@code block} arg is null
+ */
+ SafeJKScope takeUnless(ThPredicate super T, ?> block);
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThBiConsumer.java b/src/main/java/com/plugatar/jkscope/function/ThBiConsumer.java
new file mode 100644
index 0000000..94cb4f8
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThBiConsumer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.BiConsumer} specialization that might throw an exception.
+ *
+ * @param the type of the first input argument
+ * @param the type of the second input argument
+ * @param the type of the throwing exception
+ * @see java.util.function.BiConsumer
+ */
+@FunctionalInterface
+public interface ThBiConsumer {
+
+ /**
+ * Performs this operation on the given arguments.
+ *
+ * @param t the first input argument
+ * @param u the second input argument
+ * @throws E if consumer threw exception
+ */
+ void accept(T t, U u) throws E;
+
+ /**
+ * Returns this consumer as an unchecked consumer.
+ *
+ * @return unchecked consumer
+ */
+ @SuppressWarnings("unchecked")
+ default ThBiConsumer asUnchecked() {
+ return (ThBiConsumer) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThBiFunction.java b/src/main/java/com/plugatar/jkscope/function/ThBiFunction.java
new file mode 100644
index 0000000..7c58836
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThBiFunction.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.BiFunction} specialization that might throw an exception.
+ *
+ * @param the type of the first input argument
+ * @param the type of the second input argument
+ * @param the type of the result
+ * @param the type of the throwing exception
+ * @see java.util.function.BiFunction
+ */
+@FunctionalInterface
+public interface ThBiFunction {
+
+ /**
+ * Applies this function to the given arguments.
+ *
+ * @param t the first input argument
+ * @param u the second input argument
+ * @return result
+ * @throws E if function threw exception
+ */
+ R apply(T t, U u) throws E;
+
+ /**
+ * Returns this functions as an unchecked functions.
+ *
+ * @return unchecked function
+ */
+ @SuppressWarnings("unchecked")
+ default ThBiFunction asUnchecked() {
+ return (ThBiFunction) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThConsumer.java b/src/main/java/com/plugatar/jkscope/function/ThConsumer.java
new file mode 100644
index 0000000..2c28e5c
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThConsumer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Consumer} specialization that might throw an exception.
+ *
+ * @param the type of the input argument
+ * @param the type of the throwing exception
+ * @see java.util.function.Consumer
+ */
+@FunctionalInterface
+public interface ThConsumer {
+
+ /**
+ * Performs this operation on the given argument.
+ *
+ * @param t the input argument
+ * @throws E if consumer threw exception
+ */
+ void accept(T t) throws E;
+
+ /**
+ * Returns this consumer as an unchecked consumer.
+ *
+ * @return unchecked consumer
+ */
+ @SuppressWarnings("unchecked")
+ default ThConsumer asUnchecked() {
+ return (ThConsumer) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThFunction.java b/src/main/java/com/plugatar/jkscope/function/ThFunction.java
new file mode 100644
index 0000000..f311de9
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThFunction.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Function} specialization that might throw an exception.
+ *
+ * @param the type of the input argument
+ * @param the type of the result
+ * @param the type of the throwing exception
+ * @see java.util.function.Function
+ */
+@FunctionalInterface
+public interface ThFunction {
+
+ /**
+ * Applies this function to the given argument.
+ *
+ * @param t the input argument
+ * @return result
+ * @throws E if function threw exception
+ */
+ R apply(T t) throws E;
+
+ /**
+ * Returns this functions as an unchecked functions.
+ *
+ * @return unchecked function
+ */
+ @SuppressWarnings("unchecked")
+ default ThFunction asUnchecked() {
+ return (ThFunction) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThPredicate.java b/src/main/java/com/plugatar/jkscope/function/ThPredicate.java
new file mode 100644
index 0000000..a926cee
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThPredicate.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Predicate} specialization that might throw an exception.
+ *
+ * @param the type of the input argument
+ * @param the type of the throwing exception
+ * @see java.util.function.Predicate
+ */
+@FunctionalInterface
+public interface ThPredicate {
+
+ /**
+ * Applies this predicate to the given argument.
+ *
+ * @param t the input argument
+ * @return result
+ * @throws E if function threw exception
+ */
+ boolean test(T t) throws E;
+
+ /**
+ * Returns this predicate as an unchecked predicate.
+ *
+ * @return unchecked predicate
+ */
+ @SuppressWarnings("unchecked")
+ default ThPredicate asUnchecked() {
+ return (ThPredicate) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThRunnable.java b/src/main/java/com/plugatar/jkscope/function/ThRunnable.java
new file mode 100644
index 0000000..c9e50b8
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThRunnable.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link Runnable} specialization that might throw an exception.
+ *
+ * @param the type of the throwing exception
+ * @see Runnable
+ */
+@FunctionalInterface
+public interface ThRunnable {
+
+ /**
+ * Performs this operation.
+ *
+ * @throws E if runnable threw exception
+ */
+ void run() throws E;
+
+ /**
+ * Returns this runnable as an unchecked runnable.
+ *
+ * @return unchecked runnable
+ */
+ @SuppressWarnings("unchecked")
+ default ThRunnable asUnchecked() {
+ return (ThRunnable) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThSupplier.java b/src/main/java/com/plugatar/jkscope/function/ThSupplier.java
new file mode 100644
index 0000000..d036223
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThSupplier.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Supplier} specialization that might throw an exception.
+ *
+ * @param the type of the result
+ * @param the type of the throwing exception
+ * @see java.util.function.Supplier
+ */
+@FunctionalInterface
+public interface ThSupplier {
+
+ /**
+ * Gets the result.
+ *
+ * @return result
+ * @throws E if supplier threw exception
+ */
+ R get() throws E;
+
+ /**
+ * Returns this supplier as an unchecked supplier.
+ *
+ * @return unchecked runnable
+ */
+ @SuppressWarnings("unchecked")
+ default ThSupplier asUnchecked() {
+ return (ThSupplier) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThTriConsumer.java b/src/main/java/com/plugatar/jkscope/function/ThTriConsumer.java
new file mode 100644
index 0000000..1e6728a
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThTriConsumer.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Consumer} specialization for 3 input arguments that might throw an exception.
+ *
+ * @param the type of the first input argument
+ * @param the type of the second input argument
+ * @param the type of the third input argument
+ * @param the type of the throwing exception
+ */
+@FunctionalInterface
+public interface ThTriConsumer {
+
+ /**
+ * Performs this operation on the given arguments.
+ *
+ * @param t the first input argument
+ * @param u the second input argument
+ * @param v the third input argument
+ * @throws E if consumer threw exception
+ */
+ void accept(T t, U u, V v) throws E;
+
+ /**
+ * Returns this consumer as an unchecked consumer.
+ *
+ * @return unchecked consumer
+ */
+ @SuppressWarnings("unchecked")
+ default ThTriConsumer asUnchecked() {
+ return (ThTriConsumer) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/ThTriFunction.java b/src/main/java/com/plugatar/jkscope/function/ThTriFunction.java
new file mode 100644
index 0000000..8b60579
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/ThTriFunction.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope.function;
+
+/**
+ * The {@link java.util.function.Function} specialization for 3 input arguments that might throw an exception.
+ *
+ * @param the type of the first input argument
+ * @param the type of the second input argument
+ * @param the type of the third input argument
+ * @param the type of the result
+ * @param the type of the throwing exception
+ */
+@FunctionalInterface
+public interface ThTriFunction {
+
+ /**
+ * Applies this function to the given arguments.
+ *
+ * @param t the first input argument
+ * @param u the second input argument
+ * @param v the third input argument
+ * @return result
+ * @throws E if function threw exception
+ */
+ R apply(T t, U u, V v) throws E;
+
+ /**
+ * Returns this functions as an unchecked functions.
+ *
+ * @return unchecked function
+ */
+ @SuppressWarnings("unchecked")
+ default ThTriFunction asUnchecked() {
+ return (ThTriFunction) this;
+ }
+}
diff --git a/src/main/java/com/plugatar/jkscope/function/package-info.java b/src/main/java/com/plugatar/jkscope/function/package-info.java
new file mode 100644
index 0000000..1f222e0
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/function/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * Functions.
+ */
+package com.plugatar.jkscope.function;
diff --git a/src/main/java/com/plugatar/jkscope/package-info.java b/src/main/java/com/plugatar/jkscope/package-info.java
new file mode 100644
index 0000000..054cbd1
--- /dev/null
+++ b/src/main/java/com/plugatar/jkscope/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * JKScope. Java scope functions in style of Kotlin.
+ *
+ * @see GitHub repository
+ */
+package com.plugatar.jkscope;
diff --git a/src/test/java/com/plugatar/jkscope/JKScopeOptTest.java b/src/test/java/com/plugatar/jkscope/JKScopeOptTest.java
new file mode 100644
index 0000000..7e31131
--- /dev/null
+++ b/src/test/java/com/plugatar/jkscope/JKScopeOptTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 Evgenii Plugatar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.plugatar.jkscope;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link JKScopeOpt}.
+ */
+final class JKScopeOptTest {
+
+ @Test
+ void asOptionalMethodForEmpty() {
+ final JKScopeOpt