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