001 package org.shiftone.jrat.core;
002
003
004 import org.shiftone.jrat.util.Assert;
005 import org.shiftone.jrat.util.log.Logger;
006
007 import java.util.ArrayList;
008 import java.util.HashMap;
009 import java.util.List;
010 import java.util.Map;
011
012
013 /**
014 * @author jeff@shiftone.org (Jeff Drost)
015 */
016 public class Signature {
017
018 private static final Logger LOG = Logger.getLogger(Signature.class);
019 private static Map PRIM_CODES = new HashMap();
020 private String returnType;
021 private List parameterTypes = new ArrayList(5);
022
023 static {
024 PRIM_CODES.put("Z", "boolean");
025 PRIM_CODES.put("B", "byte");
026 PRIM_CODES.put("C", "char");
027 PRIM_CODES.put("D", "double");
028 PRIM_CODES.put("F", "float");
029 PRIM_CODES.put("I", "int");
030 PRIM_CODES.put("J", "long");
031 PRIM_CODES.put("S", "short");
032 PRIM_CODES.put("V", "void");
033 }
034
035 public Signature(String descriptors) {
036 parseSig(new CharacterIterator(descriptors));
037 }
038
039
040 public String getReturnType() {
041 return returnType;
042 }
043
044
045 public int getParameterCount() {
046 return parameterTypes.size();
047 }
048
049
050 public String getParameterType(int index) {
051 return (String) parameterTypes.get(index);
052 }
053
054
055 public String getShortParameterType(int index) {
056
057 String type = getParameterType(index);
058 int dotIndex = type.lastIndexOf('.');
059
060 if (dotIndex != -1) {
061 type = type.substring(dotIndex + 1);
062 }
063
064 return type;
065 }
066
067
068 public String getShortText() {
069
070 StringBuffer sb = new StringBuffer();
071
072 for (int i = 0; i < getParameterCount(); i++) {
073 if (i != 0) {
074 sb.append(",");
075 }
076
077 sb.append(getShortParameterType(i));
078 }
079
080 return sb.toString();
081 }
082
083
084 public String getLongText() {
085
086 StringBuffer sb = new StringBuffer();
087
088 for (int i = 0; i < getParameterCount(); i++) {
089 if (i != 0) {
090 sb.append(",");
091 }
092
093 sb.append(getParameterType(i));
094 }
095
096 return sb.toString();
097 }
098
099
100 private void parseSig(CharacterIterator in) {
101
102 Assert.assertTrue("first char is (", in.next() && (in.get() == '('));
103
104 boolean inParams = true;
105
106 while (in.next()) {
107 char c = in.get();
108
109 if (c == ')') {
110 inParams = false;
111 }
112
113 if (inParams) {
114 parameterTypes.add(parseType(in));
115 } else {
116 returnType = parseType(in);
117 }
118 }
119 }
120
121
122 private String parseType(CharacterIterator in) {
123
124 char c = in.get();
125
126 if (c == 'L') {
127 return parseClassType(in);
128 } else if (c == '[') {
129 return parseArrayType(in);
130 } else {
131 return (String) PRIM_CODES.get(String.valueOf(c));
132 }
133 }
134
135
136 private String parseArrayType(CharacterIterator in) {
137
138 StringBuffer sb = new StringBuffer("[]");
139
140 while (in.next() && (in.get() == '[')) {
141 sb.append("[]");
142 }
143
144 sb.insert(0, parseType(in)); // out the type at the start of the
145
146 // [][][]
147 return sb.toString();
148 }
149
150
151 private String parseClassType(CharacterIterator in) {
152
153 StringBuffer className = new StringBuffer();
154
155 while (in.next()) {
156 char c = in.get();
157
158 if (c == ';') {
159 break;
160 } else if (c == '/') {
161 className.append('.');
162 } else {
163 className.append(c);
164 }
165 }
166
167 return className.toString();
168 }
169
170
171 // todo - this is handy - make it common
172 private static class CharacterIterator {
173
174 private char[] chars;
175 private int pos = -1;
176 private char current;
177
178 public CharacterIterator(String text) {
179 this.chars = text.toCharArray();
180 }
181
182
183 public CharacterIterator(char[] chars) {
184 this.chars = chars;
185 }
186
187
188 public boolean next() {
189
190 pos++;
191
192 if (pos >= chars.length) {
193 return false;
194 } else {
195 current = chars[pos];
196
197 return true;
198 }
199 }
200
201
202 public char get() {
203 return current;
204 }
205 }
206 }