Coverage Report - org.apache.tiles.autotag.core.QDoxTemplateSuiteFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
QDoxTemplateSuiteFactory
88%
77/87
67%
46/68
5.444
 
 1  
 /*
 2  
  * $Id: QDoxTemplateSuiteFactory.java 1349964 2012-06-13 17:18:51Z nlebas $
 3  
  *
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  * http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 package org.apache.tiles.autotag.core;
 22  
 
 23  
 import java.io.File;
 24  
 import java.io.IOException;
 25  
 import java.net.URL;
 26  
 import java.util.ArrayList;
 27  
 import java.util.List;
 28  
 
 29  
 import org.apache.tiles.autotag.core.runtime.ModelBody;
 30  
 import org.apache.tiles.autotag.core.runtime.annotation.Parameter;
 31  
 import org.apache.tiles.autotag.model.TemplateClass;
 32  
 import org.apache.tiles.autotag.model.TemplateMethod;
 33  
 import org.apache.tiles.autotag.model.TemplateParameter;
 34  
 import org.apache.tiles.autotag.model.TemplateSuite;
 35  
 import org.apache.tiles.autotag.model.TemplateSuiteFactory;
 36  
 
 37  
 import com.thoughtworks.qdox.JavaDocBuilder;
 38  
 import com.thoughtworks.qdox.model.Annotation;
 39  
 import com.thoughtworks.qdox.model.DocletTag;
 40  
 import com.thoughtworks.qdox.model.JavaClass;
 41  
 import com.thoughtworks.qdox.model.JavaMethod;
 42  
 import com.thoughtworks.qdox.model.JavaParameter;
 43  
 import com.thoughtworks.qdox.model.Type;
 44  
 
 45  
 /**
 46  
  * Creates a template suite using QDox.
 47  
  *
 48  
  * @version $Rev: 1349964 $ $Date: 2012-06-13 19:18:51 +0200 (Wed, 13 Jun 2012) $
 49  
  */
 50  
 public class QDoxTemplateSuiteFactory implements TemplateSuiteFactory {
 51  
 
 52  
     /**
 53  
      * The suffix of parsed classes.
 54  
      */
 55  
     private static final String TEMPLATE_SUFFIX = "Model";
 56  
 
 57  
     /**
 58  
      * The Javadoc builder.
 59  
      */
 60  
     private JavaDocBuilder builder;
 61  
 
 62  
     /**
 63  
      * The name of the suite.
 64  
      */
 65  
     private String suiteName;
 66  
 
 67  
     /**
 68  
      * The documentation of the suite.
 69  
      */
 70  
     private String suiteDocumentation;
 71  
 
 72  
     /**
 73  
      * The request class the suite.
 74  
      */
 75  
     private String requestClass;
 76  
 
 77  
     /**
 78  
      * Constructor.
 79  
      *
 80  
      * @param sourceFiles All the source files to parse.
 81  
      */
 82  0
     public QDoxTemplateSuiteFactory(File... sourceFiles) {
 83  0
         builder = new JavaDocBuilder();
 84  
         try {
 85  0
             for (File file : sourceFiles) {
 86  0
                 builder.addSource(file);
 87  
             }
 88  0
         } catch (IOException e) {
 89  0
             throw new ClassParseException(
 90  
                     "I/O Exception when adding source files", e);
 91  0
         }
 92  0
     }
 93  
 
 94  
     /**
 95  
      * Constructor.
 96  
      *
 97  
      * @param urls All the URLs of source files to parse.
 98  
      */
 99  1
     public QDoxTemplateSuiteFactory(URL... urls) {
 100  1
         builder = new JavaDocBuilder();
 101  
         try {
 102  6
             for (URL url : urls) {
 103  5
                 builder.addSource(url);
 104  
             }
 105  0
         } catch (IOException e) {
 106  0
             throw new ClassParseException(
 107  
                     "I/O Exception when adding source files", e);
 108  1
         }
 109  1
     }
 110  
 
 111  
     /**
 112  
      * Sets the suite name to assign to the created suite.
 113  
      *
 114  
      * @param suiteName The suite name.
 115  
      */
 116  
     public void setSuiteName(String suiteName) {
 117  1
         this.suiteName = suiteName;
 118  1
     }
 119  
 
 120  
     /**
 121  
      * Sets the suite documentation to assign to the suite.
 122  
      *
 123  
      * @param suiteDocumentation The suite documentation.
 124  
      */
 125  
     public void setSuiteDocumentation(String suiteDocumentation) {
 126  1
         this.suiteDocumentation = suiteDocumentation;
 127  1
     }
 128  
 
 129  
     /**
 130  
      * Sets the request class used by the suite.
 131  
      *
 132  
      * @param requestClass The request class name.
 133  
      */
 134  
     public void setRequestClass(String requestClass) {
 135  1
         this.requestClass = requestClass;
 136  1
     }
 137  
 
 138  
     @Override
 139  
     public TemplateSuite createTemplateSuite() {
 140  1
         List<TemplateClass> classes = new ArrayList<TemplateClass>();
 141  6
         for (JavaClass clazz : builder.getClasses()) {
 142  5
             String tagClassPrefix = getTagClassPrefix(clazz);
 143  5
             if (tagClassPrefix != null) {
 144  4
                 String tagName = tagClassPrefix.substring(0, 1).toLowerCase()
 145  
                         + tagClassPrefix.substring(1);
 146  4
                 TemplateMethod executeMethod = null;
 147  8
                 for (JavaMethod method : clazz.getMethods()) {
 148  4
                     if (isFeasible(method)) {
 149  3
                         executeMethod = createMethod(method);
 150  
                     }
 151  
                 }
 152  4
                 if (executeMethod != null) {
 153  3
                     TemplateClass templateClass = new TemplateClass(clazz
 154  
                             .getFullyQualifiedName(), tagName, tagClassPrefix,
 155  
                             executeMethod);
 156  3
                     templateClass.setDocumentation(clazz.getComment());
 157  3
                     classes.add(templateClass);
 158  
                 }
 159  
             }
 160  
         }
 161  1
         return new TemplateSuite(suiteName, suiteDocumentation, classes);
 162  
     }
 163  
 
 164  
     /**
 165  
      * Computes the tag class prefix.
 166  
      *
 167  
      * @param clazz The parsed class.
 168  
      * @return The tag class prefix.
 169  
      */
 170  
     private String getTagClassPrefix(JavaClass clazz) {
 171  
         String tagName;
 172  5
         String simpleClassName = clazz.getName();
 173  5
         if (simpleClassName.endsWith(TEMPLATE_SUFFIX)
 174  
                 && simpleClassName.length() > TEMPLATE_SUFFIX.length()) {
 175  4
             tagName = simpleClassName.substring(0, 1).toUpperCase()
 176  
                     + simpleClassName.substring(1, simpleClassName.length()
 177  
                             - TEMPLATE_SUFFIX.length());
 178  
         } else {
 179  1
             tagName = null;
 180  
         }
 181  5
         return tagName;
 182  
     }
 183  
 
 184  
     /**
 185  
      * Creates a template method descriptor from a parsed method.
 186  
      *
 187  
      * @param method The parsed method.
 188  
      * @return The template method descriptor.
 189  
      */
 190  
     private TemplateMethod createMethod(JavaMethod method) {
 191  3
         List<TemplateParameter> params = new ArrayList<TemplateParameter>();
 192  14
         for (JavaParameter parameter : method.getParameters()) {
 193  11
             String exportedName = parameter.getName();
 194  11
             boolean required = false;
 195  11
             String defaultValue = null;
 196  11
             Annotation[] annotations = parameter.getAnnotations();
 197  11
             if (annotations != null && annotations.length > 0) {
 198  1
                 boolean found = false;
 199  2
                 for (int i = 0; i < annotations.length && !found; i++) {
 200  1
                     if (Parameter.class.getName().equals(annotations[i].getType().getFullyQualifiedName())) {
 201  1
                         found = true;
 202  1
                         String candidateName = (String) annotations[i].getNamedParameter("name");
 203  1
                         if (candidateName != null && candidateName.length() > 2) {
 204  1
                             exportedName = candidateName.substring(1, candidateName.length() - 1);
 205  
                         }
 206  1
                         required = "true".equals(annotations[i].getNamedParameter("required"));
 207  1
                         candidateName = (String) annotations[i].getNamedParameter("defaultValue");
 208  1
                         if (candidateName != null && candidateName.length() > 2) {
 209  1
                             defaultValue = candidateName.substring(1, candidateName.length() - 1);
 210  
                         }
 211  
                     }
 212  
                 }
 213  
             }
 214  11
             String parameterType = parameter.getType()
 215  
                     .getFullyQualifiedName();
 216  11
             TemplateParameter templateParameter = new TemplateParameter(
 217  
                     parameter.getName(), exportedName, parameterType, defaultValue, required,
 218  
                     requestClass.equals(parameterType));
 219  11
             params.add(templateParameter);
 220  
         }
 221  3
         TemplateMethod templateMethod = new TemplateMethod(method.getName(),
 222  
                 params);
 223  3
         templateMethod.setDocumentation(method.getComment());
 224  3
         DocletTag[] tags = method.getTagsByName("param");
 225  14
         for (DocletTag tag : tags) {
 226  11
             String[] tagParams = tag.getParameters();
 227  11
             if (tagParams.length > 0) {
 228  11
                 TemplateParameter templateParameter = templateMethod
 229  
                         .getParameterByName(tagParams[0]);
 230  11
                 if (templateParameter != null) {
 231  11
                     String tagValue = tag.getValue();
 232  11
                     int pos = tagValue.indexOf(" ");
 233  11
                     templateParameter.setDocumentation(tagValue.substring(pos)
 234  
                             .trim());
 235  
                 }
 236  
             }
 237  
         }
 238  3
         return templateMethod;
 239  
     }
 240  
 
 241  
     /**
 242  
      * Verifies if the method can be used as an "execute" method.
 243  
      *
 244  
      * @param method The parsed method.
 245  
      * @return <code>true</code> if it is an execute method.
 246  
      */
 247  
     private boolean isFeasible(JavaMethod method) {
 248  4
         Type returns = method.getReturns();
 249  4
         if ("execute".equals(method.getName()) && returns != null
 250  
                 && "void".equals(returns.getFullyQualifiedName())
 251  
                 && method.isPublic() && !method.isStatic()
 252  
                 && !method.isAbstract() && !method.isConstructor()) {
 253  3
             JavaParameter[] params = method.getParameters();
 254  3
             if (params.length > 0) {
 255  3
                 JavaParameter param = params[params.length - 1];
 256  3
                 if (requestClass.equals(
 257  
                         param.getType().getFullyQualifiedName())) {
 258  1
                     return true;
 259  
                 }
 260  
             }
 261  2
             if (params.length >= 2) {
 262  2
                 JavaParameter param1 = params[params.length - 2];
 263  2
                 JavaParameter param2 = params[params.length - 1];
 264  2
                 if (requestClass.equals(
 265  
                         param1.getType().getFullyQualifiedName())
 266  
                         && ModelBody.class.getName().equals(
 267  
                                 param2.getType().getFullyQualifiedName())) {
 268  2
                     return true;
 269  
                 }
 270  
             }
 271  
         }
 272  1
         return false;
 273  
     }
 274  
 }