diff --git a/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginLoader.java b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginLoader.java new file mode 100644 index 0000000..f6b7f70 --- /dev/null +++ b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginLoader.java @@ -0,0 +1,7 @@ +package com.g2forge.habitat.plugin; + +import com.g2forge.alexandria.adt.collection.ICollection; + +public interface IPluginLoader

{ + public ICollection load(); +} diff --git a/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginService.java b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginService.java new file mode 100644 index 0000000..1a80150 --- /dev/null +++ b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginService.java @@ -0,0 +1,7 @@ +package com.g2forge.habitat.plugin; + +import com.g2forge.alexandria.adt.collection.ICollection; + +public interface IPluginService { + public ICollection> load(); +} diff --git a/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginSystem.java b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginSystem.java new file mode 100644 index 0000000..e8a8ce1 --- /dev/null +++ b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/IPluginSystem.java @@ -0,0 +1,5 @@ +package com.g2forge.habitat.plugin; + +public interface IPluginSystem { + public

IPluginLoader

load(Class

type); +} diff --git a/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginDescriptor.java b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginDescriptor.java new file mode 100644 index 0000000..8013288 --- /dev/null +++ b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginDescriptor.java @@ -0,0 +1,33 @@ +package com.g2forge.habitat.plugin; + +import java.util.List; + +import com.g2forge.alexandria.java.function.IConsumer2; +import com.g2forge.alexandria.java.function.IFunction1; +import com.g2forge.alexandria.java.function.ISupplier; + +import lombok.Builder; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.Singular; + +@Data +@Builder(toBuilder = true) +@RequiredArgsConstructor +public class PluginDescriptor { + @Data + @Builder(toBuilder = true) + @RequiredArgsConstructor + public static class Dependency { + protected final Class type; + + protected final IConsumer2 callback; + } + + @Singular + protected final List> dependencies; + + protected final ISupplier constructor; + + protected final IFunction1 builder; +} diff --git a/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginSystem.java b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginSystem.java new file mode 100644 index 0000000..5cb63c5 --- /dev/null +++ b/ha-plugin/src/main/java/com/g2forge/habitat/plugin/PluginSystem.java @@ -0,0 +1,44 @@ +package com.g2forge.habitat.plugin; + +import java.util.ArrayList; +import java.util.List; + +import com.g2forge.alexandria.adt.collection.DStreamCollection; +import com.g2forge.alexandria.adt.collection.ICollection; +import com.g2forge.alexandria.annotations.note.Note; +import com.g2forge.alexandria.annotations.note.NoteType; +import com.g2forge.alexandria.java.function.ISupplier; +import com.g2forge.alexandria.java.type.ref.ITypeRef; +import com.g2forge.alexandria.service.BasicServiceLoader; +import com.g2forge.alexandria.service.IServiceLoader; + +import lombok.Getter; + +public class PluginSystem implements IPluginSystem { + @Getter(lazy = true) + private static final IPluginSystem standard = new PluginSystem(); + + @Note(type = NoteType.TODO, issue = "G2-1628") + protected P instantiate(PluginDescriptor descriptor) { + final ISupplier constructor = descriptor.getConstructor(); + final B builder = constructor.get(); + return descriptor.getBuilder().apply(builder); + } + + @Override + public

IPluginLoader

load(Class

type) { + return new IPluginLoader

() { + @Override + public ICollection load() { + final IServiceLoader loader = new BasicServiceLoader<>(IPluginService.class); + final List plugins = new ArrayList<>(); + for (IPluginService pluginService : loader.load()) { + for (PluginDescriptor descriptor : pluginService.load()) { + plugins.add(instantiate(descriptor)); + } + } + return (DStreamCollection) (() -> plugins.stream().flatMap(ITypeRef.of(type)::castIfInstance)); + } + }; + } +} diff --git a/ha-plugin/src/test/java/com/g2forge/habitat/plugin/PluginService.java b/ha-plugin/src/test/java/com/g2forge/habitat/plugin/PluginService.java new file mode 100644 index 0000000..755b6be --- /dev/null +++ b/ha-plugin/src/test/java/com/g2forge/habitat/plugin/PluginService.java @@ -0,0 +1,19 @@ +package com.g2forge.habitat.plugin; + +import com.g2forge.alexandria.adt.collection.CollectionCollection; +import com.g2forge.alexandria.adt.collection.ICollection; +import com.g2forge.alexandria.annotations.service.Service; +import com.g2forge.alexandria.java.core.helpers.HCollection; +import com.g2forge.alexandria.java.function.IFunction1; +import com.g2forge.habitat.plugin.TestPluginSystem.Plugin; + +@Service(IPluginService.class) +public class PluginService implements IPluginService { + @Override + public ICollection> load() { + final PluginDescriptor.PluginDescriptorBuilder retVal = PluginDescriptor.builder(); + retVal.constructor(Plugin::create); + retVal.builder(IFunction1.identity()); + return new CollectionCollection<>(HCollection.asList(retVal.build())); + } +} \ No newline at end of file diff --git a/ha-plugin/src/test/java/com/g2forge/habitat/plugin/TestPluginSystem.java b/ha-plugin/src/test/java/com/g2forge/habitat/plugin/TestPluginSystem.java new file mode 100644 index 0000000..bd89038 --- /dev/null +++ b/ha-plugin/src/test/java/com/g2forge/habitat/plugin/TestPluginSystem.java @@ -0,0 +1,23 @@ +package com.g2forge.habitat.plugin; + +import org.junit.Test; + +import com.g2forge.alexandria.java.core.helpers.HCollection; +import com.g2forge.alexandria.test.HAssert; + +public class TestPluginSystem { + public static class Plugin { + protected static final Plugin INSTANCE = new Plugin(); + + public static Plugin create() { + return INSTANCE; + } + + private Plugin() {} + } + + @Test + public void test() { + HAssert.assertEquals(HCollection.asList(Plugin.create()), PluginSystem.getStandard().load(Plugin.class).load().toCollection()); + } +}