📄 quotefilter.java
字号:
/**
* $RCSfile: QuoteFilter.java,v $
* $Revision: 1.1.1.1 $
* $Date: 2002/09/09 13:51:06 $
*
* Copyright (C) 1999-2002 CoolServlets, Inc. All rights reserved.
*
* This software is the proprietary information of CoolServlets, Inc.
* Use is subject to license terms.
*/
package com.jivesoftware.forum.filter;
import com.jivesoftware.forum.*;
import com.jivesoftware.util.StringUtils;
import java.io.*;
import java.util.*;
/**
* A ForumMessageFilter that highlights quoted messages
* based upon the level of indentation - very similar to
* how groups.google.com highlights quotes.
*
* @author Bruce Ritchie
*/
public class QuoteFilter extends ForumMessageFilter {
private ArrayList quoteColors;
private char quoteChar;
private boolean reformatTextEnabled;
public QuoteFilter() {
quoteColors = new ArrayList();
quoteColors.add("#660066");
quoteColors.add("#007777");
quoteColors.add("#3377ff");
quoteColors.add("#669966");
quoteColors.add("#660000");
quoteChar = '>';
reformatTextEnabled = false;
}
/**
* Clones a new filter that will have the same properties and that
* will wrap around the specified message.
*
* @param message the ForumMessage to wrap the new filter around.
*/
public ForumMessageFilter clone(ForumMessage message){
QuoteFilter filter = new QuoteFilter();
filter.quoteColors = quoteColors;
filter.reformatTextEnabled = reformatTextEnabled;
filter.quoteChar = quoteChar;
filter.message = message;
return filter;
}
public boolean isCacheable() {
return true;
}
//FROM THE FORUMMESSAGE INTERFACE//
/**
* Returns the subject of the message with URLs changed to working links if
* filtering on the subject is enabled.
*
* @return the filtered message subject.
*/
public String getSubject() {
return message.getSubject();
}
/**
* Returns the body of the message with quoted lines quoted appropriately.
*
* @return the filtered message body.
*/
public String getBody() {
return parseQuotes(message.getBody());
}
//OTHER METHODS//
public String getQuoteColors() {
StringBuffer sb = new StringBuffer();
for(int x=0; x < quoteColors.size(); x++) {
sb.append(quoteColors.get(x).toString());
if (x != quoteColors.size()-1) {
sb.append(",");
}
}
return sb.toString();
}
public void setQuoteColors(String prefix) {
if (prefix != null) {
quoteColors = new ArrayList();
StringTokenizer st = new StringTokenizer(prefix, ",");
while (st.hasMoreTokens()) {
quoteColors.add(st.nextToken());
}
}
}
public boolean isReformatTextEnabled() {
return reformatTextEnabled;
}
public void setReformatTextEnabled(boolean enabled) {
reformatTextEnabled = enabled;
}
public String getQuoteChar() {
return new Character(quoteChar).toString();
}
public void setQuoteChar(String c) {
if (c != null) {
quoteChar = c.trim().charAt(0);
}
}
/**
* This method takes a string which may contain quotes lines
* and quotes the lines accordingly. It does this
* by adding the prefix line postfix according to the appropriate
* quote level. An arbitrary level of quotes are available to be set, and
* once those are used up it restarts from the beginning of the list
*
* @param input the text to be converted.
* @returns the input string with the quoted lines handled accordingly.
*/
private String parseQuotes(String input) {
// Check if the string is null or zero length -- if so, return
// what was sent in.
if (input == null || input.length() == 0) {
return input;
}
StringBuffer sb = new StringBuffer(input.length() + 512);
BufferedReader br = new BufferedReader(new StringReader(input), 1024);
ArrayList lines = new ArrayList();
String line;
char chars[];
try {
while ((line = br.readLine()) != null) {
lines.add(line);
}
br.close();
}
catch (IOException e) { /* ignore */ }
// correct text formatting if requested
if (reformatTextEnabled) {
reformatText(lines);
}
for (int c = 0; c < lines.size(); c++) {
line = (String) lines.get(c);
chars = StringUtils.replace(line, ">", ">").toCharArray();
if (isQuoted(chars)) {
int count = countQuotes(chars) - 1;
sb.append("<font color=\"");
sb.append(quoteColors.get(count % quoteColors.size()).toString());
sb.append("\">");
sb.append(line);
// for all following lines that have the same quote level
// just append them to the buffer, we'll append the quotePostfix
// at the end. This saves on needless html being generated and
// reduces the size of the final html page. (Every little bit
// counts)
for (int g = c+1; g < lines.size(); g++) {
line = (String) lines.get(g);
chars = StringUtils.replace(line, ">", ">").toCharArray();
if (isQuoted(chars) && (countQuotes(chars) - 1 == count)) {
sb.append("\n").append(line);
c = g;
}
else {
break;
}
}
sb.append("</font>").append("\n");
}
else {
sb.append(line).append("\n");
}
}
return sb.toString();
}
/**
* This method takes a list of strings (one per line) and
* through some heuristics attempts to correct for badly wrapped
* lines.<p>
*
* This is allows for: <p>
*
* <ul>
* <li>Making the text easier to read</li>
* <li>Restoring the text format as close as possible to the original
* formatting of the text prior to being reformatted by a MUA such as
* Microsoft Outlook. MUA's often wrap lines of length > 76 characters
* regardless of whether they are quoted or not.</li>
* </ul>
*
* @param lines an arraylist of strings, one line/arraylist entry
*/
private void reformatText(ArrayList lines) {
char chars[];
int count;
int readAhead;
boolean isHTMLFilterActive = false;
for (int c = 0; c < lines.size(); c++) {
chars = getLineAsChar(lines, c);
// if this isn't a quoted line, skip it
if (!isQuoted(chars)) {
continue;
}
// check to see if we substituted any > text
if (chars.length < ((String) lines.get(c)).length()) {
isHTMLFilterActive = true;
}
count = countQuotes(chars);
readAhead = (lines.size() <= c + count + 1) ? lines.size() : c + count + 1;
LinkedList l = new LinkedList();
// For each quoted line, read ahead (n-1 quotes) lines to see
// if the following lines are actually wrapped text from the
// current quoted line.
//
// Notes: - If any of the following lines do not have < n quotes
// (no quote acceptable), they are not wrapped text. However
// if prior following lines fulfill all the other criteria,
// they are wrapped text
// - If any of the following lines have more than 2 words,
// they are not wrapped text
// - If any consecutive following lines have the same number
// of quotes, they are not wrapped text
// - If any of the following lines have less quotes than the
// previous following lines, they are not wrapped text
// - If the following line has no characters, they are not
// wrapped text
for (int g = c+1; g < readAhead; g++) {
chars = getLineAsChar(lines, g);
l.addLast(chars);
// rule 1
if (isQuoted(chars) && countQuotes(chars) > count) {
// System.err.println("Too many quotes - " + new String(chars));
l.removeLast();
break;
}
// rule 2
if (countWords(chars) > 2) {
// System.err.println("Too many words - " + new String(chars));
l.removeLast();
break;
}
// rule 3
if (countQuotes(chars) == count) {
// System.err.println("same number of quotes - " + new String(chars));
l.removeLast();
break;
}
// rule 4
if (!checkQuoteConsistency(l)) {
// System.err.println("Quote Inconsistent - " + new String(chars));
l.removeLast();
break;
}
// rule 5
if (new String(chars).trim().length() < 1) {
// System.err.println("Empty line - " + new String(chars));
l.removeLast();
break;
}
}
// we have wrapped text
if (l.size() > 0) {
Iterator iter = l.iterator();
StringBuffer sb = new StringBuffer(l.size()+1 * 80);
String line = (String) lines.get(c);
if (isHTMLFilterActive) {
line = StringUtils.replace(line, ">", ">");
}
sb.append(line);
while (iter.hasNext()) {
chars = (char[]) iter.next();
sb.append(" ");
sb.append(stripQuotes(chars));
lines.remove(c+1);
}
lines.set(c, sb.toString());
}
}
}
private char[] getLineAsChar(ArrayList lines, int number) {
String line = (String) lines.get(number);
return StringUtils.replace(line, ">", ">").toCharArray();
}
private int countWords(char[] chars) {
String line = stripQuotes(chars).trim();
int count = 0;
for (int x=0; x < line.length(); x++) {
if (line.charAt(x) == ' ') {
count++;
}
}
return count + 1;
}
private boolean checkQuoteConsistency(LinkedList l) {
for (int c = l.size()-1; c > 0; c--) {
for (int g = 0; g < c; g++) {
if (countQuotes((char[]) l.get(c)) < countQuotes((char[]) l.get(g))) {
return false;
}
}
}
return true;
}
private boolean isQuoted(char[] chars) {
for (int c = 0; c < chars.length; c++) {
if (chars[c] == quoteChar) {
return true;
}
else if (chars[c] != ' ') {
return false;
}
}
return false;
}
private int countQuotes(char[] chars) {
int quoteCount = 0;
for (int c = 0; c < chars.length; c++) {
if (chars[c] == quoteChar) {
quoteCount++;
}
else if (chars[c] == ' ') {
continue;
}
else {
return quoteCount;
}
}
return quoteCount;
}
private String stripQuotes(char[] line) {
StringBuffer sb = new StringBuffer(new String(line));
boolean start = false;
for (int c = 0; c < sb.length(); c++) {
if (!start && sb.charAt(c) == quoteChar) {
sb.deleteCharAt(c);
if (c > 0) {
c--;
}
}
else if (!start && sb.charAt(c) != ' ') {
start = true;
}
}
return sb.toString().trim();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -