diff --git a/README.md b/README.md index 3bcc4a3..fe7291d 100644 --- a/README.md +++ b/README.md @@ -39,15 +39,17 @@ The purpose of **Inspectable Wrappers** is to provide a standard for wrapper cha -------------------------------------------------------------------------------- -## 🥑 Core Classes - -- [`Wrapper`](src/main/java/io/foldright/inspectablewrappers/Wrapper.java) is core interface, used to - - identify the wrapper instances as a wrapper chain - - provide static entry methods to inspect the wrapper chain -- [`Attachable`](src/main/java/io/foldright/inspectablewrappers/Attachable.java) interface is used to - enhance the wrapper instances with the attachment storage ability -- [`WrapperAdapter`](src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java) interface is used to - adapt an existed wrapper without modifying it +## 🥑 Core + +- Core interfaces: + - [`Wrapper`](src/main/java/io/foldright/inspectablewrappers/Wrapper.java) interface is core interface, used to + be implemented by wrapper classes, make an **inspectable wrapper chain**(linked list). + - [`Attachable`](src/main/java/io/foldright/inspectablewrappers/Attachable.java) interface is used to + enhance the wrapper instances with the attachment storage ability + - [`WrapperAdapter`](src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java) interface is used to + adapt an existed wrapper instance to type `Wrapper` without modifying it +- [`Inspector`](src/main/java/io/foldright/inspectablewrappers/Inspector.java) class is used to + inspect the **wrapper chain** ## 🌰 Usage Demo @@ -123,10 +125,10 @@ public class Demo { //////////////////////////////////////// System.out.println("Is executor lazy? " + - Wrapper.isInstanceOf(executor, LazyExecutorWrapper.class)); + Inspector.isInstanceOf(executor, LazyExecutorWrapper.class)); // print true - String busy = Wrapper.getAttachment(executor, "busy"); + String busy = Inspector.getAttachment(executor, "busy"); System.out.println("Is executor busy? " + busy); // print "very, very busy!" @@ -203,9 +205,9 @@ public class IntegrationDemo { //////////////////////////////////////// System.out.println("Is executor ExistedExecutorWrapper? " + - Wrapper.isInstanceOf(executor, ExistedExecutorWrapper.class)); + Inspector.isInstanceOf(executor, ExistedExecutorWrapper.class)); // print true - String adaptAttachment = Wrapper.getAttachment(executor, "adapted-existed-executor-wrapper-msg"); + String adaptAttachment = Inspector.getAttachment(executor, "adapted-existed-executor-wrapper-msg"); System.out.println("Adapted existed executor wrapper msg: " + adaptAttachment); // print "I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~." @@ -259,7 +261,6 @@ public class IntegrationDemo { attachable.setAttachment(key, value); } - @Nullable @Override public String getAttachment(String key) { return attachable.getAttachment(key); diff --git a/src/main/java/io/foldright/inspectablewrappers/Inspector.java b/src/main/java/io/foldright/inspectablewrappers/Inspector.java index 499ae77..b4b64f0 100644 --- a/src/main/java/io/foldright/inspectablewrappers/Inspector.java +++ b/src/main/java/io/foldright/inspectablewrappers/Inspector.java @@ -3,6 +3,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; @@ -12,25 +13,24 @@ /** - * This {@code Inspector} is used to inspect wrapper implementors: + * This {@code Inspector} class is used to inspect the wrapper chain. + *

+ * Common usages: *

* + * @author Jerry Lee (oldratlee at gmail dot com) + * @author Zava (zava dot kid at gmail dot com) * @see Wrapper + * @see Attachable + * @see WrapperAdapter */ +@ParametersAreNonnullByDefault public final class Inspector { - - // no need to create instance at all - private Inspector() { - } - /** * Reports whether any wrapper on the wrapper chain matches the given type. *

@@ -108,7 +108,6 @@ public static V getAttachment(final W wrapper, final K key) { }).orElse(null); } - /** * Traverses the wrapper chain, and apply the given {@code process} function to each wrapper, * and returns the first non-empty({@link Optional#empty()}) result of the process function, @@ -124,8 +123,7 @@ public static V getAttachment(final W wrapper, final K key) { * @return the first non-empty({@link Optional#empty()}) result of the process function, * otherwise returns {@link Optional#empty()}. * @throws NullPointerException if any arguments is null or any wrapper {{@link Wrapper#unwrap()}} returns null - * @throws IllegalStateException if the adaptee of {@link WrapperAdapter} is a wrapper instance, - * the use of WrapperAdapter is unnecessary! + * @throws IllegalStateException if the adaptee of {@link WrapperAdapter} is type {@link Wrapper} */ @NonNull @SuppressWarnings("unchecked") @@ -143,7 +141,9 @@ static Optional travel(final W wrapper, final Function> if (w instanceof WrapperAdapter) { final Object adaptee = ((WrapperAdapter) w).adaptee(); if (adaptee instanceof Wrapper) { - throw new IllegalStateException("adaptee(" + adaptee.getClass().getName() + ") of WrapperAdapter(" + w.getClass().getName() + ") is a wrapper instance, the use of WrapperAdapter is unnecessary!"); + throw new IllegalStateException("adaptee(" + adaptee.getClass().getName() + + ") of WrapperAdapter(" + w.getClass().getName() + + ") is type Wrapper, adapting a Wrapper to a Wrapper is unnecessary!"); } Optional r = process.apply((W) adaptee); @@ -154,4 +154,8 @@ static Optional travel(final W wrapper, final Function> w = unwrapNonNull(w); } } + + // no need to create instance at all + private Inspector() { + } } diff --git a/src/main/java/io/foldright/inspectablewrappers/Wrapper.java b/src/main/java/io/foldright/inspectablewrappers/Wrapper.java index 29a0ffc..7c2de61 100644 --- a/src/main/java/io/foldright/inspectablewrappers/Wrapper.java +++ b/src/main/java/io/foldright/inspectablewrappers/Wrapper.java @@ -2,20 +2,26 @@ import edu.umd.cs.findbugs.annotations.NonNull; -import javax.annotation.ParametersAreNonnullByDefault; - /** * This {@code Wrapper} interface is used to be implemented by wrapper classes, - * make {@code wrapper instances} as an inspectable wrapper chain(linked list). + * make an inspectable wrapper chain(linked list). + *

+ * Note about wrapper chain:
+ *

* * @param the type of instances that be wrapped * @author Jerry Lee (oldratlee at gmail dot com) + * @author Zava (zava dot kid at gmail dot com) * @see Attachable * @see WrapperAdapter * @see Inspector */ -@ParametersAreNonnullByDefault public interface Wrapper { /** * Returns the underlying instance that be wrapped. @@ -24,6 +30,4 @@ public interface Wrapper { */ @NonNull T unwrap(); - - } diff --git a/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java b/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java index 91cad43..d35a575 100644 --- a/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java +++ b/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java @@ -4,20 +4,31 @@ /** - * Adaption an existed wrapper without modifying it. + * This {@code WrapperAdapter} interface is used to + * adapt an existed wrapper instance to type {@link Wrapper} without modifying it. *

* The existed wrapper may not be able to be modified to integrate with {@code inspectable wrappers}, * aka. implements the {@link Wrapper} interface and/or {@link Attachable} interface. * * @param the type of instances that be wrapped + * @author Jerry Lee (oldratlee at gmail dot com) + * @author Zava (zava dot kid at gmail dot com) * @see Wrapper */ public interface WrapperAdapter extends Wrapper { /** * Returns the adapted/existed wrapper. + *

+ * Note:
+ *

    + *
  • The adaptee MUST not a {@link Wrapper}, + * since adapting a {@link Wrapper} to a {@link Wrapper} is unnecessary. + *
  • If adapting a {@link Wrapper}, the inspection operations of {@link Inspector} will + * throw {@link IllegalStateException} when touch the {@link Wrapper} type adaptee. + *
* * @return the adapted wrapper. - * @see Inspector#isInstanceOf(Object, Class) + * @see Inspector */ @NonNull T adaptee(); diff --git a/src/main/java/io/foldright/inspectablewrappers/package-info.java b/src/main/java/io/foldright/inspectablewrappers/package-info.java index 24200dc..fcd63d2 100644 --- a/src/main/java/io/foldright/inspectablewrappers/package-info.java +++ b/src/main/java/io/foldright/inspectablewrappers/package-info.java @@ -3,18 +3,19 @@ * *
    *
  • {@link io.foldright.inspectablewrappers.Wrapper} is core interface, used to - *
      - *
    • identify the wrapper instances as a wrapper chain - *
    • provide static entry methods to inspect the wrapper chain - *
    + * be implemented by wrapper classes, make an inspectable wrapper chain(linked list). *
  • {@link io.foldright.inspectablewrappers.Attachable} interface is used to * enhance the wrapper instances with the attachment storage ability *
  • {@link io.foldright.inspectablewrappers.WrapperAdapter} interface is used to - * adapt an existed wrapper without modifying it + * adapt an existed wrapper instance to type {@link io.foldright.inspectablewrappers.Wrapper} without modifying it. *
+ *

+ * The {@link io.foldright.inspectablewrappers.Inspector} class is used to inspect the wrapper chain. * + * @author Jerry Lee (oldratlee at gmail dot com) * @see io.foldright.inspectablewrappers.Wrapper * @see io.foldright.inspectablewrappers.Attachable * @see io.foldright.inspectablewrappers.WrapperAdapter + * @see io.foldright.inspectablewrappers.Inspector */ package io.foldright.inspectablewrappers; diff --git a/src/test/java/io/foldright/inspectablewrappers/WrapperAdapterTest.kt b/src/test/java/io/foldright/inspectablewrappers/WrapperAdapterTest.kt index 7eae212..f519bea 100644 --- a/src/test/java/io/foldright/inspectablewrappers/WrapperAdapterTest.kt +++ b/src/test/java/io/foldright/inspectablewrappers/WrapperAdapterTest.kt @@ -60,7 +60,7 @@ class WrapperAdapterTest : FunSpec({ val errMsg = "adaptee(io.foldright.inspectablewrappers.ChattyExecutorWrapper)" + " of WrapperAdapter(io.foldright.inspectablewrappers.ChattyExecutorWrapperAdapter)" + - " is a wrapper instance, the use of WrapperAdapter is unnecessary!" + " is type Wrapper, adapting a Wrapper to a Wrapper is unnecessary!" shouldThrow { Inspector.isInstanceOf(chain, ExecutorService::class.java) @@ -77,7 +77,7 @@ class WrapperAdapterTest : FunSpec({ }) /** - * Adaption an existed wrapper(`ExistedExecutorWrapper`) without modifying it. + * Adaption an existed wrapper([ExistedExecutorWrapper]) without modifying it. */ private class ExistedExecutorWrapperAdapter(private val adaptee: ExistedExecutorWrapper) : Executor by adaptee, WrapperAdapter, Attachable by AttachableDelegate() { @@ -93,7 +93,7 @@ class ExistedExecutorWrapper(val executor: Executor) : Executor { } /** - * Wrong use the [WrapperAdapter], the adaptee is [Wrapper]. + * Wrong use the [WrapperAdapter], the adaptee is already [Wrapper]! */ private class ChattyExecutorWrapperAdapter(private val adaptee: ChattyExecutorWrapper) : Executor by adaptee, WrapperAdapter, Attachable by AttachableDelegate() {