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 034 private StringBuffer m_result = new StringBuffer(); 035 036 private StringBuffer m_buffer = new StringBuffer(); 037 038 private boolean m_trimMode = true; 039 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 } 062 m_result.append( s ); 063 m_buffer = new StringBuffer(); 064 } 065 } 066 067 private String replacePluginNewlineBackslashes( String s ) 068 { 069 Pattern p = Pattern.compile( "\\{\\{\\{(.*?)\\}\\}\\}|\\{\\{(.*?)\\}\\}|\\[\\{(.*?)\\}\\]", Pattern.DOTALL 070 + Pattern.MULTILINE ); 071 Matcher m = p.matcher( s ); 072 StringBuffer sb = new StringBuffer(); 073 while( m.find() ) 074 { 075 String groupEscaped = m.group().replaceAll( "\\\\|\\$", "\\\\$0" ); 076 if( m.group( 3 ) != null ) 077 { 078 m.appendReplacement( sb, groupEscaped.replaceAll( "\\\\\\\\\\\\\\\\", "\n" ) ); 079 } 080 else 081 { 082 m.appendReplacement( sb, groupEscaped ); 083 } 084 } 085 m.appendTail( sb ); 086 s = sb.toString(); 087 return s; 088 } 089 090 /** 091 * Returns true, if this Writer is currently trimming any whitespaces. 092 * 093 * @return True, if trimming. 094 */ 095 public boolean isWhitespaceTrimMode() 096 { 097 return m_trimMode; 098 } 099 100 /** 101 * Set the trimming mode on/off. 102 * 103 * @param trimMode True, if you want trimming to be turned on. False otherwise. 104 */ 105 public void setWhitespaceTrimMode( boolean trimMode ) 106 { 107 if( m_trimMode != trimMode ) 108 { 109 flush(); 110 m_trimMode = trimMode; 111 } 112 } 113 114 /** 115 * {@inheritDoc} 116 */ 117 @Override 118 public void write( char[] arg0, int arg1, int arg2 ) throws IOException 119 { 120 m_buffer.append( arg0, arg1, arg2 ); 121 m_currentlyOnLineBegin = ONLINE_PATTERN.matcher( m_buffer ).matches(); 122 } 123 124 /** 125 * {@inheritDoc} 126 */ 127 @Override 128 public void close() throws IOException 129 {} 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public String toString() 136 { 137 flush(); 138 return m_result.toString(); 139 } 140 141 /** 142 * Returns true, if the writer is currently writing a line start. 143 * 144 * @return True or false. 145 */ 146 public boolean isCurrentlyOnLineBegin() 147 { 148 return m_currentlyOnLineBegin; 149 } 150}