Save This Page
Home » tapestry-src-5.0.19 » org.apache.tapestry.mojo » [javadoc | source]
    1   // Copyright 2007, 2008 The Apache Software Foundation
    2   //
    3   // Licensed under the Apache License, Version 2.0 (the "License");
    4   // you may not use this file except in compliance with the License.
    5   // You may obtain a copy of the License at
    6   //
    7   //     http://www.apache.org/licenses/LICENSE-2.0
    8   //
    9   // Unless required by applicable law or agreed to in writing, software
   10   // distributed under the License is distributed on an "AS IS" BASIS,
   11   // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12   // See the License for the specific language governing permissions and
   13   // limitations under the License.
   14   
   15   package org.apache.tapestry.mojo;
   16   
   17   import com.sun.javadoc;
   18   import com.sun.javadoc.AnnotationDesc.ElementValuePair;
   19   
   20   import java.io.File;
   21   import java.io.PrintWriter;
   22   import java.util.HashMap;
   23   import java.util.Map;
   24   import java.util.regex.Pattern;
   25   
   26   /**
   27    * Generates an XML file that identifies all the classes that contain parameters, and all the parameters within each
   28    * component class. This XML is later converted into part of the Maven generated HTML site.
   29    * <p/>
   30    * To keep the -doclet parameter passed to javadoc simple, this class should not have any outside dependencies.
   31    */
   32   public class ParametersDoclet extends Doclet
   33   {
   34       static String OUTPUT_PATH_OPTION = "-o";
   35   
   36       static String outputPath;
   37   
   38       static class Worker
   39       {
   40           private PrintWriter out;
   41   
   42           private final Pattern stripper = Pattern.compile("(<.*?>|&.*?;)", Pattern.DOTALL);
   43   
   44           public void run(String outputPath, RootDoc root) throws Exception
   45           {
   46               File output = new File(outputPath);
   47   
   48               out = new PrintWriter(output);
   49   
   50               println("<component-parameters>");
   51   
   52               for (ClassDoc cd : root.classes())
   53                   emitClass(cd);
   54   
   55               println("</component-parameters>");
   56   
   57               out.close();
   58           }
   59   
   60           private void emitClass(ClassDoc classDoc)
   61           {
   62               if (!classDoc.isPublic()) return;
   63   
   64               // Components must be root classes, not nested classes.
   65               if (classDoc.containingClass() != null) return;
   66   
   67               // Check for a no-args public constructor
   68   
   69               boolean found = false;
   70   
   71               for (ConstructorDoc cons : classDoc.constructors())
   72               {
   73                   if (cons.isPublic() && cons.parameters().length == 0)
   74                   {
   75                       found = true;
   76                       break;
   77                   }
   78               }
   79   
   80               if (!found) return;
   81               
   82               Map<String, String> annotationValues = findAnnotation(classDoc, "SupportsInformalParameters");
   83   
   84               println("<class name=\"%s\" super-class=\"%s\"  supports-informal-parameters=\"%s\">", classDoc.qualifiedTypeName(),
   85                       classDoc.superclass().qualifiedTypeName(), annotationValues!=null);
   86               print("<description>");
   87               printDescription(classDoc);
   88               println("</description>", classDoc.commentText());
   89   
   90               for (FieldDoc fd : classDoc.fields())
   91               {
   92                   if (fd.isStatic()) continue;
   93   
   94                   if (!fd.isPrivate()) continue;
   95   
   96                   annotationValues = findAnnotation(fd, "Parameter");
   97   
   98                   if (annotationValues == null) continue;
   99   
  100                   String name = annotationValues.get("name");
  101                   if (name == null) name = fd.name().replaceAll("^[$_]*", "");
  102   
  103                   print("<parameter name=\"%s\" type=\"%s\" default=\"%s\" required=\"%s\" cache=\"%s\" default-prefix=\"%s\">",
  104                         name, fd.type().qualifiedTypeName(), get(annotationValues, "value", ""),
  105                         get(annotationValues, "required", "false"), get(annotationValues, "cache", "true"),
  106                         get(annotationValues, "defaultPrefix", "prop"));
  107   
  108                   // Body of a parameter is the comment text.
  109   
  110                   printDescription(fd);
  111   
  112                   println("\n</parameter>");
  113               }
  114   
  115               println("</class>");
  116           }
  117   
  118           private String get(Map<String, String> map, String key, String defaultValue)
  119           {
  120               if (map.containsKey(key)) return map.get(key);
  121   
  122               return defaultValue;
  123           }
  124   
  125           private Map<String, String> findAnnotation(ProgramElementDoc doc, String name)
  126           {
  127           	for (AnnotationDesc annotation : doc.annotations())
  128               {
  129                   if (annotation.annotationType().qualifiedTypeName().equals(
  130                           "org.apache.tapestry5.annotations."+name))
  131                   {
  132                       Map<String, String> result = new HashMap<String, String>();
  133   
  134                       for (ElementValuePair pair : annotation.elementValues())
  135                           result.put(pair.element().name(), pair.value().value().toString());
  136   
  137                       return result;
  138                   }
  139               }
  140   
  141               return null;
  142           }
  143   
  144           private void print(String format, Object... arguments)
  145           {
  146               String line = String.format(format, arguments);
  147   
  148               out.print(line);
  149           }
  150   
  151           private void println(String format, Object... arguments)
  152           {
  153               print(format, arguments);
  154   
  155               out.println();
  156           }
  157   
  158           private void printDescription(Doc holder)
  159           {
  160               StringBuilder builder = new StringBuilder();
  161   
  162               for (Tag tag : holder.inlineTags())
  163               {
  164                   if (tag.name().equals("Text"))
  165                   {
  166                       builder.append(tag.text());
  167                       continue;
  168                   }
  169   
  170                   if (tag.name().equals("@link"))
  171                   {
  172                       SeeTag seeTag = (SeeTag) tag;
  173   
  174                       String label = seeTag.label();
  175                       if (label != null && !label.equals(""))
  176                       {
  177                           builder.append(label);
  178                           continue;
  179                       }
  180   
  181                       if (seeTag.referencedClassName() != null) builder.append(seeTag.referencedClassName());
  182   
  183                       if (seeTag.referencedMemberName() != null)
  184                       {
  185                           builder.append("#");
  186                           builder.append(seeTag.referencedMemberName());
  187                       }
  188                   }
  189               }
  190   
  191               String text = builder.toString();
  192   
  193               // Fix it up a little.
  194   
  195               // Remove any simple open or close tags found in the text, as well as any XML entities.
  196   
  197               String stripped = stripper.matcher(text).replaceAll("");
  198   
  199               out.print(stripped);
  200           }
  201       }
  202   
  203       /**
  204        * Yes we are interested in annotations, etc.
  205        */
  206       public static LanguageVersion languageVersion()
  207       {
  208           return LanguageVersion.JAVA_1_5;
  209       }
  210   
  211       public static int optionLength(String option)
  212       {
  213           if (option.equals(OUTPUT_PATH_OPTION)) return 2;
  214   
  215           return 0;
  216       }
  217   
  218       public static boolean validOptions(String options[][], DocErrorReporter reporter)
  219       {
  220           for (String[] group : options)
  221           {
  222               if (group[0].equals(OUTPUT_PATH_OPTION)) outputPath = group[1];
  223   
  224               // Do we need to check for other unexpected options?
  225               // TODO: Check for duplicate -o?
  226           }
  227   
  228           if (outputPath == null) reporter.printError(String.format("Usage: javadoc %s path", OUTPUT_PATH_OPTION));
  229   
  230           return true;
  231       }
  232   
  233       public static boolean start(RootDoc root)
  234       {
  235           // Enough of this static method bullshit. What the fuck were they thinking?
  236   
  237           try
  238           {
  239               new Worker().run(outputPath, root);
  240           }
  241           catch (Exception ex)
  242           {
  243               root.printError(ex.getMessage());
  244   
  245               return false;
  246           }
  247   
  248           return true;
  249       }
  250   
  251   }

Save This Page
Home » tapestry-src-5.0.19 » org.apache.tapestry.mojo » [javadoc | source]