/** * project:pomer * * Copyright 2008 [pomer], Inc. All rights reserved. * Website: http://www.pomer.org.cn/ * */ package cn.org.rapid_framework.generator.provider.java.model; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import cn.org.rapid_framework.generator.provider.java.model.MethodParameter.JavaSourceFileMethodParametersParser; import cn.org.rapid_framework.generator.util.GLogger; import cn.org.rapid_framework.generator.util.StringHelper; import cn.org.rapid_framework.generator.util.typemapping.JavaImport; /** * * @author badqiu,Linlin Yu */ public class JavaMethod { Method method; private JavaClass clazz; //与method相关联的class public JavaMethod(Method method, JavaClass clazz) { super(); if(method == null) throw new IllegalArgumentException("method must be not null"); if(clazz == null) throw new IllegalArgumentException("clazz must be not null"); this.method = method; this.clazz = clazz; } public JavaClass getClazz() { return clazz; } public String getMethodName() { return method.getName(); } public JavaClass getReturnType() { return new JavaClass(method.getReturnType()); } public Annotation[] getAnnotations() { return method.getAnnotations(); } public boolean isBridge() { return method.isBridge(); } public List<JavaClass> getExceptionTypes() { List<JavaClass> result = new ArrayList(); for(Class c : method.getExceptionTypes()) { result.add(new JavaClass(c)); } return result; } public boolean isSynthetic() { return method.isSynthetic(); } public boolean isVarArgs() { return method.isVarArgs(); } public Set<JavaClass> getImportClasses() { Set<JavaClass> set = new LinkedHashSet<JavaClass>(); JavaImport.addImportClass(set,method.getParameterTypes()); JavaImport.addImportClass(set,method.getExceptionTypes()); JavaImport.addImportClass(set, method.getReturnType()); return set; } public List<MethodParameter> getParameters() { Class[] parameters = method.getParameterTypes(); List<MethodParameter> results = new ArrayList<MethodParameter>(); for(int i = 0; i < parameters.length; i++) { results.add(new MethodParameter(i+1,this,new JavaClass(parameters[i]))); } return results; } public String getMethodNameUpper() { return StringHelper.capitalize(getMethodName()); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((method == null) ? 0 : method.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JavaMethod other = (JavaMethod) obj; if (method == null) { if (other.method != null) return false; } else if (!method.equals(other.method)) return false; return true; } public boolean isPropertyMethod() { if(getMethodName().startsWith("set") || getMethodName().startsWith("get") || (getMethodName().startsWith("is") && getReturnType().isBooleanType())) { return true; } return false; } /** * 解析java源代码的方法,将一个方法中调用field的所有方法全部提取出来. * @return */ public List<FieldMethodInvocation> getFieldMethodInvocationSequences() { if(StringHelper.isNotBlank(clazz.getMavenJavaSourceFileContent())) { try { JavaMethodInvokeSequencesParser cmd = new JavaMethodInvokeSequencesParser(this,clazz.getMavenJavaSourceFileContent()); cmd.execute(); return cmd.getMethodInvokeSequences(); }catch(Exception e) { GLogger.warn("getFieldMethodInvocationSequences() occer error on method:"+method.toString(),e); return new ArrayList<FieldMethodInvocation>(0); } }else { return new ArrayList<FieldMethodInvocation>(0); } } public String toString() { return clazz.getJavaType()+"."+getMethodName()+"()"; } public static class FieldMethodInvocation { JavaField field; JavaMethod method; public FieldMethodInvocation(JavaField field, JavaMethod method) { super(); this.field = field; this.method = method; } public JavaField getField() { return field; } public void setField(JavaField field) { this.field = field; } public JavaMethod getMethod() { return method; } public void setMethod(JavaMethod method) { this.method = method; } public boolean equals(Object obj) { if(obj == null) return false; if(! (obj instanceof FieldMethodInvocation)) return false; FieldMethodInvocation other = (FieldMethodInvocation)obj; return field.equals(other.field) && method.equals(other.method); } public int hashCode() { return field.hashCode() + method.hashCode(); } public String toString() { return field.getFieldName()+"."+method.getMethodName()+"()"; } } /** * 解析java源代码的方法,将一个方法中调用field的所有方法全部提取出来. **/ public static class JavaMethodInvokeSequencesParser { //匹配一个field的方法调用,如 generator.deleteBy() method.getClass() public static String fieldMethodInvokeRegex = "(\\w+)\\.(\\w+)\\("; private JavaMethod method; private String javaSourceContent; private JavaClass clazz; boolean executed = false; public JavaMethodInvokeSequencesParser(JavaMethod method, String javaSourceContent) { super(); if(StringHelper.isBlank(javaSourceContent)) { throw new IllegalArgumentException("'javaSourceContent' must be not blank"); } this.method = method; this.javaSourceContent = javaSourceContent; this.clazz = method.getClazz(); } private List<FieldMethodInvocation> methodInvokeFlows = new ArrayList<FieldMethodInvocation>(); public List<FieldMethodInvocation> getMethodInvokeSequences() { if(executed) { return methodInvokeFlows; }else { throw new IllegalStateException("please invoke execute() method before getMethodInvokeFlows()"); } } public void execute() { executed = true; //本类是否有声明 if(!declaredMethodsContains()) { return; } //是否是匿名方法 if(method.getMethodName().indexOf("$") >= 0) { return; } String javaSourceContent = removeSomeThings(); String methodBody = getMethodBody(javaSourceContent); Pattern p = Pattern.compile(fieldMethodInvokeRegex); Matcher m = p.matcher(methodBody); while(m.find()) { String field = m.group(1); String methodName= m.group(2); addFieldMethodInvocation(field, methodName); } } private boolean declaredMethodsContains() { for(Method m : clazz.getClazz().getDeclaredMethods()) { if(m.equals(method.method)) { return true; } } return false; } private void addFieldMethodInvocation(String field, String methodName) { try { JavaField javaField = clazz.getField(field); JavaClass fieldType = javaField.getType(); JavaMethod method = fieldType.getMethod(methodName); if(method != null) { methodInvokeFlows.add(new FieldMethodInvocation(javaField,method)); } } catch (NoSuchFieldException e) { //ignore } } public static String modifierToString(int mod) { if ((mod & Modifier.PUBLIC) != 0) return "public"; if ((mod & Modifier.PROTECTED) != 0) return "protected"; if ((mod & Modifier.PRIVATE) != 0) return "private"; return ""; } private String getMethodBody(String javaSourceContent) { String methodStartPattern = "(?s)\\s+"+method.getMethodName()+"\\s*\\("+JavaSourceFileMethodParametersParser.getSimpleParamsPattern(method.method)+"\\)\\s*"; int methodStart = StringHelper.indexOfByRegex(javaSourceContent,methodStartPattern); if(methodStart == -1) throw new IllegalArgumentException("cannot get method body by pattern:"+methodStartPattern+" methodName:"+method.getMethodName() +"\n javaSource:"+javaSourceContent); try { String methodEnd = javaSourceContent.substring(methodStart); int[] beginAndEnd = findWrapCharEndLocation(methodEnd,'{','}'); if(beginAndEnd == null) return ""; String methodBody = methodEnd.substring(beginAndEnd[0], beginAndEnd[1]); return methodBody; }catch(RuntimeException e) { throw new IllegalArgumentException("cannot get method body by pattern:"+methodStartPattern+"\n javaSource:"+javaSourceContent,e); } } private String removeSomeThings() { String javaSourceContent = removeJavaComments(this.javaSourceContent); // javaSourceContent = removeJavaImports(javaSourceContent); // javaSourceContent = removeJavaPackage(javaSourceContent); javaSourceContent = replaceString2EmptyString(javaSourceContent); return javaSourceContent; } public static String replaceString2EmptyString(String str) { if(str == null) return null; str = str.replaceAll("\".*?\"", ""); // replace string from "234 " => "" return str; } // getName\s*\(.*?\)\s*\{.*?\;\s*} public static String removeJavaComments(String str) { if(str == null) return null; str = str.replaceAll("//.*", ""); // remove line comment: // str = str.replaceAll("(?s)/\\*.*?\\*/", ""); // remove block comment: /* */ return str; } // public static String removeJavaImports(String str) { // if(str == null) return null; // str = str.replaceAll("\\s*import\\s.*", ""); // remove java import // return str; // } // public static String removeJavaPackage(String str) { // if(str == null) return null; // str = str.replaceAll("\\s*package\\s.*", ""); // remove java package // return str; // } /** * 找到对称的一条括号所处的位置, * 如 findWrapCharEndLocation("0123{{67}}}",'{','}'), 将返回 [4,9] * 如果没有将到,将返回null **/ public static int[] findWrapCharEndLocation(String str,char begin,char end) { int count = 0; boolean foundEnd = false; boolean foundBegin = false; int[] beginAndEnd = new int[2]; for(int i = 0; i < str.length(); i++) { char c = str.charAt(i); if(c == begin) { if(!foundBegin) { beginAndEnd[0] = i; } foundBegin = true; count ++; } if(c == end) { foundEnd = true; count--; } if(count == 0 && foundBegin && foundEnd) { beginAndEnd[1] = i; return beginAndEnd; } } return null; } } }