001package org.nasdanika.html.model.app.gen.maven;
002
003import java.io.PrintStream;
004import java.util.Arrays;
005import java.util.concurrent.CancellationException;
006
007import org.apache.maven.plugin.logging.Log;
008import org.nasdanika.common.ProgressMonitor;
009import org.nasdanika.common.Status;
010
011/**
012 * Progress monitor reporting to a {@link PrintStream}, e.g. ``System.out``.
013 * This monitor indents sub-tasks and worked messages. It can be thought of as a hierarchical logger.
014 * @author Pavel
015 *
016 */
017public class LogProgressMonitor implements ProgressMonitor {
018
019        private Log log;
020        private String indent;
021        protected int indentIncrement = 2;
022        private boolean cancelled;
023        
024        /**
025         * Constructs a progress monitor for a given log.
026         */
027        public LogProgressMonitor(Log log, int indent, int indentIncrement) {
028                this.log = log;
029                StringBuilder indentBuilder = new StringBuilder();
030                for (int i = 0; i < indent; ++i) {
031                        indentBuilder.append(' ');
032                }
033                this.indent = indentBuilder.toString();
034        }
035
036        @Override
037        public boolean isCancelled() {
038                return cancelled;
039        }
040
041        @Override
042        public ProgressMonitor split(String taskName, double size, Object... data) {
043                if (isCancelled()) {
044                        throw new CancellationException();
045                }
046                log.info(indent + "  " + taskName + " ("+size+")");
047                if (data != null) {
048                        for (Object d: data) {
049                                log.info(formatDetail(d, indent + "    "));                     
050                        }
051                }
052                return new LogProgressMonitor(log, indent.length() + indentIncrement, indentIncrement) {
053                        
054                        @Override
055                        public boolean isCancelled() {
056                                return LogProgressMonitor.this.isCancelled();
057                        }
058                        
059                };
060        }
061        
062        /**
063         * Formats detail element for output. This implementation concatenates the indent with the detail.
064         * @param detail
065         * @param indent
066         * @return
067         */
068        protected String formatDetail(Object detail, String indent) {
069                return indent + detail;
070        }
071
072        @Override
073        public void worked(Status status, double work, String progressMessage, Object... data) {
074                switch (status) {
075                case ERROR:
076                case FAIL:
077                        log.error(indent + "  [" + status + " " + work + "] " + progressMessage);
078                        if (data.length > 0) {
079                                log.error(": " + Arrays.deepToString(data));
080                        }
081                        break;
082                case WARNING:
083                        log.warn(indent + "  [" + status + " " + work + "] " + progressMessage);
084                        if (data.length > 0) {
085                                log.warn(": " + Arrays.deepToString(data));
086                        }
087                        break;
088                case CANCEL:
089                case INFO:
090                case SUCCESS:
091                default:
092                        log.info(indent + "  [" + status + " " + work + "] " + progressMessage);
093                        if (data.length > 0) {
094                                log.info(": " + Arrays.deepToString(data));
095                        }
096                        if (status == Status.CANCEL) {
097                                cancelled = true;
098                        }
099                }
100        }
101
102        @Override
103        public ProgressMonitor setWorkRemaining(double size) {
104                // NOP
105                return this;
106        }
107
108        @Override
109        public void close() {
110                // NOP          
111        }
112
113}