1c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinpackage org.hamcrest; 2c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 3c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport org.hamcrest.internal.ArrayIterator; 4c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport org.hamcrest.internal.SelfDescribingValueIterator; 5c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 6c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport java.util.Arrays; 7c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport java.util.Iterator; 8c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 9c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport static java.lang.String.valueOf; 10c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 11c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin/** 12c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * A {@link Description} that is stored as a string. 13c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin */ 14c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinpublic abstract class BaseDescription implements Description { 15c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 16c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 17c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public Description appendText(String text) { 18c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(text); 19c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return this; 20c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 21c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 22c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 23c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public Description appendDescriptionOf(SelfDescribing value) { 24c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin value.describeTo(this); 25c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return this; 26c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 27c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 28c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 29c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public Description appendValue(Object value) { 30c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin if (value == null) { 31c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("null"); 32c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value instanceof String) { 33c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin toJavaSyntax((String) value); 34c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value instanceof Character) { 35c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('"'); 36c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin toJavaSyntax((Character) value); 37c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('"'); 38c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value instanceof Short) { 39c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('<'); 40c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(descriptionOf(value)); 41c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("s>"); 42c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value instanceof Long) { 43c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('<'); 44c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(descriptionOf(value)); 45c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("L>"); 46c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value instanceof Float) { 47c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('<'); 48c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(descriptionOf(value)); 49c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("F>"); 50c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else if (value.getClass().isArray()) { 51c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin appendValueList("[",", ","]", new ArrayIterator(value)); 52c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } else { 53c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('<'); 54c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(descriptionOf(value)); 55c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('>'); 56c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 57c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return this; 58c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 59c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 60c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private String descriptionOf(Object value) { 61c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin try { 62c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return valueOf(value); 63c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 64c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin catch (Exception e) { 65c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return value.getClass().getName() + "@" + Integer.toHexString(value.hashCode()); 66c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 67c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 68c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 69c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 70c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public <T> Description appendValueList(String start, String separator, String end, T... values) { 71c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return appendValueList(start, separator, end, Arrays.asList(values)); 72c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 73c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 74c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 75c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) { 76c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return appendValueList(start, separator, end, values.iterator()); 77c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 78c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 79c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) { 80c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values)); 81c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 82c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 83c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 84c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) { 85c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return appendList(start, separator, end, values.iterator()); 86c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 87c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 88c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) { 89c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin boolean separate = false; 90c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 91c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(start); 92c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin while (i.hasNext()) { 93c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin if (separate) append(separator); 94c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin appendDescriptionOf(i.next()); 95c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin separate = true; 96c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 97c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(end); 98c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 99c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return this; 100c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 101c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 102c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin /** 103c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * Append the String <var>str</var> to the description. 104c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * The default implementation passes every character to {@link #append(char)}. 105c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * Override in subclasses to provide an efficient implementation. 106c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin */ 107c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin protected void append(String str) { 108c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin for (int i = 0; i < str.length(); i++) { 109c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(str.charAt(i)); 110c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 111c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 112c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 113c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin /** 114c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * Append the char <var>c</var> to the description. 115c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin */ 116c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin protected abstract void append(char c); 117c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 118c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private void toJavaSyntax(String unformatted) { 119c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('"'); 120c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin for (int i = 0; i < unformatted.length(); i++) { 121c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin toJavaSyntax(unformatted.charAt(i)); 122c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 123c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append('"'); 124c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 125c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 126c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private void toJavaSyntax(char ch) { 127c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin switch (ch) { 128c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin case '"': 129c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("\\\""); 130c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin break; 131c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin case '\n': 132c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("\\n"); 133c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin break; 134c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin case '\r': 135c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("\\r"); 136c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin break; 137c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin case '\t': 138c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append("\\t"); 139c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin break; 140c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin default: 141c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin append(ch); 142c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 143c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 144c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin} 145