001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.java.language; 021 022 import java.util.ArrayList; 023 import java.util.Arrays; 024 import java.util.Hashtable; 025 import java.util.List; 026 import java.util.Map; 027 028 import org.apache.commons.lang.StringUtils; 029 030 public class JavaMethodSignature { 031 032 private final String methodName; 033 private final ReturnType returnType; 034 private final List<ArgumentType> argumentTypes; 035 private final boolean isConstructor; 036 037 private static Map<String, JavaType> javaTypes = new Hashtable<String, JavaType>(); 038 private static final char ARRAY = '['; 039 040 static { 041 for (JavaType javaType : Arrays.asList(JavaType.values())) { 042 javaTypes.put(javaType.JVMTypeIdentifier, javaType); 043 } 044 } 045 046 public JavaMethodSignature(String methodName, ReturnType returnType, ArgumentType... argumentTypes) { 047 this(methodName, returnType, Arrays.asList(argumentTypes)); 048 } 049 050 public JavaMethodSignature(String methodName, ReturnType returnType, List<ArgumentType> argumentTypes) { 051 this.methodName = methodName; 052 this.returnType = returnType; 053 this.argumentTypes = argumentTypes; 054 isConstructor = (returnType == null); 055 056 } 057 058 public static JavaMethodSignature create(String methodSignature) { 059 int leftBracketIndex = methodSignature.indexOf('('); 060 int rightBracketIndex = methodSignature.indexOf(')'); 061 String methodName = methodSignature.substring(0, leftBracketIndex); 062 ReturnType returnType = extractReturnType(methodSignature.substring(rightBracketIndex + 1)); 063 List<ArgumentType> argumentTypes = extractArgumentTypes(methodSignature.substring(leftBracketIndex + 1, rightBracketIndex)); 064 return new JavaMethodSignature(methodName, returnType, argumentTypes); 065 } 066 067 static List<ArgumentType> extractArgumentTypes(String argumentTypesSignature) { 068 List<ArgumentType> argumentTypes = new ArrayList<ArgumentType>(); 069 int argumentTypeStartIndex = 0; 070 int argumentTypeEndIndex = 0; 071 while ((argumentTypeEndIndex = argumentTypesSignature.indexOf(';', argumentTypeStartIndex)) != -1) { 072 ArgumentType argumentAndReturnType = extractArgumentType(argumentTypesSignature.substring(argumentTypeStartIndex, 073 argumentTypeEndIndex)); 074 argumentTypes.add(argumentAndReturnType); 075 argumentTypeStartIndex = argumentTypeEndIndex + 1; 076 } 077 return argumentTypes; 078 } 079 080 private static ArgumentType extractArgumentType(String argumentTypeSignature) { 081 return new ArgumentType(extractType(argumentTypeSignature)); 082 } 083 084 private static ReturnType extractReturnType(String returnTypeSignature) { 085 if (StringUtils.isBlank(returnTypeSignature)) { 086 return null; 087 } 088 return new ReturnType(extractType(returnTypeSignature)); 089 } 090 091 static ArgumentAndReturnType extractType(String stringTypeSignature) { 092 boolean isArray = false; 093 int index = 0; 094 String classCanonicalName = null; 095 if (stringTypeSignature.charAt(0) == ARRAY) { 096 isArray = true; 097 index++; 098 } 099 JavaType javaType = javaTypes.get(stringTypeSignature.substring(index, index + 1)); 100 index++; 101 if (javaType == JavaType.OBJECT) { 102 classCanonicalName = stringTypeSignature.substring(index); 103 classCanonicalName = StringUtils.remove(classCanonicalName, ';'); 104 } 105 return new ArgumentType(javaType, classCanonicalName, isArray); 106 } 107 108 public String dumpMethodSignature() { 109 StringBuilder builder = new StringBuilder(); 110 builder.append(methodName); 111 builder.append("("); 112 for (ArgumentAndReturnType argumentType : argumentTypes) { 113 builder.append(dumpTypeSignature(argumentType)); 114 builder.append(';'); 115 } 116 builder.append(")"); 117 if (!isConstructor) { 118 builder.append(dumpTypeSignature(returnType)); 119 if (!returnType.isVoid()) { 120 builder.append(";"); 121 } 122 } 123 return builder.toString(); 124 } 125 126 static String dumpTypeSignature(ArgumentAndReturnType argumentType) { 127 String result = ""; 128 if (argumentType.isArray()) { 129 result += ARRAY; 130 } 131 result += argumentType.getJavaType().JVMTypeIdentifier; 132 if (argumentType.isOject()) { 133 result += argumentType.getClassCanonicalName(); 134 } 135 return result; 136 } 137 }