/*
* $Id$
*
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jboss.mockgenerator;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Formattable;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
/**
* <p class="changed_added_4_0"></p>
* @author asmirnov@exadel.com
*
*/
public class MockJavaSource extends JavaSource {
private final class ParametersFormatter implements Formattable {
private final Class<?>[] parameterTypes;
private String format = ",%1$s.class";
private boolean varargs=false;
/**
* <p class="changed_added_4_0"></p>
* @param varargs the varargs to set
*/
public void setVarargs(boolean varargs) {
this.varargs = varargs;
}
private ParametersFormatter(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
public void formatTo(Formatter formatter, int flags, int width,
int precision) {
for (int i = 0; i < this.parameterTypes.length; i++) {
Class<?> parameter = this.parameterTypes[i];
formatter.format(getFormat(), classToString(parameter, varargs && i==this.parameterTypes.length-1),i,0==i?"":",");
}
}
/**
* <p class="changed_added_4_0"></p>
* @param format the format to set
*/
public void setFormat(String format) {
this.format = format;
}
/**
* <p class="changed_added_4_0"></p>
* @return the format
*/
public String getFormat() {
return format;
}
}
private final String className;
private static final String fileHeader = "/*\n" +
" * GENERATED FILE - DO NOT EDIT\n" +
" */\n" +
"\n" +
"package %1$s;\n" +
"\n" +
"import static org.easymock.EasyMock.*;\n" +
"import static %4$s.findMethod;\n" +
"import static %4$s.invokeMethod;\n\n" +
"import java.lang.reflect.Method;\n" +
"import org.easymock.IMocksControl;\n" +
"import %4$s;\n" +
"import %4$s.MockObject;\n\n" +
"public class %2$s extends %3$s implements MockObject {\n" +
"\n" +
" private final IMocksControl control;\n" +
"\n" +
" private final String name;\n" +
"\n" +
" /**\n" +
" * Default constructor\n" +
" */\n" +
" public %2$s() {\n" +
" %5$s" +
" this.control = createControl();\n" +
" this.name = null;\n" +
" }\n" +
"\n"+
" /**\n" +
" * @param control\n" +
" */\n" +
" public %2$s(IMocksControl control, String name) {\n" +
" %5$s" +
" this.control = control;\n" +
" this.name = name;\n" +
" }\n" +
"\n" +
" public IMocksControl getControl() {\n" +
" return control;\n" +
" }\n" +
"";
//private static final String fileFooter = "\n}\n";
private static final String fileFooter = "\n" +
"\n" +
" public String toString() {\n" +
" return getClass().getSimpleName() + (name != null ? name : \"\");\n" +
" }\n" +
"\n" +
" public boolean equals(Object obj) {\n" +
" return this == obj;\n" +
" }\n" +
"\n" +
" public int hashCode() {\n" +
" if (name != null) {\n" +
" final int prime = 31;\n" +
" int result = 1;\n" +
" result = prime * result + name.hashCode();\n" +
" result = prime * result + getClass().getName().hashCode();\n" +
" return result;\n" +
" } else {" +
" return System.identityHashCode(this);\n" +
" }\n" +
" }\n" +
"\n}\n";
private final String mockController;
public MockJavaSource(File directory, String mockClassName, String className, String mockController) {
super(directory, mockClassName);
this.className = className;
this.mockController = mockController;
}
public void printFileHeader(String postConstruct) {
sprintf(fileHeader,mockPackage,mockClass,className,mockController,notNullString(postConstruct));
}
private String notNullString(String postConstruct) {
return null==postConstruct?"":postConstruct;
}
private static final String methodConstant=" private static final Method %2$sMethod%4$d = findMethod(%1$s.class, \"%2$s\"%3$s);\n";
private static final String voidMethod="// @Override\n" +
" public void %2$s(%3$s) {\n" +
" invokeMethod(this.control,this, %2$sMethod%5$d %4$s);\n" +
" }\n" +
"";
private static final String valueMethod="// @Override\n" +
" public %1$s %2$s(%3$s) {\n" +
" return (%6$s)invokeMethod(this.control,this, %2$sMethod%5$d %4$s);\n" +
" }\n" +
"";
/**
* <p class="changed_added_4_0">This map holds counters of methods with same name. That counter value is appended
* to method constant name to avoid conflicts.</p>
*/
private Map<String, Integer> methods = new HashMap<String, Integer>();
/**
* <p class="changed_added_4_0"></p>
* TODO - analyze type arguments.
* @param method
*/
public void printMethod(Method method){
String name = method.getName();
Integer methodNumber = methods.get(name);
if(null == methodNumber){
methodNumber = new Integer(0);
} else {
methodNumber = methodNumber+1;
}
methods.put(name, methodNumber);
final Class<?>[] parameterTypes = method.getParameterTypes();
ParametersFormatter parameterTypesFormat = new ParametersFormatter(parameterTypes);
parameterTypesFormat.setFormat(",%1$s.class");
sprintf(methodConstant, className,name,parameterTypesFormat,methodNumber);
parameterTypesFormat.setFormat("%3$s%1$s arg%2$d");
parameterTypesFormat.setVarargs(method.isVarArgs());
ParametersFormatter argumentsFormat = new ParametersFormatter(parameterTypes);
argumentsFormat.setFormat(",arg%2$d");
Class<?> returnType = method.getReturnType();
if(void.class.equals(returnType)){
sprintf(voidMethod, "void",name,parameterTypesFormat,argumentsFormat,methodNumber);
} else {
sprintf(valueMethod, classToString(returnType, false),name,parameterTypesFormat,argumentsFormat,methodNumber,boxingClassName(returnType));
}
}
public void printFileFooter(String codeSegment){
if(null != codeSegment){
write(codeSegment);
}
write(fileFooter);
}
}