package ch.akuhn.util;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
public class PrintOn implements Appendable, Closeable {
private Appendable buf;
public PrintOn() {
this(new StringBuilder());
}
public PrintOn(Appendable buf) {
this.buf = buf;
}
public final PrintOn append(char c) {
try {
buf.append(c);
} catch (IOException ex) {
throw Throw.exception(ex);
}
return this;
}
public final PrintOn append(CharSequence string) {
try {
buf.append(string);
} catch (IOException ex) {
throw Throw.exception(ex);
}
return this;
}
public final PrintOn append(CharSequence string, int start, int end) {
try {
buf.append(string, start, end);
} catch (IOException ex) {
throw Throw.exception(ex);
}
return this;
}
public final PrintOn cr() {
return append('\n');
}
public final PrintOn print(double value) {
return append(Double.toString(value));
}
public final PrintOn print(int value) {
return append(Integer.toString(value));
}
public final PrintOn print(Object object) {
if (object == null) {
append("null");
}
// Custom #toString precedes.
else if (overridesToString(object)) {
append(object.toString());
}
// Print arrays as [elem, elem, elem, ...]
else if (object.getClass().isArray()) {
printEach(As.iterable(object));
}
// Print arrays as [elem, elem, elem, ...]
else if (object instanceof Iterable<?>) {
printEach(object);
}
else {
append(object.toString());
}
return this;
}
private void printEach(Object object) {
PrintOn out = new PrintOn(this);
out.append('[');
for (Object each: (Iterable<?>) object) out.separatedBy(", ").print(each);
out.append(']');
}
public final PrintOn space() {
return append(' ');
}
public final PrintOn tab() {
return append('\t');
}
@Override
public final String toString() {
return buf.toString();
}
public final void close() {
if (buf instanceof Closeable) {
try {
((Closeable) buf).close();
} catch (IOException ex) {
throw Throw.exception(ex);
}
}
}
boolean separate = false;
public final PrintOn separatedBy(String string) {
if (separate) this.append(string);
separate = true;
return this;
}
private boolean overridesToString(Object object) {
try {
Class<?> type = object.getClass();
Method toString = type.getMethod("toString");
return toString.getDeclaringClass() != Object.class;
} catch (SecurityException ex) {
throw Throw.exception(ex);
} catch (NoSuchMethodException ex) {
throw Throw.exception(ex);
}
}
public void beginLoop() {
separate = false;
}
public PrintOn p(String string) {
return this.append(string);
}
public PrintOn p(int n) {
return this.append(Integer.toString(n));
}
public PrintOn p(double d) {
return this.append(Double.toString(d));
}
public PrintOn comma() {
if (separate) this.append(',');
separate = true;
return this;
}
}