11ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotpackage org.hamcrest;
21ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
31ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotimport static java.lang.String.valueOf;
41ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
51ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotimport java.util.Arrays;
61ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotimport java.util.Iterator;
71ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
81ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotimport org.hamcrest.internal.ArrayIterator;
91ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotimport org.hamcrest.internal.SelfDescribingValueIterator;
101ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
111ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot/**
121ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot * A {@link Description} that is stored as a string.
131ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot */
141ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabotpublic abstract class BaseDescription implements Description {
151ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    public Description appendText(String text) {
161ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        append(text);
171ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        return this;
181ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
191ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
201ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    public Description appendDescriptionOf(SelfDescribing value) {
211ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    	value.describeTo(this);
221ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    	return this;
231ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
241ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
251ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    public Description appendValue(Object value) {
261ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        if (value == null) {
271ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append("null");
281ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value instanceof String) {
291ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            toJavaSyntax((String) value);
301ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value instanceof Character) {
311ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('"');
321ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            toJavaSyntax((Character) value);
331ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('"');
341ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value instanceof Short) {
351ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('<');
361ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append(valueOf(value));
371ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append("s>");
381ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value instanceof Long) {
391ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('<');
401ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append(valueOf(value));
411ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append("L>");
421ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value instanceof Float) {
431ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('<');
441ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append(valueOf(value));
451ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append("F>");
461ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else if (value.getClass().isArray()) {
471ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        	appendValueList("[",", ","]", new ArrayIterator(value));
481ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        } else {
491ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('<');
501ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append(valueOf(value));
511ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            append('>');
521ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        }
531ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        return this;
541ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
551ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
561ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    public <T> Description appendValueList(String start, String separator, String end, T... values) {
571ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        return appendValueList(start, separator, end, Arrays.asList(values));
581ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot	}
591ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
601ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot	public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) {
611ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot		return appendValueList(start, separator, end, values.iterator());
621ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot	}
631ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
641ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot	private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) {
651ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot		return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values));
661ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot	}
671ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
681ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) {
691ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        return appendList(start, separator, end, values.iterator());
701ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
711ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
721ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) {
731ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        boolean separate = false;
741ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
751ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        append(start);
761ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        while (i.hasNext()) {
771ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            if (separate) append(separator);
781ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            appendDescriptionOf(i.next());
791ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            separate = true;
801ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        }
811ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        append(end);
821ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
831ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        return this;
841ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
851ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
861ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
871ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    /** Append the String <var>str</var> to the description.
881ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot     *  The default implementation passes every character to {@link #append(char)}.
891ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot     *  Override in subclasses to provide an efficient implementation.
901ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot     */
911ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    protected void append(String str) {
921ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    	for (int i = 0; i < str.length(); i++) {
931ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    		append(str.charAt(i));
941ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    	}
951ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
961ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
971ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    /** Append the char <var>c</var> to the description.
981ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot     */
991ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    protected abstract void append(char c);
1001ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
1011ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    private void toJavaSyntax(String unformatted) {
1021ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        append('"');
1031ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        for (int i = 0; i < unformatted.length(); i++) {
1041ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            toJavaSyntax(unformatted.charAt(i));
1051ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        }
1061ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        append('"');
1071ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
1081ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot
1091ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    private void toJavaSyntax(char ch) {
1101ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        switch (ch) {
1111ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            case '"':
1121ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                append("\\\"");
1131ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                break;
1141ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            case '\n':
1151ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                append("\\n");
1161ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                break;
1171ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            case '\r':
1181ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                append("\\r");
1191ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                break;
1201ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            case '\t':
1211ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                append("\\t");
1221ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                break;
1231ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot            default:
1241ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot                append(ch);
1251ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot        }
1261ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot    }
1271ecfda91236a8970119144e59e0ba6113dc22c0fBrett Chabot}
128