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 */
019 package org.apache.wiki.htmltowiki;
020
021 import java.io.IOException;
022 import java.io.Writer;
023 import java.util.regex.Matcher;
024 import java.util.regex.Pattern;
025
026 /**
027 * Part of the XHtmlToWikiTranslator.
028 *
029 */
030 // FIXME: Needs a better description as to how it works.
031 public 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 }