Skip to content

Commit

Permalink
Merge pull request #47 from gdgib/G2-1624-BasicPlugins
Browse files Browse the repository at this point in the history
G2-1624 Implement basic plugins
  • Loading branch information
gdgib authored Aug 23, 2024
2 parents 773f9e3 + 26e82dc commit 7a6b931
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.g2forge.habitat.plugin;

import com.g2forge.alexandria.adt.collection.ICollection;

public interface IPluginLoader<P> {
public ICollection<? extends P> load();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.g2forge.habitat.plugin;

import com.g2forge.alexandria.adt.collection.ICollection;

public interface IPluginService {
public ICollection<PluginDescriptor<?, ?>> load();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.g2forge.habitat.plugin;

public interface IPluginSystem {
public <P> IPluginLoader<P> load(Class<P> type);
}
Original file line number Diff line number Diff line change
@@ -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<P, B> {
@Data
@Builder(toBuilder = true)
@RequiredArgsConstructor
public static class Dependency<T, U> {
protected final Class<U> type;

protected final IConsumer2<? super T, ? super U> callback;
}

@Singular
protected final List<Dependency<B, ?>> dependencies;

protected final ISupplier<B> constructor;

protected final IFunction1<? super B, ? extends P> builder;
}
Original file line number Diff line number Diff line change
@@ -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, B> P instantiate(PluginDescriptor<P, B> descriptor) {
final ISupplier<B> constructor = descriptor.getConstructor();
final B builder = constructor.get();
return descriptor.getBuilder().apply(builder);
}

@Override
public <P> IPluginLoader<P> load(Class<P> type) {
return new IPluginLoader<P>() {
@Override
public ICollection<? extends P> load() {
final IServiceLoader<IPluginService> loader = new BasicServiceLoader<>(IPluginService.class);
final List<Object> plugins = new ArrayList<>();
for (IPluginService pluginService : loader.load()) {
for (PluginDescriptor<?, ?> descriptor : pluginService.load()) {
plugins.add(instantiate(descriptor));
}
}
return (DStreamCollection<? extends P>) (() -> plugins.stream().flatMap(ITypeRef.of(type)::castIfInstance));
}
};
}
}
Original file line number Diff line number Diff line change
@@ -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<PluginDescriptor<?, ?>> load() {
final PluginDescriptor.PluginDescriptorBuilder<Plugin, Plugin> retVal = PluginDescriptor.builder();
retVal.constructor(Plugin::create);
retVal.builder(IFunction1.identity());
return new CollectionCollection<>(HCollection.asList(retVal.build()));
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit 7a6b931

Please sign in to comment.