This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch df
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9b664d32bb8a041c0959a232f4ec0dd13ef1aef8
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Tue Oct 29 14:08:30 2024 +0100

    CAMEL-21391: Add support for <dataFormats> in model to xml dumper
---
 .../org/apache/camel/spi/ModelToXMLDumper.java     | 11 +++
 .../camel/impl/DefaultDumpRoutesStrategy.java      | 41 +++++++++++
 .../org/apache/camel/xml/LwModelToXMLDumper.java   | 75 +++++++++++++++++++
 .../java/org/apache/camel/xml/out/BaseWriter.java  |  4 +-
 .../camel/xml/jaxb/JaxbModelToXMLDumper.java       | 84 ++++++++++++++++++++++
 .../dsl/jbang/core/commands/TransformRoute.java    | 17 ++---
 6 files changed, 223 insertions(+), 9 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ModelToXMLDumper.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/ModelToXMLDumper.java
index 4c41645a4d1..951f3da64d0 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ModelToXMLDumper.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ModelToXMLDumper.java
@@ -17,6 +17,7 @@
 package org.apache.camel.spi;
 
 import java.util.List;
+import java.util.Map;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.NamedNode;
@@ -65,4 +66,14 @@ public interface ModelToXMLDumper {
      */
     String dumpBeansAsXml(CamelContext context, List<Object> beans) throws 
Exception;
 
+    /**
+     * Dumps the global data formats as XML
+     *
+     * @param  context     the CamelContext
+     * @param  dataFormats list of data formats (DataFormatDefinition)
+     * @return             the output in XML (is formatted)
+     * @throws Exception is throw if error marshalling to XML
+     */
+    String dumpDataFormatsAsXml(CamelContext context, Map<String, Object> 
dataFormats) throws Exception;
+
 }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
index d3237e4210b..b89c8fb39ac 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
@@ -384,6 +384,18 @@ public class DefaultDumpRoutesStrategy extends 
ServiceSupport implements DumpRou
         }
     }
 
+    protected void doDumpXmlDataFormats(
+            CamelContext camelContext, Map dataFormats, Resource resource,
+            ModelToXMLDumper dumper, String kind, StringBuilder sbLocal, 
StringBuilder sbLog) {
+        try {
+            String dump = dumper.dumpDataFormatsAsXml(camelContext, 
dataFormats);
+            sbLocal.append(dump);
+            appendLogDump(resource, dump, sbLog);
+        } catch (Exception e) {
+            LOG.warn("Error dumping {}} to XML due to {}. This exception is 
ignored.", kind, e.getMessage(), e);
+        }
+    }
+
     protected void doDumpRoutesAsXml(CamelContext camelContext) {
         final ModelToXMLDumper dumper = 
PluginHelper.getModelToXMLDumper(camelContext);
         final Model model = 
camelContext.getCamelContextExtension().getContextPlugin(Model.class);
@@ -419,6 +431,35 @@ public class DefaultDumpRoutesStrategy extends 
ServiceSupport implements DumpRou
             }
         }
 
+        if (include.contains("*") || include.contains("all") || 
include.contains("dataFormats")) {
+            int size = model.getDataFormats().size();
+            if (size > 0) {
+                Map<Resource, Map<String, DataFormatDefinition>> groups = new 
LinkedHashMap<>();
+                for (Map.Entry<String, DataFormatDefinition> entry : 
model.getDataFormats().entrySet()) {
+                    Resource res = entry.getValue().getResource();
+                    if (res == null) {
+                        res = dummy;
+                    }
+                    Map<String, DataFormatDefinition> dfs = 
groups.computeIfAbsent(res, resource -> new LinkedHashMap<>());
+                    dfs.put(entry.getKey(), entry.getValue());
+                }
+                StringBuilder sbLog = new StringBuilder();
+                for (Map.Entry<Resource, Map<String, DataFormatDefinition>> 
entry : groups.entrySet()) {
+                    Map<String, DataFormatDefinition> dfs = entry.getValue();
+                    Resource resource = entry.getKey();
+
+                    StringBuilder sbLocal = new StringBuilder();
+                    doDumpXmlDataFormats(camelContext, dfs, resource == dummy 
? null : resource, dumper, "dataFormats", sbLocal, sbLog);
+                    // dump each resource into its own file
+                    doDumpToDirectory(resource, sbLocal, "dataFormats", "xml", 
files);
+                }
+                if (!sbLog.isEmpty() && log) {
+                    LOG.info("Dumping {} data formats as XML", size);
+                    LOG.info("{}", sbLog);
+                }
+            }
+        }
+
         if (include.contains("*") || include.contains("all") || 
include.contains("routes")) {
             int size = model.getRouteDefinitions().size();
             if (size > 0) {
diff --git 
a/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java 
b/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
index 92fc6489e1b..76dd36e1f30 100644
--- 
a/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
+++ 
b/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
@@ -31,7 +31,9 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Expression;
 import org.apache.camel.NamedNode;
+import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.model.BeanFactoryDefinition;
+import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.model.ExpressionNode;
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.OptionalIdentifiedDefinition;
@@ -41,6 +43,8 @@ import org.apache.camel.model.RouteTemplatesDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.SendDefinition;
 import org.apache.camel.model.ToDynamicDefinition;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
+import org.apache.camel.model.dataformat.DataFormatsDefinition;
 import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.spi.ModelToXMLDumper;
 import org.apache.camel.spi.NamespaceAware;
@@ -198,6 +202,29 @@ public class LwModelToXMLDumper implements 
ModelToXMLDumper {
         return buffer.toString();
     }
 
+    @Override
+    public String dumpDataFormatsAsXml(CamelContext context, Map<String, 
Object> dataFormats) throws Exception {
+        StringWriter buffer = new StringWriter();
+        DataFormatModelWriter writer = new DataFormatModelWriter(buffer);
+
+        Map<String, DataFormatDefinition> map = new LinkedHashMap<>();
+        for (Map.Entry<String, Object> entry : dataFormats.entrySet()) {
+            if (entry.getValue() instanceof DataFormatDefinition def) {
+                map.put(entry.getKey(), def);
+            }
+        }
+        writer.setCamelContext(context);
+        writer.start();
+        try {
+            writer.writeDataFormats(map);
+        } finally {
+            writer.stop();
+        }
+        buffer.write("\n");
+
+        return buffer.toString();
+    }
+
     /**
      * Extract all XML namespaces from the expressions in the route
      *
@@ -375,4 +402,52 @@ public class LwModelToXMLDumper implements 
ModelToXMLDumper {
         }
     }
 
+    private static class DataFormatModelWriter implements CamelContextAware {
+
+        private final StringWriter buffer;
+        private CamelContext camelContext;
+
+        public DataFormatModelWriter(StringWriter buffer) {
+            this.buffer = buffer;
+        }
+
+        @Override
+        public CamelContext getCamelContext() {
+            return camelContext;
+        }
+
+        @Override
+        public void setCamelContext(CamelContext camelContext) {
+            this.camelContext = camelContext;
+        }
+
+        public void start() {
+            // noop
+        }
+
+        public void stop() {
+            // noop
+        }
+
+        public void writeDataFormats(Map<String, DataFormatDefinition> 
dataFormats) throws Exception {
+            if (dataFormats.isEmpty()) {
+                return;
+            }
+
+            DataFormatsDefinition def = new DataFormatsDefinition();
+            def.setDataFormats(new ArrayList<>(dataFormats.values()));
+
+            StringWriter tmp = new StringWriter();
+            ModelWriter writer = new ModelWriter(tmp, null);
+            writer.writeDataFormatsDefinition(def);
+
+            // output with 4 space indent
+            for (String line : tmp.toString().split("\n")) {
+                buffer.write("    ");
+                buffer.write(line);
+                buffer.write("\n");
+            }
+        }
+    }
+
 }
diff --git 
a/core/camel-xml-io/src/main/java/org/apache/camel/xml/out/BaseWriter.java 
b/core/camel-xml-io/src/main/java/org/apache/camel/xml/out/BaseWriter.java
index 9a0ef341381..a8c4b779ce7 100644
--- a/core/camel-xml-io/src/main/java/org/apache/camel/xml/out/BaseWriter.java
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/out/BaseWriter.java
@@ -39,7 +39,9 @@ public class BaseWriter {
 
     public BaseWriter(Writer writer, String namespace) throws IOException {
         this.writer = new XMLWriter(writer);
-        this.namespacesStack.push(namespace);
+        if (namespace != null) {
+            this.namespacesStack.push(namespace);
+        }
     }
 
     protected void startElement(String name) throws IOException {
diff --git 
a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
 
b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
index 294e81c45f1..f12752fa7fe 100644
--- 
a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
+++ 
b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
@@ -36,6 +36,9 @@ import jakarta.xml.bind.Marshaller;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.TransformerException;
 
+import org.apache.camel.model.DataFormatDefinition;
+import org.apache.camel.model.dataformat.DataFormatsDefinition;
+import org.apache.camel.util.StringHelper;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -242,6 +245,29 @@ public class JaxbModelToXMLDumper implements 
ModelToXMLDumper {
         return buffer.toString();
     }
 
+    @Override
+    public String dumpDataFormatsAsXml(CamelContext context, Map<String, 
Object> dataFormats) throws Exception {
+        StringWriter buffer = new StringWriter();
+        DataFormatModelWriter writer = new DataFormatModelWriter(buffer);
+
+        Map<String, DataFormatDefinition> map = new LinkedHashMap<>();
+        for (Map.Entry<String, Object> entry : dataFormats.entrySet()) {
+            if (entry.getValue() instanceof DataFormatDefinition def) {
+                map.put(entry.getKey(), def);
+            }
+        }
+        writer.setCamelContext(context);
+        writer.start();
+        try {
+            writer.writeDataFormats(map);
+        } finally {
+            writer.stop();
+        }
+        buffer.write("\n");
+
+        return buffer.toString();
+    }
+
     private static void sanitizeXml(Node node, boolean generatedIds) {
         // we want to remove all customId="false" attributes as they are noisy
         if (node.hasAttributes()) {
@@ -358,4 +384,62 @@ public class JaxbModelToXMLDumper implements 
ModelToXMLDumper {
         }
     }
 
+    private static class DataFormatModelWriter implements CamelContextAware {
+
+        private final StringWriter buffer;
+        private CamelContext camelContext;
+
+        public DataFormatModelWriter(StringWriter buffer) {
+            this.buffer = buffer;
+        }
+
+        @Override
+        public CamelContext getCamelContext() {
+            return camelContext;
+        }
+
+        @Override
+        public void setCamelContext(CamelContext camelContext) {
+            this.camelContext = camelContext;
+        }
+
+        public void start() {
+            // noop
+        }
+
+        public void stop() {
+            // noop
+        }
+
+        public void writeDataFormats(Map<String, DataFormatDefinition> 
dataFormats) throws Exception {
+            if (dataFormats.isEmpty()) {
+                return;
+            }
+
+            DataFormatsDefinition def = new DataFormatsDefinition();
+            def.setDataFormats(new ArrayList<>(dataFormats.values()));
+
+            final JAXBContext jaxbContext = getJAXBContext(camelContext);
+
+            StringWriter tmp = new StringWriter();
+            Marshaller marshaller = jaxbContext.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, 
Boolean.TRUE);
+            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+            marshaller.marshal(def, tmp);
+
+            // remove unwanted namespace
+            String xml = tmp.toString();
+            xml = xml.replace("<dataFormats 
xmlns=\"http://camel.apache.org/schema/spring\";>", "<dataFormats>");
+            xml = StringHelper.after(xml, "<dataFormats>");
+
+            // output with 4 space indent
+            buffer.write("    <dataFormats>");
+            for (String line : xml.split("\n")) {
+                buffer.write("    ");
+                buffer.write(line);
+                buffer.write("\n");
+            }
+        }
+    }
+
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
index 586eacdaa7e..79bf8ad5d8d 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
@@ -45,9 +45,8 @@ public class TransformRoute extends CamelCommand {
     private String output;
 
     @CommandLine.Option(names = { "--format" },
-                        description = "Output format (xml or yaml), if only 
yaml files are provided, the format defaults to xml and vice versa",
-                        defaultValue = "yaml")
-    String format = "yaml";
+                        description = "Output format (xml or yaml), if only 
yaml files are provided, the format defaults to xml and vice versa")
+    String format;
 
     @CommandLine.Option(names = { "--resolve-placeholders" }, defaultValue = 
"false",
                         description = "Whether to resolve property 
placeholders in the dumped output")
@@ -68,11 +67,13 @@ public class TransformRoute extends CamelCommand {
 
     @Override
     public Integer doCall() throws Exception {
-        // Automatically transform to xml if all files are yaml
-        if (files.stream().allMatch(file -> file.endsWith(".yaml"))) {
-            format = "xml";
-        } else {
-            format = "yaml";
+        if (format == null) {
+            // Automatically transform to xml if all files are yaml
+            if (files.stream().allMatch(file -> file.endsWith(".yaml"))) {
+                format = "xml";
+            } else {
+                format = "yaml";
+            }
         }
 
         String dump = output;

Reply via email to