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    }