From 9a23e5c744e5bb4f0e6db8bacd9e20d902863a7c Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Sat, 23 Mar 2024 20:17:34 +0800 Subject: [PATCH] feat: add `WrapperAdapter` --- README.md | 45 ++++++++++++----- .../inspectablewrappers/Wrapper.java | 8 ++- .../inspectablewrappers/WrapperAdapter.java | 24 +++++++++ .../demo/integration/IntegrationDemo.java | 49 ++++++++++++++----- 4 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java diff --git a/README.md b/README.md index d7d4214..ec4b474 100644 --- a/README.md +++ b/README.md @@ -200,12 +200,12 @@ public class IntegrationDemo { // inspect the executor(wrapper chain) //////////////////////////////////////// - System.out.println("Is executor chatty? " + - Wrapper.isInstanceOf(executor, ChattyExecutorWrapper.class)); - // print true - System.out.println("Is executor IntegrateExistedExecutor? " + - Wrapper.isInstanceOf(executor, IntegrateExistedExecutorWrapper.class)); + System.out.println("Is executor ExistedExecutorWrapper? " + + Wrapper.isInstanceOf(executor, ExistedExecutorWrapper.class)); // print true + String adaptAttachment = Wrapper.getAttachment(executor, "adopted-existed-executor-wrapper-msg"); + System.out.println("Adopted existed executor wrapper msg: " + adaptAttachment); + // print "very, very busy!" //////////////////////////////////////// // call executor(wrapper chain) @@ -220,6 +220,7 @@ public class IntegrationDemo { final ExistedExecutorWrapper existed = new ExistedExecutorWrapper(base); final IntegrateExistedExecutorWrapper integrate = new IntegrateExistedExecutorWrapper(existed); + integrate.setAttachment("adopted-existed-executor-wrapper-msg", "I'm existed executor, have nothing to do with ~inspectable~wrappers~."); return new ChattyExecutorWrapper(integrate); } @@ -227,21 +228,39 @@ public class IntegrationDemo { /** * Integrate an existed executor wrapper(`ExistedExecutorWrapper`) without modification */ - private static class IntegrateExistedExecutorWrapper implements Executor, Wrapper { - private final ExistedExecutorWrapper existedExecutorWrapper; + private static class IntegrateExistedExecutorWrapper implements Executor, WrapperAdapter, Attachable { + private final ExistedExecutorWrapper adaptee; - public IntegrateExistedExecutorWrapper(ExistedExecutorWrapper existedExecutorWrapper) { - this.existedExecutorWrapper = existedExecutorWrapper; + public IntegrateExistedExecutorWrapper(ExistedExecutorWrapper adaptee) { + this.adaptee = adaptee; } @Override public Executor unwrap() { - return existedExecutorWrapper.getExecutor(); + return adaptee.getExecutor(); + } + + @Override + public Executor adaptee() { + return adaptee; } @Override public void execute(Runnable command) { - existedExecutorWrapper.execute(command); + adaptee.execute(command); + } + + private final Attachable attachable = new AttachableDelegate<>(); + + @Override + public void setAttachment(String key, String value) { + attachable.setAttachment(key, value); + } + + @Nullable + @Override + public String getAttachment(String key) { + return attachable.getAttachment(key); } } } @@ -249,8 +268,8 @@ public class IntegrationDemo { /* demo output: -Is executor chatty? true -Is executor IntegrateExistedExecutor? true +Is executor ExistedExecutorWrapper? true +Adopted existed executor wrapper msg: I'm existed executor, have nothing to do with ~inspectable~wrappers~. BlaBlaBla... I'm existed executor, have nothing to do with ~inspectable~wrappers~. diff --git a/src/main/java/io/foldright/inspectablewrappers/Wrapper.java b/src/main/java/io/foldright/inspectablewrappers/Wrapper.java index 102bcee..45ca802 100644 --- a/src/main/java/io/foldright/inspectablewrappers/Wrapper.java +++ b/src/main/java/io/foldright/inspectablewrappers/Wrapper.java @@ -44,7 +44,13 @@ public interface Wrapper { static boolean isInstanceOf(W wrapper, Class clazz) { requireNonNull(wrapper, "wrapper is null"); requireNonNull(clazz, "clazz is null"); - return inspect(wrapper, w -> clazz.isAssignableFrom(w.getClass())); + return inspect(wrapper, w -> { + if (w instanceof WrapperAdapter) { + Object adaptee = ((WrapperAdapter) w).adaptee(); + if (clazz.isAssignableFrom(adaptee.getClass())) return true; + } + return clazz.isAssignableFrom(w.getClass()); + }); } /** diff --git a/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java b/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java new file mode 100644 index 0000000..da25ff5 --- /dev/null +++ b/src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java @@ -0,0 +1,24 @@ +package io.foldright.inspectablewrappers; + +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; + + +/** + * Adaption an existed wrapper without modification. + * The existed wrapper can not be modified to integrated with {@code inspectable wrappers}, + * aka. implements the {@link Wrapper} interface and/or {@link Attachable} interface. + * + * @param the type of instances that be wrapped + */ +@ParametersAreNonnullByDefault +@ReturnValuesAreNonnullByDefault +public interface WrapperAdapter extends Wrapper { + /** + * Returns the adapted/existed wrapper. + * + * @return the adapted wrapper. + */ + T adaptee(); +} diff --git a/src/test/java/io/foldright/demo/integration/IntegrationDemo.java b/src/test/java/io/foldright/demo/integration/IntegrationDemo.java index 6dc8f4b..6a3bb58 100644 --- a/src/test/java/io/foldright/demo/integration/IntegrationDemo.java +++ b/src/test/java/io/foldright/demo/integration/IntegrationDemo.java @@ -1,8 +1,12 @@ package io.foldright.demo.integration; +import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; import io.foldright.demo.ChattyExecutorWrapper; +import io.foldright.inspectablewrappers.Attachable; import io.foldright.inspectablewrappers.Wrapper; +import io.foldright.inspectablewrappers.WrapperAdapter; +import io.foldright.inspectablewrappers.utils.AttachableDelegate; import javax.annotation.ParametersAreNonnullByDefault; import java.util.concurrent.Executor; @@ -18,12 +22,12 @@ public static void main(String[] args) { // inspect the executor(wrapper chain) //////////////////////////////////////// - System.out.println("Is executor chatty? " + - Wrapper.isInstanceOf(executor, ChattyExecutorWrapper.class)); - // print true - System.out.println("Is executor IntegrateExistedExecutor? " + - Wrapper.isInstanceOf(executor, IntegrateExistedExecutorWrapper.class)); + System.out.println("Is executor ExistedExecutorWrapper? " + + Wrapper.isInstanceOf(executor, ExistedExecutorWrapper.class)); // print true + String adaptAttachment = Wrapper.getAttachment(executor, "adopted-existed-executor-wrapper-msg"); + System.out.println("Adopted existed executor wrapper msg: " + adaptAttachment); + // print "very, very busy!" //////////////////////////////////////// // call executor(wrapper chain) @@ -38,6 +42,7 @@ private static Executor buildExecutorChain() { final ExistedExecutorWrapper existed = new ExistedExecutorWrapper(base); final IntegrateExistedExecutorWrapper integrate = new IntegrateExistedExecutorWrapper(existed); + integrate.setAttachment("adopted-existed-executor-wrapper-msg", "I'm existed executor, have nothing to do with ~inspectable~wrappers~."); return new ChattyExecutorWrapper(integrate); } @@ -45,21 +50,39 @@ private static Executor buildExecutorChain() { /** * Integrate an existed executor wrapper(`ExistedExecutorWrapper`) without modification */ - private static class IntegrateExistedExecutorWrapper implements Executor, Wrapper { - private final ExistedExecutorWrapper existedExecutorWrapper; + private static class IntegrateExistedExecutorWrapper implements Executor, WrapperAdapter, Attachable { + private final ExistedExecutorWrapper adaptee; - public IntegrateExistedExecutorWrapper(ExistedExecutorWrapper existedExecutorWrapper) { - this.existedExecutorWrapper = existedExecutorWrapper; + public IntegrateExistedExecutorWrapper(ExistedExecutorWrapper adaptee) { + this.adaptee = adaptee; } @Override public Executor unwrap() { - return existedExecutorWrapper.getExecutor(); + return adaptee.getExecutor(); + } + + @Override + public Executor adaptee() { + return adaptee; } @Override public void execute(Runnable command) { - existedExecutorWrapper.execute(command); + adaptee.execute(command); + } + + private final Attachable attachable = new AttachableDelegate<>(); + + @Override + public void setAttachment(String key, String value) { + attachable.setAttachment(key, value); + } + + @Nullable + @Override + public String getAttachment(String key) { + return attachable.getAttachment(key); } } } @@ -67,8 +90,8 @@ public void execute(Runnable command) { /* demo output: -Is executor chatty? true -Is executor IntegrateExistedExecutor? true +Is executor ExistedExecutorWrapper? true +Adopted existed executor wrapper msg: I'm existed executor, have nothing to do with ~inspectable~wrappers~. BlaBlaBla... I'm existed executor, have nothing to do with ~inspectable~wrappers~.