KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > net > nntp > Article


1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2001-2005 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" and
27  * "Apache Commons" must not be used to endorse or promote products
28  * derived from this software without prior written permission. For
29  * written permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without
33  * prior written permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  */

54  
55 package org.apache.commons.net.nntp;
56
57 import java.util.ArrayList JavaDoc;
58 import java.util.StringTokenizer JavaDoc;
59
60 /**
61  * This is a class that contains the basic state needed for message retrieval and threading.
62  * With thanks to Jamie Zawinski <jwz@jwz.org>
63  * @author rwinston <rwinston@checkfree.com>
64  *
65  */

66 public class Article implements Threadable {
67     private int articleNumber;
68     private String JavaDoc subject;
69     private String JavaDoc date;
70     private String JavaDoc articleId;
71     private String JavaDoc simplifiedSubject;
72     private String JavaDoc from;
73     private StringBuffer JavaDoc header;
74     private StringBuffer JavaDoc references;
75     private boolean isReply = false;
76     
77     public Article kid, next;
78
79     public Article() {
80         header = new StringBuffer JavaDoc();
81     }
82
83     /**
84      * Adds an arbitrary header key and value to this message's header.
85      * @param name the header name
86      * @param val the header value
87      */

88     public void addHeaderField(String JavaDoc name, String JavaDoc val) {
89         header.append(name);
90         header.append(": ");
91         header.append(val);
92         header.append('\n');
93     }
94     
95     /**
96      * Adds a message-id to the list of messages that this message references (i.e. replies to)
97      * @param msgId
98      */

99     public void addReference(String JavaDoc msgId) {
100         if (references == null) {
101             references = new StringBuffer JavaDoc();
102             references.append("References: ");
103         }
104         references.append(msgId);
105         references.append("\t");
106     }
107
108     /**
109      * Returns the MessageId references as an array of Strings
110      * @return an array of message-ids
111      */

112     public String JavaDoc[] getReferences() {
113         if (references == null)
114             return new String JavaDoc[0];
115         ArrayList JavaDoc list = new ArrayList JavaDoc();
116         int terminator = references.toString().indexOf(':');
117         StringTokenizer JavaDoc st =
118             new StringTokenizer JavaDoc(references.substring(terminator), "\t");
119         while (st.hasMoreTokens()) {
120             list.add(st.nextToken());
121         }
122         return (String JavaDoc[]) list.toArray();
123     }
124     
125     /**
126      * Attempts to parse the subject line for some typical reply signatures, and strip them out
127      *
128      */

129     private void simplifySubject() {
130             int start = 0;
131             String JavaDoc subject = getSubject();
132             int len = subject.length();
133
134             boolean done = false;
135
136             while (!done) {
137                 done = true;
138
139                 // skip whitespace
140
// "Re: " breaks this
141
while (start < len && subject.charAt(start) == ' ') {
142                     start++;
143                 }
144
145                 if (start < (len - 2)
146                     && (subject.charAt(start) == 'r' || subject.charAt(start) == 'R')
147                     && (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) {
148
149                     if (subject.charAt(start + 2) == ':') {
150                         start += 3; // Skip "Re:"
151
isReply = true;
152                         done = false;
153                     } else if (
154                         start < (len - 2)
155                         &&
156                         (subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) {
157                         
158                         int i = start + 3;
159
160                         while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9')
161                             i++;
162
163                         if (i < (len - 1)
164                             && (subject.charAt(i) == ']' || subject.charAt(i) == ')')
165                             && subject.charAt(i + 1) == ':') {
166                             start = i + 2;
167                             isReply = true;
168                             done = false;
169                         }
170                     }
171                 }
172
173                 if (simplifiedSubject == "(no subject)")
174                     simplifiedSubject = "";
175
176                 int end = len;
177
178                 while (end > start && subject.charAt(end - 1) < ' ')
179                     end--;
180
181                 if (start == 0 && end == len)
182                     simplifiedSubject = subject;
183                 else
184                     simplifiedSubject = subject.substring(start, end);
185             }
186         }
187         
188     /**
189      * Recursive method that traverses a pre-threaded graph (or tree)
190      * of connected Article objects and prints them out.
191      * @param article the root of the article 'tree'
192      * @param depth the current tree depth
193      */

194     public static void printThread(Article article, int depth) {
195             for (int i = 0; i < depth; ++i)
196                 System.out.print("==>");
197             System.out.println(article.getSubject() + "\t" + article.getFrom());
198             if (article.kid != null)
199                 printThread(article.kid, depth + 1);
200             if (article.next != null)
201                 printThread(article.next, depth);
202     }
203
204     public String JavaDoc getArticleId() {
205         return articleId;
206     }
207
208     public int getArticleNumber() {
209         return articleNumber;
210     }
211
212     public String JavaDoc getDate() {
213         return date;
214     }
215
216     public String JavaDoc getFrom() {
217         return from;
218     }
219
220     public String JavaDoc getSubject() {
221         return subject;
222     }
223
224     public void setArticleId(String JavaDoc string) {
225         articleId = string;
226     }
227
228     public void setArticleNumber(int i) {
229         articleNumber = i;
230     }
231
232     public void setDate(String JavaDoc string) {
233         date = string;
234     }
235
236     public void setFrom(String JavaDoc string) {
237         from = string;
238     }
239
240     public void setSubject(String JavaDoc string) {
241         subject = string;
242     }
243
244     
245     public boolean isDummy() {
246         return (getSubject() == null);
247     }
248
249     public String JavaDoc messageThreadId() {
250         return articleId;
251     }
252     
253     public String JavaDoc[] messageThreadReferences() {
254         return getReferences();
255     }
256     
257     public String JavaDoc simplifiedSubject() {
258         if(simplifiedSubject == null)
259             simplifySubject();
260         return simplifiedSubject;
261     }
262
263     
264     public boolean subjectIsReply() {
265         if(simplifiedSubject == null)
266             simplifySubject();
267         return isReply;
268     }
269
270     
271     public void setChild(Threadable child) {
272         this.kid = (Article) child;
273         flushSubjectCache();
274     }
275
276     private void flushSubjectCache() {
277         simplifiedSubject = null;
278     }
279
280     
281     public void setNext(Threadable next) {
282         this.next = (Article)next;
283         flushSubjectCache();
284     }
285
286     
287     public Threadable makeDummy() {
288         return (Threadable)new Article();
289     }
290 }
291
Popular Tags