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 if (returnType == null) { 055 isConstructor = true; 056 } else { 057 isConstructor = false; 058 } 059 060 } 061 062 public static JavaMethodSignature create(String methodSignature) { 063 int leftBracketIndex = methodSignature.indexOf('('); 064 int rightBracketIndex = methodSignature.indexOf(')'); 065 String methodName = methodSignature.substring(0, leftBracketIndex); 066 ReturnType returnType = extractReturnType(methodSignature.substring(rightBracketIndex + 1)); 067 List<ArgumentType> argumentTypes = extractArgumentTypes(methodSignature.substring(leftBracketIndex + 1, rightBracketIndex)); 068 return new JavaMethodSignature(methodName, returnType, argumentTypes); 069 } 070 071 static List<ArgumentType> extractArgumentTypes(String argumentTypesSignature) { 072 List<ArgumentType> argumentTypes = new ArrayList<ArgumentType>(); 073 int argumentTypeStartIndex = 0; 074 int argumentTypeEndIndex = 0; 075 while ((argumentTypeEndIndex = argumentTypesSignature.indexOf(';', argumentTypeStartIndex)) != -1) { 076 ArgumentType argumentAndReturnType = extractArgumentType(argumentTypesSignature.substring(argumentTypeStartIndex, 077 argumentTypeEndIndex)); 078 argumentTypes.add(argumentAndReturnType); 079 argumentTypeStartIndex = argumentTypeEndIndex + 1; 080 } 081 return argumentTypes; 082 } 083 084 private static ArgumentType extractArgumentType(String argumentTypeSignature) { 085 return new ArgumentType(extractType(argumentTypeSignature)); 086 } 087 088 private static ReturnType extractReturnType(String returnTypeSignature) { 089 if (StringUtils.isBlank(returnTypeSignature)) { 090 return null; 091 } 092 return new ReturnType(extractType(returnTypeSignature)); 093 } 094 095 static ArgumentAndReturnType extractType(String stringTypeSignature) { 096 boolean isArray = false; 097 int index = 0; 098 String classCanonicalName = null; 099 if (stringTypeSignature.charAt(0) == ARRAY) { 100 isArray = true; 101 index++; 102 } 103 JavaType javaType = javaTypes.get(stringTypeSignature.substring(index, index + 1)); 104 index++; 105 if (javaType == JavaType.OBJECT) { 106 classCanonicalName = stringTypeSignature.substring(index); 107 classCanonicalName = StringUtils.remove(classCanonicalName, ';'); 108 } 109 return new ArgumentType(javaType, classCanonicalName, isArray); 110 } 111 112 public String dumpMethodSignature() { 113 StringBuilder builder = new StringBuilder(); 114 builder.append(methodName); 115 builder.append("("); 116 for (ArgumentAndReturnType argumentType : argumentTypes) { 117 builder.append(dumpTypeSignature(argumentType)); 118 builder.append(';'); 119 } 120 builder.append(")"); 121 if (!isConstructor) { 122 builder.append(dumpTypeSignature(returnType)); 123 if (!returnType.isVoid()) { 124 builder.append(";"); 125 } 126 } 127 return builder.toString(); 128 } 129 130 static String dumpTypeSignature(ArgumentAndReturnType argumentType) { 131 String result = ""; 132 if (argumentType.isArray()) { 133 result += ARRAY; 134 } 135 result += argumentType.getJavaType().JVMTypeIdentifier; 136 if (argumentType.isOject()) { 137 result += argumentType.getClassCanonicalName(); 138 } 139 return result; 140 } 141 }