/** * Arara, the cool TeX automation tool * Copyright (c) 2012 -- 2019, Paulo Roberto Massa Cereda * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the project's author nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package com.github.cereda.arara.utils; import com.github.cereda.arara.controller.ConfigurationController; import com.github.cereda.arara.controller.LanguageController; import com.github.cereda.arara.model.AraraException; import com.github.cereda.arara.model.Conditional; import com.github.cereda.arara.model.Messages; import com.github.cereda.arara.model.StopWatch; import java.io.File; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implements display utilitary methods. * @author Paulo Roberto Massa Cereda * @version 4.0 * @since 4.0 */ public class DisplayUtils { // the application messages obtained from the // language controller private static final LanguageController messages = LanguageController.getInstance(); // get the logger context from a factory private static final Logger logger = LoggerFactory.getLogger(DisplayUtils.class); /** * Displays the short version of the current entry in the terminal. * @param name Rule name. * @param task Task name. */ private static void buildShortEntry(String name, String task) { int width = getWidth(); int result = getLongestMatch(); if (result >= width) { result = 10; } int space = width - result - 1; StringBuilder entry = new StringBuilder(); entry.append("(").append(name).append(") "); entry.append(task).append(" "); String line = StringUtils.abbreviate(entry.toString(), space - 4); entry = new StringBuilder(); entry.append(StringUtils.rightPad(line, space, ".")).append(" "); System.out.print(entry); } /** * Displays the short version of the current entry result in the terminal. * @param value The boolean value to be displayed. */ private static void buildShortResult(boolean value) { int result = getLongestMatch(); System.out.println(StringUtils.leftPad(getResult(value), result)); } /** * Displays the current entry result in the terminal. * @param value The boolean value to be displayed. */ public static void printEntryResult(boolean value) { ConfigurationController.getInstance().put("display.line", false); ConfigurationController.getInstance().put("display.result", true); ConfigurationController.getInstance() .put("execution.status", value ? 0 : 1); logger.info( messages.getMessage( Messages.LOG_INFO_TASK_RESULT ).concat(" ").concat(getResult(value)) ); if (!isDryRunMode()) { if (!isVerboseMode()) { buildShortResult(value); } else { buildLongResult(value); } } } /** * Displays a long version of the current entry result in the terminal. * @param value The boolean value to be displayed */ private static void buildLongResult(boolean value) { int width = getWidth(); System.out.println("\n".concat(StringUtils.leftPad( " ".concat(getResult(value)), width, "-" ))); } /** * Displays the current entry in the terminal. * @param name The rule name. * @param task The task name. */ public static void printEntry(String name, String task) { logger.info( messages.getMessage( Messages.LOG_INFO_INTERPRET_TASK, task, name ) ); ConfigurationController.getInstance().put("display.line", true); ConfigurationController.getInstance().put("display.result", false); if (!isDryRunMode()) { if (!isVerboseMode()) { buildShortEntry(name, task); } else { buildLongEntry(name, task); } } else { buildDryRunEntry(name, task); } } /** * Gets the length of the longest result match. * @return An integer value representing the longest result match. */ private static int getLongestMatch() { String[] values = new String[]{ messages.getMessage(Messages.INFO_LABEL_ON_SUCCESS), messages.getMessage(Messages.INFO_LABEL_ON_FAILURE), messages.getMessage(Messages.INFO_LABEL_ON_ERROR) }; int max = values[0].length(); for (String value : values) { if (max < value.length()) { max = value.length(); } } return max; } /** * Displays a long version of the current entry in the terminal. * @param name Rule name. * @param task Task name. */ private static void buildLongEntry(String name, String task) { if (ConfigurationController.getInstance().contains("display.rolling")) { addNewLine(); } else { ConfigurationController.getInstance().put("display.rolling", true); } StringBuilder line = new StringBuilder(); line.append("(").append(name).append(") "); line.append(task); System.out.println(displaySeparator()); System.out.println(StringUtils.abbreviate(line.toString(), getWidth())); System.out.println(displaySeparator()); } /** * Displays a dry-run version of the current entry in the terminal. * @param name The rule name. * @param task The task name. */ private static void buildDryRunEntry(String name, String task) { if (ConfigurationController.getInstance().contains("display.rolling")) { addNewLine(); } else { ConfigurationController.getInstance().put("display.rolling", true); } StringBuilder line = new StringBuilder(); line.append("[DR] (").append(name).append(") "); line.append(task); System.out.println(StringUtils.abbreviate(line.toString(), getWidth())); System.out.println(displaySeparator()); } /** * Displays the exception in the terminal. * @param exception The exception object. */ public static void printException(AraraException exception) { ConfigurationController.getInstance().put("display.exception", true); ConfigurationController.getInstance().put("execution.status", 2); boolean display = false; if (ConfigurationController.getInstance().contains("display.line")) { display = (Boolean) ConfigurationController. getInstance().get("display.line"); } if (ConfigurationController.getInstance().contains("display.result")) { if (((Boolean) ConfigurationController. getInstance().get("display.result")) == true) { addNewLine(); } } if (display) { if (!isDryRunMode()) { if (!isVerboseMode()) { buildShortError(); } else { buildLongError(); } addNewLine(); } } String text = exception.hasException() ? exception.getMessage().concat(" ").concat( messages.getMessage( Messages.INFO_DISPLAY_EXCEPTION_MORE_DETAILS ) ) : exception.getMessage(); logger.error(text); wrapText(text); if (exception.hasException()) { addNewLine(); displayDetailsLine(); String details = exception.getException().getMessage(); logger.error(details); wrapText(details); } } /** * Gets the string representation of the provided boolean value. * @param value The boolean value. * @return The string representation. */ private static String getResult(boolean value) { return (value == true ? messages.getMessage( Messages.INFO_LABEL_ON_SUCCESS ) : messages.getMessage(Messages.INFO_LABEL_ON_FAILURE)); } /** * Displays the short version of an error in the terminal. */ private static void buildShortError() { int result = getLongestMatch(); System.out.println(StringUtils.leftPad( messages.getMessage( Messages.INFO_LABEL_ON_ERROR ), result )); } /** * Displays the long version of an error in the terminal. */ private static void buildLongError() { String line = StringUtils.leftPad( " ".concat(messages.getMessage(Messages.INFO_LABEL_ON_ERROR)), getWidth(), "-"); System.out.println(line); } /** * Gets the default terminal width defined in the settings. * @return An integer representing the terminal width. */ private static int getWidth() { return (Integer) ConfigurationController. getInstance().get("application.width"); } /** * Displays the provided text wrapped nicely according to the default * terminal width. * @param text The text to be displayed. */ public static void wrapText(String text) { System.out.println(WordUtils.wrap(text, getWidth())); } /** * Checks if the execution is in dry-run mode. * @return A boolean value indicating if the execution is in dry-run mode. */ private static boolean isDryRunMode() { return (Boolean) ConfigurationController. getInstance().get("execution.dryrun"); } /** * Checks if the execution is in verbose mode. * @return A boolean value indicating if the execution is in verbose mode. */ private static boolean isVerboseMode() { return (Boolean) ConfigurationController. getInstance().get("execution.verbose"); } /** * Displays the rule authors in the terminal. * @param authors The list of authors. */ public static void printAuthors(List authors) { StringBuilder line = new StringBuilder(); line.append(authors.size() == 1 ? messages.getMessage(Messages.INFO_LABEL_AUTHOR) : messages.getMessage(Messages.INFO_LABEL_AUTHORS)); String text = authors.isEmpty() ? messages.getMessage(Messages.INFO_LABEL_NO_AUTHORS) : CommonUtils.getCollectionElements( CommonUtils.trimSpaces(authors), "", "", ", "); line.append(" ").append(text); wrapText(line.toString()); } /** * Displays the current conditional in the terminal. * @param conditional The conditional object. */ public static void printConditional(Conditional conditional) { if (conditional.getType() != Conditional.ConditionalType.NONE) { StringBuilder line = new StringBuilder(); line.append(messages.getMessage(Messages.INFO_LABEL_CONDITIONAL)); line.append(" ("); line.append(String.valueOf(conditional.getType())); line.append(") ").append(conditional.getCondition()); wrapText(line.toString()); } } /** * Displays the file information in the terminal. */ public static void printFileInformation() { File file = (File) ConfigurationController. getInstance().get("execution.reference"); String version = (String) ConfigurationController. getInstance().get("application.version"); String revision = (String) ConfigurationController. getInstance().get("application.revision"); String line = messages.getMessage( Messages.INFO_DISPLAY_FILE_INFORMATION, file.getName(), CommonUtils.calculateFileSize(file), CommonUtils.getLastModifiedInformation(file) ); logger.info(messages.getMessage( Messages.LOG_INFO_WELCOME_MESSAGE, version, revision )); logger.info(displaySeparator()); logger.info(String.format("::: arara @ %s", getApplicationPath() )); logger.info(String.format("::: Java %s, %s", CommonUtils.getSystemProperty("java.version", "[unknown version]"), CommonUtils.getSystemProperty("java.vendor", "[unknown vendor]") )); logger.info(String.format("::: %s", CommonUtils.getSystemProperty("java.home", "[unknown location]") )); logger.info(String.format("::: %s, %s, %s", CommonUtils.getSystemProperty("os.name", "[unknown OS name]"), CommonUtils.getSystemProperty("os.arch", "[unknown OS arch]"), CommonUtils.getSystemProperty("os.version", "[unknown OS version]") )); logger.info(String.format("::: user.home @ %s", CommonUtils.getSystemProperty("user.home", "[unknown user's home directory]") )); logger.info(String.format("::: user.dir @ %s", CommonUtils.getSystemProperty("user.dir", "[unknown user's working directory]") )); logger.info(String.format("::: CF @ %s", (String) ConfigurationController. getInstance().get("execution.configuration.name") )); logger.info(displaySeparator()); logger.info(line); wrapText(line); addNewLine(); } /** * Displays the elapsed time in the terminal. */ public static void printTime() { if (ConfigurationController.getInstance().contains("display.time")) { if ((ConfigurationController.getInstance().contains("display.line")) || (ConfigurationController.getInstance(). contains("display.exception"))) { addNewLine(); } String text = messages.getMessage( Messages.INFO_DISPLAY_EXECUTION_TIME, StopWatch.getTime()); logger.info(text); wrapText(text); } } /** * Displays the application logo in the terminal. */ public static void printLogo() { StringBuilder builder = new StringBuilder(); builder.append(" __ _ _ __ __ _ _ __ __ _ ").append("\n"); builder.append(" / _` | '__/ _` | '__/ _` |").append("\n"); builder.append("| (_| | | | (_| | | | (_| |").append("\n"); builder.append(" \\__,_|_| \\__,_|_| \\__,_|"); System.out.println(builder.toString()); addNewLine(); } /** * Adds a new line in the terminal. */ private static void addNewLine() { System.out.println(); } /** * Displays a line containing details. */ private static void displayDetailsLine() { String line = messages.getMessage( Messages.INFO_LABEL_ON_DETAILS).concat(" "); line = StringUtils.rightPad( StringUtils.abbreviate(line, getWidth()), getWidth(), "-"); System.out.println(line); } /** * Gets the output separator with the provided text. * @param message The provided text. * @return A string containing the output separator with the provided text. */ public static String displayOutputSeparator(String message) { return StringUtils.center(" ".concat(message).concat(" "), getWidth(), "-"); } /** * Gets the line separator. * @return A string containing the line separator. */ public static String displaySeparator() { return StringUtils.repeat("-", getWidth()); } /** * Gets the application path. * @return A string containing the application path. */ private static String getApplicationPath() { try { return ConfigurationUtils.getApplicationPath(); } catch (AraraException ae) { return "[unknown application path]"; } } }