/******************************************************************************* * Copyright (c) 2016 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package melnorme.utilbox.misc; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import java.util.function.Consumer; import melnorme.utilbox.collections.Indexable; /** * Helper for more complex toString printing. */ public class ToStringHelper { public interface ToString { @Override public String toString(); default String defaultToString() { ToStringHelper sh = new ToStringHelper(); toString(sh); return sh.getString(); } void toString(ToStringHelper sh); } public static abstract class DefaultToString implements ToString { @Override public String toString() { return defaultToString(); } } /* ----------------- ----------------- */ protected final String newline; protected final String indentationUnit = " "; protected final StringBuilder sb; protected int indentation = 0; protected boolean afterNewline = false; protected boolean preventNextIndentation; public ToStringHelper(String newline, StringBuilder sb) { this.newline = newline; this.sb = sb; } public ToStringHelper() { this("\n", new StringBuilder()); } @Override public String toString() { return sb.toString(); } public String getString() { return sb.toString(); } public String getIndentationUnit() { return indentationUnit; } public String getNewline() { return newline; } public void writeIndentation() { if(preventNextIndentation) { preventNextIndentation = false; return; } append(getIndentationString()); } public String getIndentationString() { return StringUtil.newFilledString(indentation, getIndentationUnit()); } public void append(String string) { this.afterNewline = false; sb.append(string); } public void writeNewline() { if(!afterNewline) { append(getNewline()); } this.afterNewline = true; } /* ----------------- ----------------- */ public void writeElement(Object element) { doWriteElement(element); } protected void doWriteElement(Object element) { if(element == null) { return; } innerWriteElem(element); writeNewline(); } public void innerWriteElem(Object obj) { if(obj == null) { return; } if(obj instanceof ToString) { ToString toString = (ToString) obj; toString.toString(this); } else if(obj instanceof Iterable<?>) { Iterable<?> iterable = (Iterable<?>) obj; listToString("[", iterable, "]").toString(this); } else { writeIndentation(); sb.append(obj); } } public void writeElementWithPrefix(String prefix, Object element) { writeElementWithPrefix(prefix, element, false); } public void writeElementWithPrefix(String prefix, Object element, boolean ignoreNull) { if(ignoreNull && element == null) { return; } append(getIndentationString()); append(prefix); if(element == null) { element = "null"; } this.preventNextIndentation = true; doWriteElement(element); } /* ----------------- ----------------- */ public void writeList(Indexable<?> list) { writeList("[", list, "]"); } public void writeList(String prefix, Indexable<?> indexable, String suffix) { if(indexable == null) { return; } listToString(prefix, indexable, suffix).toString(this); } public void writeBlock(String prefix, Consumer<ToStringHelper> blockWriter, String suffix) { assertNotNull(blockWriter); writeElement(prefix); indentation++; blockWriter.accept(this); indentation--; //writeNewline(); append(getIndentationString()); append(suffix); writeNewline(); } public ToString listToString(String prefix, Iterable<?> indexable, String suffix) { ToString listToString = new ToString() { @Override public void toString(ToStringHelper sh) { writeBlock(prefix, (sh2) -> { for (Object object : indexable) { sh.writeElement(object); } }, suffix); } }; return listToString; } }