diff options
Diffstat (limited to 'module/ri-engine/src/main/java/io/trygvis/rules/engine')
8 files changed, 221 insertions, 71 deletions
diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java index b8ee03a..d3d309a 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java @@ -14,6 +14,8 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import org.drools.core.common.DefaultFactHandle; import org.drools.core.factmodel.GeneratedFact; import org.kie.api.KieBase; +import org.kie.api.definition.type.FactType; +import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.rule.FactHandle; import java.io.File; @@ -29,14 +31,14 @@ public class DbIo { private static final List<String> prioritizedKeys = List.of("key", "name", "fqdn"); - public DbIo(KieBase kieBase) { + public DbIo(KieContainer container, KieBase kieBase) { var factory = new YAMLFactory(); factory.enable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID); factory.enable(YAMLGenerator.Feature.USE_NATIVE_OBJECT_ID); mapper = new ObjectMapper(factory); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); var typeFactory = TypeFactory.defaultInstance() - .withClassLoader(new AcmeClassLoader(kieBase)); + .withClassLoader(new DbClassLoader(container, kieBase)); mapper.setTypeFactory(typeFactory); mapper.findAndRegisterModules(); @@ -50,7 +52,7 @@ public class DbIo { for (String name : prioritizedKeys) { try { final String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); - var f = klass.getMethod(getter); + klass.getMethod(getter); return new ObjectIdInfo(PropertyName.construct(name), null, ObjectIdGenerators.PropertyGenerator.class, null); } catch (NoSuchMethodException ignore) { } @@ -64,8 +66,8 @@ public class DbIo { }); } - public List<Object> load(String file) throws IOException { - var parser = mapper.getFactory().createParser(new File(file)); + public List<Object> load(File file) throws IOException { + var parser = mapper.getFactory().createParser(file); var objects = mapper.readValues(parser, DbObject.class).readAll(new ArrayList<>()); @@ -79,6 +81,8 @@ public class DbIo { } items.add(x); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + System.out.println("e.getClass() = " + e.getClass().getName()); + System.out.println("e.getMessage() = " + e.getMessage()); // ignore } } @@ -86,8 +90,8 @@ public class DbIo { return items; } - public void dump(String s, Collection<FactHandle> factHandles) throws IOException { - dump(s, factHandles, (o) -> true); + public void dump(File file, Collection<FactHandle> factHandles) throws IOException { + dump(file, factHandles, (o) -> true); } // This should just sort by all getters instead. @@ -221,10 +225,8 @@ public class DbIo { static record DbObject2(String type, Object data) { } - public void dump(String s, Collection<FactHandle> factHandles, Function<Object, Boolean> filter) throws IOException { - var yamlFile = new File("out", s + ".yaml"); - - FileUtil.createMissingParentDirectories(yamlFile); + public void dump(File file, Collection<FactHandle> factHandles, Function<Object, Boolean> filter) throws IOException { + FileUtil.createMissingParentDirectories(file); var facts = new TreeMap<Class<?>, FactCollection<Object>>(Comparator.comparing(Class::getName)); for (var handle : factHandles) { @@ -260,16 +262,18 @@ public class DbIo { objects.sort(new DbObjectComparator()); var factory = mapper.getFactory(); - try (var writer = new FileWriter(yamlFile); + try (var writer = new FileWriter(file); var g = factory.createGenerator(writer)) { g.writeObject(objects); } } - private static class AcmeClassLoader extends ClassLoader { + private static class DbClassLoader extends ClassLoader { private final KieBase kieBase; + private final KieContainer container; - public AcmeClassLoader(KieBase kieBase) { + public DbClassLoader(KieContainer container, KieBase kieBase) { + this.container = container; this.kieBase = kieBase; } @@ -287,7 +291,18 @@ public class DbIo { pkg = name.substring(0, i); klass = name.substring(i + 1); } - var clazz = kieBase.getFactType(pkg, klass); + + try { + return container.getClassLoader().loadClass(name); + } catch (ClassNotFoundException ignore) { + } + + FactType clazz = null; + try { + clazz = kieBase.getFactType(pkg, klass); + } catch (UnsupportedOperationException ignore) { + System.out.println("AcmeClassLoader.loadClass: " + name); + } if (clazz == null) { throw e; } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java index b73e2e8..3db1625 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java @@ -2,41 +2,83 @@ package io.trygvis.rules.engine; import org.drools.core.audit.WorkingMemoryConsoleLogger; import org.kie.api.KieServices; +import org.kie.api.builder.Message; +import org.kie.api.builder.Message.Level; +import org.kie.api.builder.ReleaseId; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.RuleRuntimeEventListener; import org.kie.api.runtime.KieSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.File; import java.io.IOException; public class Engine implements Closeable { + private final Logger logger = LoggerFactory.getLogger(getClass()); + public final DbIo io; public final KieSession session; - public Engine(String name, String database, File output, String[] agendaGroups) throws IOException { + public Engine(String name, File database, File output, String[] agendaGroups, File[] modules) throws IOException { + logger.info("Getting KieServices"); + var services = KieServices.Factory.get(); - var container = services.getKieClasspathContainer(); - var kieBase = container.getKieBase(name); - io = new DbIo(kieBase); - var objects = io.load(database); + ReleaseId releaseId = null; + for (File path : (modules == null ? new File[0] : modules)) { + logger.info("New KieBuilder: {}", path); + + +// var kieBuilder = services.newKieBuilder(fileSystem); + var kieBuilder = services.newKieBuilder(path); + logger.info("Building module"); + kieBuilder.buildAll(); + + logger.info("Module built!"); + + var results = kieBuilder.getResults(); + + for (Message message : results.getMessages(Level.INFO, Level.WARNING, Level.ERROR)) { +// logger.info("{} {}", message.getLevel(), message.getText()); + logger.info(message.toString()); + } + + var module = kieBuilder.getKieModule(); + releaseId = module.getReleaseId(); + logger.info("module.getReleaseId() = {}", releaseId); + logger.info("module.getClass() = {}", module.getClass()); + } + + logger.info("Creating classpath container"); +// var container = services.getKieClasspathContainer(); + var container = services.newKieContainer(releaseId); + + logger.info("Creating KieBase"); + logger.info("Available kie base names: {}", container.getKieBaseNames()); + var kieBase = container.getKieBase(name); session = container.newKieSession(name); - var logger = new WorkingMemoryConsoleLogger(session); - session.addEventListener((AgendaEventListener) logger); - session.addEventListener((RuleRuntimeEventListener) logger); + var l = new WorkingMemoryConsoleLogger(session); + session.addEventListener((AgendaEventListener) l); + session.addEventListener((RuleRuntimeEventListener) l); - session.setGlobal("te", new TemplateEngine(output)); + session.setGlobal("te", new JinjavaTemplateEngine(output)); + + logger.info("Loading data"); + io = new DbIo(container, kieBase); + var objects = io.load(database); + logger.info("Loaded {} objects", objects.size()); for (var object : objects) { - System.out.println("object = " + object); + logger.info("object = " + object); session.insert(object); } for (var agendaGroup : agendaGroups) { - System.out.println("Setting agenda: " + agendaGroup); + logger.info("Setting agenda: " + agendaGroup); session.getAgenda().getAgendaGroup(agendaGroup).setFocus(); session.fireAllRules(); } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java new file mode 100644 index 0000000..42b2127 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java @@ -0,0 +1,40 @@ +package io.trygvis.rules.engine; + +import ch.qos.logback.core.util.FileUtil; +import com.hubspot.jinjava.Jinjava; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +public class JinjavaTemplateEngine implements TemplateEngine { + private final Jinjava jinjava = new Jinjava(); + + private final File basedir; + + public JinjavaTemplateEngine(File basedir) { + this.basedir = basedir; + } + + @Override + public void clean() { + try { + System.out.println("Cleaning gen!"); + FileUtils.deleteDirectory(basedir); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void template(String name, String output, Map<String, Object> params) throws IOException { + var template = Files.readString(Path.of("j2", name + ".j2")); + String renderedTemplate = jinjava.render(template, params); + var f = new File(basedir, output); + FileUtil.createMissingParentDirectories(f); + Files.writeString(f.toPath(), renderedTemplate); + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java deleted file mode 100644 index 5046169..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.trygvis.rules.engine; - -public class KeyValue { - public String key; - public String value; - - public KeyValue() { - } - - public KeyValue(String key, String value) { - this.key = key; - this.value = value; - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java new file mode 100644 index 0000000..4f06091 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java @@ -0,0 +1,20 @@ +package io.trygvis.rules.engine; + +import io.trygvis.rules.engine.cli.DatabaseCommand; +import io.trygvis.rules.engine.cli.RunCommand; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +@Command( + name = "engine", + subcommands = {RunCommand.class, DatabaseCommand.class}, + mixinStandardHelpOptions = true, + version = "UNSPECIFIED") +class Main { + + public static void main(String... args) { + //noinspection InstantiationOfUtilityClass + int exitCode = new CommandLine(new Main()).execute(args); + System.exit(exitCode); + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java index cc085c0..eafa6e4 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java @@ -1,38 +1,10 @@ package io.trygvis.rules.engine; -import ch.qos.logback.core.util.FileUtil; -import com.hubspot.jinjava.Jinjava; -import org.apache.commons.io.FileUtils; - -import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Map; -public class TemplateEngine { - private final Jinjava jinjava = new Jinjava(); - - private final File basedir; - - public TemplateEngine(File basedir) { - this.basedir = basedir; - } - - public void clean() { - try { - System.out.println("Cleaning gen!"); - FileUtils.deleteDirectory(basedir); - } catch (IOException e) { - throw new RuntimeException(e); - } - } +public interface TemplateEngine { + void clean(); - public void template(String name, String output, Map<String, Object> params) throws IOException { - var template = Files.readString(Path.of("j2", name + ".j2")); - String renderedTemplate = jinjava.render(template, params); - var f = new File(basedir, output); - FileUtil.createMissingParentDirectories(f); - Files.writeString(f.toPath(), renderedTemplate); - } + void template(String name, String output, Map<String, Object> params) throws IOException; } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java new file mode 100644 index 0000000..03650b5 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java @@ -0,0 +1,20 @@ +package io.trygvis.rules.engine.cli; + +import picocli.CommandLine.Command; + +import java.util.concurrent.Callable; + +import static picocli.CommandLine.Option; + +@Command(name = "database") +public class DatabaseCommand implements Callable<Integer> { + + @Option(names = {"-v", "--verbose"}) + private boolean verbose; + + @Override + public Integer call() { + System.out.println("DatabaseCommand.call"); + return 0; + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java new file mode 100644 index 0000000..345d8b8 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java @@ -0,0 +1,55 @@ +package io.trygvis.rules.engine.cli; + +import io.trygvis.rules.engine.Engine; + +import java.io.File; +import java.util.concurrent.Callable; + +import static picocli.CommandLine.Command; +import static picocli.CommandLine.Option; + +@Command(name = "run") +public class RunCommand implements Callable<Integer> { + + @Option(names = {"-n", "--name"}) + public String name; + + @Option(names = {"-i", "--input"}) + public File input; + + @Option(names = {"--output-state"}) + public File outputState; + + @Option(names = {"--generated-output"}) + public File generatedOutput; + + @Option(names = {"--agenda-groups"}) + public String[] agendaGroups; + + @Option(names = {"--modules"}, split = ",") + public File[] modules; + + @Override + public Integer call() throws Exception { + System.out.println("RunCommand.call"); + + if (agendaGroups == null || agendaGroups.length == 0) { + agendaGroups = new String[]{"init", "generate"}; + } + + try (var engine = new Engine(name, input, generatedOutput, agendaGroups, modules)) { + engine.io.dump(outputState, engine.session.getFactHandles(), (Object o) -> + o.getClass().getName().contains("Wg") || + o.getClass().getSimpleName().contains("Machine") || + o.getClass().getSimpleName().contains("DnsEntry") || + o.getClass().getSimpleName().contains("Ipv4Cidr") || + o.getClass().getSimpleName().contains("Ipv4Address") + ); + System.out.println("RunCommand.call"); + } + + System.out.println("RunCommand.call"); + + return 0; + } +} |