All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.runtime.log.internal.SequenceDiagramWriter Maven / Gradle / Ivy

/*
 * $Id: SequenceDiagramWriter.java,v 1.9 2016/02/27 11:14:32 oboehm Exp $
 *
 * Copyright (c) 2015 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 14.06.2015 by oliver ([email protected])
 */

package patterntesting.runtime.log.internal;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

import org.apache.commons.io.*;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint.StaticPart;
import org.slf4j.*;

import patterntesting.runtime.io.FileHelper;
import patterntesting.runtime.util.Converter;

/**
 * The Class SequenceDiagramWriter uses the format of websequence diagram to
 * generate the chart. You can find this format at www.websequencediagrams.com.
 *
 * @author oliver
 * @version $Revision: 1.9 $
 * @since 1.6 (14.06.2015)
 */
public class SequenceDiagramWriter {

    private static final Logger LOG = LoggerFactory.getLogger(SequenceDiagramWriter.class);

    private final Writer writer;
    private final List statements = new ArrayList();
    private final Map placeholders = new HashMap();

    /**
     * Instantiates a new sequence diagram writer.
     *
     * @param file the file
     */
    public SequenceDiagramWriter(final File file) {
        this(FileHelper.getStreamFor(file));
        writeHeaderFor(file);
    }

    /**
     * Instantiates a new sequence diagram writer.
     *
     * @param ostream the ostream
     */
    public SequenceDiagramWriter(final OutputStream ostream) {
        this(new BufferedWriter(new OutputStreamWriter(ostream, Charset.forName("UTF-8"))));
    }

    /**
     * Instantiates a new sequence diagram writer.
     *
     * @param writer the writer
     */
    public SequenceDiagramWriter(final Writer writer) {
        this.writer = writer;
    }

    /**
     * Instantiates a new sequence diagram writer.
     *
     * @param writer the writer
     * @param statements the statements
     */
    public SequenceDiagramWriter(final Writer writer, final List statements) {
        this(writer);
        this.statements.addAll(statements);
    }

    /**
     * Gets the writer.
     *
     * @return the writer
     */
    protected Writer getWriter() {
        return writer;
    }

    /**
     * Gets the statements.
     *
     * @return the statements
     */
    protected List getStatements() {
        return Collections.unmodifiableList(statements);
    }

    /**
     * Adds the statements.
     *
     * @param drawStatements the statements
     */
    public void addStatements(final Collection drawStatements) {
        this.statements.addAll(drawStatements);
    }

    /**
     * Adds a statement.
     *
     * @param stmt the statement.
     */
    public void addStatement(final DrawStatement stmt) {
        this.statements.add(stmt);
    }

    /**
     * Write sequence diagram.
     */
    public void writeSequenceDiagram() {
        for (DrawStatement stmt : this.statements) {
            switch (stmt.getType()) {
                case ACTOR:
                    placeholders.put(stmt.getSender(), stmt.getTarget());
                    break;
                case OBJECT:
                    addToPlaceholders(stmt.getSender(), stmt.getTarget());
                    break;
                case PLACEHOLDER_OBJECT:
                    LOG.debug("Statement '{}' is ignored for generated diagram.", stmt);
                    break;
                case CREATE_MESSAGE:
                    writeCreateMessage(stmt);
                    break;
                case MESSAGE:
                    writeMessage(stmt);
                    break;
                case RETURN_MESSAGE:
                    writeReturnMessage(stmt);
                    break;
                default:
                    writeLine(stmt.toString());
                    break;
            }
        }
    }

    private void addToPlaceholders(final String varname, final String label) {
        if (this.getNumberOfObjectLabels(label) == 1) {
            this.placeholders.put(varname, toName(label, varname));
        } else {
            this.placeholders.put(varname, toName(label, ""));
        }
    }

    private int getNumberOfObjectLabels(final String label) {
        int n = 0;
        for (DrawStatement stmt : this.statements) {
            if ((stmt.getType() == DrawType.OBJECT) && (label.equals(stmt.getSender()))) {
                n++;
            }
        }
        return n;
    }

    private void writeCreateMessage(final DrawStatement stmt) {
        String name = toName((String) stmt.getArgs()[0], stmt.getTarget());
        placeholders.put(stmt.getTarget(), name);
        writeLine("# " + this.placeholders.get(stmt.getSender()) + " ->  +" + name + ": <>");
    }

    private void writeMessage(final DrawStatement stmt) {
        StaticPart jpInfo = stmt.getJpInfo();
        String target = stmt.getTarget();
        writeLine(this.placeholders.get(stmt.getSender()) + " ->  +" + this.placeholders.get(target) + ": "
                + jpInfo.getSignature().getName() + stmt.getArgsAsString());
    }

    private void writeReturnMessage(final DrawStatement stmt) {
        writeLine(this.placeholders.get(stmt.getTarget()) + " --> -" + this.placeholders.get(stmt.getSender()) + ": "
                + Converter.toShortString(stmt.getArgs()[0]));
    }

    private static String toName(final String label, final String varname) {
        String[] parts = label.split(":");
        String name = parts[0];
        if (StringUtils.isEmpty(name)) {
            name = varname;
        }
        name = parts[1] + " " + name;
        return name.trim();
    }

    /**
     * This method can be used to write the title of the diagram. The title
     * will be derived from the file name.
     *
     * @param file the file
     */
    public void writeHeaderFor(final File file) {
        this.writeLine("title " + FilenameUtils.getBaseName(file.getName()));
        this.writeLine("");
    }

    /**
     * Write line.
     *
     * @param line the line
     */
    protected final void writeLine(final String line) {
        try {
            this.getWriter().write(line.trim());
            this.getWriter().write("\n");
        } catch (IOException ioe) {
            LOG.debug("Writing to {} failed:", this.getWriter(), ioe);
            LOG.info(line);
        }
    }

    /**
     * Close quietly.
     */
    public void close() {
        IOUtils.closeQuietly(this.writer);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy