All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.net.nntp.Article Maven / Gradle / Ivy

There is a newer version: 1.8.0
Show newest version
package panda.net.nntp;

import java.io.PrintStream;
import java.util.ArrayList;

/**
 * This is a class that contains the basic state needed for message retrieval and threading. With
 * thanks to Jamie Zawinski ([email protected])
 */
public class Article implements Threadable {
	private long articleNumber;
	private String subject;
	private String date;
	private String articleId;
	private String simplifiedSubject;
	private String from;
	private ArrayList references;
	private boolean isReply = false;

	public Article kid, next;

	public Article() {
		articleNumber = -1; // isDummy
	}

	/**
	 * Adds a message-id to the list of messages that this message references (i.e. replies to)
	 * 
	 * @param msgId the message id to add
	 */
	public void addReference(String msgId) {
		if (msgId == null || msgId.length() == 0) {
			return;
		}
		if (references == null) {
			references = new ArrayList();
		}
		isReply = true;
		for (String s : msgId.split(" ")) {
			references.add(s);
		}
	}

	/**
	 * Returns the MessageId references as an array of Strings
	 * 
	 * @return an array of message-ids
	 */
	public String[] getReferences() {
		if (references == null) {
			return new String[0];
		}
		return references.toArray(new String[references.size()]);
	}

	/**
	 * Attempts to parse the subject line for some typical reply signatures, and strip them out
	 */
	private void simplifySubject() {
		int start = 0;
		String subject = getSubject();
		int len = subject.length();

		boolean done = false;

		while (!done) {
			done = true;

			// skip whitespace
			// "Re: " breaks this
			while (start < len && subject.charAt(start) == ' ') {
				start++;
			}

			if (start < (len - 2) && (subject.charAt(start) == 'r' || subject.charAt(start) == 'R')
					&& (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) {

				if (subject.charAt(start + 2) == ':') {
					start += 3; // Skip "Re:"
					done = false;
				}
				else if (start < (len - 2) && (subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) {

					int i = start + 3;

					while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9') {
						i++;
					}

					if (i < (len - 1) && (subject.charAt(i) == ']' || subject.charAt(i) == ')')
							&& subject.charAt(i + 1) == ':') {
						start = i + 2;
						done = false;
					}
				}
			}

			if ("(no subject)".equals(simplifiedSubject)) {
				simplifiedSubject = "";
			}

			int end = len;

			while (end > start && subject.charAt(end - 1) < ' ') {
				end--;
			}

			if (start == 0 && end == len) {
				simplifiedSubject = subject;
			}
			else {
				simplifiedSubject = subject.substring(start, end);
			}
		}
	}

	/**
	 * Recursive method that traverses a pre-threaded graph (or tree) of connected Article objects
	 * and prints them out.
	 * 
	 * @param article the root of the article 'tree'
	 */
	public static void printThread(Article article) {
		printThread(article, 0, System.out);
	}

	/**
	 * Recursive method that traverses a pre-threaded graph (or tree) of connected Article objects
	 * and prints them out.
	 * 
	 * @param article the root of the article 'tree'
	 * @param ps the PrintStream to use
	 */
	public static void printThread(Article article, PrintStream ps) {
		printThread(article, 0, ps);
	}

	/**
	 * Recursive method that traverses a pre-threaded graph (or tree) of connected Article objects
	 * and prints them out.
	 * 
	 * @param article the root of the article 'tree'
	 * @param depth the current tree depth
	 */
	public static void printThread(Article article, int depth) {
		printThread(article, depth, System.out);
	}

	/**
	 * Recursive method that traverses a pre-threaded graph (or tree) of connected Article objects
	 * and prints them out.
	 * 
	 * @param article the root of the article 'tree'
	 * @param depth the current tree depth
	 * @param ps the PrintStream to use
	 */
	public static void printThread(Article article, int depth, PrintStream ps) {
		for (int i = 0; i < depth; ++i) {
			ps.print("==>");
		}
		ps.println(article.getSubject() + "\t" + article.getFrom() + "\t" + article.getArticleId());
		if (article.kid != null) {
			printThread(article.kid, depth + 1);
		}
		if (article.next != null) {
			printThread(article.next, depth);
		}
	}

	public String getArticleId() {
		return articleId;
	}

	public long getArticleNumberLong() {
		return articleNumber;
	}

	public String getDate() {
		return date;
	}

	public String getFrom() {
		return from;
	}

	public String getSubject() {
		return subject;
	}

	public void setArticleId(String string) {
		articleId = string;
	}

	public void setArticleNumber(long l) {
		articleNumber = l;
	}

	public void setDate(String string) {
		date = string;
	}

	public void setFrom(String string) {
		from = string;
	}

	public void setSubject(String string) {
		subject = string;
	}

	// @Override
	public boolean isDummy() {
		return (articleNumber == -1);
	}

	// @Override
	public String messageThreadId() {
		return articleId;
	}

	// @Override
	public String[] messageThreadReferences() {
		return getReferences();
	}

	// @Override
	public String simplifiedSubject() {
		if (simplifiedSubject == null) {
			simplifySubject();
		}
		return simplifiedSubject;
	}

	// @Override
	public boolean subjectIsReply() {
		return isReply;
	}

	// @Override
	public void setChild(Threadable child) {
		this.kid = (Article)child;
		flushSubjectCache();
	}

	private void flushSubjectCache() {
		simplifiedSubject = null;
	}

	// @Override
	public void setNext(Threadable next) {
		this.next = (Article)next;
		flushSubjectCache();
	}

	// @Override
	public Threadable makeDummy() {
		return new Article();
	}

	@Override
	public String toString() { // Useful for Eclipse debugging
		return articleNumber + " " + articleId + " " + subject;
	}

	// DEPRECATED METHODS - for API compatibility only - DO NOT USE

	@Deprecated
	public int getArticleNumber() {
		return (int)articleNumber;
	}

	@Deprecated
	public void setArticleNumber(int a) {
		articleNumber = a;
	}

	@Deprecated
	public void addHeaderField(String name, String val) {
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy