KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > classycle > ClassNameExtractor


1 /*
2  * Copyright (c) 2003-2006, Franz-Josef Elmer, All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * - Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */

25 /*
26  * Created on 24.09.2006
27  */

28 package classycle;
29
30 import java.util.Collections JavaDoc;
31 import java.util.LinkedHashSet JavaDoc;
32 import java.util.Set JavaDoc;
33
34 import classycle.classfile.UTF8Constant;
35
36 class ClassNameExtractor
37 {
38   /** Returns <tt>true</tt> if <tt>className</tt> is a valid class name. */
39   static boolean isValid(String JavaDoc className)
40   {
41     boolean valid = true;
42     boolean firstCharacter = true;
43     for (int i = 0, n = className.length(); valid && i < n; i++)
44     {
45       char c = className.charAt(i);
46       if (firstCharacter)
47       {
48         firstCharacter = false;
49         valid = Character.isJavaIdentifierStart(c);
50       } else
51       {
52         if (c == '.')
53         {
54           firstCharacter = true;
55         } else
56         {
57           valid = Character.isJavaIdentifierPart(c);
58         }
59       }
60     }
61     return valid && firstCharacter == false;
62   }
63   
64   private final String JavaDoc _constant;
65   
66   private int _index;
67   private int _endIndex;
68   private Set JavaDoc _classNames = new LinkedHashSet JavaDoc();
69   private boolean _valid = true;
70   
71   ClassNameExtractor(UTF8Constant constant)
72   {
73     _constant = constant.getString();
74     _endIndex = _constant.length();
75   }
76   
77   Set JavaDoc extract()
78   {
79     if (getCurrentCharacter() == '<')
80     {
81       int ddIndex = _constant.indexOf("::", _index);
82       if (ddIndex > 0)
83       {
84         _index = ddIndex + 2;
85         parseTypes(false);
86         if (getCurrentCharacter() == '>')
87         {
88           _index++;
89         } else
90         {
91           setInvalid();
92         }
93       } else
94       {
95         setInvalid();
96       }
97     }
98     if (getCurrentCharacter() == '(')
99     {
100       int endIndex = _constant.indexOf(')', _index);
101       if (endIndex > 0)
102       {
103         _index++;
104         _endIndex = endIndex;
105         parseTypes(false);
106         _index = endIndex + 1;
107         _endIndex = _constant.length();
108       } else
109       {
110         setInvalid();
111       }
112     }
113     if (_valid)
114     {
115       int numberOfTypes = parseTypes(false);
116       if (numberOfTypes == 0)
117       {
118         setInvalid();
119       }
120     }
121     return _valid ? _classNames : Collections.EMPTY_SET;
122   }
123   
124   private int parseTypes(boolean generics)
125   {
126     int numberOfTypes = 0;
127     while (_valid && endOfTypes() == false)
128     {
129       parseType(generics);
130       numberOfTypes++;
131     }
132     return numberOfTypes;
133   }
134
135   private char getCurrentCharacter()
136   {
137     return _index < _endIndex ? _constant.charAt(_index) : 0;
138   }
139
140   private void setInvalid()
141   {
142     _valid = false;
143   }
144   
145   private boolean endOfTypes()
146   {
147     return _index >= _endIndex || _constant.charAt(_index) == '>';
148   }
149   
150   private void parseType(boolean generics)
151   {
152     if (generics)
153     {
154       char currentCharacter = getCurrentCharacter();
155       if (currentCharacter == '+')
156       {
157         _index++;
158       } else if (currentCharacter == '*')
159       {
160         _index++;
161         return;
162       }
163     }
164     boolean arrayType = false;
165     for (; getCurrentCharacter() == '['; _index++)
166     {
167       arrayType = true;
168     }
169     if (arrayType && endOfTypes())
170     {
171       setInvalid();
172     } else
173     {
174       char c = getCurrentCharacter();
175       _index++;
176       if (c == 'L')
177       {
178         parseComplexType();
179       } else if (c == 'T')
180       {
181         int index = _constant.indexOf(';', _index);
182         if (index < 0)
183         {
184           setInvalid();
185         } else
186         {
187           _index = index + 1;
188         }
189       } else if ("BCDFIJSVZ".indexOf(c) < 0)
190       {
191         setInvalid();
192       }
193     }
194   }
195   
196   private void parseComplexType()
197   {
198     int typeIndex = _constant.indexOf('<', _index);
199     int endIndex = _constant.indexOf(';', _index);
200     if (typeIndex >= 0 && typeIndex < endIndex) {
201       extractClassName(typeIndex);
202       parseTypes(true);
203       _index += 2;
204     } else if (endIndex > 0)
205     {
206       extractClassName(endIndex);
207     } else
208     {
209       setInvalid();
210     }
211   }
212   
213   private void extractClassName(int endIndex)
214   {
215     String JavaDoc className = _constant.substring(_index, endIndex);
216     className = className.replace('/', '.');
217     _classNames.add(className);
218     _index = endIndex + 1;
219     if (isValid(className) == false)
220     {
221       setInvalid();
222     }
223   }
224
225 }
226
Popular Tags