001 /***
002 *
003 * Copyright (c) 2007 Paul Hammant
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 * 1. Redistributions of source code must retain the above copyright
010 * notice, this list of conditions and the following disclaimer.
011 * 2. Redistributions in binary form must reproduce the above copyright
012 * notice, this list of conditions and the following disclaimer in the
013 * documentation and/or other materials provided with the distribution.
014 * 3. Neither the name of the copyright holders nor the names of its
015 * contributors may be used to endorse or promote products derived from
016 * this software without specific prior written permission.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028 * THE POSSIBILITY OF SUCH DAMAGE.
029 */
030 package com.thoughtworks.paranamer.generator;
031
032 import com.thoughtworks.qdox.JavaDocBuilder;
033 import com.thoughtworks.qdox.model.JavaClass;
034 import com.thoughtworks.qdox.model.JavaMethod;
035 import com.thoughtworks.qdox.model.JavaParameter;
036
037 import java.io.File;
038 import java.io.IOException;
039 import java.util.*;
040
041 /**
042 * Qdox-based implementation of ParanamerGenerator which parses Java source files to processSourcePath
043 * parameter names lists.
044 *
045 * @author Paul Hammant
046 * @author Mauro Talevi
047 * @author Guilherme Silveira
048 */
049 public class QdoxParanamerGenerator implements ParanamerGenerator {
050
051 private static final String SPACE = " ";
052 private static final String NEWLINE = "\n";
053 private static final String COMMA = ",";
054 private static final String EMPTY = "";
055
056 public QdoxParanamerGenerator() {
057 }
058
059 public void processSourcePath(String sourcePath, String outputPath) throws IOException {
060 JavaClass[] classes = getClassesSortedByName(sourcePath);
061 processClasses(classes, outputPath);
062 }
063
064 private JavaClass[] getClassesSortedByName(String sourcePath) {
065 JavaDocBuilder builder = new JavaDocBuilder();
066 builder.addSourceTree(new File(sourcePath));
067 JavaClass[] classes = builder.getClasses();
068 Arrays.sort(classes);
069 return classes;
070 }
071
072 public void processClasses(JavaClass[] classes, String outputPath) throws IOException {
073 for (JavaClass javaClass : classes) {
074 String content = addMethods(javaClass.getMethods());
075 // TODO problem with inner classes
076 makeEnhancer().enhance(new File(outputPath, javaClass.getFullyQualifiedName().replace('.', File.separatorChar) + ".class"), content);
077
078 }
079 }
080
081 public Enhancer makeEnhancer() {
082 return new Enhancer();
083 }
084
085 private String addMethods(JavaMethod[] methods) {
086 Arrays.sort(methods);
087 StringBuffer buffer = new StringBuffer();
088 for (JavaMethod javaMethod : methods) {
089 if (!Arrays.asList(javaMethod.getModifiers()).contains("private")
090 && javaMethod.getParameters().length > 0) {
091 buffer.append(addMethod(javaMethod));
092 }
093 }
094 return buffer.toString();
095 }
096
097 private String addMethod(JavaMethod method) {
098 JavaParameter[] parameters = method.getParameters();
099 return format(method, parameters);
100 }
101
102 private String format(JavaMethod method, JavaParameter[] parameters) {
103 StringBuffer sb = new StringBuffer();
104 String methodName = method.getName();
105 if (method.isConstructor()) {
106 methodName = "<init>";
107 }
108 String parameterTypes = getParameterTypes(parameters);
109 sb.append(formatLine(methodName, parameterTypes, getParameterNames(parameters)));
110 return sb.toString();
111 }
112
113 private String formatLine(String methodName, String paramTypes, String paramNames){
114 StringBuffer sb = new StringBuffer();
115 // processClasses line structure: methodName paramTypes paramNames
116 sb.append(methodName).append(SPACE);
117 if ( paramTypes.length() > 0 ) {
118 sb.append(paramTypes.trim()).append(SPACE);
119 sb.append(paramNames.trim()).append(SPACE);
120 }
121 sb.append(NEWLINE);
122 return sb.toString();
123 }
124
125 private String getParameterNames(JavaParameter[] parameters) {
126 StringBuffer sb = new StringBuffer();
127 for (int i = 0; i < parameters.length; i++) {
128 sb.append(parameters[i].getName());
129 sb.append(comma(i, parameters.length));
130 }
131 return sb.toString();
132 }
133
134 private String getParameterTypes(JavaParameter[] parameters) {
135 StringBuffer sb = new StringBuffer();
136 for (int i = 0; i < parameters.length; i++) {
137 sb.append(parameters[i].getType());
138 sb.append(comma(i, parameters.length));
139 }
140 return sb.toString();
141 }
142
143 private String comma(int index, int size) {
144 return (index + 1 < size) ? COMMA : EMPTY;
145 }
146
147 }