1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.nntp;
19
20 import java.io.PrintStream;
21 import java.util.ArrayList;
22 import java.util.Collections;
23
24 import org.apache.commons.net.util.NetConstants;
25
26
27
28
29 public class Article implements Threadable<Article> {
30
31
32
33
34
35
36
37 public static void printThread(final Article article) {
38 printThread(article, 0, System.out);
39 }
40
41
42
43
44
45
46
47 public static void printThread(final Article article, final int depth) {
48 printThread(article, depth, System.out);
49 }
50
51
52
53
54
55
56
57
58
59 public static void printThread(final Article article, final int depth, final PrintStream ps) {
60 for (int i = 0; i < depth; ++i) {
61 ps.print("==>");
62 }
63 ps.println(article.getSubject() + "\t" + article.getFrom() + "\t" + article.getArticleId());
64 if (article.kid != null) {
65 printThread(article.kid, depth + 1);
66 }
67 if (article.next != null) {
68 printThread(article.next, depth);
69 }
70 }
71
72
73
74
75
76
77
78
79 public static void printThread(final Article article, final PrintStream ps) {
80 printThread(article, 0, ps);
81 }
82
83 private long articleNumber;
84 private String subject;
85 private String date;
86 private String articleId;
87
88 private String simplifiedSubject;
89
90 private String from;
91 private ArrayList<String> references;
92
93 private boolean isReply;
94
95
96
97
98
99
100 @Deprecated
101 public Article kid;
102
103
104
105
106
107
108 @Deprecated
109 public Article next;
110
111
112
113
114 public Article() {
115 articleNumber = -1;
116 }
117
118
119
120
121
122
123
124 @Deprecated
125 public void addHeaderField(final String name, final String val) {
126
127 }
128
129
130
131
132
133
134 public void addReference(final String msgId) {
135 if (msgId == null || msgId.isEmpty()) {
136 return;
137 }
138 if (references == null) {
139 references = new ArrayList<>();
140 }
141 isReply = true;
142 Collections.addAll(references, msgId.split(" "));
143 }
144
145 private void flushSubjectCache() {
146 simplifiedSubject = null;
147 }
148
149
150
151
152
153
154 public String getArticleId() {
155 return articleId;
156 }
157
158
159
160
161
162
163 @Deprecated
164 public int getArticleNumber() {
165 return (int) articleNumber;
166 }
167
168
169
170
171
172
173 public long getArticleNumberLong() {
174 return articleNumber;
175 }
176
177
178
179
180
181
182
183 public Article getChild() {
184 return kid;
185 }
186
187
188
189
190
191
192 public String getDate() {
193 return date;
194 }
195
196
197
198
199
200
201 public String getFrom() {
202 return from;
203 }
204
205
206
207
208
209
210
211 public Article getNext() {
212 return next;
213 }
214
215
216
217
218
219
220 public String[] getReferences() {
221 if (references == null) {
222 return NetConstants.EMPTY_STRING_ARRAY;
223 }
224 return references.toArray(NetConstants.EMPTY_STRING_ARRAY);
225 }
226
227
228
229
230
231
232 public String getSubject() {
233 return subject;
234 }
235
236 @Override
237 public boolean isDummy() {
238 return articleNumber == -1;
239 }
240
241 @Override
242 public Article makeDummy() {
243 return new Article();
244 }
245
246 @Override
247 public String messageThreadId() {
248 return articleId;
249 }
250
251 @Override
252 public String[] messageThreadReferences() {
253 return getReferences();
254 }
255
256
257
258
259
260
261 public void setArticleId(final String string) {
262 articleId = string;
263 }
264
265
266
267
268
269
270 @Deprecated
271 public void setArticleNumber(final int articleNumber) {
272 this.articleNumber = articleNumber;
273 }
274
275
276
277
278
279
280 public void setArticleNumber(final long articleNumber) {
281 this.articleNumber = articleNumber;
282 }
283
284 @Override
285 public void setChild(final Article child) {
286 this.kid = child;
287 flushSubjectCache();
288 }
289
290
291
292
293
294
295 public void setDate(final String date) {
296 this.date = date;
297 }
298
299
300
301
302
303
304 public void setFrom(final String from) {
305 this.from = from;
306 }
307
308 @Override
309 public void setNext(final Article next) {
310 this.next = next;
311 flushSubjectCache();
312 }
313
314
315
316
317
318
319 public void setSubject(final String subject) {
320 this.subject = subject;
321 }
322
323 @Override
324 public String simplifiedSubject() {
325 if (simplifiedSubject == null) {
326 simplifySubject();
327 }
328 return simplifiedSubject;
329 }
330
331
332
333
334 private void simplifySubject() {
335 int start = 0;
336 final String subject = getSubject();
337 final int len = subject.length();
338
339 boolean done = false;
340
341 while (!done) {
342 done = true;
343
344
345
346 while (start < len && subject.charAt(start) == ' ') {
347 start++;
348 }
349
350 if (start < len - 2 && (subject.charAt(start) == 'r' || subject.charAt(start) == 'R')
351 && (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) {
352
353 if (subject.charAt(start + 2) == ':') {
354 start += 3;
355 done = false;
356 } else if (start < len - 2 && (subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) {
357
358 int i = start + 3;
359
360 while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9') {
361 i++;
362 }
363
364 if (i < len - 1 && (subject.charAt(i) == ']' || subject.charAt(i) == ')') && subject.charAt(i + 1) == ':') {
365 start = i + 2;
366 done = false;
367 }
368 }
369 }
370
371 if ("(no subject)".equals(simplifiedSubject)) {
372 simplifiedSubject = "";
373 }
374
375 int end = len;
376
377 while (end > start && subject.charAt(end - 1) < ' ') {
378 end--;
379 }
380
381 if (start == 0 && end == len) {
382 simplifiedSubject = subject;
383 } else {
384 simplifiedSubject = subject.substring(start, end);
385 }
386 }
387 }
388
389 @Override
390 public boolean subjectIsReply() {
391 return isReply;
392 }
393
394 @Override
395 public String toString() {
396 return articleNumber + " " + articleId + " " + subject;
397 }
398
399 }