001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.htmltowiki; 020 021import java.io.IOException; 022import java.io.Writer; 023import java.util.regex.Matcher; 024import java.util.regex.Pattern; 025 026/** 027 * Part of the XHtmlToWikiTranslator. 028 * 029 */ 030// FIXME: Needs a better description as to how it works. 031public class WhitespaceTrimWriter extends Writer { 032 033 private final StringBuffer m_result = new StringBuffer(); 034 035 private StringBuffer m_buffer = new StringBuffer(); 036 037 private boolean m_trimMode = true; 038 039 public static final String NO_TRIMMED_SPACE = " "; 040 private static final Pattern ONLINE_PATTERN = Pattern.compile( ".*?\\n\\s*?", Pattern.MULTILINE ); 041 042 private boolean m_currentlyOnLineBegin = true; 043 044 /** 045 * {@inheritDoc} 046 */ 047 @Override 048 public void flush() 049 { 050 if( m_buffer.length() > 0 ) 051 { 052 String s = m_buffer.toString(); 053 s = s.replaceAll( "\r\n", "\n" ); 054 if( m_trimMode ) 055 { 056 s = s.replaceAll( "(\\w+) \\[\\?\\|Edit\\.jsp\\?page=\\1\\]", "[$1]" ); 057 s = s.replaceAll( "\n{2,}", "\n\n" ); 058 s = s.replaceAll( "\\p{Blank}+", " " ); 059 s = s.replaceAll( "[ ]*\n[ ]*", "\n" ); 060 s = replacePluginNewlineBackslashes( s ); 061 s = s.replace( NO_TRIMMED_SPACE, " " ); 062 } 063 m_result.append( s ); 064 m_buffer = new StringBuffer(); 065 } 066 } 067 068 private String replacePluginNewlineBackslashes( String s ) 069 { 070 final Pattern p = Pattern.compile( "\\{\\{\\{(.*?)\\}\\}\\}|\\{\\{(.*?)\\}\\}|\\[\\{(.*?)\\}\\]", Pattern.DOTALL 071 + Pattern.MULTILINE ); 072 final Matcher m = p.matcher( s ); 073 final StringBuffer sb = new StringBuffer(); 074 while( m.find() ) 075 { 076 final String groupEscaped = m.group().replaceAll( "\\\\|\\$", "\\\\$0" ); 077 if( m.group( 3 ) != null ) 078 { 079 m.appendReplacement( sb, groupEscaped.replaceAll( "\\\\\\\\\\\\\\\\", "\n" ) ); 080 } 081 else 082 { 083 m.appendReplacement( sb, groupEscaped ); 084 } 085 } 086 m.appendTail( sb ); 087 s = sb.toString(); 088 return s; 089 } 090 091 /** 092 * Returns true, if this Writer is currently trimming any whitespaces. 093 * 094 * @return True, if trimming. 095 */ 096 public boolean isWhitespaceTrimMode() 097 { 098 return m_trimMode; 099 } 100 101 /** 102 * Set the trimming mode on/off. 103 * 104 * @param trimMode True, if you want trimming to be turned on. False otherwise. 105 */ 106 public void setWhitespaceTrimMode(final boolean trimMode ) 107 { 108 if( m_trimMode != trimMode ) 109 { 110 flush(); 111 m_trimMode = trimMode; 112 } 113 } 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public void write(final char[] arg0, final int arg1, final int arg2 ) throws IOException 120 { 121 m_buffer.append( arg0, arg1, arg2 ); 122 m_currentlyOnLineBegin = ONLINE_PATTERN.matcher( m_buffer ).matches(); 123 } 124 125 /** 126 * {@inheritDoc} 127 */ 128 @Override 129 public void close() throws IOException 130 {} 131 132 /** 133 * {@inheritDoc} 134 */ 135 @Override 136 public String toString() 137 { 138 flush(); 139 return m_result.toString(); 140 } 141 142 /** 143 * Returns true, if the writer is currently writing a line start. 144 * 145 * @return True or false. 146 */ 147 public boolean isCurrentlyOnLineBegin() 148 { 149 return m_currentlyOnLineBegin; 150 } 151}