o deprecated toText and move this method to PluginUtils

git-svn-id: https://svn.apache.org/repos/asf/maven/plugin-tools/trunk@683374 13f79535-47bb-0310-9956-ffa450edef68
master
Vincent Siveton 2008-08-06 19:03:43 +00:00
parent 2900246e01
commit 741179ac0c
2 changed files with 280 additions and 258 deletions

View File

@ -22,7 +22,6 @@ package org.apache.maven.tools.plugin.generator;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
@ -30,12 +29,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
@ -130,7 +123,7 @@ public class PluginHelpGenerator
/**
* Creates a minimalistic mojo descriptor for the generated help goal.
*
*
* @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be
* <code>null</code>.
* @return The mojo descriptor for the generated help goal, never <code>null</code>.
@ -202,13 +195,13 @@ public class PluginHelpGenerator
{
throw new RuntimeException( "Failed to setup parameters for help goal", e );
}
return descriptor;
}
/**
* Find the best package name, based on the number of hits of actual Mojo classes.
*
*
* @param pluginDescriptor
* @return the best name of the package for the generated mojo
*/
@ -257,7 +250,7 @@ public class PluginHelpGenerator
/**
* Generates the <code>HelpMojo</code> class.
*
*
* @param writer
* @param pluginDescriptor
* @param helpDescriptor
@ -622,7 +615,7 @@ public class PluginHelpGenerator
/**
* Gets the effective string to use for the plugin/mojo/parameter description.
*
*
* @param description The description of the element, may be <code>null</code>.
* @return The effective description string, never <code>null</code>.
*/
@ -630,7 +623,7 @@ public class PluginHelpGenerator
{
if ( StringUtils.isNotEmpty( description ) )
{
return StringUtils.escape( toText( description ) );
return StringUtils.escape( PluginUtils.toText( description ) );
}
else
{
@ -650,253 +643,13 @@ public class PluginHelpGenerator
* to a single space. The resulting space denotes a possible point for line wrapping.</li>
* <li>Each space in preformatted text will be converted to a non-breaking space (U+00A0).</li>
* </ul>
*
*
* @param html The HTML fragment to convert to plain text, may be <code>null</code>.
* @return A string with HTML tags converted into pure text, never <code>null</code>.
* @deprecated since 2.4.3, using {@link PluginUtils#toText(String)} instead of.
*/
protected static String toText( String html )
{
if ( StringUtils.isEmpty( html ) )
{
return "";
}
final StringBuffer sb = new StringBuffer();
HTMLEditorKit.Parser parser = new ParserDelegator();
HTMLEditorKit.ParserCallback htmlCallback = new HTMLEditorKit.ParserCallback()
{
/**
* Holds the index of the current item in a numbered list.
*/
class Counter
{
public int value;
}
/**
* A flag whether the parser is currently in the body element.
*/
private boolean body;
/**
* A flag whether the parser is currently processing preformatted text, actually a counter to track nesting.
*/
private int preformatted;
/**
* The current indentation depth for the output.
*/
private int depth;
/**
* A stack of {@link Counter} objects corresponding to the nesting of (un-)ordered lists. A
* <code>null</code> element denotes an unordered list.
*/
private Stack numbering = new Stack();
/**
* A flag whether an implicit line break is pending in the output buffer. This flag is used to postpone the
* output of implicit line breaks until we are sure that are not to be merged with other implicit line
* breaks.
*/
private boolean pendingNewline;
/**
* A flag whether we have just parsed a simple tag.
*/
private boolean simpleTag;
/** {@inheritDoc} */
public void handleSimpleTag( HTML.Tag t, MutableAttributeSet a, int pos )
{
simpleTag = true;
if ( body && HTML.Tag.BR.equals( t ) )
{
newline( false );
}
}
/** {@inheritDoc} */
public void handleStartTag( HTML.Tag t, MutableAttributeSet a, int pos )
{
simpleTag = false;
if ( body && ( t.breaksFlow() || t.isBlock() ) )
{
newline( true );
}
if ( HTML.Tag.OL.equals( t ) )
{
numbering.push( new Counter() );
}
else if ( HTML.Tag.UL.equals( t ) )
{
numbering.push( null );
}
else if ( HTML.Tag.LI.equals( t ) )
{
Counter counter = (Counter) numbering.peek();
if ( counter == null )
{
text( "-\t" );
}
else
{
text( ++counter.value + ".\t" );
}
depth++;
}
else if ( HTML.Tag.DD.equals( t ) )
{
depth++;
}
else if ( t.isPreformatted() )
{
preformatted++;
}
else if ( HTML.Tag.BODY.equals( t ) )
{
body = true;
}
}
/** {@inheritDoc} */
public void handleEndTag( HTML.Tag t, int pos )
{
if ( HTML.Tag.OL.equals( t ) || HTML.Tag.UL.equals( t ) )
{
numbering.pop();
}
else if ( HTML.Tag.LI.equals( t ) || HTML.Tag.DD.equals( t ) )
{
depth--;
}
else if ( t.isPreformatted() )
{
preformatted--;
}
else if ( HTML.Tag.BODY.equals( t ) )
{
body = false;
}
if ( body && ( t.breaksFlow() || t.isBlock() ) && !HTML.Tag.LI.equals( t ) )
{
if ( ( HTML.Tag.P.equals( t ) || HTML.Tag.PRE.equals( t ) || HTML.Tag.OL.equals( t )
|| HTML.Tag.UL.equals( t ) || HTML.Tag.DL.equals( t ) )
&& numbering.isEmpty() )
{
newline( pendingNewline = false );
}
else
{
newline( true );
}
}
}
/** {@inheritDoc} */
public void handleText( char[] data, int pos )
{
/*
* NOTE: Parsers before JRE 1.6 will parse XML-conform simple tags like <br/> as "<br>" followed by
* the text event ">..." so we need to watch out for the closing angle bracket.
*/
int offset = 0;
if ( simpleTag && data[0] == '>' )
{
simpleTag = false;
for ( ++offset; offset < data.length && data[offset] <= ' '; )
{
offset++;
}
}
if ( offset < data.length )
{
String text = new String( data, offset, data.length - offset );
text( text );
}
}
/** {@inheritDoc} */
public void flush()
{
flushPendingNewline();
}
/**
* Writes a line break to the plain text output.
*
* @param implicit A flag whether this is an explicit or implicit line break. Explicit line breaks are
* always written to the output whereas consecutive implicit line breaks are merged into a single
* line break.
*/
private void newline( boolean implicit )
{
if ( implicit )
{
pendingNewline = true;
}
else
{
flushPendingNewline();
sb.append( '\n' );
}
}
/**
* Flushes a pending newline (if any).
*/
private void flushPendingNewline()
{
if ( pendingNewline )
{
pendingNewline = false;
if ( sb.length() > 0 )
{
sb.append( '\n' );
}
}
}
/**
* Writes the specified character data to the plain text output. If the last output was a line break, the
* character data will automatically be prefixed with the current indent.
*
* @param data The character data, must not be <code>null</code>.
*/
private void text( String data )
{
flushPendingNewline();
if ( sb.length() <= 0 || sb.charAt( sb.length() - 1 ) == '\n' )
{
for ( int i = 0; i < depth; i++ )
{
sb.append( '\t' );
}
}
String text;
if ( preformatted > 0 )
{
text = data.replace( ' ', '\u00A0' );
}
else
{
text = data.replace( '\n', ' ' );
}
sb.append( text );
}
};
try
{
parser.parse( new StringReader( PluginUtils.makeHtmlValid( html ) ), htmlCallback, true );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
return sb.toString().replace( '\"', '\'' ); // for CDATA
return PluginUtils.toText( html );
}
}

View File

@ -22,6 +22,8 @@ package org.apache.maven.tools.plugin.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
@ -32,9 +34,15 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
@ -237,7 +245,7 @@ public final class PluginUtils
/**
* Fixes some javadoc comment to become a valid XHTML snippet.
*
*
* @param description Javadoc description with HTML tags, may be <code>null</code>.
* @return The description with valid XHTML tags, never <code>null</code>.
*/
@ -398,7 +406,7 @@ public final class PluginUtils
/**
* Sorts the specified mojo descriptors by goal name.
*
*
* @param mojoDescriptors The mojo descriptors to sort, may be <code>null</code>.
*/
public static void sortMojos( List mojoDescriptors )
@ -419,4 +427,265 @@ public final class PluginUtils
}
}
/**
* Converts a HTML fragment as extracted from a javadoc comment to a plain text string. This method tries to retain
* as much of the text formatting as possible by means of the following transformations:
* <ul>
* <li>List items are converted to leading tabs (U+0009), followed by the item number/bullet, another tab and
* finally the item contents. Each tab denotes an increase of indentation.</li>
* <li>Flow breaking elements as well as literal line terminators in preformatted text are converted to a newline
* (U+000A) to denote a mandatory line break.</li>
* <li>Consecutive spaces and line terminators from character data outside of preformatted text will be normalized
* to a single space. The resulting space denotes a possible point for line wrapping.</li>
* <li>Each space in preformatted text will be converted to a non-breaking space (U+00A0).</li>
* </ul>
*
* @param html The HTML fragment to convert to plain text, may be <code>null</code>.
* @return A string with HTML tags converted into pure text, never <code>null</code>.
* @since 2.4.3
*/
public static String toText( String html )
{
if ( StringUtils.isEmpty( html ) )
{
return "";
}
final StringBuffer sb = new StringBuffer();
HTMLEditorKit.Parser parser = new ParserDelegator();
HTMLEditorKit.ParserCallback htmlCallback = new HTMLEditorKit.ParserCallback()
{
/**
* Holds the index of the current item in a numbered list.
*/
class Counter
{
public int value;
}
/**
* A flag whether the parser is currently in the body element.
*/
private boolean body;
/**
* A flag whether the parser is currently processing preformatted text, actually a counter to track nesting.
*/
private int preformatted;
/**
* The current indentation depth for the output.
*/
private int depth;
/**
* A stack of {@link Counter} objects corresponding to the nesting of (un-)ordered lists. A
* <code>null</code> element denotes an unordered list.
*/
private Stack numbering = new Stack();
/**
* A flag whether an implicit line break is pending in the output buffer. This flag is used to postpone the
* output of implicit line breaks until we are sure that are not to be merged with other implicit line
* breaks.
*/
private boolean pendingNewline;
/**
* A flag whether we have just parsed a simple tag.
*/
private boolean simpleTag;
/** {@inheritDoc} */
public void handleSimpleTag( HTML.Tag t, MutableAttributeSet a, int pos )
{
simpleTag = true;
if ( body && HTML.Tag.BR.equals( t ) )
{
newline( false );
}
}
/** {@inheritDoc} */
public void handleStartTag( HTML.Tag t, MutableAttributeSet a, int pos )
{
simpleTag = false;
if ( body && ( t.breaksFlow() || t.isBlock() ) )
{
newline( true );
}
if ( HTML.Tag.OL.equals( t ) )
{
numbering.push( new Counter() );
}
else if ( HTML.Tag.UL.equals( t ) )
{
numbering.push( null );
}
else if ( HTML.Tag.LI.equals( t ) )
{
Counter counter = (Counter) numbering.peek();
if ( counter == null )
{
text( "-\t" );
}
else
{
text( ++counter.value + ".\t" );
}
depth++;
}
else if ( HTML.Tag.DD.equals( t ) )
{
depth++;
}
else if ( t.isPreformatted() )
{
preformatted++;
}
else if ( HTML.Tag.BODY.equals( t ) )
{
body = true;
}
}
/** {@inheritDoc} */
public void handleEndTag( HTML.Tag t, int pos )
{
if ( HTML.Tag.OL.equals( t ) || HTML.Tag.UL.equals( t ) )
{
numbering.pop();
}
else if ( HTML.Tag.LI.equals( t ) || HTML.Tag.DD.equals( t ) )
{
depth--;
}
else if ( t.isPreformatted() )
{
preformatted--;
}
else if ( HTML.Tag.BODY.equals( t ) )
{
body = false;
}
if ( body && ( t.breaksFlow() || t.isBlock() ) && !HTML.Tag.LI.equals( t ) )
{
if ( ( HTML.Tag.P.equals( t ) || HTML.Tag.PRE.equals( t ) || HTML.Tag.OL.equals( t )
|| HTML.Tag.UL.equals( t ) || HTML.Tag.DL.equals( t ) )
&& numbering.isEmpty() )
{
newline( pendingNewline = false );
}
else
{
newline( true );
}
}
}
/** {@inheritDoc} */
public void handleText( char[] data, int pos )
{
/*
* NOTE: Parsers before JRE 1.6 will parse XML-conform simple tags like <br/> as "<br>" followed by
* the text event ">..." so we need to watch out for the closing angle bracket.
*/
int offset = 0;
if ( simpleTag && data[0] == '>' )
{
simpleTag = false;
for ( ++offset; offset < data.length && data[offset] <= ' '; )
{
offset++;
}
}
if ( offset < data.length )
{
String text = new String( data, offset, data.length - offset );
text( text );
}
}
/** {@inheritDoc} */
public void flush()
{
flushPendingNewline();
}
/**
* Writes a line break to the plain text output.
*
* @param implicit A flag whether this is an explicit or implicit line break. Explicit line breaks are
* always written to the output whereas consecutive implicit line breaks are merged into a single
* line break.
*/
private void newline( boolean implicit )
{
if ( implicit )
{
pendingNewline = true;
}
else
{
flushPendingNewline();
sb.append( '\n' );
}
}
/**
* Flushes a pending newline (if any).
*/
private void flushPendingNewline()
{
if ( pendingNewline )
{
pendingNewline = false;
if ( sb.length() > 0 )
{
sb.append( '\n' );
}
}
}
/**
* Writes the specified character data to the plain text output. If the last output was a line break, the
* character data will automatically be prefixed with the current indent.
*
* @param data The character data, must not be <code>null</code>.
*/
private void text( String data )
{
flushPendingNewline();
if ( sb.length() <= 0 || sb.charAt( sb.length() - 1 ) == '\n' )
{
for ( int i = 0; i < depth; i++ )
{
sb.append( '\t' );
}
}
String text;
if ( preformatted > 0 )
{
text = data.replace( ' ', '\u00A0' );
}
else
{
text = data.replace( '\n', ' ' );
}
sb.append( text );
}
};
try
{
parser.parse( new StringReader( makeHtmlValid( html ) ), htmlCallback, true );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
return sb.toString().replace( '\"', '\'' ); // for CDATA
}
}