Skip to content

Commit

Permalink
docs: improve javadoc 📚 add missing QA annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed Mar 26, 2024
1 parent 72e4ad1 commit 8eed883
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 47 deletions.
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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!"

Expand Down Expand Up @@ -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~."

Expand Down Expand Up @@ -259,7 +261,6 @@ public class IntegrationDemo {
attachable.setAttachment(key, value);
}

@Nullable
@Override
public String getAttachment(String key) {
return attachable.getAttachment(key);
Expand Down
38 changes: 21 additions & 17 deletions src/main/java/io/foldright/inspectablewrappers/Inspector.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -12,25 +13,24 @@


/**
* This {@code Inspector} is used to inspect wrapper implementors:
* This {@code Inspector} class is used to inspect the wrapper chain.
* <p>
* Common usages:
* <ul>
* <li>
* Reports whether any wrapper on the wrapper chain matches the given type by static method {@link #isInstanceOf(Object, Class)}
* </li>
* <li>
* Retrieve the attachment from wrapper chain(wrapper instances implement interface {@link Wrapper})
* by static method {@link #getAttachment(Object, Object)}.
* </li>
* <li>Reports whether any wrapper on the wrapper chain matches the given type
* by static method {@link #isInstanceOf(Object, Class)}
* <li>Retrieve the attachment from wrapper chain(wrapper instances implement interface {@link Wrapper})
* by static method {@link #getAttachment(Object, Object)}
* </ul>
*
* @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.
* <p>
Expand Down Expand Up @@ -108,7 +108,6 @@ public static <W, K, V> 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,
Expand All @@ -124,8 +123,7 @@ public static <W, K, V> 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")
Expand All @@ -143,7 +141,9 @@ static <W, T> Optional<T> travel(final W wrapper, final Function<W, Optional<T>>
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<T> r = process.apply((W) adaptee);
Expand All @@ -154,4 +154,8 @@ static <W, T> Optional<T> travel(final W wrapper, final Function<W, Optional<T>>
w = unwrapNonNull(w);
}
}

// no need to create instance at all
private Inspector() {
}
}
16 changes: 10 additions & 6 deletions src/main/java/io/foldright/inspectablewrappers/Wrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <b>inspectable wrapper chain</b>(linked list).
* make an <b>inspectable wrapper chain</b>(linked list).
* <p>
* <b><i>Note about wrapper chain:<br></i></b>
* <ul>
* <li>The wrapper chain consists of wrapper itself, followed by the wrappers
* obtained by repeatedly calling {@link Wrapper#unwrap()}
* <li>The last instance of wrapper chain is never type {@link Wrapper}
* <li>Uses the static methods in {@link Inspector} to inspect the wrapper chain
* </ul>
*
* @param <T> 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<T> {
/**
* Returns the underlying instance that be wrapped.
Expand All @@ -24,6 +30,4 @@ public interface Wrapper<T> {
*/
@NonNull
T unwrap();


}
15 changes: 13 additions & 2 deletions src/main/java/io/foldright/inspectablewrappers/WrapperAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* 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 <T> 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<T> extends Wrapper<T> {
/**
* Returns the adapted/existed wrapper.
* <p>
* <b><i>Note:<br></i></b>
* <ul>
* <li>The adaptee MUST not a {@link Wrapper},
* since adapting a {@link Wrapper} to a {@link Wrapper} is unnecessary.
* <li>If adapting a {@link Wrapper}, the inspection operations of {@link Inspector} will
* throw {@link IllegalStateException} when touch the {@link Wrapper} type adaptee.
* </ul>
*
* @return the adapted wrapper.
* @see Inspector#isInstanceOf(Object, Class)
* @see Inspector
*/
@NonNull
T adaptee();
Expand Down
11 changes: 6 additions & 5 deletions src/main/java/io/foldright/inspectablewrappers/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
*
* <ul>
* <li>{@link io.foldright.inspectablewrappers.Wrapper} is core interface, used to
* <ul>
* <li>identify the wrapper instances as a wrapper chain
* <li>provide static entry methods to inspect the wrapper chain
* </ul>
* be implemented by wrapper classes, make an <b>inspectable wrapper chain</b>(linked list).
* <li>{@link io.foldright.inspectablewrappers.Attachable} interface is used to
* enhance the wrapper instances with the attachment storage ability
* <li>{@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.
* </ul>
* <p>
* 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;
Original file line number Diff line number Diff line change
Expand Up @@ -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<IllegalStateException> {
Inspector.isInstanceOf(chain, ExecutorService::class.java)
Expand All @@ -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<Executor>, Attachable<String, String> by AttachableDelegate() {
Expand All @@ -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<Executor>, Attachable<String, String> by AttachableDelegate() {
Expand Down

0 comments on commit 8eed883

Please sign in to comment.