Hi,

I do not have the right permission to commit to maven-reporting-api. 
So, could someone commit the attached patch?

Thanks a lot,

Cheers, 

Vincent
Index: src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java
===================================================================
--- src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java   
(révision 216032)
+++ src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java   
(copie de travail)
@@ -16,11 +16,20 @@
  * limitations under the License.
  */
 
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
 import org.apache.commons.validator.EmailValidator;
 import org.apache.commons.validator.UrlValidator;
 import org.codehaus.doxia.sink.Sink;
+import org.codehaus.plexus.util.StringUtils;
 
 /**
+ * An abstract class to manage report generation.
+ * 
  * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
  * @author <a href="[EMAIL PROTECTED]">Emmanuel Venisse</a>
  * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Siveton</a>
@@ -38,19 +47,19 @@
     {
         this.sink = sink;
     }
-
+    
     public void render()
     {
         sink.head();
 
         sink.title();
 
-        sink.text( getTitle() );
+        text( getTitle() );
 
         sink.title_();
 
         sink.head_();
-
+        
         sink.body();
 
         renderBody();
@@ -72,7 +81,7 @@
         sink.table_();
     }
 
-    protected void startSection( String name )
+    protected void startSection( final String name )
     {
         section = section + 1;
 
@@ -104,7 +113,7 @@
                 break;
         }
 
-        sink.text( name );
+        text( name );
 
         switch ( section )
         {
@@ -163,150 +172,423 @@
         }
     }
 
-    protected void tableHeaderCell( String text )
+    protected void tableHeaderCell( final String text )
     {
         sink.tableHeaderCell();
 
-        sink.text( text );
+        text( text );
 
         sink.tableHeaderCell_();
     }
 
-    protected void tableCell( String text )
+    /**
+     * Add a cell in a table.
+     * <p>The text could be a link patterned text defined by <code>{text, 
url}</code></p>
+     * 
+     * @see #linkPatternedText(String)
+     * 
+     * @param text
+     */
+    protected void tableCell( final String text )
     {
         sink.tableCell();
 
-        if ( text != null )
+        linkPatternedText( text );
+
+        sink.tableCell_();
+    }
+    
+    protected void tableRow( final String[] content )
+    {
+        sink.tableRow();
+
+        for ( int i = 0; i < content.length; i++ )
         {
-            sink.text( text );
+            tableCell( content[i] );
         }
-        else
+
+        sink.tableRow_();
+    }
+
+    protected void tableHeader( final String[] content )
+    {
+        sink.tableRow();
+
+        for ( int i = 0; i < content.length; i++ )
         {
-            sink.nonBreakingSpace();
+            tableHeaderCell( content[i] );
         }
 
-        sink.tableCell_();
+        sink.tableRow_();
     }
 
+    protected void tableCaption( final String caption )
+    {
+        sink.tableCaption();
+        text( caption );
+        sink.tableCaption_();
+    }
+
+    protected void paragraph( final String paragraph )
+    {
+        sink.paragraph();
+
+        text( paragraph );
+
+        sink.paragraph_();
+    }
+
+    protected void link( final String href, final String name )
+    {
+        sink.link( href );
+
+        text( name );
+
+        sink.link_();
+    }
+
     /**
-     * Create a cell with a potential link.
-     *
-     * @param text the text
-     * @param href the href
+     * Add a new text.
+     * <p>If text is empty of has a null value, add the "-" charater</p> 
+     *  
+     * @param text a string
      */
-    protected void tableCellWithLink( String text, String href )
+    protected void text( final String text )
     {
-        sink.tableCell();
-
-        if ( text != null )
+        if ( ( text == null || text.length() == 0 ) ) // Take care of spaces
         {
-            if ( href != null )
-            {
-                String[] schemes = {"http", "https"};
-                UrlValidator urlValidator = new UrlValidator( schemes );
-
-                if ( EmailValidator.getInstance().isValid( href ) )
-                {
-                    link( "mailto:"; + href, text );
-                }
-                else if ( href.toLowerCase().startsWith( "mailto:"; ) )
-                {
-                    link( href, text );
-                }
-                else if ( urlValidator.isValid( href ) )
-                {
-                    link( href, text );
-                }
-                else
-                {
-                    sink.text( text );
-                }
-            }
-            else
-            {
-                sink.text( text );
-            }
+            sink.text( "-" );
         }
         else
         {
-            sink.nonBreakingSpace();
+            sink.text( text );
         }
+    }
 
-        sink.tableCell_();
+    /**
+     * Add a verbatim text. 
+     *  
+     * @see #text(String)
+     * 
+     * @param text a string
+     */
+    protected void verbatimText( final String text )
+    {
+        sink.verbatim( true );
+        
+        text( text );
+
+        sink.verbatim_();
     }
 
-    protected void tableRow( String[] content )
+    /**
+     * Add a verbatim text with a specific link. 
+     *  
+     * @see #link(String, String)
+     * 
+     * @param text a string
+     * @param href an href could be null
+     */
+    protected void verbatimLink( final String text, final String href )
     {
-        sink.tableRow();
-
-        for ( int i = 0; i < content.length; i++ )
+        if ( StringUtils.isEmpty( href ) )
         {
-            tableCell( content[i] );
+            verbatimText( text );
+        } 
+        else
+        {
+            sink.verbatim( true );
+            
+            link( href, text );
+    
+            sink.verbatim_();
         }
+    }
 
-        sink.tableRow_();
+    /**
+     * Add a Javascript code. 
+     * 
+     * @param jsCode a string of Javascript 
+     */
+    protected void javaScript( final String jsCode )
+    {
+        sink.rawText( "<script type=\"text/javascript\">\n" + jsCode + 
"</script>" );
     }
 
     /**
-     * Create a new row : each cell could have a link.
-     * <br>
-     * The arrays should have the same size.
-     *
-     * @param texts an array of text
-     * @param hrefs an array of href
+     * Add a text with links inside.
+     * <p>The text variable should contained this given pattern <code>{text, 
url}</code> 
+     * to handle the link creation.</p>
+     * 
+     * @see #text(String)
+     * @see #applyPattern(String)
+     * 
+     * @param text a text with link pattern defined.
      */
-    protected void tableRowWithLink( String[] texts, String[] hrefs )
+    public void linkPatternedText( final String text )
     {
-        if ( hrefs.length != texts.length )
+        if ( StringUtils.isEmpty( text ) )
         {
-            throw new IllegalArgumentException( "The arrays should have the 
same size" );
+            text( text );
+        } 
+        else
+        {
+            Map segments = applyPattern( text );
+    
+            if ( segments == null )
+            {
+                text( text );
+            } 
+            else
+            {
+                for (Iterator it = segments.entrySet().iterator(); 
it.hasNext(); )
+                {
+                    Map.Entry entry = (Map.Entry) it.next();
+        
+                    String name = (String) entry.getKey();
+                    String href = (String) entry.getValue();
+
+                    if ( href == null )
+                    {
+                        text( name );
+                    }
+                    else
+                    {
+                        if ( getValidHref( href ) != null)
+                        {
+                            link( getValidHref( href ), name );
+                        }
+                        else
+                        {
+                            text( text );
+                        }
+                    }
+                }
+            }
         }
+    }
 
-        sink.tableRow();
+    /**
+     * Create a link pattern text defined by <code>{text, url}</code>.
+     * <p>This created pattern could be used by the method 
<code>linkPatternedText(String)</code> to
+     * handle a text with link.</p>
+     *  
+     * @see #linkPatternedText(String)
+     *  
+     * @param text
+     * @param href
+     * @return a link pattern
+     */
+    protected static String createLinkPatternedText( final String text, final 
String href )
+    {
+        if ( text == null )
+        {
+            return text;
+        }
 
-        for ( int i = 0; i < texts.length; i++ )
+        if ( href == null )
         {
-            tableCellWithLink( texts[i], hrefs[i] );
+            return text;
         }
 
-        sink.tableRow_();
+        StringBuffer sb = new StringBuffer();
+        sb.append( "{" ).append( text ).append ( ", " ).append( href ).append( 
"}" );
+        
+        return sb.toString();
     }
-
-    protected void tableHeader( String[] content )
+    
+    /**
+     * Convenience method to display a <code>Properties</code> object comma 
separated.
+     * 
+     * @param props
+     * @return the properties object as comma separated String
+     */
+    protected static String propertiesToString( final Properties props )
     {
-        sink.tableRow();
+        StringBuffer sb = new StringBuffer();
+        
+        if ( ( props == null ) || ( props.isEmpty() ) )
+        {
+            return sb.toString();
+        }
+        
+        for ( Iterator i = props.keySet().iterator(); i.hasNext() ; )
+        {
+            String key = (String)i.next();
+            sb.append(key).append( "=" ).append(props.get(key));
+            if ( i.hasNext() )
+            {
+                sb.append( ", " );
+            }
+        }
+        
+        return sb.toString();
+    }
+    
+    /**
+     * Return a valid href. 
+     * <p>A valid href could start by <code>mailto:</code></p>. 
+     * 
+     * @param href an href
+     * @return a valid href or null if the href is not valid.
+     */
+    private static String getValidHref( String href )
+    {
+        href = href.trim();
+        
+        String[] schemes = {"http", "https"};
+        UrlValidator urlValidator = new UrlValidator( schemes );
 
-        for ( int i = 0; i < content.length; i++ )
+        if ( EmailValidator.getInstance().isValid( href ) )
         {
-            tableHeaderCell( content[i] );
+            return "mailto:"; + href;
         }
+        else if ( href.toLowerCase().startsWith( "mailto:"; ) )
+        {
+            return href;
+        }
+        else if ( urlValidator.isValid( href ) )
+        {
+            return href;
+        }
+        else
+        {
+            // TODO Waiting for new release of Validator
+            // http://issues.apache.org/bugzilla/show_bug.cgi?id=30686
+            String hrefTmp = null;
+            if ( !href.trim().endsWith("/") )
+            {
+                hrefTmp = href + "/index.html";
+            }
+            else
+            {
+                hrefTmp = href + "index.html";
+            }
 
-        sink.tableRow_();
-    }
+            if ( urlValidator.isValid( hrefTmp ) )
+            {
+                return href;
+            }
 
-    protected void tableCaption( String caption )
-    {
-        sink.tableCaption();
-        sink.text( caption );
-        sink.tableCaption_();
+            return null;
+        }
     }
+    
+    /**
+     * The method parses a text an apply the given pattern <code>{text, 
url}</code> to create 
+     * a map of text/href.
+     * 
+     * @param text a text with or without the pattern <code>{text, url}</code>
+     * @return a map of text/href
+     */
+    private static Map applyPattern( final String text )
+    {   
+        if ( StringUtils.isEmpty( text ) )
+        {
+            return null;
+        }
+        
+        // Map defined by key/value name/href
+        // If href == null, it means 
+        Map segments = new LinkedHashMap();
 
-    protected void paragraph( String paragraph )
-    {
-        sink.paragraph();
+        // TODO Special case http://jira.codehaus.org/browse/MEV-40
+        if ( text.indexOf( "${") != -1 )
+        {
+            int lastComma = text.lastIndexOf( "," );
+            int lastSemi = text.lastIndexOf( "}" );
+            if ( ( lastComma != -1 ) && ( lastSemi != -1 ) )
+            {
+                segments.put( text.substring( lastComma + 1, lastSemi 
).trim(), null );
+            } 
+            else
+            {
+                segments.put( text, null );
+            }
+                
+            return segments; 
+        }
+        
+        boolean inQuote = false;
+        int braceStack = 0;
+        int lastOffset = 0;
 
-        sink.text( paragraph );
+        for ( int i = 0; i < text.length(); i++ ) {
+            char ch = text.charAt(i);
 
-        sink.paragraph_();
-    }
+            if (ch == '\'') 
+            {
+                // handle: ''
+                if ( ( i + 1 < text.length() ) && 
+                        ( text.charAt( i + 1 ) == '\'' ) ) 
+                {
+                    i++;
+                } 
+                else 
+                {
+                    inQuote = true;
+                }
+            }
+            else 
+            {
+                switch (ch) {
+                case '{':
+                    if ( !inQuote )
+                    {
+                        if ( braceStack == 0 ) {
+                            if ( i != 0 ) // handle { at first character
+                            {
+                                segments.put( text.substring( lastOffset, i ), 
null);
+                            }
+                            lastOffset = i + 1;
+                            braceStack++;
+                        } 
+                    }
+                    break;
+                case '}':
+                    if ( !inQuote )
+                    {
+                        braceStack--;
+                        if (braceStack == 0) 
+                        {
+                            String subString = text.substring( lastOffset, i );
+                            lastOffset = i + 1;
 
-    protected void link( String href, String name )
-    {
-        sink.link( href );
+                            int lastComma = subString.lastIndexOf( "," );
+                            if ( lastComma != -1 )
+                            {
+                                segments.put( subString.substring( 0, 
lastComma ).trim(), 
+                                        subString.substring( lastComma + 1 
).trim() );
+                            }
+                            else
+                            {
+                                segments.put( subString.substring( 0, 
lastComma ).trim(), null );
+                            }
+                        }
+                    }
+                    break;
+                case '\'':
+                    if ( inQuote ) {
+                        inQuote = false;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
 
-        sink.text( name );
+        if ( !StringUtils.isEmpty( text.substring( lastOffset, text.length() ) 
) )
+        {
+            segments.put( text.substring( lastOffset, text.length() ), null );
+        }
 
-        sink.link_();
+        if (braceStack != 0) 
+        {
+            throw new IllegalArgumentException("Unmatched braces in the 
pattern.");
+        }
+        
+        return Collections.unmodifiableMap( segments );
     }
 
     public abstract String getTitle();
Index: pom.xml
===================================================================
--- pom.xml     (révision 216032)
+++ pom.xml     (copie de travail)
@@ -1,3 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
 <project>
   <modelVersion>4.0.0</modelVersion>
   <parent>
@@ -6,12 +26,17 @@
     <version>2.0-beta-1-SNAPSHOT</version>
   </parent>
   <artifactId>maven-reporting-api</artifactId>
-  <contributors>
-    <contributor>
+  <developers>
+    <developer>
+      <id>vsiveton</id>
       <name>Vincent Siveton</name>
       <email>[EMAIL PROTECTED]</email>
-    </contributor>
-  </contributors>
+      <roles>
+        <role>Java Developer</role>
+      </roles>
+      <timezone>-5</timezone>
+    </developer>
+  </developers>
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to