# GraphMLModelExporter.java

    package org.thewonderlemming.c4plantuml.graphml.export;

    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.util.Optional;

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.parsers.ParserConfigurationException;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.thewonderlemming.c4plantuml.graphml.model.GraphMLModel;

    /**
     * An exporter to transform a JAXB {@link GraphMLModel} to a GraphML string.
     *
     * @author thewonderlemming
     *
     */
    public class GraphMLModelExporter {

        private static final Logger LOGGER = LoggerFactory.getLogger(GraphMLModelExporter.class);

        /**
         * Exports a JAXB {@link GraphMLModel} instance to a valid GraphML string, using {@code UTF-8} as a default
         * {@link Charset}, turning off the formatting and turning on the strict XML validation on the output.
         *
         * @param graphml the JAXB model instance.
         * @return the generated GraphML as a string if no silent error occurred, or empty else.
         */
        public static final Optional<String> export(final GraphMLModel graphml) {
            return export(graphml, StandardCharsets.UTF_8, false);
        }

        /**
         * Exports a JAXB {@link GraphMLModel} instance to a valid GraphML string, using {@code UTF-8} as a default
         * {@link Charset}, and turning on the strict XML validation on the output.
         *
         * @param graphml the JAXB model instance.
         * @param formatOutput a flag to tell whether or not the output should fit on a single line.
         * @return the generated GraphML as a string if no silent error occurred, or empty else.
         */
        public static final Optional<String> export(final GraphMLModel graphml, final boolean formatOutput) {
            return export(graphml, StandardCharsets.UTF_8, formatOutput);
        }

        /**
         * Exports a JAXB {@link GraphMLModel} instance to a valid GraphML string, turning on the strict XML validation on
         * the output.
         *
         * @param graphml the JAXB model instance.
         * @param charset the {@link Charset} to use for the GraphML output.
         * @param formatOutput a flag to tell whether or not the output should fit on a single line.
         * @return the generated GraphML as a string if no silent error occurred, or empty else.
         */
        public static final Optional<String> export(final GraphMLModel graphml, final Charset charset,
            final boolean formatOutput) {

            return export(graphml, charset, formatOutput, true, true);
        }

        /**
         * Exports a JAXB {@link GraphMLModel} instance to a valid GraphML string.
         *
         * @param graphml the JAXB model instance.
         * @param charset the {@link Charset} to use for the GraphML output.
         * @param formatOutput a flag to tell whether or not the output should fit on a single line.
         * @param validate a flag to tell whether or not the output should be validated against an XSD.
         * @param strictValidation a flag to tell whether or not a validation error should fail the export.
         * @return the generated GraphML as a string if no silent error occurred, or empty else.
         */
        public static final Optional<String> export(final GraphMLModel graphml, final Charset charset,
            final boolean formatOutput, final boolean validate, final boolean strictValidation) {

            try {

                final JAXBContext jaxbContext = JAXBContext.newInstance(GraphMLModel.class.getPackage().getName());
                final Marshaller marshaller = jaxbContext.createMarshaller();

                marshaller.setEventHandler(event -> {
                    LOGGER.debug("New event: {}", event.getMessage(), event.getLinkedException());
                    return true;
                });

                final CDataDocumentDecorator doc = CDataDocumentDecorator.newInstance();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formatOutput);
                marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, GraphMLModel.SCHEMA_LOCATION);
                marshaller.setProperty(Marshaller.JAXB_ENCODING, charset.name());
                marshaller.marshal(graphml, doc);

                return doc.exportAsString(charset, formatOutput, validate, strictValidation);

            } catch (final JAXBException | ParserConfigurationException e) {
                LOGGER.error("Unable to export to GraphML format: {}", e.getMessage(), e);
            }

            return Optional.empty();
        }

        private GraphMLModelExporter() {
        }
    }