From c49ee687277b16ebd1402245160a73d5013f6f51 Mon Sep 17 00:00:00 2001 From: Preston Cabe Date: Fri, 28 Feb 2025 10:57:00 -0500 Subject: [PATCH 1/2] WIP relates to #60 --- .../prestoncabe/generators/DMNLayoutTool.java | 44 ++++++ .../generators/SimpleKogitoDMNExample.java | 146 ++++++++++++++++++ src/main/resources/addFive.dmn | 18 +++ src/main/resources/discount-calculator.dmn | 41 +++++ 4 files changed, 249 insertions(+) create mode 100644 src/main/java/org/prestoncabe/generators/DMNLayoutTool.java create mode 100644 src/main/java/org/prestoncabe/generators/SimpleKogitoDMNExample.java create mode 100644 src/main/resources/addFive.dmn create mode 100644 src/main/resources/discount-calculator.dmn diff --git a/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java b/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java new file mode 100644 index 0000000..baaef8b --- /dev/null +++ b/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java @@ -0,0 +1,44 @@ +package org.prestoncabe.generators; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.file.Paths; + +import org.kie.dmn.api.marshalling.DMNMarshaller; +import org.kie.dmn.backend.marshalling.v1x.DMNMarshallerFactory; +import org.kie.dmn.model.api.Definitions; +import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess; +import org.kie.kogito.serverless.workflow.parser.ServerlessWorkflowParser; +import org.kie.kogito.serverless.workflow.utils.ServerlessWorkflowUtils; + +public class DMNLayoutAdder { + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.out.println("Usage: java DMNLayoutAdder [output.dmn]"); + return; + } + + String inputPath = args[0]; + String outputPath = args.length > 1 ? args[1] : inputPath.replace(".dmn", "-with-layout.dmn"); + + // Load DMN file + DMNMarshaller marshaller = DMNMarshallerFactory.newDefaultMarshaller(); + Definitions definitions = marshaller.unmarshal(new FileInputStream(inputPath)); + + // The layout service is typically used by the editor, but we can use its components + // In Kogito 1.44.1, we need to use internal APIs to generate layout + + // This is a simplified version - the internal API has changed in Kogito 1.44.1 + // Add layout information + org.kie.dmn.feel.util.Pair + dmndi = org.kie.dmn.core.internal.utils.DMNDIUtils.generateDMNDI(definitions); + definitions.setDMNDI(dmndi.getLeft()); + + // Save the file with layout + try (FileOutputStream fos = new FileOutputStream(outputPath)) { + marshaller.marshal(definitions, fos); + } + + System.out.println("Layout added to " + outputPath); + } +} \ No newline at end of file diff --git a/src/main/java/org/prestoncabe/generators/SimpleKogitoDMNExample.java b/src/main/java/org/prestoncabe/generators/SimpleKogitoDMNExample.java new file mode 100644 index 0000000..f6f66d4 --- /dev/null +++ b/src/main/java/org/prestoncabe/generators/SimpleKogitoDMNExample.java @@ -0,0 +1,146 @@ +package org.prestoncabe.generators; + +import org.kie.dmn.model.v1_2.*; +import org.kie.dmn.model.v1_2.dmndi.*; +import org.kie.dmn.backend.marshalling.v1x.DMNMarshallerFactory; +import javax.xml.namespace.QName; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; + +public class SimpleKogitoDMNExample { + public static void main(String[] args) { + // Load the sample file to see how it structures QNames + try { + // Generate unique IDs + String modelId = "_" + UUID.randomUUID().toString().toUpperCase(); + String modelName = "discount_calculator"; + String namespaceURI = "https://kiegroup.org/dmn/" + UUID.randomUUID().toString(); + + // Create the DMN model definition + TDefinitions definitions = new TDefinitions(); + definitions.setId(modelId); + definitions.setName(modelName); + definitions.setNamespace(namespaceURI); + + // Set required namespaces + definitions.setTypeLanguage("http://www.omg.org/spec/DMN/20180521/FEEL/"); + definitions.getNsContext().put("dmn", "http://www.omg.org/spec/DMN/20180521/MODEL/"); + definitions.getNsContext().put("feel", "http://www.omg.org/spec/DMN/20180521/FEEL/"); + definitions.getNsContext().put("kie", "http://www.drools.org/kie/dmn/1.2"); + definitions.getNsContext().put("dmndi", "http://www.omg.org/spec/DMN/20180521/DMNDI/"); + definitions.getNsContext().put("di", "http://www.omg.org/spec/DMN/20180521/DI/"); + definitions.getNsContext().put("dc", "http://www.omg.org/spec/DMN/20180521/DC/"); + + // Create input data node + TInputData purchaseAmountInput = new TInputData(); + String purchaseInputId = "_" + UUID.randomUUID().toString().toUpperCase(); + purchaseAmountInput.setId(purchaseInputId); + purchaseAmountInput.setName("Purchase Amount"); + + // Create input variable + TInformationItem purchaseVariable = new TInformationItem(); + purchaseVariable.setId("_" + UUID.randomUUID().toString().toUpperCase()); + purchaseVariable.setName("Purchase Amount"); + purchaseVariable.setTypeRef(new QName("number")); + purchaseAmountInput.setVariable(purchaseVariable); + + // Create decision node + TDecision discountDecision = new TDecision(); + String decisionId = "_" + UUID.randomUUID().toString().toUpperCase(); + discountDecision.setId(decisionId); + discountDecision.setName("Discount Amount"); + + // Create decision variable + TInformationItem decisionVariable = new TInformationItem(); + decisionVariable.setId("_" + UUID.randomUUID().toString().toUpperCase()); + decisionVariable.setName("Discount Amount"); + decisionVariable.setTypeRef(new QName("number")); + discountDecision.setVariable(decisionVariable); + + // Create literal expression + TLiteralExpression expression = new TLiteralExpression(); + String expressionId = "_" + UUID.randomUUID().toString().toUpperCase(); + expression.setId(expressionId); + expression.setText("if Purchase Amount > 100 then Purchase Amount * 0.1 else 0"); + discountDecision.setExpression(expression); + + // Create information requirement + TInformationRequirement requirement = new TInformationRequirement(); + String requirementId = "_" + UUID.randomUUID().toString().toUpperCase(); + requirement.setId(requirementId); + TDMNElementReference reference = new TDMNElementReference(); + reference.setHref("#" + purchaseInputId); + requirement.setRequiredInput(reference); + discountDecision.getInformationRequirement().add(requirement); + + // Add nodes to definitions + definitions.getDrgElement().add(purchaseAmountInput); + definitions.getDrgElement().add(discountDecision); + + // Marshal to XML + String dmnXML = DMNMarshallerFactory.newDefaultMarshaller().marshal(definitions); + + // Add DMNDI using string manipulation + String dmndiXml = createDMNDI(purchaseInputId, decisionId, requirementId); + dmnXML = dmnXML.replace("", dmndiXml + "\n"); + + // Save the file + Path resourcesPath = Paths.get("src", "main", "resources"); + Files.createDirectories(resourcesPath); + File dmnFile = new File(resourcesPath.toFile(), "discount-calculator.dmn"); + + try (FileWriter writer = new FileWriter(dmnFile)) { + writer.write(dmnXML); + System.out.println("DMN file saved to: " + dmnFile.getAbsolutePath()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static String createDMNDI(String inputId, String decisionId, String requirementId) { + StringBuilder dmndi = new StringBuilder(); + + dmndi.append(" \n"); + dmndi.append(" \n"); + + // Input shape + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + + // Decision shape + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + + // Edge + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + dmndi.append(" \n"); + + dmndi.append(" \n"); + dmndi.append(" "); + + return dmndi.toString(); + } +} \ No newline at end of file diff --git a/src/main/resources/addFive.dmn b/src/main/resources/addFive.dmn new file mode 100644 index 0000000..52d57c1 --- /dev/null +++ b/src/main/resources/addFive.dmn @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + inputNumber + 5 + + + \ No newline at end of file diff --git a/src/main/resources/discount-calculator.dmn b/src/main/resources/discount-calculator.dmn new file mode 100644 index 0000000..9269914 --- /dev/null +++ b/src/main/resources/discount-calculator.dmn @@ -0,0 +1,41 @@ + + + + + + + + + + + + if Purchase Amount > 100 then Purchase Amount * 0.1 else 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 832ecfd24155d539d711b5006719c63127eb4af1 Mon Sep 17 00:00:00 2001 From: Preston Cabe Date: Fri, 28 Feb 2025 15:21:10 -0500 Subject: [PATCH 2/2] remove broken layout code --- .../prestoncabe/generators/DMNLayoutTool.java | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/main/java/org/prestoncabe/generators/DMNLayoutTool.java diff --git a/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java b/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java deleted file mode 100644 index baaef8b..0000000 --- a/src/main/java/org/prestoncabe/generators/DMNLayoutTool.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.prestoncabe.generators; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.nio.file.Paths; - -import org.kie.dmn.api.marshalling.DMNMarshaller; -import org.kie.dmn.backend.marshalling.v1x.DMNMarshallerFactory; -import org.kie.dmn.model.api.Definitions; -import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess; -import org.kie.kogito.serverless.workflow.parser.ServerlessWorkflowParser; -import org.kie.kogito.serverless.workflow.utils.ServerlessWorkflowUtils; - -public class DMNLayoutAdder { - public static void main(String[] args) throws Exception { - if (args.length < 1) { - System.out.println("Usage: java DMNLayoutAdder [output.dmn]"); - return; - } - - String inputPath = args[0]; - String outputPath = args.length > 1 ? args[1] : inputPath.replace(".dmn", "-with-layout.dmn"); - - // Load DMN file - DMNMarshaller marshaller = DMNMarshallerFactory.newDefaultMarshaller(); - Definitions definitions = marshaller.unmarshal(new FileInputStream(inputPath)); - - // The layout service is typically used by the editor, but we can use its components - // In Kogito 1.44.1, we need to use internal APIs to generate layout - - // This is a simplified version - the internal API has changed in Kogito 1.44.1 - // Add layout information - org.kie.dmn.feel.util.Pair - dmndi = org.kie.dmn.core.internal.utils.DMNDIUtils.generateDMNDI(definitions); - definitions.setDMNDI(dmndi.getLeft()); - - // Save the file with layout - try (FileOutputStream fos = new FileOutputStream(outputPath)) { - marshaller.marshal(definitions, fos); - } - - System.out.println("Layout added to " + outputPath); - } -} \ No newline at end of file