001: /*
002: * This file is part of the GeOxygene project source files.
003: *
004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
005: * the development and deployment of geographic (GIS) applications. It is a open source
006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
007: * National Mapping Agency).
008: *
009: * See: http://oxygene-project.sourceforge.net
010: *
011: * Copyright (C) 2005 Institut Géographique National
012: *
013: * This library is free software; you can redistribute it and/or modify it under the terms
014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
015: * either version 2.1 of the License, or any later version.
016: *
017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public License along with
022: * this library (see file LICENSE if present); if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: *
025: */
026:
027: package fr.ign.cogit.geoxygene.util.browser;
028:
029: import java.awt.event.WindowAdapter;
030: import java.awt.event.WindowEvent;
031: import java.lang.reflect.Array;
032: import java.lang.reflect.Field;
033: import java.lang.reflect.Method;
034: import java.lang.reflect.Modifier;
035: import java.util.Collection;
036: import java.util.Vector;
037:
038: /**
039: * Classe mettant en oeuvre le navigateur d'objet graphique de GeOxygene.
040: * <br>Elle instancie le "modèle" du navigateur d'objet de GeOxygene, conformement à
041: * l'architecture à modèle séparable de Sun Microsystems. Elle pilote la construction de
042: * l'interface graphique (vue) représentant l'objet Java (classe ObjectBrowserGUI).
043: * <br><br> Cette classe utilise intensivement le package reflection du J2SDK afin de rendre
044: * possible la représentation graphique et la navigation au sein de n'importe quel schéma de
045: * classes Java.
046: *
047: * @author Thierry Badard & Arnaud Braun
048: * @version 1.0
049: *
050: */
051:
052: public class ObjectBrowser {
053:
054: private static final int NULL = 0;
055: private static final int PRIMITIVE = 1;
056: private static final int ARRAY = 2;
057: private static final int OBJECT = 3;
058: private static final int STRING = 4;
059: private static final int COLLECTION = 5;
060:
061: /** Flag indiquant si un bandeau portant le nom de la classe doit être
062: * affiché dans l'interface (vrai par défaut). */
063: private static final boolean SHOW_CLASSNAME = true;
064: /** Flag indiquant si les attributs publics de l'objet doivent être
065: * affichés dans l'interface (vrai par défaut). */
066: private static final boolean SHOW_PUBLIC_ATTRIBUTES = true;
067: /** Flag indiquant si les attributs protected de l'objet doivent être
068: * affichés dans l'interface (vrai par défaut). */
069: private static final boolean SHOW_PROTECTED_ATTRIBUTES = true;
070: /** Flag indiquant si les méthodes publiques de l'objet doivent être
071: * affichées dans l'interface (vrai par défaut). */
072: private static final boolean SHOW_PUBLIC_METHODS = true;
073: /** Flag indiquant si les méthodes protected de l'objet doivent être
074: * affichées dans l'interface (vrai par défaut). */
075: private static final boolean SHOW_PROTECTED_METHODS = true;
076: /** Fixe le comportement par défaut lors d'une demande de rafraichissement de la représentation
077: * graphique d'un objet. Par défaut, l'ancienne représentation de l'objet reste visible et une
078: * nouvelle représentation est affichée. */
079: protected static final boolean HIDE_WHEN_REFRESH = false;
080:
081: /** Référence vers l'interface graphique du navigateur d'objet. */
082: private static ObjectBrowserGUI browserInterface;
083:
084: /**
085: * Teste si l'objet passé en paramètre est une instance de Collection (au sens Java du terme).
086: * @param obj l'objet à tester.
087: * @return vrai si l'objet passé en paramètre est une instance de Collection, faux sinon.
088: */
089: private static boolean isCollectionClass(Object obj) {
090: try {
091: Object[] arrayFromCollectionObject = ((Collection) obj)
092: .toArray();
093: return true;
094: } catch (ClassCastException ccex) {
095: return false;
096: }
097: }
098:
099: /**
100: * Méthode statique de conversion d'une Collection en tableau d'Object.
101: *
102: * @param obj l'objet instance de collection à convertir.
103: * @return le tableau d'object correspondant à la collection passée en paramètre. Si la classe n'est pas de type
104: * Collection renvoie null.
105: */
106: private static Object[] convertCollectionToArray(Object obj) {
107: try {
108: return ((Collection) obj).toArray();
109: } catch (ClassCastException ccex) {
110: return null;
111: }
112: }
113:
114: /**
115: * Teste si la classe passée en paramètre est de type Array (tableau).
116: *
117: * @param classObject la classe à tester.
118: * @return vrai si classObject est de type Array, faux sinon.
119: */
120: private static boolean isArrayClass(Class classObject) {
121: return classObject.isArray();
122: }
123:
124: /**
125: * Si classObject est de type Array, cette méthode permet de déterminer le type de contenu de ce "tableau".
126: *
127: * @param classObject la classe de type tableau dont on cherche à déterminer le type de contenu.
128: * @return ObjectBrowser.PRIMITIVE dans le cas où le contenu du tableau est de type primitif,
129: * ObjectBrowser.OBJECT (i.e. de type objet) dans tous les autres cas.
130: */
131: private static int getArrayClassComponentType(Class classObject) {
132: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
133: Class componentType = classObject.getComponentType();
134: if (componentType.isPrimitive()) {
135: return PRIMITIVE;
136: } else {
137: return OBJECT;
138: }
139: }
140:
141: /**
142: * Méthode statique permettant de tester si la classe passée en argument est de type tableau
143: * d'un type primitif (int, short, long, boolean, char, etc.).
144: *
145: * @param classObject la classe à tester.
146: * @return vrai si la classe passée en argument est de type tableau d'un type primitif, faux sinon.
147: */
148: private static boolean isArrayClassComponentTypePrimitive(
149: Class classObject) {
150: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
151: if (getArrayClassComponentType(classObject) == PRIMITIVE) {
152: return true;
153: } else {
154: return false;
155: }
156: }
157:
158: /**
159: * Méthode statique renvoyant la dimension de l'objet de type tableau passé en argument.
160: * @param obj l'objet de type tableau pour lequel on cherche la dimension.
161: * @return la dimension de l'objet de type tableau passé en argument.
162: */
163: private static int getArrayLevel(Object obj) {
164: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
165: String arrayValueString;
166:
167: arrayValueString = obj.toString();
168: return (arrayValueString.lastIndexOf("[") + 1);
169: }
170:
171: /**
172: * Méthode statique retournant la dimension de l'attribut field sur l'objet obj.
173: *
174: * @param field l'attribut dont on cherche la dimension (tableau).
175: * @param obj l'objet qui porte l'attribut field.
176: * @return la dimension de l'attribut field porté par obj ou 0 s'il ne s'agit pas d'un attribut de type tableau (Array).
177: */
178: private static int getArrayLevel(Field field, Object obj) {
179: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
180: String arrayValueString;
181:
182: try {
183: arrayValueString = field.get(obj).toString();
184: return (arrayValueString.lastIndexOf("[") + 1);
185: } catch (IllegalAccessException e) {
186: return 0;
187: }
188:
189: }
190:
191: /**
192: * Méthode statique retournant le type du contenu d'un champ de type tableau (Array), passé
193: * en argument de la méthode.
194: *
195: * @param field le champ de type tableau pour lequel on cherche le type de contenu.
196: * @return ObjectBrowser.STRING s'il s'agit d'un tableau de chaîne de caractères,
197: * ObjectBrowser.PRIMITIVE pour un tableau d'éléments de type primitif, et
198: * ObjectBrowser.OBJECT sinon.
199: */
200: private static int getArrayComponentType(Field field) {
201: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
202: Class fieldType = field.getType();
203: String fieldTypeName = fieldType.getName();
204: String underlyingFieldTypeName;
205: char underlyingType;
206: int typeIndex;
207:
208: typeIndex = fieldTypeName.lastIndexOf("[") + 1;
209: underlyingType = fieldTypeName.charAt(typeIndex);
210:
211: switch (underlyingType) {
212: case 'L':
213: underlyingFieldTypeName = fieldTypeName.substring(
214: typeIndex + 1, fieldTypeName.length() - 1);
215: if (underlyingFieldTypeName.equals("java.lang.String")) {
216: return STRING;
217: } else {
218: return OBJECT;
219: }
220: default:
221: return PRIMITIVE;
222: }
223:
224: }
225:
226: /**
227: * Méthode statique renvoyant le nom du type ou de la classe de l'objet tableau passé en paramètre.
228: *
229: * @param obj l'objet dont on cherche le type.
230: * @return le nom de la classe ou du type de contenu du tableau.
231: */
232: private static String getArrayComponentTypeName(Object obj) {
233: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
234: String typeName = obj.toString();
235: String underlyingTypeName;
236: char underlyingType;
237: int typeIndex;
238:
239: typeIndex = typeName.lastIndexOf("[") + 1;
240: underlyingType = typeName.charAt(typeIndex);
241:
242: switch (underlyingType) {
243: case 'L':
244: underlyingTypeName = typeName.substring(typeIndex + 1,
245: typeName.length() - 1);
246: return underlyingTypeName;
247: case 'B':
248: return "byte";
249: case 'C':
250: return "char";
251: case 'D':
252: return "double";
253: case 'F':
254: return "float";
255: case 'I':
256: return "int";
257: case 'J':
258: return "long";
259: case 'S':
260: return "short";
261: case 'Z':
262: return "boolean";
263: default:
264: return "void";
265: }
266: }
267:
268: /**
269: * Si l'attribut field passé en paramètre est de type tableau, cette méthode statique
270: * renvoie le nom du type ou de la classe qualifiant le contenu du tableau.
271: *
272: * @param field le champ de type tableau dont on cherche à déterminer le type de contenu.
273: * @return le nom de la classe ou du type de contenu du tableau.
274: */
275: private static String getArrayComponentTypeName(Field field) {
276: // Faudrait peut-être intercepter le fait que ce soit pas un Array !!! ;-))
277: Class fieldType = field.getType();
278: String fieldTypeName = fieldType.getName();
279: String underlyingFieldTypeName;
280: char underlyingType;
281: int typeIndex;
282:
283: typeIndex = fieldTypeName.lastIndexOf("[") + 1;
284: underlyingType = fieldTypeName.charAt(typeIndex);
285:
286: switch (underlyingType) {
287: case 'L':
288: underlyingFieldTypeName = fieldTypeName.substring(
289: typeIndex + 1, fieldTypeName.length() - 1);
290: return underlyingFieldTypeName;
291: case 'B':
292: return "byte";
293: case 'C':
294: return "char";
295: case 'D':
296: return "double";
297: case 'F':
298: return "float";
299: case 'I':
300: return "int";
301: case 'J':
302: return "long";
303: case 'S':
304: return "short";
305: case 'Z':
306: return "boolean";
307: default:
308: return "void";
309: }
310: }
311:
312: /**
313: * Pour l'attribut field de type Collection sur l'objet obj, retourne le type
314: * du contenu de la Collection.
315: *
316: * @param field l'attribut de type Collection.
317: * @param obj l'objet portant l'attribut field.
318: * @return ObjectBrowser.NULL s'il ne s'agit pas d'un champ de type Collection,
319: * ObjectBrowser.PRIMITIVE (resp. ObjectBrowser.OBJECT) s'il s'agit d'une Collection
320: * d'éléments de type primitif (resp. de type objet).
321: */
322: private static int getCollectionComponentType(Field field,
323: Object obj) {
324: // Faudrait peut-être intercepter le fait que ce soit pas une Collection !!! ;-))
325:
326: String fieldValue;
327:
328: try {
329: fieldValue = field.get(obj).toString();
330: if (fieldValue.indexOf("@") > -1) {
331: return OBJECT;
332: } else if (fieldValue.lastIndexOf("[") > 0) {
333: return OBJECT;
334: } else {
335: return PRIMITIVE;
336: }
337:
338: } catch (IllegalAccessException e) {
339: return NULL;
340: }
341: }
342:
343: /**
344: * Retourne le type de l'attribut field porté par l'objet obj.
345: *
346: * @param field l'attribut dont on cherche le type.
347: * @param obj l'objet portant l'attribut field.
348: * @return suivant le type, une valeur entière parmi ObjectBrowser.PRIMITIVE,
349: * ObjectBrowser.ARRAY, ObjectBrowser.OBJECT, ObjectBrowser.STRING,
350: * ObjectBrowser.OBJECT ou ObjectBrowser.NULL.
351: */
352: private static int getFieldType(Field field, Object obj) {
353:
354: Class fieldType = field.getType();
355: String fieldTypeName = fieldType.getName();
356: Object fieldValue;
357: String fieldValueString;
358: String fieldClass;
359: int index;
360:
361: if ((index = fieldTypeName.lastIndexOf(".")) > -1) {
362: fieldClass = fieldTypeName.substring(index + 1);
363: } else {
364: fieldClass = "";
365: }
366:
367: try {
368: fieldValue = field.get(obj);
369: fieldValueString = fieldValue.toString();
370:
371: if (fieldType.isPrimitive()) {
372: return PRIMITIVE;
373: } else if (fieldType.isArray()) {
374: return ARRAY;
375: } else {
376: if (fieldValueString.indexOf(fieldClass + "@") > -1) {
377: return OBJECT;
378: } else {
379: if (fieldTypeName.equals("java.lang.String")) {
380: return STRING;
381: } else {
382: try {
383: Collection testCollection = (Collection) fieldValue;
384: return COLLECTION;
385: } catch (ClassCastException cce) {
386: return OBJECT;
387: }
388: }
389: }
390: }
391: } catch (IllegalAccessException e) {
392: return NULL;
393: }
394: }
395:
396: /**
397: * Teste si l'attribut field porté par l'objet obj est de type primitif.
398: *
399: * @param field l'attribut à tester.
400: * @param obj l'objet portant l'attribut field.
401: * @return vrai si l'attribut est de type primitif, faux sinon.
402: */
403: private static boolean isFieldTypePrimitive(Field field, Object obj) {
404: if (getFieldType(field, obj) == PRIMITIVE) {
405: return true;
406: } else {
407: return false;
408: }
409: }
410:
411: /**
412: * Teste si l'attribut field porté par l'objet obj est de type tableau (Array).
413: *
414: * @param field l'attribut à tester.
415: * @param obj l'objet portant l'attribut field.
416: * @return vrai si l'attribut est de type tableau (Array), faux sinon.
417: */
418: private static boolean isFieldTypeArray(Field field, Object obj) {
419: if (getFieldType(field, obj) == ARRAY) {
420: return true;
421: } else {
422: return false;
423: }
424: }
425:
426: /**
427: * Teste si l'attribut field porté par l'objet obj est de type objet.
428: *
429: * @param field l'attribut à tester.
430: * @param obj l'objet portant l'attribut field.
431: * @return vrai si l'attribut est de type objet, faux sinon.
432: */
433: private static boolean isFieldTypeObject(Field field, Object obj) {
434: if (getFieldType(field, obj) == OBJECT) {
435: return true;
436: } else {
437: return false;
438: }
439: }
440:
441: /**
442: * Teste si l'attribut field porté par l'objet obj est de type chaîne de caractères (String).
443: *
444: * @param field l'attribut à tester.
445: * @param obj l'objet portant l'attribut field.
446: * @return vrai si l'attribut est de type chaîne de caractères (String), faux sinon.
447: */
448: private static boolean isFieldTypeString(Field field, Object obj) {
449: if (getFieldType(field, obj) == STRING) {
450: return true;
451: } else {
452: return false;
453: }
454: }
455:
456: /**
457: * Teste si l'attribut field porté par l'objet obj est de type Collection d'objets.
458: *
459: * @param field l'attribut à tester.
460: * @param obj l'objet portant l'attribut field.
461: * @return vrai si l'attribut est de type Collection d'objets, faux sinon.
462: */
463: private static boolean isFieldTypeCollection(Field field, Object obj) {
464: if (getFieldType(field, obj) == COLLECTION) {
465: return true;
466: } else {
467: return false;
468: }
469: }
470:
471: /**
472: * En fonction de la valeur des constantes SHOW_PUBLIC_ATTRIBUTES et SHOW_PROTECTED_ATTRIBUTES, renvoie
473: * l'ensemble des attributs publics et/ou protected accessibles de la classe classObj passée en argument.
474: *
475: * @param classObj la classe sur laquelle on cherche les attributs publics et/ou protected accessibles.
476: * @return un tableau (Field[]) contenant l'ensemble des attributs accessibles de la classe.
477: */
478: private static Field[] getAccessibleFields(Class classObj) {
479: return getAccessibleFields(classObj, SHOW_PUBLIC_ATTRIBUTES,
480: SHOW_PROTECTED_ATTRIBUTES);
481: }
482:
483: /**
484: * En fonction de la valeur des arguments retrievePublicFields et retrieveProtectedFields, renvoie
485: * l'ensemble des attributs publics et/ou protected accessibles de la classe classObj passée en argument.
486: *
487: * @param classObj la classe sur laquelle on cherche les attributs publics et/ou protected accessibles.
488: * @param retrievePublicFields si vrai, l'ensemble des champs publics de la classe sera retourné par la méthode.
489: * @param retrieveProtectedFields si vrai, l'ensemble des champs protected de la classe sera retourné par la méthode.
490: * @return un tableau (Field[]) contenant l'ensemble des attributs accessibles de la classe.
491: */
492: public static Field[] getAccessibleFields(Class classObj,
493: boolean retrievePublicFields,
494: boolean retrieveProtectedFields) {
495:
496: //Field[] allAccessibleFields = classObj.getDeclaredFields();
497: Field[] publicFields = classObj.getFields();
498: int nbPublicFields = publicFields.length;
499: Field[] localFields = classObj.getDeclaredFields();
500: int nbLocalFields = localFields.length;
501:
502: /* TreeSet allFields=new TreeSet(new Comparator() {
503: public int compare(Object o1, Object o2) {
504: return ((Field)o1).getName().compareTo(((Field)o2).getName());
505: }
506: }); */
507:
508: Vector allFields = new Vector();
509: boolean isAlreadyInVector;
510:
511: for (int i = 0; i < nbLocalFields; i++) {
512: allFields.add(localFields[i]);
513: }
514:
515: for (int i = 0; i < nbPublicFields; i++) {
516: isAlreadyInVector = false;
517: for (int j = 0; j < allFields.size(); j++) {
518: if (publicFields[i].equals((Field) allFields.get(j))) {
519: isAlreadyInVector = true;
520: break;
521: }
522: }
523: if (!isAlreadyInVector) {
524: allFields.add(publicFields[i]);
525: }
526: }
527:
528: ///////////////////////////////////////////////////////////
529: //// debut ajout Arnaud pour recuperer les champs "primitive" protected herites
530: //// en fait on fait ceci pour recuper l'id !
531: Class super Class = classObj.getSuperclass();
532: while (super Class != Object.class) {
533: Field[] super AccessibleFields = super Class
534: .getDeclaredFields();
535: for (int i = 0; i < super AccessibleFields.length; i++)
536: if (super AccessibleFields[i].getType().isPrimitive())
537: allFields.add(super AccessibleFields[i]);
538: super Class = super Class.getSuperclass();
539: }
540: //// fin ajout Arnaud
541: ///////////////////////////////////////////////////////////
542:
543: Object[] allObjectFields = allFields.toArray();
544:
545: Field[] allAccessibleFields = new Field[allObjectFields.length];
546: for (int i = 0; i < allObjectFields.length; i++) {
547: allAccessibleFields[i] = (Field) allObjectFields[i];
548: }
549:
550: int nbAllAccessibleFields = allAccessibleFields.length;
551: Vector accessibleFields = new Vector();
552: Field[] resultAccessibleFields;
553: int nbAccessibleFields = 0;
554: int fieldModifier = 0;
555:
556: for (int i = 0; i < nbAllAccessibleFields; i++) {
557: fieldModifier = allAccessibleFields[i].getModifiers();
558:
559: if (Modifier.isPublic(fieldModifier)
560: && (!(Modifier.isStatic(fieldModifier)))
561: && retrievePublicFields) {
562: accessibleFields.add(allAccessibleFields[i]);
563: } else if (Modifier.isProtected(fieldModifier)
564: && (!(Modifier.isStatic(fieldModifier)))
565: && retrieveProtectedFields) {
566: accessibleFields.add(allAccessibleFields[i]);
567: try {
568: if (!(allAccessibleFields[i].isAccessible())) {
569: allAccessibleFields[i].setAccessible(true);
570: }
571: } catch (Exception e) {
572: e.printStackTrace();
573: }
574: }
575: }
576:
577: nbAccessibleFields = accessibleFields.size();
578: resultAccessibleFields = new Field[nbAccessibleFields];
579: for (int i = 0; i < nbAccessibleFields; i++) {
580: resultAccessibleFields[i] = (Field) (accessibleFields
581: .get(i));
582: }
583:
584: return resultAccessibleFields;
585: }
586:
587: /**
588: * En fonction de la valeur des constantes SHOW_PUBLIC_METHODS et SHOW_PROTECTED_METHODS, renvoie
589: * l'ensemble des méthodes publiques et/ou protected locales et héritées, ne prenant aucun argument et accessibles de la classe
590: * classObj passée en argument.
591: *
592: * @param classObj la classe sur laquelle on cherche les méthodes locales et héritées, publiques
593: * et/ou protected.
594: * @return un tableau (Method[]) contenant l'ensemble des méthodes publiques et/ou protected, locales et héritées, ne prenant aucun argument et accessibles de la classe.
595: */
596: private static Method[] getAccessibleMethods(Class classObj) {
597: return getAccessibleMethods(classObj, SHOW_PUBLIC_METHODS,
598: SHOW_PROTECTED_METHODS);
599: }
600:
601: /**
602: * En fonction de la valeur des arguments retrievePublicMethods et retrieveProtectedMethods, renvoie
603: * l'ensemble des méthodes publiques et/ou protected, locales et héritées, ne prenant aucun argument et accessibles de la classe
604: * classObj passée en argument.
605: *
606: * @param classObj la classe sur laquelle on cherche les méthodes publiques et/ou protected, locales
607: * et héritées.
608: * @param retrievePublicMethods si vrai, l'ensemble des méthodes publiques, locales et héritées, portées par la classe classObj sera retourné par la méthode.
609: * @param retrieveProtectedMethods si vrai, l'ensemble des méthodes protected, locales et héritées, portées par la classe classObj sera retourné par la méthode.
610: * @return un tableau (Method[]) contenant l'ensemble des méthodes publiques et/ou protected, locales et héritées, ne prenant aucun argument et accessibles de la classe.
611: */
612: private static Method[] getAccessibleMethods(Class classObj,
613: boolean retrievePublicMethods,
614: boolean retrieveProtectedMethods) {
615: Method[] allAccessibleMethods;
616: Vector allAccessibleMethodsVector = new Vector();
617: Method[] publicMethods = classObj.getMethods();
618: Method[] localMethods = classObj.getDeclaredMethods();
619: Vector localMethodNames = new Vector();
620: int nbLocalMethods = localMethods.length;
621: int nbPublicMethods = publicMethods.length;
622: boolean isInVector;
623:
624: int nbAllAccessibleMethods;
625: Vector accessibleMethods;
626: Method[] resultAccessibleMethods;
627: int nbAccessibleMethods = 0;
628: int methodModifier = 0;
629: int nbParameters;
630: Class methodReturnType;
631:
632: for (int j = 0; j < nbLocalMethods; j++) {
633: localMethodNames.add(localMethods[j].getName());
634: allAccessibleMethodsVector.add(localMethods[j]);
635: }
636:
637: for (int i = 0; i < nbPublicMethods; i++) {
638: isInVector = false;
639: for (int j = 0; j < nbLocalMethods; j++) {
640: if (publicMethods[i].getName().equals(
641: localMethodNames.get(j))) {
642: isInVector = true;
643: break;
644: }
645: }
646: if (!(isInVector)) {
647: allAccessibleMethodsVector.add(publicMethods[i]);
648: }
649: }
650:
651: nbAllAccessibleMethods = allAccessibleMethodsVector.size();
652: allAccessibleMethods = new Method[nbAllAccessibleMethods];
653: for (int i = 0; i < nbAllAccessibleMethods; i++) {
654: allAccessibleMethods[i] = (Method) (allAccessibleMethodsVector
655: .get(i));
656: }
657: accessibleMethods = new Vector();
658:
659: for (int i = 0; i < nbAllAccessibleMethods; i++) {
660: methodModifier = allAccessibleMethods[i].getModifiers();
661: nbParameters = allAccessibleMethods[i].getParameterTypes().length;
662: methodReturnType = allAccessibleMethods[i].getReturnType();
663:
664: if (Modifier.isPublic(methodModifier)
665: && (!(Modifier.isStatic(methodModifier)))
666: && retrievePublicMethods) {
667: if ((nbParameters == 0)
668: && (!(methodReturnType.getName().equals("void")))) {
669: accessibleMethods.add(allAccessibleMethods[i]);
670: }
671: } else if (Modifier.isProtected(methodModifier)
672: && (!(Modifier.isStatic(methodModifier)))
673: && retrieveProtectedMethods) {
674: if ((nbParameters == 0)
675: && (!(methodReturnType.getName().equals("void")))) {
676: accessibleMethods.add(allAccessibleMethods[i]);
677: try {
678: if (!(allAccessibleMethods[i].isAccessible())) {
679: allAccessibleMethods[i].setAccessible(true);
680: }
681: } catch (Exception e) {
682: e.printStackTrace();
683: }
684: }
685: }
686: }
687:
688: nbAccessibleMethods = accessibleMethods.size();
689: resultAccessibleMethods = new Method[nbAccessibleMethods];
690: for (int i = 0; i < nbAccessibleMethods; i++) {
691: resultAccessibleMethods[i] = (Method) (accessibleMethods
692: .get(i));
693: }
694:
695: return resultAccessibleMethods;
696: }
697:
698: /**
699: * Lance l'affichage par défaut (défini par les constantes SHOW_CLASSNAME, SHOW_PUBLIC_ATTRIBUTES,
700: * SHOW_PROTECTED_ATTRIBUTES, SHOW_PUBLIC_METHODS, SHOW_PROTECTED_METHODS) de la représentation
701: * graphique de l'objet obj passé en argument.
702: *
703: * @param obj l'objet dont on souhaite obtenir une représentaion par défaut dans le navigateur d'objet de GeOxygene.
704: */
705: public static void browse(Object obj) {
706: browse(obj, SHOW_CLASSNAME, SHOW_PUBLIC_ATTRIBUTES,
707: SHOW_PROTECTED_ATTRIBUTES, SHOW_PUBLIC_METHODS,
708: SHOW_PROTECTED_METHODS);
709: }
710:
711: /**
712: * Lance l'affichage de la représentation graphique de l'objet obj passé en argument.
713: *
714: * @param obj obj l'objet dont on souhaite obtenir une représentaion dans le navigateur d'objet de GeOxygene.
715: * @param showClassName si vrai, affiche dans l'interface un bandeau avec le nom du type de l'objet.
716: * @param showPublicAttributes si vrai, affiche dans l'interface les attributs publics portés par l'objet.
717: * @param showProtectedAttributes si vrai, affiche dans l'interface les attributs protected portés par l'objet.
718: * @param showPublicMethods si vrai, affiche dans l'interface les méthodes publiques, locales et héritées, portées par l'objet.
719: * @param showProtectedMethods si vrai, affiche dans l'interface les méthodes protected, locales et héritées, portées par l'objet.
720: */
721: public static void browse(Object obj, boolean showClassName,
722: boolean showPublicAttributes,
723: boolean showProtectedAttributes, boolean showPublicMethods,
724: boolean showProtectedMethods) {
725:
726: try {
727: Class objectClass;
728: String objectClassName;
729: Field[] objectFields;
730: int nbFields = 0;
731: Method[] objectMethods;
732: int nbMethods = 0;
733:
734: Field currentField;
735: String currentFieldName;
736: Class currentFieldType;
737: String currentFieldTypeName;
738: Object currentFieldValue;
739: int arrayFieldLength;
740: int arrayLevel;
741:
742: Method currentMethod;
743: String currentMethodName;
744: Class[] currentMethodParameters;
745: int nbCurrentMethodParameters;
746:
747: try {
748: objectClass = obj.getClass();
749: objectClassName = objectClass.getName();
750: objectFields = getAccessibleFields(objectClass,
751: showPublicAttributes, showProtectedAttributes);
752: objectMethods = getAccessibleMethods(objectClass,
753: showPublicMethods, showProtectedMethods);
754: nbFields = objectFields.length;
755: nbMethods = objectMethods.length;
756:
757: browserInterface = new ObjectBrowserGUI(obj,
758: showClassName, showPublicAttributes,
759: showProtectedAttributes, showPublicMethods,
760: showProtectedMethods, objectClassName);
761:
762: // Special case of Array classes.
763: if (isArrayClass(objectClass)) {
764: int nbArrayElements = Array.getLength(obj);
765: Vector arrayElements = new Vector();
766: for (int i = 0; i < nbArrayElements; i++) {
767: arrayElements.add(Array.get(obj, i));
768: }
769: if (showClassName) {
770: arrayLevel = getArrayLevel(obj);
771: String arrayObjectClassName = "";
772: for (int i = 0; i < arrayLevel; i++) {
773: arrayObjectClassName += "[";
774: }
775: arrayObjectClassName += getArrayComponentTypeName(obj);
776: for (int i = 0; i < arrayLevel; i++) {
777: arrayObjectClassName += "]";
778: }
779: browserInterface
780: .addClassNameLabel(arrayObjectClassName);
781: browserInterface
782: .changeTitle(arrayObjectClassName);
783:
784: }
785:
786: if (isArrayClassComponentTypePrimitive(objectClass)) {
787: browserInterface
788: .addAttributeList(arrayElements);
789: } else {
790: browserInterface
791: .addObjectAttributeList(arrayElements);
792: }
793: } else if (showClassName) {
794: browserInterface.addClassNameLabel(objectClassName);
795: }
796:
797: // Special Case of Collection classes.
798: if (isCollectionClass(obj)) {
799: Object[] arrayFromCollectionObject = convertCollectionToArray(obj);
800:
801: int nbCollectionElements = arrayFromCollectionObject.length;
802: Vector collectionElements = new Vector();
803: for (int i = 0; i < nbCollectionElements; i++) {
804: collectionElements
805: .add(arrayFromCollectionObject[i]);
806: }
807:
808: if (isArrayClassComponentTypePrimitive(arrayFromCollectionObject
809: .getClass())) {
810: browserInterface
811: .addAttributeList(collectionElements);
812: } else {
813: browserInterface
814: .addObjectAttributeList(collectionElements);
815: }
816:
817: }
818:
819: for (int i = 0; i < nbFields; i++) {
820: currentField = objectFields[i];
821: currentFieldName = currentField.getName();
822: currentFieldType = currentField.getType();
823: currentFieldTypeName = currentFieldType.getName();
824:
825: try {
826: currentFieldValue = currentField.get(obj);
827:
828: if (isFieldTypeObject(currentField, obj)) {
829: browserInterface.addObjectAttribute(
830: currentFieldName,
831: currentFieldTypeName,
832: currentFieldValue);
833: }
834:
835: if (isFieldTypePrimitive(currentField, obj)
836: || isFieldTypeString(currentField, obj)) {
837: browserInterface.addAttribute(
838: currentFieldName, currentFieldValue
839: .toString());
840: }
841:
842: if (isFieldTypeCollection(currentField, obj)) {
843:
844: if (getCollectionComponentType(
845: currentField, obj) != OBJECT) {
846: browserInterface
847: .addAttributeList(
848: currentFieldName,
849: new Vector(
850: (Collection) (currentFieldValue)));
851: } else {
852: browserInterface
853: .addObjectAttributeList(
854: currentFieldName,
855: new Vector(
856: (Collection) (currentFieldValue)));
857: }
858: }
859:
860: if (isFieldTypeArray(currentField, obj)) {
861:
862: arrayFieldLength = Array
863: .getLength(currentFieldValue);
864: arrayLevel = getArrayLevel(currentField,
865: obj);
866: Vector attribvalarray = new Vector();
867:
868: for (int j = 0; j < arrayFieldLength; j++) {
869: attribvalarray.add(Array.get(
870: currentFieldValue, j));
871: }
872:
873: if (((getArrayComponentType(currentField) == STRING) || (getArrayComponentType(currentField) == PRIMITIVE))
874: && (arrayLevel == 1)) {
875: browserInterface.addAttributeList(
876: currentFieldName,
877: attribvalarray);
878: } else {
879: if (arrayLevel == 1) {
880: browserInterface
881: .addObjectAttributeList(
882: currentFieldName,
883: attribvalarray);
884: } else {
885: browserInterface
886: .addObjectAttributeList(
887: currentFieldName,
888: attribvalarray,
889: arrayLevel - 1,
890: getArrayComponentTypeName(currentField));
891: }
892: }
893: }
894:
895: } catch (NullPointerException npex) {
896:
897: //browserInterface.add_attribute(currentFieldName,"NULL");
898: browserInterface.addObjectAttribute(
899: currentFieldName, "null", null);
900: }
901: }
902:
903: for (int i = 0; i < nbMethods; i++) {
904: currentMethod = objectMethods[i];
905: currentMethodName = currentMethod.getName();
906:
907: currentMethodParameters = currentMethod
908: .getParameterTypes();
909: nbCurrentMethodParameters = currentMethodParameters.length;
910:
911: browserInterface.addMethod(obj, currentMethod);
912: }
913:
914: browserInterface.pack();
915: //browserInterface.setSize(browserInterface.getPreferredSize());
916:
917: browserInterface.show();
918:
919: browserInterface.addWindowListener(new WindowAdapter() {
920: public void windowClosing(WindowEvent e) {
921: browserInterface.dispose();
922: }
923: });
924: } catch (NullPointerException npex) {
925: ObjectBrowserNullPointerFrame nullFrame = new ObjectBrowserNullPointerFrame();
926: }
927: } catch (IllegalAccessException e) {
928: ObjectBrowserIllegalAccessFrame illegalAccessFrame = new ObjectBrowserIllegalAccessFrame();
929: //e.printStackTrace();
930: }
931:
932: }
933:
934: /**
935: * Déclenche de façon programmatique le rafraichissement de l'interface représentant l'objet. Le
936: * comportement du rafraîchissement (l'ancienne représentation de l'objet disparaît-elle ?) est
937: * fixé par la valeur de la constante ObjectBrowser.HIDE_WHEN_REFRESH.
938: * <p>De plus, Le nouvel affichage de l'objet est régi par les valeurs des constantes SHOW_CLASSNAME,
939: * SHOW_PUBLIC_ATTRIBUTES,SHOW_PROTECTED_ATTRIBUTES, SHOW_PUBLIC_METHODS et SHOW_PROTECTED_METHODS.</p>
940: *
941: * @param obj objet dont on veut rafrîchir la représentation graphique.
942: */
943: public static void refresh(Object obj) {
944: refresh(obj, HIDE_WHEN_REFRESH);
945: }
946:
947: /**
948: * Déclenche de façon programmatique le rafraichissement de l'interface représentant l'objet. Le nouvel
949: * affichage de l'objet est régi par les valeurs des constantes SHOW_CLASSNAME, SHOW_PUBLIC_ATTRIBUTES,
950: * SHOW_PROTECTED_ATTRIBUTES, SHOW_PUBLIC_METHODS et SHOW_PROTECTED_METHODS.
951: *
952: * @param obj objet dont on veut rafrîchir la représentation graphique.
953: * @param dispose si vrai, l'ancienne représentation de l'objet disparaît.
954: */
955: public static void refresh(Object obj, boolean dispose) {
956: refresh(obj, dispose, SHOW_CLASSNAME, SHOW_PUBLIC_ATTRIBUTES,
957: SHOW_PROTECTED_ATTRIBUTES, SHOW_PUBLIC_METHODS,
958: SHOW_PROTECTED_METHODS);
959: }
960:
961: /**
962: * Déclenche de façon programmatique le rafraichissement de l'interface représentant l'objet.
963: *
964: * @param obj objet dont on veut rafrîchir la représentation graphique.
965: * @param dispose si vrai, l'ancienne représentation de l'objet disparaît.
966: * @param showClassName si vrai, affiche dans l'interface un bandeau avec le nom du type de l'objet.
967: * @param showPublicAttributes si vrai, affiche dans l'interface les attributs publics portés par l'objet.
968: * @param showProtectedAttributes si vrai, affiche dans l'interface les attributs protected portés par l'objet.
969: * @param showPublicMethods si vrai, affiche dans l'interface les méthodes publiques, locales et héritées, portées par l'objet.
970: * @param showProtectedMethods si vrai, affiche dans l'interface les méthodes protected, locales et héritées, portées par l'objet.
971: */
972: public static void refresh(Object obj, boolean dispose,
973: boolean showClassName, boolean showPublicAttributes,
974: boolean showProtectedAttributes, boolean showPublicMethods,
975: boolean showProtectedMethods) {
976: browserInterface.setVisible(!dispose);
977: browse(obj, showClassName, showPublicAttributes,
978: showProtectedAttributes, showPublicMethods,
979: showProtectedMethods);
980: }
981:
982: }
|