1 package org.djutils.decoderdumper;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.util.ArrayList;
7 import java.util.List;
8
9
10
11
12
13
14
15
16
17
18
19 public class Dumper<T>
20 {
21
22 private List<Decoder> decoders = new ArrayList<>();
23
24
25 private int address = 0;
26
27
28 private OutputStream outputStream = System.out;
29
30
31 private boolean suppressMultipleIdenticalLines = false;
32
33
34 private int suppressedCount = 0;
35
36
37 private String lastPattern = "";
38
39
40 private String lastOutput = "";
41
42
43 private static final String SUPPRESSEDOUTPUTINDICATORLINE = "*\n";
44
45
46
47
48
49 public Dumper(final int addressOffset)
50 {
51 this.address = addressOffset;
52 }
53
54
55
56
57 public Dumper()
58 {
59 this(0);
60 }
61
62
63
64
65
66
67 public Dumper<T> setOutputStream(final OutputStream newOutputStream)
68 {
69 this.outputStream = newOutputStream;
70 return this;
71 }
72
73
74
75
76
77
78
79 public Dumper<T> setSuppressMultipleIdenticalLines(final boolean newState)
80 {
81 this.suppressMultipleIdenticalLines = newState;
82 return this;
83 }
84
85
86
87
88
89 public void addDecoder(final Decoder decoder)
90 {
91 this.decoders.add(decoder);
92 }
93
94
95
96
97
98
99
100
101 public Dumper<T> addDecoder(final int index, final Decoder decoder) throws IndexOutOfBoundsException
102 {
103 this.decoders.add(index, decoder);
104 return this;
105 }
106
107
108
109
110
111
112 private void writeOutput(final String outputText) throws IOException
113 {
114 this.outputStream.write(outputText.getBytes("UTF-8"));
115 }
116
117
118
119
120
121
122
123 private void writeFilteringOutput(final String outputText, final String pattern) throws IOException
124 {
125 if (this.suppressedCount > 0 && ((!this.suppressMultipleIdenticalLines) || (!pattern.equals(this.lastPattern))))
126 {
127
128 if (!outputText.equals(this.lastPattern))
129 {
130 writeOutput(this.lastOutput);
131 }
132 this.suppressedCount = 0;
133 }
134 this.lastOutput = outputText;
135 if ((!this.suppressMultipleIdenticalLines) || (!pattern.equals(this.lastPattern)))
136 {
137 writeOutput(outputText);
138 }
139 else
140 {
141
142 if (1 == this.suppressedCount++)
143 {
144
145 writeOutput(SUPPRESSEDOUTPUTINDICATORLINE);
146 }
147 }
148 this.lastPattern = pattern;
149 }
150
151
152
153
154
155
156
157 public boolean append(final byte theByte) throws IOException
158 {
159 boolean needFlush = false;
160 for (Decoder decoder : this.decoders)
161 {
162 needFlush |= decoder.append(this.address, theByte);
163 }
164 this.address++;
165 if (needFlush)
166 {
167 return flush();
168 }
169 return false;
170 }
171
172
173
174
175
176
177
178 public Dumper<T> append(final byte[] bytes) throws IOException
179 {
180 return append(bytes, 0, bytes.length);
181 }
182
183
184
185
186
187
188
189
190
191
192 public Dumper<T> append(final byte[] bytes, final int start, final int len) throws IOException
193 {
194 for (int pos = start; pos < start + len; pos++)
195 {
196 append(bytes[pos]);
197 }
198 return this;
199 }
200
201
202
203
204
205
206
207
208
209
210 public Dumper<T> append(final InputStream inputStream) throws IOException
211 {
212 byte[] buffer = new byte[8192];
213 int read;
214 while ((read = inputStream.read(buffer)) >= 0)
215 {
216 append(buffer, 0, read);
217 }
218 return this;
219 }
220
221
222
223
224
225
226
227 public boolean flush() throws IOException
228 {
229 StringBuilder result = new StringBuilder();
230 StringBuilder pattern = new StringBuilder();
231 int totalReturnedWidth = 0;
232 for (Decoder decoder : this.decoders)
233 {
234 String part = decoder.getResult();
235 totalReturnedWidth += part.length();
236 if (part.length() < decoder.getMaximumWidth())
237 {
238 String format = String.format("%%-%ds", decoder.getMaximumWidth());
239 part = String.format(format, part);
240 }
241 result.append(part);
242 if (!decoder.ignoreForIdenticalOutputCheck())
243 {
244 pattern.append(part);
245 }
246 }
247 writeFilteringOutput(totalReturnedWidth == 0 ? "" : result.toString(), pattern.toString());
248 return totalReturnedWidth > 0;
249 }
250
251
252
253
254
255 public int getMaximumWidth()
256 {
257 int result = 0;
258 for (Decoder decoder : this.decoders)
259 {
260 result += decoder.getMaximumWidth();
261 }
262 return result;
263 }
264
265 @Override
266 public String toString()
267 {
268 return "Dumper [decoders=" + this.decoders + ", address=" + this.address + ", outputStream=" + this.outputStream
269 + ", suppressMultipleIdenticalLines=" + this.suppressMultipleIdenticalLines + ", suppressedCount="
270 + this.suppressedCount + ", lastPattern=" + this.lastPattern + "]";
271 }
272
273 }