/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.internal.util; import java.io.ByteArrayOutputStream; import java.io.PrintStream; /** * This is a convenience class with various improvements to * <tt>StringBuilder</tt>. * <p> * It provides for example <tt>append()</tt> and <tt>appendln()</tt>, both with * varargs. The latter is using the platform specific line break characters * from <tt>System.getProperty("line.separator")</tt>. * <p> * This class also provides a convenience method <tt>{@link #fill(int, char)} * </tt> to append a number of characters to an existing buffer. * <p> * Most methods also return the updated instance in order to allow chaining * of commands, e.g. <tt>buf.append("123.5435").pad(10);</tt> * <p> * Special version of <tt>append()</tt> and <tt>appendln()</tt> have been added, * which take <tt>Throwable</tt>s as argument, allowing easy printing of * exceptions. * * @author Tilmann Zaeschke */ public class FormattedStringBuilder { /** New Line. */ public final static String NL = System.getProperty("line.separator"); private StringBuilder _delegate; /** * Creates a new <tt>FormattedStringBuilder</tt>. */ public FormattedStringBuilder() { _delegate = new StringBuilder(); } /** * Creates a new <tt>FormattedStringBuilder</tt> with the given initial content. * @param initial */ public FormattedStringBuilder(String initial) { _delegate = new StringBuilder(initial); } /** * Appends the specified string(s) to this character sequence. * @param strings * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder append(String ... strings) { for(String s: strings) { _delegate.append(s); } return this; } /** * Appends the specified string(s) to this character sequence and * after all strings appended add a new line. * @param strings * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder appendln(String ... strings) { append(strings); _delegate.append(NL); return this; } /** * Appends the string representation of the char argument to this sequence. * @param c * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder append(char c) { _delegate.append(c); return this; } /** * Appends the string representation of the int argument to this sequence. * @param i * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder append(int i) { _delegate.append(i); return this; } /** * Appends the stack trace of the Throwable argument to this sequence. * @param t Exception to print. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder append(Throwable t) { ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream p = new PrintStream(os); t.printStackTrace(p); p.close(); return append(os.toString()); } /** * Appends the stack trace of the Throwable argument to this sequence * and then a new line. * @param t Exception to print. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder appendln(Throwable t) { return append(t).appendln(); } /** * Appends to the line the white spaces and then the string <tt>s</tt> * so that the end of the string <tt>s</tt> is at the position * <tt>alignPosition</tt>. If the string is longer than the free space * in the buffer to the align position then an IllegalArgumentException * is thrown. * * @param s String to append. * @param alignPosition index of the last character of the string * relative to the current line in the buffer. * @return The updated instance of FormattedStringBuilder. * @throws IllegalArgumentException if not enough space is allocated for * the string. */ public FormattedStringBuilder appendRightAligned(String s, int alignPosition) { int lineStart = _delegate.lastIndexOf(NL); int currentLength = _delegate.length(); int rightPosition = alignPosition; if(lineStart != -1) { lineStart += NL.length(); rightPosition = lineStart + alignPosition; } int fillPosition = rightPosition - s.length(); if(fillPosition<currentLength) { throw new IllegalArgumentException("String \"" + s + "\" to right " + "align is longer than the unfilled buffer space [" + (rightPosition - currentLength) + "]"); } else { fillBuffer(fillPosition, ' '); } return append(s); } /** * Attempts to append <tt>c</tt> until the buffer gets the length <tt> * newLength</tt>. If the buffer is already as long or longer than <tt> * newLength</tt>, then nothing is appended. * @param newLength Minimal new length of the returned buffer. * @param c Character to append. * @return The updated instance of FormattedStringBuilder. */ private FormattedStringBuilder fillBuffer(int newLength, char c) { for (int i = _delegate.length(); i < newLength; i++ ) { _delegate.append(c); } return this; } /** * Attempts to append <tt>c</tt> until the current line gets the length <tt> * newLength</tt>. If the line is already as long or longer than <tt> * newLength</tt>, then nothing is appended. * @param newLength Minimal new length of the last line. * @param c Character to append. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder fill(int newLength, char c) { int lineStart = _delegate.lastIndexOf(NL); if (lineStart == -1) { return fillBuffer(newLength, c); } lineStart += NL.length(); return fillBuffer(lineStart + newLength, c); } /** * Attempts to append white spaces until the current line gets the length <tt> * newLength</tt>. If the line is already as long or longer than <tt> * newLength</tt>, then nothing is appended. * * @param newLength Minimal new length of the last line. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder fill(int newLength) { return fill(newLength, ' '); } /** * Attempts to append <tt>c</tt> until the line gets the length <tt> * newLength</tt>. If the line is already longer than <tt>newLength</tt>, * then the internal strings is cut to <tt>newLength</tt>. * @param newLength New length of the last line. * @param c Character to append. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder fillOrCut(int newLength, char c) { if (newLength < 0) { throw new IllegalArgumentException(); } int lineStart = _delegate.lastIndexOf(NL); if (lineStart == -1) { lineStart = 0; } else { lineStart += NL.length(); } int lineLen = _delegate.length() - lineStart; if (newLength < lineLen) { _delegate = new StringBuilder(_delegate.substring(0, lineStart + newLength)); return this; } return fill(newLength, c); } /** * Attempts to append <tt>c</tt> until the buffer gets the length <tt> * newLength</tt>. If the buffer is already longer than <tt>newLength</tt>, * then the internal strings is cut to <tt>newLength</tt>. * @param newLength New length of the returned buffer. * @param c Character to append. * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder fillOrCutBuffer(int newLength, char c) { if (newLength < _delegate.length()) { _delegate = new StringBuilder(_delegate.substring(0, newLength)); return this; } for (int i = _delegate.length(); i < newLength; i++ ) { _delegate.append(c); } return this; } /** * @return length of the internal builder. */ public int length() { return _delegate.length(); } /** * Inserts the string into this character sequence. * * @param offset the offset * @param str the string * @return The updated instance of FormattedStringBuilder. */ public FormattedStringBuilder insert(int offset, String str) { _delegate.insert(offset, str); return this; } /** * Creates a new instance that is wrapped around a given <tt>StringBuilder * </tt>. * @param builder * @return the new instance of <tt>FormattedStringBuilder</tt>. */ public static FormattedStringBuilder wrap(StringBuilder builder) { FormattedStringBuilder b = new FormattedStringBuilder(); b._delegate = builder; return b; } /** * @see java.lang.Object#toString() */ public String toString() { return _delegate.toString(); } }