# ReportingMojo.java

    package org.thewonderlemming.c4plantuml.mojo;

    import java.io.BufferedOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;

    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugin.MojoFailureException;
    import org.apache.maven.plugins.annotations.LifecyclePhase;
    import org.apache.maven.plugins.annotations.Mojo;
    import org.apache.maven.plugins.annotations.Parameter;
    import org.thewonderlemming.c4plantuml.graphml.C4Graph;

    /**
     * A MOJO that parses the C4 PlantUML files that are contained in the output directory and generates a GraphML file with
     * the gathered information.
     *
     * @author thewonderlemming
     *
     */
    @Mojo(name = "report", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
    public class ReportingMojo extends AbstractParentMojo {

        /**
         * Default value for the {@code failOnParseErrors} property.
         */
        public static final String FAIL_ON_PARSE_ERRORS_DEFAULT_VALUE = "false";

        /**
         * Default value for the {@code formatOutput} property.
         */
        public static final String FORMAT_OUTPUT_DEFAULT_VALUE = "true";

        /**
         * Default value for the generated GraphML filename.
         * <p>
         * It is linked to the {@code outputFilename} property. If the given {@code outputFilename} is not an absolute path,
         * then it will be created in the {@code outputDirectory}.
         */
        public static final String OUTPUT_FILENAME_DEFAULT_VALUE = "c4graph.graphml";

        @Parameter(property = "failOnParseErrors", defaultValue = FAIL_ON_PARSE_ERRORS_DEFAULT_VALUE,
            alias = "failOnParseErrors")
        private boolean failOnParseErrors;

        @Parameter(property = "formatOutput", defaultValue = FORMAT_OUTPUT_DEFAULT_VALUE, alias = "formatOutput")
        private boolean formatOutput;

        @Parameter(property = "outputFilename", defaultValue = OUTPUT_FILENAME_DEFAULT_VALUE, alias = "outputFilename")
        private String outputFilename;

        /**
         * Gathers information from the C4 PlantUML files and outputs it as a GraphML file.
         * <p>
         * {@inheritDoc}
         */
        @Override
        protected void doExecute() throws MojoExecutionException, MojoFailureException {

            validateOutputFilename();
            generateReportFile();
        }

        private void generateReportFile() throws MojoFailureException {

            try {

                final C4Graph c4Graph = new C4Graph(getCurrentCharset(), this.formatOutput, this.failOnParseErrors);
                final List<Path> c4Files = new ArrayList<>();

                processOutputDirectoryFiles(c4Files::add);

                if (c4Files.isEmpty()) {
                    throw new MojoFailureException("No data found to report");
                }

                final Optional<String> content = c4Graph.addAndProcessC4Files(c4Files).export();

                if (content.isPresent()) {
                    writeReportFile(content.get());

                } else {
                    throw new MojoFailureException("Unable to export to GraphML format");
                }

            } catch (final Throwable e) {

                final String errMsg = String
                    .format("Cannot process output directory: \"%s\" for reporting because of the following: %s",
                        getOutputDirectory(),
                        e.getMessage());

                throw new MojoFailureException(errMsg, e);
            }
        }

        private void validateOutputFilename() {

            assert (this.outputFilename != null) : "Expected outputFilename to be set";

            final File outputFile = new File(this.outputFilename);

            if (!outputFile.isAbsolute()) {

                this.outputFilename = getOutputDirectory() + "/" + this.outputFilename;

                getLog()
                    .info(
                        "The given report filename is not absolute. \"" + this.outputFilename + "\" will be used instead.");
            }
        }

        private void writeReportFile(final String content) throws IOException {

            try (final FileOutputStream fos = new FileOutputStream(this.outputFilename);
                final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(fos))) {

                dos.write(content.getBytes(getCurrentCharset()));
            }
        }
    }