package xapi.fu; import static xapi.fu.Immutable.immutable1; import static xapi.fu.Out1.EMPTY_STRING; import static xapi.fu.Out1.NEW_LINE; import static xapi.fu.X_Fu.STRING_DUPLICATE; import java.util.Iterator; /** * @author James X. Nelson (james@wetheinter.net) * Created on 4/18/16. */ public interface Coercible { Out1<String> LEFT_BRACE = immutable1("["); Out1<String> RIGHT_BRACE = immutable1("]"); default String listSeparator() { return ""; } default String coerce(Object obj) { return coerce(obj, LEFT_BRACE, RIGHT_BRACE, NEW_LINE, EMPTY_STRING); } default String coerce(Object obj, boolean first) { StringBuilder b = new StringBuilder(); if (!first) { b.append(perIndent()); b.append(listSeparator()); } b.append(coerce(obj, LEFT_BRACE, RIGHT_BRACE, NEW_LINE, EMPTY_STRING)); return b.toString(); } default String coerce(Object obj, Out1<String> before, Out1<String> after, Out1<String> newline, Out1<String> emptyString) { final StringBuilder b = new StringBuilder(); final String listSeparator = listSeparator(); final boolean printEdges = !listSeparator.isEmpty(); final In1Out1<Object, String> descend = next -> coerce(next, before.map(STRING_DUPLICATE), after.map(STRING_DUPLICATE), newline.map(s -> ( s.startsWith("\n//") ? // This will print n repetitions of "//x\\" on each descended newline "\n////x\\\\\n" + s.substring(3).replaceFirst("\n", "//x\\\\\n") : s + perIndent() ) ), emptyString ); if (obj instanceof Iterable){ Iterator i = ((Iterable)obj).iterator(); if (i.hasNext()) { if (printEdges) { b.append(before.out1()); } final Object next = i.next(); if (isAddNewlines(next)) { String newlineSurround = newline.out1(); b.append(newlineSurround); } b.append(descend.io(next)); for (;i.hasNext();) { final Object value = i.next(); b.append(listSeparator); b.append(descend.io(value)); } } else { // Iterator was empty... print our empty string (notify it was empty) b.append(emptyString.out1()); } if (printEdges) { b.append(after.out1()); } return b.toString(); } else if (obj != null && obj.getClass().isArray()){ int max = X_Fu.getLength(obj); if (max == 0) { if (listSeparator.isEmpty()) { return emptyString.out1(); } return b .append(before.out1()) .append(emptyString.out1()) .append(after.out1()) .toString(); } if (printEdges) { b.append(before.out1()); } b.append(descend.io(X_Fu.getValue(obj, 0))); for (int i = 1; i < max; i++ ) { final Object value = X_Fu.getValue(obj, i); if (isAddNewlines(value)) { String newlineSurround = newline.out1(); b.append(newlineSurround); } b.append(listSeparator); b.append(descend.io(value)); } if (printEdges) { b.append(after.out1()); } return b.toString(); } else { return String.valueOf(obj); } } default boolean isAddNewlines(Object next) { return next instanceof Iterable || X_Fu.getLength(next) > 0 || (next instanceof String && ((String)next).startsWith("\n//x")); } default String perIndent() { return " "; } }