org.jvault.extension.JvaultRuntimeExtension Maven / Gradle / Ivy
package org.jvault.extension;
import org.jvault.factory.buildinfo.extensible.BeanReader;
import org.jvault.metadata.API;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Extension point of the Jvault library's behavior.
* If the client implements the extensiblepoint of Jvault library and passes it to this class,
* the behavior of the library is changed.
*
* Current extensiblepoints : {@link BeanReader}
* JvaultRuntimeExtension uses {@link Optional} to mean that no extension is given. Therefore, be careful not to pass type parameter {@link Optional}.
*
* @author devxb
* @since 0.1
*/
@API
public final class JvaultRuntimeExtension {
private final static JvaultRuntimeExtension INSTANCE = new JvaultRuntimeExtension();
private final static ConcurrentMap, Object> EXPANDED;
static {
EXPANDED = new ConcurrentHashMap<>();
EXPANDED.put(BeanReader.class, Optional.empty());
}
private JvaultRuntimeExtension() {}
/**
* Receive extensiblepoint implementation of Jvault and change library behavior.
*
* If a non-extensible type parameter is passed, an {@link IllegalArgumentException} is thrown.
*
* @param instance the instance of ExtensiblePoint
* @param type the class type of ExtensiblePoint
* @param the real type of ExtensiblePoint
* @author devxb
* @since 0.1
*/
public static void extend(T instance, Class type) {
INSTANCE.throwIfIsNotExtensible(type);
EXPANDED.replace(type, instance);
}
/**
* Receive extensiblepoint implementation of Jvault and reset to the default implementation of the Jvault library.
*
* Ignored if there is no ExtensiblePoint implementation corresponding to the passed parameter.
*
* @param type the class type of ExtensiblePoint
* @param the real type of ExtensiblePoint
* @author devxb
* @since 0.1
*/
public static void reset(Class type) {
try {
EXPANDED.replace(type, Optional.empty());
} catch (NullPointerException ignored) {
}
}
/**
* Reset all registered extensiblepoint implementations to the Jvault default implementations of extensiblepoint.
*
* @author devxb
* @since 0.1
*/
public static void resetAll() {
EXPANDED.replaceAll((k, v) -> Optional.empty());
}
static JvaultRuntimeExtension getInstance() {
return INSTANCE;
}
/**
* Internal API.
* Jvault libraries accessible to JvaultRuntimeExtension are used to obtain extension implementations.
*
* @param cls the class type of ExtensiblePoint
* @param the real type of ExtensiblePoint
* @return T Implement of ExtensiblePoint.
*/
public T getExtension(Class cls) {
throwIfIsNotExtensible(cls);
if (EXPANDED.get(cls).getClass() == Optional.class) return null;
return cls.cast(EXPANDED.get(cls));
}
private void throwIfIsNotExtensible(Class type) {
if (EXPANDED.containsKey(type)) return;
throw new IllegalArgumentException("Cannot be expanded cause there is no extension point that matched \"" + type + "\"");
}
}