Subject: [PATCH] 7_jaxb_marshal
---
Index: src/main/java/ru/javaops/docjava/xml/jaxb/JaxbMarshaller.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbMarshaller.java b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbMarshaller.java
new file mode 100644
--- /dev/null	(date 1695983202589)
+++ b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbMarshaller.java	(date 1695983202589)
@@ -0,0 +1,34 @@
+package ru.javaops.docjava.xml.jaxb;
+
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Marshaller;
+
+import javax.xml.validation.Schema;
+import java.io.StringWriter;
+import java.io.Writer;
+
+public class JaxbMarshaller {
+    private final Marshaller marshaller;
+
+    public JaxbMarshaller(JAXBContext ctx) throws JAXBException {
+        marshaller = ctx.createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+    }
+
+    public void setSchema(Schema schema) {
+        marshaller.setSchema(schema);
+    }
+
+    public void marshal(Object instance, Writer writer) throws JAXBException {
+        marshaller.marshal(instance, writer);
+    }
+
+    public String marshal(Object instance) throws JAXBException {
+        StringWriter sw = new StringWriter();
+        marshal(instance, sw);
+        return sw.toString();
+    }
+}
Index: src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java b/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java
--- a/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java	(revision d816b29a64be19b20f51b24e37f22a31c332b076)
+++ b/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java	(date 1695983223418)
@@ -17,13 +17,13 @@
 
     @Test
     public void processOK() throws JAXBException, IOException {
-        UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, Map.of());
+        UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, Map.of(), new File("out/jaxb.xml"));
         assertEquals(new UsersWithMeals.Users(getUsers()), usersWithMeals.getUsers());
     }
 
     @Test
     void processFiltered() throws IOException, JAXBException {
-        UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, paramsMap);
+        UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, paramsMap, new File("out/jaxbFiltered.xml"));
         assertEquals(new UsersWithMeals.Users(getFilteredUsers()), usersWithMeals.getUsers());
     }
 
Index: src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java
--- a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java	(revision d816b29a64be19b20f51b24e37f22a31c332b076)
+++ b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java	(date 1695993181826)
@@ -1,36 +1,39 @@
 package ru.javaops.docjava.xml.jaxb;
 
-import jakarta.xml.bind.JAXBContext;
 import jakarta.xml.bind.JAXBException;
 import lombok.experimental.UtilityClass;
 import ru.javaops.docjava.schema.ObjectFactory;
 import ru.javaops.docjava.schema.UsersWithMeals;
 import ru.javaops.docjava.util.MealsUtil;
-import ru.javaops.docjava.xml.xsd.Schemas;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.Reader;
+import java.io.Writer;
 import java.nio.file.Files;
 import java.util.Map;
 
 @UtilityClass
 public class JaxbUtil {
+    private static final JaxbParser jaxbParser;
+    private static final JaxbMarshaller marshaller;
     private static final JaxbUnmarshaller unmarshaller;
 
     static {
         try {
-            JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class);
-            unmarshaller = new JaxbUnmarshaller(ctx);
-            unmarshaller.setSchema(Schemas.of(new File("in/usersWithMeals.xsd")));
+            jaxbParser = JaxbParser.of(ObjectFactory.class);
+            jaxbParser.setSchema(new File("in/usersWithMeals.xsd"));
+            marshaller = jaxbParser.createMarshaller();
+            unmarshaller = jaxbParser.createUnmarshaller();
         } catch (JAXBException e) {
             throw new RuntimeException(e);
         }
     }
 
-    public static UsersWithMeals process(File inputXml, Map<String, Object> params) throws IOException, JAXBException {
+    public static UsersWithMeals process(File inputXml, Map<String, Object> params, File outputXml) throws IOException, JAXBException {
         UsersWithMeals users = unmarshalAndFilter(inputXml, params);
-        System.out.println("JAXB processing completed successfully");
+        marshal(users, outputXml);
+        System.out.println("JAXB processing completed successfully, result in " + outputXml.getAbsolutePath());
         return users;
     }
 
@@ -45,4 +48,10 @@
             return unmarshaller.unmarshal(reader);
         }
     }
+
+    public static void marshal(UsersWithMeals users, File outputXml) throws IOException, JAXBException {
+        try (Writer writer = Files.newBufferedWriter(outputXml.toPath())) {
+            marshaller.marshal(users, writer);
+        }
+    }
 }
Index: src/main/java/ru/javaops/docjava/xml/jaxb/JaxbParser.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbParser.java b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbParser.java
new file mode 100644
--- /dev/null	(date 1695983257750)
+++ b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbParser.java	(date 1695983257750)
@@ -0,0 +1,44 @@
+package ru.javaops.docjava.xml.jaxb;
+
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import ru.javaops.docjava.xml.xsd.Schemas;
+
+import javax.xml.validation.Schema;
+import java.io.File;
+
+public class JaxbParser {
+
+    private final JAXBContext ctx;
+    protected Schema schema;
+
+    public static JaxbParser of(Class... classesToBeBound) throws JAXBException {
+        return new JaxbParser(classesToBeBound);
+    }
+
+    private JaxbParser(Class... classesToBeBound) throws JAXBException {
+        ctx = JAXBContext.newInstance(classesToBeBound);
+    }
+
+    public void setSchema(File xsdSchema) {
+        this.schema = Schemas.of(xsdSchema);
+    }
+
+    //    https://stackoverflow.com/a/7400735/548473
+    public JaxbMarshaller createMarshaller() throws JAXBException {
+        JaxbMarshaller marshaller = new JaxbMarshaller(ctx);
+        if (schema != null) {
+            marshaller.setSchema(schema);
+        }
+        return marshaller;
+    }
+
+    //    https://stackoverflow.com/a/7400735/548473
+    public JaxbUnmarshaller createUnmarshaller() throws JAXBException {
+        JaxbUnmarshaller unmarshaller = new JaxbUnmarshaller(ctx);
+        if (schema != null) {
+            unmarshaller.setSchema(schema);
+        }
+        return unmarshaller;
+    }
+}
Index: src/main/java/ru/javaops/docjava/Commands.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/ru/javaops/docjava/Commands.java b/src/main/java/ru/javaops/docjava/Commands.java
--- a/src/main/java/ru/javaops/docjava/Commands.java	(revision d816b29a64be19b20f51b24e37f22a31c332b076)
+++ b/src/main/java/ru/javaops/docjava/Commands.java	(date 1695993181825)
@@ -5,7 +5,6 @@
 import org.springframework.shell.standard.ShellMethod;
 import org.springframework.shell.standard.ShellOption;
 import org.xml.sax.SAXException;
-import ru.javaops.docjava.schema.UsersWithMeals;
 import ru.javaops.docjava.xml.jaxb.JaxbUtil;
 import ru.javaops.docjava.xml.xsd.SchemaUtil;
 
@@ -28,7 +27,7 @@
             @ShellOption(value = {"input", "-i"}, help = "Input file") File inputFile,
             @ShellOption(value = {"filter", "-f"}, help = "Filter params", defaultValue = "") List<String> params,
             @ShellOption(value = {"output", "-o"}, help = "Output file") File outputFile) throws JAXBException, IOException {
-        JaxbUtil.process(inputFile, parseParams(params));
+        JaxbUtil.process(inputFile, parseParams(params), outputFile);
     }
 
     @ShellMethod(key = "stax", value = "Process XML file via StAX")
diff --git a/out/placeholder b/out/placeholder
new file mode 100644
