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() {
    }
}