1 /* 2 * Copyright (C) 2016 Hobrasoft s.r.o. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Affero General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Affero General Public License for more details. 13 * 14 * You should have received a copy of the GNU Affero General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 package cz.hobrasoft.pdfmu; 18 19 import java.io.Flushable; 20 import java.io.IOException; 21 import java.io.PrintStream; 22 import org.apache.commons.lang3.StringUtils; 23 24 /** 25 * Prints indented messages to a {@link PrintStream} 26 * 27 * <p> 28 * The indentation level starts at 0 and can be changed using 29 * {@link #indentMore} and {@link #indentLess}. 30 * 31 * <p> 32 * Example of usage: 33 * <pre> 34 * {@code 35 * TextOutput to = new TextOutput(System.out); 36 * to.println("Hello!"); 37 * to.indentMore("My favorite fruits:"); 38 * to.println("Banana"); 39 * to.println("Apple"); 40 * to.indentLess(); 41 * to.flush(); 42 * } 43 * </pre> 44 * 45 * @author <a href="mailto:filip.bartek@hobrasoft.cz">Filip Bartek</a> 46 */ 47 public class TextOutput implements Flushable { 48 49 private final PrintStream ps; 50 private int indentLevel = 0; 51 private static final String indentString = " "; 52 53 /** 54 * Creates a {@link TextOutput} bound to a {@link PrintStream} 55 * 56 * @param ps the {@link PrintStream} to print messages to 57 */ 58 public TextOutput(PrintStream ps) { 59 // ps may be null 60 this.ps = ps; 61 } 62 63 /** 64 * Creates a {@link TextOutput} that discards all the messages 65 */ 66 public TextOutput() { 67 this(null); 68 } 69 70 /** 71 * Prints a message on a separate line 72 * 73 * <p> 74 * The message is indented by the current indentation level (starting at 0) 75 * and printed using the specified {@link PrintStream}. 76 * 77 * <p> 78 * Mimics {@link PrintStream#println(String x)}. 79 * 80 * @param x message to print 81 */ 82 public void println(String x) { 83 if (ps != null) { 84 assert indentLevel >= 0; 85 String prefix = StringUtils.repeat(indentString, indentLevel); 86 ps.println(String.format("%s%s", prefix, x)); 87 } 88 } 89 90 /** 91 * Increments the indentation level 92 * 93 * <p> 94 * If the code between {@link #indentMore} and {@link #indentLess} may throw 95 * a (checked) exception, surround the code with a 96 * {@code try}-{@code finally} block like this to maintain consistency: 97 * <pre> 98 * {@code 99 * TextOutput to; 100 * to.indentMore(); 101 * try { 102 * // Do stuff, possibly throwing an exception 103 * // Possibly catch the exception 104 * } finally { 105 * to.indentLess(); 106 * } 107 * } 108 * </pre> 109 */ 110 public void indentMore() { 111 ++indentLevel; 112 } 113 114 /** 115 * Prints a message and increments the indentation level 116 * 117 * @param message message to print 118 */ 119 public void indentMore(String message) { 120 println(message); 121 indentMore(); 122 } 123 124 /** 125 * Decrements the indentation level 126 */ 127 public void indentLess() { 128 if (indentLevel > 0) { 129 --indentLevel; 130 } 131 assert indentLevel >= 0; 132 } 133 134 /** 135 * Flushes the underlying {@link PrintStream} 136 * 137 * @throws IOException if the underlying {@link PrintStream#flush} throws an 138 * {@link IOException} 139 */ 140 @Override 141 public void flush() throws IOException { 142 if (ps != null) { 143 ps.flush(); 144 } 145 } 146 }