/* * $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); } }