BuilderOperatorProvider.java
package space.sunqian.fs.object.builder;
import space.sunqian.annotation.Nonnull;
import space.sunqian.annotation.Nullable;
import space.sunqian.annotation.RetainedParam;
import space.sunqian.annotation.ThreadSafe;
import space.sunqian.fs.cache.SimpleCache;
import space.sunqian.fs.collect.ListKit;
import space.sunqian.fs.object.builder.handlers.CommonBuilderHandler;
import java.lang.reflect.Type;
import java.util.List;
/**
* This interface is the provider of {@link BuilderOperator}.
* <p>
* The default {@link BuilderOperatorProvider} is {@link BuilderOperatorProvider#defaultProvider()}.
*
* @author sunqian
*/
@ThreadSafe
public interface BuilderOperatorProvider {
/**
* Returns the default {@link BuilderOperatorProvider}. Here are handlers in the default provider:
* <ul>
* <li>{@link CommonBuilderHandler#getInstance()}</li>
* </ul>
* <p>
* Note the default {@link BuilderOperatorProvider} is singleton, and never caches the returned {@link BuilderOperator}
* instances.
*
* @return the default {@link BuilderOperatorProvider}
* @see CommonBuilderHandler
*/
static @Nonnull BuilderOperatorProvider defaultProvider() {
return BuilderOperatorProviderBack.defaultProvider();
}
/**
* Returns the default cached {@link BuilderOperatorProvider}, which is based on {@link #defaultProvider()} and
* caches the results with a {@link SimpleCache#ofSoft()}.
* <p>
* Note the default cached {@link BuilderOperatorProvider} is singleton.
*
* @return the default {@link BuilderOperatorProvider}
* @see #defaultProvider()
*/
static @Nonnull BuilderOperatorProvider defaultCachedProvider() {
return BuilderOperatorProviderBack.defaultCachedProvider();
}
/**
* Creates and returns a new {@link BuilderOperatorProvider} with the given handlers.
* <p>
* Note the created {@link BuilderOperatorProvider} never caches the returned {@link BuilderOperator} instances.
*
* @param handlers the given handlers
* @return a new {@link BuilderOperatorProvider} with the given handlers
*/
static @Nonnull BuilderOperatorProvider newProvider(@Nonnull @RetainedParam Handler @Nonnull ... handlers) {
return newProvider(ListKit.list(handlers));
}
/**
* Creates and returns a new {@link BuilderOperatorProvider} with given handlers.
* <p>
* Note the created {@link BuilderOperatorProvider} never caches the returned {@link BuilderOperator} instances.
*
* @param handlers given handlers
* @return a new {@link BuilderOperatorProvider} with given handlers
*/
static @Nonnull BuilderOperatorProvider newProvider(@Nonnull @RetainedParam List<@Nonnull Handler> handlers) {
return BuilderOperatorProviderBack.newProvider(handlers);
}
/**
* Returns a new {@link BuilderOperatorProvider} that caches the returned {@link BuilderOperator} instances with the
* specified cache.
* <p>
* Note the behavior of the non-creating methods of the returned {@link BuilderOperatorProvider}, such as
* {@link #handlers()}, {@link #asHandler()} and {@link #withFirstHandler(Handler)}, will directly invoke the
* underlying {@link BuilderOperatorProvider}.
*
* @param cache the specified cache to store the results
* @param provider the underlying {@link BuilderOperatorProvider} to create the type
* @return a new {@link BuilderOperatorProvider} that caches the results with the specified cache
*/
static @Nonnull BuilderOperatorProvider newCachedProvider(
@Nonnull SimpleCache<@Nonnull Type, @Nonnull BuilderOperator> cache,
@Nonnull BuilderOperatorProvider provider
) {
return BuilderOperatorProviderBack.newCachedProvider(cache, provider);
}
/**
* Returns an instance of {@link BuilderOperator} for the target type, or {@code null} if the target type is
* unsupported.
*
* @param target the target type
* @return a new {@link BuilderOperator}, or {@code null} if the target type is unsupported
* @throws ObjectBuilderException if an error occurs while creating the {@link BuilderOperator}
* @implNote The default implementation of this method invokes the {@link Handler#newOperator(Type)} in the order of
* {@link #handlers()} until one of the handlers returns a non-{@code null} {@link BuilderOperator}. The codes are
* similar to:
* <pre>{@code
* for (Handler handler : handlers()) {
* BuilderOperator operator = handler.newOperator(target);
* if (operator != null) {
* return operator;
* }
* }
* return null;
* }</pre>
*/
default @Nullable BuilderOperator forType(@Nonnull Type target) throws ObjectBuilderException {
try {
return BuilderOperatorProviderBack.operatorForType(target, handlers());
} catch (Exception e) {
throw new ObjectBuilderException(e);
}
}
/**
* Returns all handlers of this {@link BuilderOperatorProvider}.
*
* @return all handlers of this {@link BuilderOperatorProvider}
*/
@Nonnull
List<@Nonnull Handler> handlers();
/**
* Returns a new {@link BuilderOperatorProvider} of which first handler is the given handler and the next handler is
* this {@link BuilderOperatorProvider} as a {@link Handler}. This method is equivalent:
* <pre>{@code
* newProvider(firstHandler, this.asHandler())
* }</pre>
*
* @param firstHandler the first handler
* @return a new {@link BuilderOperatorProvider} of which first handler is the given handler and the next handler is
* this {@link BuilderOperatorProvider} as a {@link Handler}
*/
default @Nonnull BuilderOperatorProvider withFirstHandler(@Nonnull Handler firstHandler) {
return newProvider(firstHandler, this.asHandler());
}
/**
* Returns this {@link BuilderOperatorProvider} as a {@link Handler}.
*
* @return this {@link BuilderOperatorProvider} as a {@link Handler}
*/
@Nonnull
Handler asHandler();
/**
* Handler for {@link BuilderOperatorProvider}, provides the actual {@link BuilderOperator} generating logic.
*
* @author sunqian
*/
@ThreadSafe
interface Handler {
/**
* Creates and returns a new {@link BuilderOperator} for the target type, or {@code null} if the target type is
* unsupported.
*
* @param target the target type
* @return a new {@link BuilderOperator}, or {@code null} if the target type is unsupported
* @throws Exception if an error occurs
*/
@Nullable
BuilderOperator newOperator(@Nonnull Type target) throws Exception;
}
}