Skip to content

πŸͺ Inspectable Wrappers Specification, provides the interfaces to make wrapper instances as an inspectable wrapper chain.

License

Notifications You must be signed in to change notification settings

foldright/inspectable-wrappers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

90 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸͺ Inspectable Wrappers

Github Workflow Build Status Codecov Java support License Javadocs Maven Central GitHub Releases GitHub Stars GitHub Forks GitHub Issues GitHub Contributors GitHub repo size gitpod: Ready to Code

inspectable-wrappers

The purpose of Inspectable Wrappers is to provide a standard for wrapper chain with the inspection ability.



🍑 Files

  • The core interfaces/specification interfaces:
    • Wrapper interface is used to be implemented by wrapper classes, make an inspectable wrapper chain(linked list)
    • Attachable interface is used to enhance the wrapper instances with the attachment storage ability
    • WrapperAdapter interface is used to adapt an existed wrapper instance to type Wrapper without modifying it
  • The Inspector class is used to inspect the wrapper chain
  • The utility classes:
    • AttachableDelegate class provides a simple Attachable delegate implementation
    • WrapperAdapterUtils class provides utility methods for creating WrapperAdapter instances without writing boilerplate codes of creating new adapter classes

🌰 Usage Demo

Below use the Executor Wrapper to demonstrate the usage.

demo wrapper implementations in your application code

// a wrapper implementation
public class ChattyExecutorWrapper implements Executor, Wrapper<Executor> {
  private final Executor executor;

  public ChattyExecutorWrapper(Executor executor) {
    this.executor = executor;
  }

  @Override
  public void execute(Runnable command) {
    System.out.println("BlaBlaBla...");
    executor.execute(command);
  }

  @Override
  public Executor unwrap_() {
    return executor;
  }
}

// another wrapper implementation
public class LazyExecutorWrapper implements Executor, Wrapper<Executor>, Attachable<String, String> {
  private final Executor executor;

  public LazyExecutorWrapper(Executor executor) {
    this.executor = executor;
  }

  @Override
  public void execute(Runnable command) {
    System.out.println("I'm lazy, sleep before work.");
    sleep();

    executor.execute(command);
  }

  @Override
  public Executor unwrap_() {
    return executor;
  }

  private final Attachable<String, String> attachable = new AttachableDelegate<>();

  @Override
  public void setAttachment_(String key, String value) {
    attachable.setAttachment_(key, value);
  }

  @Override
  public String getAttachment_(String key) {
    return attachable.getAttachment_(key);
  }
}

inspection of the wrapper chain

public class Demo {
  public static void main(String[] args) {
    final Executor executor = buildExecutorChain();

    ////////////////////////////////////////
    // inspect the executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println("Is executor lazy? " +
        containsInstanceTypeOnWrapperChain(executor, LazyExecutorWrapper.class));
    // print true

    String busy = getAttachmentFromWrapperChain(executor, "busy");
    System.out.println("Is executor busy? " + busy);
    // print "very, very busy!"

    ////////////////////////////////////////
    // call executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println();
    executor.execute(() -> System.out.println("I'm working."));
  }

  /**
   * prepare executor instances/wrappers, build the executor/wrapper chain
   **/
  private static Executor buildExecutorChain() {
    final Executor base = Runnable::run;

    final LazyExecutorWrapper lazy = new LazyExecutorWrapper(base);
    lazy.setAttachment_("busy", "very, very busy!");

    return new ChattyExecutorWrapper(lazy);
  }
}

/*
demo output:

Is executor lazy? true
Is executor busy? very, very busy!

BlaBlaBla...
I'm lazy, sleep before work.
I'm working.
 */

Runnable demo codes in project: Demo.java

🌰 Integration Demo

Integrate an existed wrapper instance to type Wrapper without modifying it.

the demo existed wrapper which cannot be modified

public class ExistedExecutorWrapper implements Executor {
  private final Executor executor;

  public ExistedExecutorWrapper(Executor executor) {
    this.executor = executor;
  }

  @Override
  public void execute(Runnable command) {
    System.out.println("I'm existed executor, have nothing to do with ~inspectable~wrappers~.");
    executor.execute(command);
  }
}

the integration code

public class IntegrationDemo {
  public static void main(String[] args) {
    final Executor executor = buildExecutorChain();

    ////////////////////////////////////////
    // inspect the executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println("Is executor ExistedExecutorWrapper? " +
        containsInstanceTypeOnWrapperChain(executor, ExistedExecutorWrapper.class));
    // print true
    String adaptAttachment = getAttachmentFromWrapperChain(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~."

    ////////////////////////////////////////
    // call executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println();
    executor.execute(() -> System.out.println("I'm working."));
  }

  private static Executor buildExecutorChain() {
    final Executor base = Runnable::run;
    final ExistedExecutorWrapperAdapter adapter = createExistedExecutorWrapperAdapter(base);
    return new ChattyExecutorWrapper(adapter);
  }

  private static ExistedExecutorWrapperAdapter createExistedExecutorWrapperAdapter(Executor base) {
    final ExistedExecutorWrapper existed = new ExistedExecutorWrapper(base);
    final ExistedExecutorWrapperAdapter adapter = new ExistedExecutorWrapperAdapter(base, existed);
    adapter.setAttachment_("adapted-existed-executor-wrapper-msg", "I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.");
    return adapter;
  }

  /**
   * Adaption an existed wrapper(`ExistedExecutorWrapper`) without modifying it.
   */
  private static class ExistedExecutorWrapperAdapter implements Executor, WrapperAdapter<Executor>, Attachable<String, String> {
    private final Executor base;
    private final Executor adaptee;

    public ExistedExecutorWrapperAdapter(Executor base, Executor adaptee) {
      this.base = base;
      this.adaptee = adaptee;
    }

    @Override
    public Executor unwrap_() {
      return base;
    }

    @Override
    public Executor adaptee_() {
      return adaptee;
    }

    @Override
    public void execute(Runnable command) {
      adaptee.execute(command);
    }

    private final Attachable<String, String> 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);
    }
  }
}

/*
demo output:

Is executor ExistedExecutorWrapper? true
Adapted existed executor wrapper msg: I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.

BlaBlaBla...
I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.
I'm working.
 */

Runnable demo codes in project: IntegrationDemo.java

🌰 Integration Demo using WrapperAdapterUtils

Uses WrapperAdapterUtils to create WrapperAdapter instances without writing boilerplate codes of creating new adapter classes.

public class IntegrationDemoUsingWrapperAdapterUtils {
  public static void main(String[] args) {
    final Executor executor = buildExecutorChain();

    ////////////////////////////////////////
    // inspect the executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println("Is executor ExistedExecutorWrapper? " +
        containsInstanceTypeOnWrapperChain(executor, ExistedExecutorWrapper.class));
    // print true
    String adaptAttachment = getAttachmentFromWrapperChain(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~."

    ////////////////////////////////////////
    // call executor(wrapper chain)
    ////////////////////////////////////////

    System.out.println();
    executor.execute(() -> System.out.println("I'm working."));
  }

  private static Executor buildExecutorChain() {
    final Executor base = Runnable::run;
    final Executor adapter = createExistedExecutorWrapperAdapter(base);
    return new ChattyExecutorWrapper(adapter);
  }

  private static Executor createExistedExecutorWrapperAdapter(Executor base) {
    final Executor existed = new ExistedExecutorWrapper(base);

    Attachable<String, String> attachable = new AttachableDelegate<>();
    attachable.setAttachment_("adapted-existed-executor-wrapper-msg", "I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.");

    return WrapperAdapterUtils.createWrapperAdapter(Executor.class, base, existed, attachable);
  }
}

/*
demo output:

Is executor ExistedExecutorWrapper? true
Adapted existed executor wrapper msg: I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.

BlaBlaBla...
I'm an adapter of an existed executor which have nothing to do with ~inspectable~wrappers~.
I'm working.
 */

Runnable demo codes in project: IntegrationDemoUsingWrapperAdapterUtils.java

🍼 Java API Docs

The current version Java API documentation: https://foldright.io/inspectable-wrappers/apidocs/

πŸͺ Dependency

For Maven projects:

<dependency>
  <groupId>io.foldright</groupId>
  <artifactId>inspectable-wrappers</artifactId>
  <version>0.5.5</version>
</dependency>

For Gradle projects:

// Gradle Kotlin DSL
implementation("io.foldright:inspectable-wrappers:0.5.5")
// Gradle Groovy DSL
implementation 'io.foldright:inspectable-wrappers:0.5.5'

inspectable-wrappers has published to maven central, find the latest version at central.sonatype.com.