Usage
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.junit.jupiter.api.Test;
import kiss.Extensible;
import kiss.I;
public class ExtensionTest {
/**
* This is extension point.
*/
interface Codec<T> extends Extensible {
String encode(T value);
}
/**
* This is extension with LocalDate key.
*/
class LocalDateCodec implements Codec<LocalDate> {
public String encode(LocalDate value) {
return DateTimeFormatter.ISO_DATE.format(value);
}
}
/**
* Load all extensions once at application's entry point.
*/
static {
I.load(ExtensionTest.class);
}
/**
* User code.
*/
@Test
void usage() {
// find extension by type
Codec<LocalDate> codec = I.find(Codec.class, LocalDate.class);
assert codec.encode(LocalDate.of(2022, 11, 11)).equals("2022-11-11");
}
}
Extension Point
Sinobu has a general-purpose plug-in mechanism for extending application functions.
An
extensible place is called Extension Point, and its substance is a type (interface or
class) marked with the Extensible
interface.
We give a definition of Extension Point like the following.
- It implements
Extensible
interface directly.
interface ThisIsExtensionPoint extends Extensible {
}
class ThisIsAlsoExtensionPoint implements Extensible {
// This class is both Extension Point and Extension.
}
interface ThisIsNotExtensionPoint extends ThisIsExtensionPoint {
}
In the usage example, Codec is the extension point that converts any object to a string representation.
interface Codec<T> extends Extensible {
String encode(T value);
}
Extension
We give a definition of Extension like the following.
- It implements any Extension Point or is Extension Point itself.
- It must be concrete class and has a suitable constructor for Sinobu (see also
I#make(Class)
method).
class ThisIsExtension implements Extensible {
// This class is both Extension Point and Extension.
}
class ThisIsAlsoExtension extends ThisIsExtension {
// But not Extension Point.
}
class ThisIsNotExtension extends ThisIsExtension {
public ThisIsNotExtension(NotInjectable object) {
// because of invalid constructor
}
}
In the usage example, LocalDateCodec is the extension that is special implementation
for
LocalDate
.
class LocalDateCodec implements Codec<LocalDate> {
public String encode(LocalDate value) {
return DateTimeFormatter.ISO_DATE.format(value);
}
}
Extension Key
You can provide Extension Key for each Extensions by using parameter.
interface ExtensionPointWithKey<K> extends Extensible {
}
class ExtensionWithStringKey implements ExtensionPointWithKey<String> {
// Associate this Extension with String class.
}
class ExtensionWithListKey implements ExtensionPointWithKey<List> {
// Associate this Extension with List interface.
}
The key makes easy finding an Extension you need (see also
I#find(Class, Class)
).
void findExtensionByKey() {
assert I.find(ExtensionPointWithKey.class, String.class) instanceof ExtensionWithStringKey;
}
Dynamic Loading
All extensions are not recognized automatically, you have to load them explicitly
using
I#load(Class)
.
class ExtensionUser {
static {
I.load(ExtensionUser.class);
}
// write your code
}
class ApplicationMain {
public static void main(String[] args) {
I.load(ApplicationMain.class);
// start your application
}
}