KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > renderable > ParameterBlock


1 /*
2  * @(#)ParameterBlock.java 1.14 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image.renderable;
9 import java.awt.image.RenderedImage JavaDoc;
10 import java.io.Serializable JavaDoc;
11 import java.util.Vector JavaDoc;
12
13 /**
14  * A <code>ParameterBlock</code> encapsulates all the information about sources and
15  * parameters (Objects) required by a RenderableImageOp, or other
16  * classes that process images.
17  *
18  * <p> Although it is possible to place arbitrary objects in the
19  * source Vector, users of this class may impose semantic constraints
20  * such as requiring all sources to be RenderedImages or
21  * RenderableImage. <code>ParameterBlock</code> itself is merely a container and
22  * performs no checking on source or parameter types.
23  *
24  * <p> All parameters in a <code>ParameterBlock</code> are objects; convenience
25  * add and set methods are available that take arguments of base type and
26  * construct the appropriate subclass of Number (such as
27  * Integer or Float). Corresponding get methods perform a
28  * downward cast and have return values of base type; an exception
29  * will be thrown if the stored values do not have the correct type.
30  * There is no way to distinguish between the results of
31  * "short s; add(s)" and "add(new Short(s))".
32  *
33  * <p> Note that the get and set methods operate on references.
34  * Therefore, one must be careful not to share references between
35  * <code>ParameterBlock</code>s when this is inappropriate. For example, to create
36  * a new <code>ParameterBlock</code> that is equal to an old one except for an
37  * added source, one might be tempted to write:
38  *
39  * <pre>
40  * ParameterBlock addSource(ParameterBlock pb, RenderableImage im) {
41  * ParameterBlock pb1 = new ParameterBlock(pb.getSources());
42  * pb1.addSource(im);
43  * return pb1;
44  * }
45  * </pre>
46  *
47  * <p> This code will have the side effect of altering the original
48  * <code>ParameterBlock</code>, since the getSources operation returned a reference
49  * to its source Vector. Both pb and pb1 share their source Vector,
50  * and a change in either is visible to both.
51  *
52  * <p> A correct way to write the addSource function is to clone
53  * the source Vector:
54  *
55  * <pre>
56  * ParameterBlock addSource (ParameterBlock pb, RenderableImage im) {
57  * ParameterBlock pb1 = new ParameterBlock(pb.getSources().clone());
58  * pb1.addSource(im);
59  * return pb1;
60  * }
61  * </pre>
62  *
63  * <p> The clone method of <code>ParameterBlock</code> has been defined to
64  * perform a clone of both the source and parameter Vectors for
65  * this reason. A standard, shallow clone is available as
66  * shallowClone.
67  *
68  * <p> The addSource, setSource, add, and set methods are
69  * defined to return 'this' after adding their argument. This allows
70  * use of syntax like:
71  *
72  * <pre>
73  * ParameterBlock pb = new ParameterBlock();
74  * op = new RenderableImageOp("operation", pb.add(arg1).add(arg2));
75  * </pre>
76  * */

77 public class ParameterBlock implements Cloneable JavaDoc, Serializable JavaDoc {
78     /** A Vector of sources, stored as arbitrary Objects. */
79     protected Vector JavaDoc<Object JavaDoc> sources = new Vector JavaDoc<Object JavaDoc>();
80     
81     /** A Vector of non-source parameters, stored as arbitrary Objects. */
82     protected Vector JavaDoc<Object JavaDoc> parameters = new Vector JavaDoc<Object JavaDoc>();
83
84     /** A dummy constructor. */
85     public ParameterBlock() {}
86
87     /**
88      * Constructs a <code>ParameterBlock</code> with a given Vector
89      * of sources.
90      * @param sources a <code>Vector</code> of source images
91      */

92     public ParameterBlock(Vector JavaDoc<Object JavaDoc> sources) {
93         setSources(sources);
94     }
95     
96     /**
97      * Constructs a <code>ParameterBlock</code> with a given Vector of sources and
98      * Vector of parameters.
99      * @param sources a <code>Vector</code> of source images
100      * @param parameters a <code>Vector</code> of parameters to be used in the
101      * rendering operation
102      */

103     public ParameterBlock(Vector JavaDoc<Object JavaDoc> sources,
104               Vector JavaDoc<Object JavaDoc> parameters)
105     {
106         setSources(sources);
107         setParameters(parameters);
108     }
109     
110     /**
111      * Creates a shallow copy of a <code>ParameterBlock</code>. The source and
112      * parameter Vectors are copied by reference -- additions or
113      * changes will be visible to both versions.
114      *
115      * @return an Object clone of the <code>ParameterBlock</code>.
116      */

117     public Object JavaDoc shallowClone() {
118         try {
119             return super.clone();
120         } catch (Exception JavaDoc e) {
121             // We can't be here since we implement Cloneable.
122
return null;
123         }
124     }
125
126     /**
127      * Creates a copy of a <code>ParameterBlock</code>. The source and parameter
128      * Vectors are cloned, but the actual sources and parameters are
129      * copied by reference. This allows modifications to the order
130      * and number of sources and parameters in the clone to be invisible
131      * to the original <code>ParameterBlock</code>. Changes to the shared sources or
132      * parameters themselves will still be visible.
133      *
134      * @return an Object clone of the <code>ParameterBlock</code>.
135      */

136     public Object JavaDoc clone() {
137         ParameterBlock JavaDoc theClone;
138
139         try {
140             theClone = (ParameterBlock JavaDoc) super.clone();
141         } catch (Exception JavaDoc e) {
142             // We can't be here since we implement Cloneable.
143
return null;
144         }
145
146         if (sources != null) {
147             theClone.setSources((Vector JavaDoc)sources.clone());
148         }
149         if (parameters != null) {
150             theClone.setParameters((Vector JavaDoc)parameters.clone());
151         }
152         return (Object JavaDoc) theClone;
153     }
154
155     /**
156      * Adds an image to end of the list of sources. The image is
157      * stored as an object in order to allow new node types in the
158      * future.
159      *
160      * @param source an image object to be stored in the source list.
161      * @return a new <code>ParameterBlock</code> containing the specified
162      * <code>source</code>.
163      */

164     public ParameterBlock JavaDoc addSource(Object JavaDoc source) {
165         sources.addElement(source);
166         return this;
167     }
168     
169     /**
170      * Returns a source as a general Object. The caller must cast it into
171      * an appropriate type.
172      *
173      * @param index the index of the source to be returned.
174      * @return an <code>Object</code> that represents the source located
175      * at the specified index in the <code>sources</code>
176      * <code>Vector</code>.
177      * @see #setSource(Object, int)
178      */

179     public Object JavaDoc getSource(int index) {
180         return sources.elementAt(index);
181     }
182
183     /**
184      * Replaces an entry in the list of source with a new source.
185      * If the index lies beyond the current source list,
186      * the list is extended with nulls as needed.
187      * @param source the specified source image
188      * @param index the index into the <code>sources</code>
189      * <code>Vector</code> at which to
190      * insert the specified <code>source</code>
191      * @return a new <code>ParameterBlock</code> that contains the
192      * specified <code>source</code> at the specified
193      * <code>index</code>.
194      * @see #getSource(int)
195      */

196     public ParameterBlock JavaDoc setSource(Object JavaDoc source, int index) {
197         int oldSize = sources.size();
198         int newSize = index + 1;
199         if (oldSize < newSize) {
200             sources.setSize(newSize);
201         }
202         sources.setElementAt(source, index);
203         return this;
204     }
205     
206     /**
207      * Returns a source as a <code>RenderedImage</code>. This method is
208      * a convenience method.
209      * An exception will be thrown if the source is not a RenderedImage.
210      *
211      * @param index the index of the source to be returned
212      * @return a <code>RenderedImage</code> that represents the source
213      * image that is at the specified index in the
214      * <code>sources</code> <code>Vector</code>.
215      */

216     public RenderedImage JavaDoc getRenderedSource(int index) {
217         return (RenderedImage JavaDoc) sources.elementAt(index);
218     }
219     
220     /**
221      * Returns a source as a RenderableImage. This method is a
222      * convenience method.
223      * An exception will be thrown if the sources is not a RenderableImage.
224      *
225      * @param index the index of the source to be returned
226      * @return a <code>RenderableImage</code> that represents the source
227      * image that is at the specified index in the
228      * <code>sources</code> <code>Vector</code>.
229      */

230     public RenderableImage JavaDoc getRenderableSource(int index) {
231         return (RenderableImage JavaDoc) sources.elementAt(index);
232     }
233
234     /**
235      * Returns the number of source images.
236      * @return the number of source images in the <code>sources</code>
237      * <code>Vector</code>.
238      */

239     public int getNumSources() {
240         return sources.size();
241     }
242     
243     /**
244      * Returns the entire Vector of sources.
245      * @return the <code>sources</code> <code>Vector</code>.
246      * @see #setSources(Vector)
247      */

248     public Vector JavaDoc<Object JavaDoc> getSources() {
249         return sources;
250     }
251     
252     /**
253      * Sets the entire Vector of sources to a given Vector.
254      * @param sources the <code>Vector</code> of source images
255      * @see #getSources
256      */

257     public void setSources(Vector JavaDoc<Object JavaDoc> sources) {
258         this.sources = sources;
259     }
260     
261     /** Clears the list of source images. */
262     public void removeSources() {
263         sources = new Vector JavaDoc();
264     }
265     
266     /**
267      * Returns the number of parameters (not including source images).
268      * @return the number of parameters in the <code>parameters</code>
269      * <code>Vector</code>.
270      */

271     public int getNumParameters() {
272         return parameters.size();
273     }
274     
275     /**
276      * Returns the entire Vector of parameters.
277      * @return the <code>parameters</code> <code>Vector</code>.
278      * @see #setParameters(Vector)
279      */

280     public Vector JavaDoc<Object JavaDoc> getParameters() {
281         return parameters;
282     }
283     
284     /**
285      * Sets the entire Vector of parameters to a given Vector.
286      * @param parameters the specified <code>Vector</code> of
287      * parameters
288      * @see #getParameters
289      */

290     public void setParameters(Vector JavaDoc<Object JavaDoc> parameters) {
291         this.parameters = parameters;
292     }
293     
294     /** Clears the list of parameters. */
295     public void removeParameters() {
296         parameters = new Vector JavaDoc();
297     }
298     
299     /**
300      * Adds an object to the list of parameters.
301      * @param obj the <code>Object</code> to add to the
302      * <code>parameters</code> <code>Vector</code>
303      * @return a new <code>ParameterBlock</code> containing
304      * the specified parameter.
305      */

306     public ParameterBlock JavaDoc add(Object JavaDoc obj) {
307         parameters.addElement(obj);
308         return this;
309     }
310
311     /**
312      * Adds a Byte to the list of parameters.
313      * @param b the byte to add to the
314      * <code>parameters</code> <code>Vector</code>
315      * @return a new <code>ParameterBlock</code> containing
316      * the specified parameter.
317      */

318     public ParameterBlock JavaDoc add(byte b) {
319         return add(new Byte JavaDoc(b));
320     }
321     
322     /**
323      * Adds a Character to the list of parameters.
324      * @param c the char to add to the
325      * <code>parameters</code> <code>Vector</code>
326      * @return a new <code>ParameterBlock</code> containing
327      * the specified parameter.
328      */

329     public ParameterBlock JavaDoc add(char c) {
330         return add(new Character JavaDoc(c));
331     }
332     
333     /**
334      * Adds a Short to the list of parameters.
335      * @param s the short to add to the
336      * <code>parameters</code> <code>Vector</code>
337      * @return a new <code>ParameterBlock</code> containing
338      * the specified parameter.
339      */

340     public ParameterBlock JavaDoc add(short s) {
341         return add(new Short JavaDoc(s));
342     }
343     
344     /**
345      * Adds a Integer to the list of parameters.
346      * @param i the int to add to the
347      * <code>parameters</code> <code>Vector</code>
348      * @return a new <code>ParameterBlock</code> containing
349      * the specified parameter.
350      */

351     public ParameterBlock JavaDoc add(int i) {
352         return add(new Integer JavaDoc(i));
353     }
354     
355     /**
356      * Adds a Long to the list of parameters.
357      * @param l the long to add to the
358      * <code>parameters</code> <code>Vector</code>
359      * @return a new <code>ParameterBlock</code> containing
360      * the specified parameter.
361      */

362     public ParameterBlock JavaDoc add(long l) {
363         return add(new Long JavaDoc(l));
364     }
365
366     /**
367      * Adds a Float to the list of parameters.
368      * @param f the float to add to the
369      * <code>parameters</code> <code>Vector</code>
370      * @return a new <code>ParameterBlock</code> containing
371      * the specified parameter.
372      */

373     public ParameterBlock JavaDoc add(float f) {
374         return add(new Float JavaDoc(f));
375     }
376
377     /**
378      * Adds a Double to the list of parameters.
379      * @param d the double to add to the
380      * <code>parameters</code> <code>Vector</code>
381      * @return a new <code>ParameterBlock</code> containing
382      * the specified parameter.
383      */

384     public ParameterBlock JavaDoc add(double d) {
385         return add(new Double JavaDoc(d));
386     }
387
388     /**
389      * Replaces an Object in the list of parameters.
390      * If the index lies beyond the current source list,
391      * the list is extended with nulls as needed.
392      * @param obj the parameter that replaces the
393      * parameter at the specified index in the
394      * <code>parameters</code> <code>Vector</code>
395      * @param index the index of the parameter to be
396      * replaced with the specified parameter
397      * @return a new <code>ParameterBlock</code> containing
398      * the specified parameter.
399      */

400     public ParameterBlock JavaDoc set(Object JavaDoc obj, int index) {
401         int oldSize = parameters.size();
402         int newSize = index + 1;
403         if (oldSize < newSize) {
404             parameters.setSize(newSize);
405         }
406         parameters.setElementAt(obj, index);
407         return this;
408     }
409
410     /**
411      * Replaces an Object in the list of parameters with a Byte.
412      * If the index lies beyond the current source list,
413      * the list is extended with nulls as needed.
414      * @param b the parameter that replaces the
415      * parameter at the specified index in the
416      * <code>parameters</code> <code>Vector</code>
417      * @param index the index of the parameter to be
418      * replaced with the specified parameter
419      * @return a new <code>ParameterBlock</code> containing
420      * the specified parameter.
421      */

422     public ParameterBlock JavaDoc set(byte b, int index) {
423         return set(new Byte JavaDoc(b), index);
424     }
425
426     /**
427      * Replaces an Object in the list of parameters with a Character.
428      * If the index lies beyond the current source list,
429      * the list is extended with nulls as needed.
430      * @param c the parameter that replaces the
431      * parameter at the specified index in the
432      * <code>parameters</code> <code>Vector</code>
433      * @param index the index of the parameter to be
434      * replaced with the specified parameter
435      * @return a new <code>ParameterBlock</code> containing
436      * the specified parameter.
437      */

438     public ParameterBlock JavaDoc set(char c, int index) {
439         return set(new Character JavaDoc(c), index);
440     }
441
442     /**
443      * Replaces an Object in the list of parameters with a Short.
444      * If the index lies beyond the current source list,
445      * the list is extended with nulls as needed.
446      * @param s the parameter that replaces the
447      * parameter at the specified index in the
448      * <code>parameters</code> <code>Vector</code>
449      * @param index the index of the parameter to be
450      * replaced with the specified parameter
451      * @return a new <code>ParameterBlock</code> containing
452      * the specified parameter.
453      */

454     public ParameterBlock JavaDoc set(short s, int index) {
455         return set(new Short JavaDoc(s), index);
456     }
457
458     /**
459      * Replaces an Object in the list of parameters with an Integer.
460      * If the index lies beyond the current source list,
461      * the list is extended with nulls as needed.
462      * @param i the parameter that replaces the
463      * parameter at the specified index in the
464      * <code>parameters</code> <code>Vector</code>
465      * @param index the index of the parameter to be
466      * replaced with the specified parameter
467      * @return a new <code>ParameterBlock</code> containing
468      * the specified parameter.
469      */

470     public ParameterBlock JavaDoc set(int i, int index) {
471         return set(new Integer JavaDoc(i), index);
472     }
473
474     /**
475      * Replaces an Object in the list of parameters with a Long.
476      * If the index lies beyond the current source list,
477      * the list is extended with nulls as needed.
478      * @param l the parameter that replaces the
479      * parameter at the specified index in the
480      * <code>parameters</code> <code>Vector</code>
481      * @param index the index of the parameter to be
482      * replaced with the specified parameter
483      * @return a new <code>ParameterBlock</code> containing
484      * the specified parameter.
485      */

486     public ParameterBlock JavaDoc set(long l, int index) {
487         return set(new Long JavaDoc(l), index);
488     }
489
490     /**
491      * Replaces an Object in the list of parameters with a Float.
492      * If the index lies beyond the current source list,
493      * the list is extended with nulls as needed.
494      * @param f the parameter that replaces the
495      * parameter at the specified index in the
496      * <code>parameters</code> <code>Vector</code>
497      * @param index the index of the parameter to be
498      * replaced with the specified parameter
499      * @return a new <code>ParameterBlock</code> containing
500      * the specified parameter.
501      */

502     public ParameterBlock JavaDoc set(float f, int index) {
503         return set(new Float JavaDoc(f), index);
504     }
505
506     /**
507      * Replaces an Object in the list of parameters with a Double.
508      * If the index lies beyond the current source list,
509      * the list is extended with nulls as needed.
510      * @param d the parameter that replaces the
511      * parameter at the specified index in the
512      * <code>parameters</code> <code>Vector</code>
513      * @param index the index of the parameter to be
514      * replaced with the specified parameter
515      * @return a new <code>ParameterBlock</code> containing
516      * the specified parameter.
517      */

518     public ParameterBlock JavaDoc set(double d, int index) {
519         return set(new Double JavaDoc(d), index);
520     }
521
522     /**
523      * Gets a parameter as an object.
524      * @param index the index of the parameter to get
525      * @return an <code>Object</code> representing the
526      * the parameter at the specified index
527      * into the <code>parameters</code>
528      * <code>Vector</code>.
529      */

530     public Object JavaDoc getObjectParameter(int index) {
531         return parameters.elementAt(index);
532     }
533
534     /**
535      * A convenience method to return a parameter as a byte. An
536      * exception is thrown if the parameter is
537      * <code>null</code> or not a <code>Byte</code>.
538      *
539      * @param index the index of the parameter to be returned.
540      * @return the parameter at the specified index
541      * as a <code>byte</code> value.
542      * @throws ClassCastException if the parameter at the
543      * specified index is not a <code>Byte</code>
544      * @throws NullPointerException if the parameter at the specified
545      * index is <code>null</code>
546      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
547      * is negative or not less than the current size of this
548      * <code>ParameterBlock</code> object
549      */

550     public byte getByteParameter(int index) {
551         return ((Byte JavaDoc)parameters.elementAt(index)).byteValue();
552     }
553
554     /**
555      * A convenience method to return a parameter as a char. An
556      * exception is thrown if the parameter is
557      * <code>null</code> or not a <code>Character</code>.
558      *
559      * @param index the index of the parameter to be returned.
560      * @return the parameter at the specified index
561      * as a <code>char</code> value.
562      * @throws ClassCastException if the parameter at the
563      * specified index is not a <code>Character</code>
564      * @throws NullPointerException if the parameter at the specified
565      * index is <code>null</code>
566      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
567      * is negative or not less than the current size of this
568      * <code>ParameterBlock</code> object
569      */

570     public char getCharParameter(int index) {
571         return ((Character JavaDoc)parameters.elementAt(index)).charValue();
572     }
573     
574     /**
575      * A convenience method to return a parameter as a short. An
576      * exception is thrown if the parameter is
577      * <code>null</code> or not a <code>Short</code>.
578      *
579      * @param index the index of the parameter to be returned.
580      * @return the parameter at the specified index
581      * as a <code>short</code> value.
582      * @throws ClassCastException if the parameter at the
583      * specified index is not a <code>Short</code>
584      * @throws NullPointerException if the parameter at the specified
585      * index is <code>null</code>
586      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
587      * is negative or not less than the current size of this
588      * <code>ParameterBlock</code> object
589      */

590     public short getShortParameter(int index) {
591         return ((Short JavaDoc)parameters.elementAt(index)).shortValue();
592     }
593
594     /**
595      * A convenience method to return a parameter as an int. An
596      * exception is thrown if the parameter is
597      * <code>null</code> or not an <code>Integer</code>.
598      *
599      * @param index the index of the parameter to be returned.
600      * @return the parameter at the specified index
601      * as a <code>int</code> value.
602      * @throws ClassCastException if the parameter at the
603      * specified index is not a <code>Integer</code>
604      * @throws NullPointerException if the parameter at the specified
605      * index is <code>null</code>
606      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
607      * is negative or not less than the current size of this
608      * <code>ParameterBlock</code> object
609      */

610     public int getIntParameter(int index) {
611         return ((Integer JavaDoc)parameters.elementAt(index)).intValue();
612     }
613
614     /**
615      * A convenience method to return a parameter as a long. An
616      * exception is thrown if the parameter is
617      * <code>null</code> or not a <code>Long</code>.
618      *
619      * @param index the index of the parameter to be returned.
620      * @return the parameter at the specified index
621      * as a <code>long</code> value.
622      * @throws ClassCastException if the parameter at the
623      * specified index is not a <code>Long</code>
624      * @throws NullPointerException if the parameter at the specified
625      * index is <code>null</code>
626      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
627      * is negative or not less than the current size of this
628      * <code>ParameterBlock</code> object
629      */

630     public long getLongParameter(int index) {
631         return ((Long JavaDoc)parameters.elementAt(index)).longValue();
632     }
633
634     /**
635      * A convenience method to return a parameter as a float. An
636      * exception is thrown if the parameter is
637      * <code>null</code> or not a <code>Float</code>.
638      *
639      * @param index the index of the parameter to be returned.
640      * @return the parameter at the specified index
641      * as a <code>float</code> value.
642      * @throws ClassCastException if the parameter at the
643      * specified index is not a <code>Float</code>
644      * @throws NullPointerException if the parameter at the specified
645      * index is <code>null</code>
646      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
647      * is negative or not less than the current size of this
648      * <code>ParameterBlock</code> object
649      */

650     public float getFloatParameter(int index) {
651         return ((Float JavaDoc)parameters.elementAt(index)).floatValue();
652     }
653
654     /**
655      * A convenience method to return a parameter as a double. An
656      * exception is thrown if the parameter is
657      * <code>null</code> or not a <code>Double</code>.
658      *
659      * @param index the index of the parameter to be returned.
660      * @return the parameter at the specified index
661      * as a <code>double</code> value.
662      * @throws ClassCastException if the parameter at the
663      * specified index is not a <code>Double</code>
664      * @throws NullPointerException if the parameter at the specified
665      * index is <code>null</code>
666      * @throws ArrayIndexOutOfBoundsException if <code>index</code>
667      * is negative or not less than the current size of this
668      * <code>ParameterBlock</code> object
669      */

670     public double getDoubleParameter(int index) {
671         return ((Double JavaDoc)parameters.elementAt(index)).doubleValue();
672     }
673
674     /**
675      * Returns an array of Class objects describing the types
676      * of the parameters.
677      * @return an array of <code>Class</code> objects.
678      */

679     public Class JavaDoc [] getParamClasses() {
680         int numParams = getNumParameters();
681         Class JavaDoc [] classes = new Class JavaDoc[numParams];
682         int i;
683
684         for (i = 0; i < numParams; i++) {
685             Object JavaDoc obj = getObjectParameter(i);
686             if (obj instanceof Byte JavaDoc) {
687               classes[i] = byte.class;
688             } else if (obj instanceof Character JavaDoc) {
689               classes[i] = char.class;
690             } else if (obj instanceof Short JavaDoc) {
691               classes[i] = short.class;
692             } else if (obj instanceof Integer JavaDoc) {
693               classes[i] = int.class;
694             } else if (obj instanceof Long JavaDoc) {
695               classes[i] = long.class;
696             } else if (obj instanceof Float JavaDoc) {
697               classes[i] = float.class;
698             } else if (obj instanceof Double JavaDoc) {
699               classes[i] = double.class;
700             } else {
701               classes[i] = obj.getClass();
702             }
703         }
704         
705         return classes;
706     }
707 }
708
Popular Tags