KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > attributes > AttributeIndex


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.attributes;
17
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.io.BufferedReader;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Field;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.Enumeration;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.StringTokenizer;
34
35 /**
36  * An index providing a list of elements with given attributes. This
37  * requires that the attribute is {@link Indexed} and that the
38  * attribute indexer tool has been run on the jar file containing the
39  * classes.
40  */

41 public class AttributeIndex {
42     
43     /**
44      * Reference to a method parameter. A method parameter
45      * is defined by the Method object it is defined in, and the index
46      * of the parameter in the method's parameter list.
47      */

48     public static class MethodParameter {
49         
50         private final Method method;
51         private final int index;
52         
53         /**
54          * Constructs a new MethodParameter.
55          */

56         public MethodParameter (Method method, int index) {
57             this.method = method;
58             this.index = index;
59         }
60         
61         /**
62          * Get the method this parameter is defined in.
63          */

64         public Method getMethod () {
65             return method;
66         }
67         
68         /**
69          * Get the index of this parameter in the parameter list of the method.
70          */

71         public int getIndex () {
72             return index;
73         }
74         
75         /**
76          * Compares two <code>MethodParameter</code>s for equality.
77          * They must point to the same method and have the same index.
78          */

79         public boolean equals (Object o) {
80             return o != null && o instanceof MethodParameter &&
81                 method.equals (((MethodParameter) o).method) &&
82                 index == ((MethodParameter) o).index;
83         }
84         
85         /**
86          * Computes the hashCode.
87          */

88         public int hashCode () {
89             return method.hashCode () + index;
90         }
91         
92         /**
93          * Converts this method parameter into a human-readable string.
94          */

95         public String toString () {
96             return method.toString () + ":" + index;
97         }
98     }
99     
100     /**
101      * A constructor parameter. A method parameter
102      * is defined by the Method object it is defined in, and the index
103      * of the parameter in the method's parameter list.
104      */

105     public static class ConstructorParameter {
106         
107         private final Constructor ctor;
108         private final int index;
109         
110         
111         /**
112          * Constructs a new ConstructorParameter.
113          */

114         public ConstructorParameter (Constructor ctor, int index) {
115             this.ctor = ctor;
116             this.index = index;
117         }
118         
119         /**
120          * Get the constructor this parameter is defined in.
121          */

122         public Constructor getConstructor () {
123             return ctor;
124         }
125         
126         /**
127          * Get the index of this parameter in the parameter list of the constructor.
128          */

129         public int getIndex () {
130             return index;
131         }
132         
133         /**
134          * Compares two <code>ConstructorParameter</code>s for equality.
135          * They must point to the same constructor and have the same index.
136          */

137         public boolean equals (Object o) {
138             return o != null && o instanceof ConstructorParameter &&
139                 ctor.equals (((ConstructorParameter) o).ctor) &&
140                 index == ((ConstructorParameter) o).index;
141         }
142         
143         /**
144          * Computes the hashCode.
145          */

146         public int hashCode () {
147             return ctor.hashCode () + index;
148         }
149         
150         /**
151          * Converts this constructor parameter into a human-readable string.
152          */

153         public String toString () {
154             return ctor.toString () + ":" + index;
155         }
156     }
157     
158     private static class IndexNode {
159         public Collection classes = new HashSet ();
160         public Collection fields = new HashSet ();
161         public Collection methods = new HashSet ();
162         public Collection constructors = new HashSet ();
163         public Collection returnValues = new HashSet ();
164         public Collection constructorParameters = new HashSet ();
165         public Collection methodParameters = new HashSet ();
166         
167         public void seal () {
168             classes = seal (classes);
169             fields = seal (fields);
170             methods = seal (methods);
171             constructors = seal (constructors);
172             returnValues = seal (returnValues);
173             constructorParameters = seal (constructorParameters);
174             methodParameters = seal (methodParameters);
175         }
176         
177         private Collection seal (Collection coll) {
178             return Collections.unmodifiableCollection (coll);
179         }
180     }
181     
182     private final HashMap index = new HashMap ();
183     private final ClassLoader classLoader;
184     
185     /**
186      * Creates a new AttributeIndex for the given ClassLoader.
187      */

188     public AttributeIndex (ClassLoader cl) throws Exception {
189         this.classLoader = cl;
190         Enumeration enum = cl.getResources ("META-INF/attrs.index");
191         while (enum.hasMoreElements ()) {
192             URL url = (URL) enum.nextElement ();
193             loadFromURL (url);
194         }
195         
196         Iterator iter = index.values ().iterator ();
197         while (iter.hasNext ()) {
198             ((IndexNode) iter.next ()).seal ();
199         }
200     }
201     
202     private IndexNode getNode (Class attributeClass) {
203         IndexNode node = (IndexNode) index.get (attributeClass.getName ());
204         if (node == null) {
205             node = new IndexNode ();
206             index.put (attributeClass.getName (), node);
207         }
208         
209         return node;
210     }
211     
212     private void addIndex (Collection attributes, Class clazz) {
213         Iterator iter = attributes.iterator ();
214         while (iter.hasNext ()) {
215             getNode (iter.next ().getClass ()).classes.add (clazz);
216         }
217     }
218     
219     private void addIndex (Collection attributes, Field field) {
220         Iterator iter = attributes.iterator ();
221         while (iter.hasNext ()) {
222             getNode (iter.next ().getClass ()).fields.add (field);
223         }
224     }
225     
226     private void addIndex (Collection attributes, Method method) {
227         Iterator iter = attributes.iterator ();
228         while (iter.hasNext ()) {
229             getNode (iter.next ().getClass ()).methods.add (method);
230         }
231     }
232     
233     private void addIndex (Collection attributes, Constructor constructor) {
234         Iterator iter = attributes.iterator ();
235         while (iter.hasNext ()) {
236             getNode (iter.next ().getClass ()).constructors.add (constructor);
237         }
238     }
239     
240     private void addReturnIndex (Collection attributes, Method method) {
241         Iterator iter = attributes.iterator ();
242         while (iter.hasNext ()) {
243             getNode (iter.next ().getClass ()).returnValues.add (method);
244         }
245     }
246     
247     private void addIndex (Collection attributes, Method method, int parameter) {
248         Iterator iter = attributes.iterator ();
249         while (iter.hasNext ()) {
250             getNode (iter.next ().getClass ()).methodParameters.add (new MethodParameter (method, parameter));
251         }
252     }
253     
254     private void addIndex (Collection attributes, Constructor ctor, int parameter) {
255         Iterator iter = attributes.iterator ();
256         while (iter.hasNext ()) {
257             getNode (iter.next ().getClass ()).constructorParameters.add (new ConstructorParameter (ctor, parameter));
258         }
259     }
260     
261     /**
262      * Add a class to the index.
263      */

264     private void addClass (String clazzName) throws Exception {
265         Class clazz = classLoader.loadClass (clazzName);
266         
267         // Get the attributes attached to the class itself...
268
Collection coll = Attributes.getAttributes (clazz);
269         
270         coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
271         addIndex (coll, clazz);
272         
273         Field[] fields = clazz.getDeclaredFields ();
274         for (int i = 0; i < fields.length; i++) {
275             coll = Attributes.getAttributes (fields[i]);
276             
277             coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
278             addIndex (coll, fields[i]);
279         }
280         
281         Method[] methods = clazz.getDeclaredMethods ();
282         for (int i = 0; i < methods.length; i++) {
283             coll = Attributes.getAttributes (methods[i]);
284             
285             coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
286             addIndex (coll, methods[i]);
287             
288             // Return values
289
coll = Attributes.getReturnAttributes (methods[i]);
290             
291             coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
292             addReturnIndex (coll, methods[i]);
293             
294             // Parameters
295
int numParameters = methods[i].getParameterTypes().length;
296             for (int j = 0; j < numParameters; j++) {
297                 coll = Attributes.getParameterAttributes (methods[i], j);
298                 
299                 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
300                 addIndex (coll, methods[i], j);
301             }
302         }
303         
304         Constructor[] ctors = clazz.getDeclaredConstructors ();
305         for (int i = 0; i < ctors.length; i++) {
306             coll = Attributes.getAttributes (ctors[i]);
307             
308             coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
309             addIndex (coll, ctors[i]);
310             
311             // Parameters
312
int numParameters = ctors[i].getParameterTypes().length;
313             for (int j = 0; j < numParameters; j++) {
314                 coll = Attributes.getParameterAttributes (ctors[i], j);
315                 
316                 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
317                 addIndex (coll, ctors[i], j);
318             }
319         }
320     }
321     
322     /**
323      * Load the attrs.index from a given URL.
324      */

325     private void loadFromURL (URL url) throws Exception {
326         URLConnection connection = url.openConnection ();
327         BufferedReader br = new BufferedReader (new InputStreamReader (connection.getInputStream ()));
328         try {
329             String currentAttributeClass = null;
330             String line = null;
331             while ((line = br.readLine ()) != null) {
332                 if (line.startsWith ("Class: ")) {
333                     String className = line.substring ("Class: ".length ()).trim ();
334                     addClass (className);
335                 }
336             }
337         } finally {
338             br.close ();
339         }
340     }
341     
342     /**
343      * Gets a Collection of the classes that have an attribute of the specified class.
344      * The Collection contains the class names (String).
345      *
346      * @deprecated Use the getClasses(Class) method instead.
347      */

348     public Collection getClassesWithAttribute (String attributeClass) {
349         if (index.containsKey (attributeClass)) {
350             Collection classes = ((IndexNode) index.get (attributeClass)).classes;
351             Iterator iter = classes.iterator ();
352             Collection converted = new ArrayList (classes.size ());
353             while (iter.hasNext ()) {
354                 converted.add (((Class) iter.next ()).getName ().replace ('$', '.'));
355             }
356             return converted;
357         } else {
358             return Collections.EMPTY_SET;
359         }
360     }
361     
362     /**
363      * Gets a Collection of the classes that have an attribute of the specified class.
364      * The Collection contains the class names (String).
365      *
366      * @deprecated Use the getClasses(Class) method instead.
367      */

368     public Collection getClassesWithAttribute (Class attributeClass) {
369         return getClassesWithAttribute (attributeClass.getName ());
370     }
371     
372     /**
373      * Gets a Collection of the <code>Class</code>es that have an attribute of the specified class.
374      * The Collection contains the classes (Class).
375      */

376     public Collection getClasses (Class attributeClass) {
377         if (index.containsKey (attributeClass.getName ())) {
378             return ((IndexNode) index.get (attributeClass.getName ())).classes;
379         } else {
380             return Collections.EMPTY_SET;
381         }
382     }
383     
384     /**
385      * Gets a Collection of the <code>Method</code>s that have an attribute of the specified class.
386      * The Collection contains the methods (java.lang.reflect.Method).
387      */

388     public Collection getMethods (Class attributeClass) {
389         if (index.containsKey (attributeClass.getName ())) {
390             return ((IndexNode) index.get (attributeClass.getName ())).methods;
391         } else {
392             return Collections.EMPTY_SET;
393         }
394     }
395     
396     /**
397      * Gets a Collection of the <code>Method</code>s whose return value has an attribute of the specified class.
398      * The Collection contains the methods (java.lang.reflect.Method).
399      */

400     public Collection getMethodsReturning (Class attributeClass) {
401         if (index.containsKey (attributeClass.getName ())) {
402             return ((IndexNode) index.get (attributeClass.getName ())).returnValues;
403         } else {
404             return Collections.EMPTY_SET;
405         }
406     }
407     
408     /**
409      * Gets a Collection of the <code>Field</code>s that have an attribute of the specified class.
410      * The Collection contains the methods (java.lang.reflect.Field).
411      */

412     public Collection getFields (Class attributeClass) {
413         if (index.containsKey (attributeClass.getName ())) {
414             return ((IndexNode) index.get (attributeClass.getName ())).fields;
415         } else {
416             return Collections.EMPTY_SET;
417         }
418     }
419     
420     /**
421      * Gets a Collection of the <code>Constructor</code>s that have an attribute of the specified class.
422      * The Collection contains the methods (java.lang.reflect.Constructor).
423      */

424     public Collection getConstructors (Class attributeClass) {
425         if (index.containsKey (attributeClass.getName ())) {
426             return ((IndexNode) index.get (attributeClass.getName ())).constructors;
427         } else {
428             return Collections.EMPTY_SET;
429         }
430     }
431     
432     /**
433      * Gets a Collection of the <code>ConstructorParameter</code>s that have an attribute of the specified class.
434      * The Collection contains the methods ({@link AttributeIndex.ConstructorParameter}).
435      */

436     public Collection getConstructorParameters (Class attributeClass) {
437         if (index.containsKey (attributeClass.getName ())) {
438             return ((IndexNode) index.get (attributeClass.getName ())).constructorParameters;
439         } else {
440             return Collections.EMPTY_SET;
441         }
442     }
443     
444     /**
445      * Gets a Collection of the <code>MethodParameter</code>s that have an attribute of the specified class.
446      * The Collection contains the methods ({@link AttributeIndex.MethodParameter}).
447      */

448     public Collection getMethodParameters (Class attributeClass) {
449         if (index.containsKey (attributeClass.getName ())) {
450             return ((IndexNode) index.get (attributeClass.getName ())).methodParameters;
451         } else {
452             return Collections.EMPTY_SET;
453         }
454     }
455 }
Popular Tags