KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > loaders > InstanceNode


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.loaders;
21
22
23 import java.awt.Image JavaDoc;
24 import java.beans.*;
25 import java.beans.beancontext.*;
26 import java.io.IOException JavaDoc;
27 import java.lang.reflect.*;
28 import java.util.logging.Level JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import javax.swing.*;
31 import org.openide.cookies.InstanceCookie;
32 import org.openide.filesystems.*;
33 import org.openide.nodes.*;
34 import org.openide.util.*;
35
36 /** Node to represent a .settings, .ser or .instance file.
37  *
38  * @author Jaroslav Tulach, Jan Pokorsky
39  */

40 final class InstanceNode extends DataNode implements Runnable JavaDoc {
41     
42     /** icon base */
43     private static final String JavaDoc INSTANCE_ICON_BASE =
44         "org/openide/loaders/instanceObject.gif"; // NOI18N
45

46     /** File extension for xml settings. */
47     private static final String JavaDoc XML_EXT = "settings"; //NOI18N
48

49     /** listener for properties */
50     private PropL propertyChangeListener = null;
51     private PropertyChangeListener dobjListener;
52     private boolean isSheetCreated = false;
53     /** bean info is not used only if the file specifies
54      * <attr name="beaninfo" booleanvalue="false" />
55      */

56     private boolean noBeanInfo = false;
57
58     /** Constructor */
59     public InstanceNode (InstanceDataObject obj) {
60         this (obj, Boolean.FALSE.equals (obj.getPrimaryFile ().getAttribute ("beaninfo"))); // NOI18N
61
}
62      
63     /** @param obj the object to use
64      * @param noBeanInfo info to use
65      */

66     private InstanceNode (InstanceDataObject obj, boolean noBeanInfo) {
67         super (obj, getChildren(obj, noBeanInfo));
68         
69         initIconBase();
70
71         this.noBeanInfo = noBeanInfo;
72         
73         if (!noBeanInfo && !getDataObject().getPrimaryFile().hasExt(XML_EXT)) {
74             SwingUtilities.invokeLater (this);
75         }
76         
77         // listen on the cookie change of the instance data object
78
dobjListener = new PropertyChangeListener() {
79             public void propertyChange(PropertyChangeEvent evt) {
80                 if (evt.getPropertyName().equals(DataObject.PROP_COOKIE)) {
81                     if (propertyChangeListener != null) {
82                         propertyChangeListener.destroy();
83                         propertyChangeListener = null;
84                     }
85                     if (InstanceNode.this.noBeanInfo || ic() == null) {
86                        initIconBase();
87                     } else {
88                        fireIconChange();
89                     }
90                     fireNameChange(null, null);
91                     fireDisplayNameChange(null, null);
92                     fireShortDescriptionChange(null, null);
93                     if (isSheetCreated) setSheet(createSheet());
94                 }
95             }
96         };
97         obj.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(dobjListener, obj));
98     }
99     
100     /** initialize the icon base according to state of the settings instance (valid/broken) */
101     private void initIconBase() {
102         InstanceCookie.Of ic = ic();
103         String JavaDoc iconBase = INSTANCE_ICON_BASE;
104         if (ic == null) {//XXX && io.instanceOf(XMLSettingsSupport.BrokenSettings.class)) {
105
iconBase = "org/openide/loaders/instanceBroken.gif"; // NOI18N
106
}
107         setIconBaseWithExtension(iconBase);
108     }
109     
110     private static Children getChildren(DataObject dobj, boolean noBeanInfo) {
111         if (noBeanInfo) {
112             return Children.LEAF;
113         }
114         InstanceCookie inst = (InstanceCookie)dobj.getCookie(InstanceCookie.class);
115         if (inst == null) return Children.LEAF;
116         try {
117             Class JavaDoc clazz = inst.instanceClass();
118             if (BeanContext.class.isAssignableFrom(clazz) ||
119                 BeanContextProxy.class.isAssignableFrom(clazz)) {
120                 return new InstanceChildren ((InstanceDataObject) dobj);
121             } else {
122                 return Children.LEAF;
123             }
124         } catch (Exception JavaDoc ex) {
125             return Children.LEAF;
126         }
127     }
128     
129     /** Getter for instance data object.
130      * @return instance data object
131      */

132     private InstanceDataObject i () {
133         return (InstanceDataObject)getDataObject ();
134     }
135     
136     private InstanceCookie.Of ic () {
137         return (InstanceCookie.Of) getDataObject().getCookie(InstanceCookie.Of.class);
138     }
139
140     /** Find an icon for this node (in the closed state).
141     * @param type constant from {@link java.beans.BeanInfo}
142     * @return icon to use to represent the node
143     */

144     public Image JavaDoc getIcon (int type) {
145         if (noBeanInfo) return super.getIcon(type);
146         Image JavaDoc img = null;
147         try {
148             DataObject dobj = getDataObject();
149             img = dobj.getPrimaryFile().getFileSystem().getStatus().
150                 annotateIcon (img, type, dobj.files ());
151         } catch (FileStateInvalidException e) {
152             // no fs, do nothing
153
}
154         
155         if (img == null) img = initIcon(type);
156         if (img == null) img = super.getIcon(type);
157         return img;
158     }
159
160     /** Find an icon for this node (in the open state).
161     * This icon is used when the node may have children and is expanded.
162     *
163     * @param type constant from {@link java.beans.BeanInfo}
164     * @return icon to use to represent the node when open
165     */

166     public Image JavaDoc getOpenedIcon (int type) {
167         return getIcon (type);
168     }
169
170     /** try to register PropertyChangeListener to instance to fire its changes.*/
171     private void initPList () {
172         try {
173             InstanceCookie ic = ic();
174             if (ic == null) return;
175             BeanInfo info = Utilities.getBeanInfo(ic.instanceClass());
176             java.beans.EventSetDescriptor JavaDoc[] descs = info.getEventSetDescriptors();
177             Method setter = null;
178             for (int i = 0; descs != null && i < descs.length; i++) {
179                 setter = descs[i].getAddListenerMethod();
180                 if (setter != null && setter.getName().equals("addPropertyChangeListener")) { // NOI18N
181
Object JavaDoc bean = ic.instanceCreate();
182                     propertyChangeListener = new PropL();
183                     setter.invoke(bean, new Object JavaDoc[] {org.openide.util.WeakListeners.propertyChange(propertyChangeListener, bean)});
184                 }
185             }
186         } catch (Exception JavaDoc ex) {
187         } catch (LinkageError JavaDoc ex) {
188             // #30650 - catch also LinkageError.
189
// Ignoring exception the same way as the Exception handler above.
190
}
191     }
192     
193     private Image JavaDoc initIcon (int type) {
194         Image JavaDoc beanInfoIcon = null;
195         try {
196             InstanceCookie ic = ic();
197             if (ic == null) return null;
198             Class JavaDoc clazz = ic.instanceClass();
199             //Fixed bug #5610
200
//Class javax.swing.JToolBar$Separator does not have icon
201
//we will use temporarily icon from javax.swing.JSeparator
202
//New icon is requested.
203

204             String JavaDoc className = clazz.getName ();
205             BeanInfo bi;
206             if (
207                 className.equals ("javax.swing.JSeparator") || // NOI18N
208
className.equals ("javax.swing.JToolBar$Separator") // NOI18N
209
) {
210                 Class JavaDoc clazzTmp = Class.forName ("javax.swing.JSeparator"); // NOI18N
211
bi = Utilities.getBeanInfo (clazzTmp);
212             } else {
213                 bi = Utilities.getBeanInfo (clazz);
214             }
215
216             if (bi != null) {
217                 beanInfoIcon = bi.getIcon (type);
218                 if (beanInfoIcon != null) {
219                     beanInfoIcon = toBufferedImage(beanInfoIcon, true);
220                 }
221             }
222             // Also specially handle action instances.
223
if (beanInfoIcon == null && Action.class.isAssignableFrom(clazz)) {
224                 Action action = (Action)ic.instanceCreate();
225                 Icon icon = (Icon)action.getValue(Action.SMALL_ICON);
226                 if (icon != null) {
227                     beanInfoIcon = Utilities.icon2Image(icon);
228                 } else {
229                     beanInfoIcon = Utilities.loadImage("org/openide/loaders/empty.gif", true); // NOI18N
230
}
231             }
232         } catch (Exception JavaDoc e) {
233             // Problem ==>> use default icon
234
Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, e);
235         } catch (LinkageError JavaDoc e) {
236             // #30650 - catch also LinkageError.
237
// Problem ==>> use default icon
238
Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, e);
239         }
240
241         return beanInfoIcon;
242     }
243
244     /** try to initialize display name.
245     */

246     public void run() {
247         try {
248             InstanceCookie ic = ic();
249             if (ic == null) return;
250             Class JavaDoc clazz = ic.instanceClass();
251         
252         String JavaDoc className = clazz.getName ();
253         if (className.equals ("javax.swing.JSeparator") || // NOI18N
254
className.equals ("javax.swing.JToolBar$Separator")) { // NOI18N
255

256             setDisplayName (NbBundle.getMessage (InstanceDataObject.class,
257                 "LBL_separator_instance")); // NOI18N
258
return;
259         }
260         // Also specially handle action instances.
261
if (Action.class.isAssignableFrom(clazz)) {
262             Action action = (Action)ic.instanceCreate();
263             // Set node's display name.
264
String JavaDoc name = (String JavaDoc)action.getValue(Action.NAME);
265             
266             // #31227 - some action does not implement its name properly.
267
// Throw exception with the name of the class.
268
if (name == null) {
269                 DataObject.LOG.warning(
270                     "Please attach following information to the issue " + // NOI18N
271
"<http://www.netbeans.org/issues/show_bug.cgi?id=31227>: " + // NOI18N
272
"action " + className + " does not implement SystemAction.getName() or Action.getValue(NAME) properly. It returns null!"); // NOI18N
273
setDisplayName(className);
274                 return;
275             }
276             
277             int amper = name.indexOf ((char) '&');
278             if (amper != -1)
279                 name = name.substring (0, amper) + name.substring (amper + 1);
280             if (name.endsWith ("...")) // NOI18N
281
name = name.substring (0, name.length () - 3);
282             name = name.trim ();
283             setDisplayName (name);
284             return;
285         }
286         } catch (Exception JavaDoc e) {
287             Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, e);
288             setDisplayName(getDataObject().getName());
289             return;
290         }
291     }
292     
293     /** Try to get display name of the bean.
294      */

295     private String JavaDoc getNameForBean() {
296         try {
297             InstanceCookie ic = ic();
298             if (ic == null) {
299                 // it must be unrecognized setting
300
return NbBundle.getMessage(InstanceNode.class,
301                     "LBL_BrokenSettings"); //NOI18N
302
}
303             Class JavaDoc clazz = ic.instanceClass();
304             Method nameGetter;
305             Class JavaDoc[] param = new Class JavaDoc [0];
306             try {
307                 nameGetter = clazz.getMethod ("getName", param); // NOI18N
308
if (nameGetter.getReturnType () != String JavaDoc.class) throw new NoSuchMethodException JavaDoc ();
309             } catch (NoSuchMethodException JavaDoc e) {
310                 try {
311                     nameGetter = clazz.getMethod ("getDisplayName", param); // NOI18N
312
if (nameGetter.getReturnType () != String JavaDoc.class) throw new NoSuchMethodException JavaDoc ();
313                 } catch (NoSuchMethodException JavaDoc ee) {
314                     return null;
315                 }
316             }
317             Object JavaDoc bean = ic.instanceCreate();
318             return (String JavaDoc) nameGetter.invoke (bean);
319         } catch (Exception JavaDoc ex) {
320             return null;
321         }
322     }
323     
324     /** try to find setter setName/setDisplayName, if none declared return null */
325     private Method getDeclaredSetter() {
326         Method nameSetter = null;
327         try {
328             InstanceCookie ic = ic();
329             if (ic == null) return null;
330             Class JavaDoc clazz = ic.instanceClass();
331             Class JavaDoc[] param = new Class JavaDoc[] {String JavaDoc.class};
332             // find the setter for the name
333
try {
334                 nameSetter = clazz.getMethod ("setName", param); // NOI18N
335
} catch (NoSuchMethodException JavaDoc e) {
336                 nameSetter = clazz.getMethod ("setDisplayName", param); // NOI18N
337
}
338         } catch (Exception JavaDoc ex) {
339         }
340         return nameSetter;
341     }
342     
343     public void setName(String JavaDoc name) {
344         if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) {
345             super.setName(name);
346             return ;
347         }
348         String JavaDoc old = getNameImpl();
349         if (old != null && old.equals(name)) return;
350         InstanceCookie ic = ic();
351         if (ic == null) {
352             super.setName(name);
353             return;
354         }
355         
356         Method nameSetter = getDeclaredSetter();
357         if (nameSetter != null) {
358             try {
359                 Object JavaDoc bean = ic.instanceCreate();
360                 nameSetter.invoke(bean, new Object JavaDoc[] {name});
361                 i().scheduleSave();
362             } catch (Exception JavaDoc ex) {
363                 ex.printStackTrace();
364             }
365         }
366         super.setName(name);
367     }
368     
369     /** Get the display name for the node.
370      * A filesystem may {@link org.openide.filesystems.FileSystem#getStatus specially alter} this.
371      * @return the desired name
372     */

373     public String JavaDoc getDisplayName () {
374         String JavaDoc name = (String JavaDoc) getDataObject().getPrimaryFile().
375             getAttribute(InstanceDataObject.EA_NAME);
376         if (name == null) {
377             try {
378                 String JavaDoc def = "\b"; // NOI18N
379
FileSystem.Status fsStatus = getDataObject().getPrimaryFile().
380                     getFileSystem().getStatus();
381                 name = fsStatus.annotateName(def, getDataObject().files());
382                 if (name.indexOf(def) < 0) {
383                     return name;
384                 } else {
385                     name = getNameForBean();
386                     if (name != null) {
387                         name = fsStatus.annotateName (name, getDataObject().files());
388                     } else {
389                         name = super.getDisplayName();
390                     }
391                 }
392             } catch (FileStateInvalidException e) {
393                 // no fs, do nothing
394
}
395         }
396         return name;
397     }
398     
399     /** try to get name by colling getter on the instance. */
400     private String JavaDoc getNameImpl() {
401         String JavaDoc name;
402         name = getNameForBean();
403         if (name == null) name = getName();
404
405         return name;
406     }
407     
408     protected Sheet createSheet () {
409         Sheet orig;
410     
411         if (getDataObject ().getPrimaryFile ().hasExt ("ser") || // NOI18N
412
getDataObject ().getPrimaryFile ().hasExt (XML_EXT)) {
413             orig = new Sheet();
414             changeSheet (orig);
415         } else {
416             // just instance file, change here
417
orig = super.createSheet ();
418             Sheet.Set props = orig.get (Sheet.PROPERTIES);
419             final InstanceCookie ic = ic();
420             if (ic == null) {
421                 props.put (new PropertySupport.ReadOnly<String JavaDoc> (
422                     "className", String JavaDoc.class, // NOI18N
423
NbBundle.getMessage (InstanceDataObject.class, "PROP_instance_class"), // NOI18N
424
NbBundle.getMessage (InstanceDataObject.class, "HINT_instance_class") // NOI18N
425
) {
426                     public String JavaDoc getValue () {
427                         return ic.instanceName ();
428                     }
429                 });
430             }
431         }
432         
433         isSheetCreated = true;
434         return orig;
435     }
436         
437         
438     private void changeSheet (Sheet orig) {
439         Sheet.Set props = orig.get (Sheet.PROPERTIES);
440
441         try {
442             InstanceCookie ic = ic();
443             if (ic == null) return;
444             // properties
445
BeanInfo beanInfo = Utilities.getBeanInfo (ic.instanceClass ());
446             BeanNode.Descriptor descr = BeanNode.computeProperties (ic.instanceCreate (), beanInfo);
447             initPList();
448
449             props = Sheet.createPropertiesSet();
450             if (descr.property != null) {
451                 convertProps (props, descr.property, i ());
452             }
453             orig.put (props);
454
455             if (descr.expert != null && descr.expert.length != 0) {
456                 Sheet.Set p = Sheet.createExpertSet();
457                 convertProps (p, descr.expert, i ());
458                 orig.put (p);
459             }
460         } catch (ClassNotFoundException JavaDoc ex) {
461             Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, ex);
462         } catch (IOException JavaDoc ex) {
463             Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, ex);
464         } catch (IntrospectionException ex) {
465             Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, ex);
466         } catch (LinkageError JavaDoc ex) {
467             // #30650 - catch also LinkageError.
468
Logger.getLogger(InstanceNode.class.getName()).log(Level.WARNING, null, ex);
469         }
470     }
471     
472     
473     /** Method that converts properties of an object.
474      * @param set set to add properties to
475      * @param arr array of Node.Property and Node.IndexedProperty
476      * @param ido IDO providing task to invoke when a property changes
477      */

478     private static final void convertProps (
479         Sheet.Set set, Node.Property[] arr, InstanceDataObject ido
480     ) {
481         for (int i = 0; i < arr.length; i++) {
482             if (arr[i] instanceof Node.IndexedProperty) {
483                 set.put (new I ((Node.IndexedProperty)arr[i], ido));
484             } else {
485                 set.put (new P (arr[i], ido));
486             }
487         }
488     }
489     
490     /** The method creates a BufferedImage which represents the same Image as the
491      * parameter but consumes less memory.
492      */

493     private static final java.awt.Image JavaDoc toBufferedImage(Image JavaDoc img, boolean load) {
494         // load the image
495
if (load) {
496             new javax.swing.ImageIcon JavaDoc(img);
497         }
498         
499         java.awt.image.BufferedImage JavaDoc rep = createBufferedImage();
500         java.awt.Graphics JavaDoc g = rep.createGraphics();
501         g.drawImage(img, 0, 0, null);
502         g.dispose();
503         img.flush();
504         return rep;
505     }
506
507     /** Creates BufferedImage 16x16 and Transparency.BITMASK */
508     private static final java.awt.image.BufferedImage JavaDoc createBufferedImage() {
509         java.awt.image.ColorModel JavaDoc model = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().
510                                           getDefaultScreenDevice().getDefaultConfiguration().getColorModel(java.awt.Transparency.BITMASK);
511         java.awt.image.BufferedImage JavaDoc buffImage = new java.awt.image.BufferedImage JavaDoc(model,
512                 model.createCompatibleWritableRaster(16, 16), model.isAlphaPremultiplied(), null);
513         return buffImage;
514     }
515     
516     /** Indicate whether the node may be renamed.
517      * @return tests {@link DataObject#isRenameAllowed}
518      */

519     public boolean canRename() {
520         if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canRename();
521         return getDeclaredSetter() != null;
522     }
523     
524     /** Indicate whether the node may be destroyed.
525      * @return tests {@link DataObject#isDeleteAllowed}
526      */

527     public boolean canDestroy() {
528         if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canDestroy();
529         try {
530             InstanceCookie ic = ic();
531             if (ic == null) return true;
532             Class JavaDoc clazz = ic.instanceClass();
533             return (!SharedClassObject.class.isAssignableFrom(clazz));
534         } catch (Exception JavaDoc ex) {
535             return false;
536         }
537     }
538     
539     public boolean canCut() {
540         if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canCut();
541         try {
542             InstanceCookie ic = ic();
543             if (ic == null) return false;
544             Class JavaDoc clazz = ic.instanceClass();
545             return (!SharedClassObject.class.isAssignableFrom(clazz));
546         } catch (Exception JavaDoc ex) {
547             return false;
548         }
549     }
550     
551     public boolean canCopy() {
552         if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canCopy();
553         try {
554             InstanceCookie ic = ic();
555             if (ic == null) return false;
556             Class JavaDoc clazz = ic.instanceClass();
557 //XXX if (XMLSettingsSupport.BrokenSettings.class.isAssignableFrom(clazz))
558
// return false;
559
return (!SharedClassObject.class.isAssignableFrom(clazz));
560         } catch (Exception JavaDoc ex) {
561             return false;
562         }
563     }
564     
565     /** Gets the short description of this feature. */
566     public String JavaDoc getShortDescription() {
567         if (noBeanInfo) return super.getShortDescription();
568         
569         try {
570             InstanceCookie ic = ic();
571             if (ic == null) {
572                 // it must be unrecognized instance
573
return getDataObject().getPrimaryFile().toString();
574             }
575             
576             Class JavaDoc clazz = ic.instanceClass();
577             java.beans.BeanDescriptor JavaDoc bd = Utilities.getBeanInfo(clazz).getBeanDescriptor();
578             String JavaDoc desc = bd.getShortDescription();
579             return (desc.equals(bd.getName()))? getDisplayName(): desc;
580         } catch (Exception JavaDoc ex) {
581             return super.getShortDescription();
582         } catch (LinkageError JavaDoc ex) {
583             // #30650 - catch also LinkageError.
584
return super.getShortDescription();
585         }
586     }
587     
588     /* do not want CustomizeBean to be invoked on double-click */
589     public Action getPreferredAction() {
590         return null;
591     }
592     
593     //
594
// inner classes - properties
595
//
596

597     /** A property that delegates every call to original property
598      * but when modified, also starts a saving task.
599      */

600     private static final class P<T> extends Node.Property<T> {
601         /** delegate */
602         private Node.Property<T> del;
603         /** task to executed */
604         private InstanceDataObject t;
605
606         public P (Node.Property<T> del, InstanceDataObject t) {
607             super (del.getValueType ());
608             this.del = del;
609             this.t = t;
610         }
611
612         public void setName(java.lang.String JavaDoc str) {
613             del.setName(str);
614         }
615
616         public void restoreDefaultValue() throws IllegalAccessException JavaDoc, InvocationTargetException {
617             del.restoreDefaultValue();
618         }
619
620         public void setValue(java.lang.String JavaDoc str, java.lang.Object JavaDoc obj) {
621             del.setValue(str, obj);
622         }
623
624         public boolean supportsDefaultValue() {
625             return del.supportsDefaultValue();
626         }
627
628         public boolean canRead() {
629             return del.canRead ();
630         }
631
632         public PropertyEditor getPropertyEditor() {
633             return del.getPropertyEditor();
634         }
635
636         public boolean isHidden() {
637             return del.isHidden();
638         }
639
640         public T getValue() throws IllegalAccessException JavaDoc, InvocationTargetException {
641             return del.getValue ();
642         }
643
644         public void setExpert(boolean param) {
645             del.setExpert(param);
646         }
647
648         /** Delegates the set value and also saves the bean.
649          */

650         public void setValue(T val) throws IllegalAccessException JavaDoc, IllegalArgumentException JavaDoc, InvocationTargetException {
651             del.setValue (val);
652             t.scheduleSave();
653         }
654
655         public void setShortDescription(java.lang.String JavaDoc str) {
656             del.setShortDescription(str);
657         }
658
659         public boolean isExpert() {
660             return del.isExpert();
661         }
662
663         public boolean canWrite() {
664             return del.canWrite ();
665         }
666
667         public Class JavaDoc<T> getValueType() {
668             return del.getValueType();
669         }
670
671         public java.lang.String JavaDoc getDisplayName() {
672             return del.getDisplayName();
673         }
674
675         public java.util.Enumeration JavaDoc<String JavaDoc> attributeNames() {
676             return del.attributeNames();
677         }
678
679         public java.lang.String JavaDoc getShortDescription() {
680             return del.getShortDescription();
681         }
682
683         public java.lang.String JavaDoc getName() {
684             return del.getName();
685         }
686
687         public void setHidden(boolean param) {
688             del.setHidden(param);
689         }
690
691         public void setDisplayName(java.lang.String JavaDoc str) {
692             del.setDisplayName(str);
693         }
694
695         public boolean isPreferred() {
696             return del.isPreferred();
697         }
698
699         public java.lang.Object JavaDoc getValue(java.lang.String JavaDoc str) {
700             return del.getValue(str);
701         }
702
703         public void setPreferred(boolean param) {
704             del.setPreferred(param);
705         }
706
707     } // end of P
708

709     /** A property that delegates every call to original property
710      * but when modified, also starts a saving task.
711      */

712     private static final class I<T> extends Node.IndexedProperty<T, InstanceDataObject> {
713         /** delegate */
714         private Node.IndexedProperty<T, InstanceDataObject> del;
715         /** task to executed */
716         private InstanceDataObject t;
717
718         public I (Node.IndexedProperty<T, InstanceDataObject> del, InstanceDataObject t) {
719             super (del.getValueType (), del.getElementType ());
720             this.del = del;
721             this.t = t;
722         }
723
724         public void setName(java.lang.String JavaDoc str) {
725             del.setName(str);
726         }
727
728         public void restoreDefaultValue() throws IllegalAccessException JavaDoc, InvocationTargetException {
729             del.restoreDefaultValue();
730         }
731
732         public void setValue(java.lang.String JavaDoc str, java.lang.Object JavaDoc obj) {
733             del.setValue(str, obj);
734         }
735
736         public boolean supportsDefaultValue() {
737             return del.supportsDefaultValue();
738         }
739
740         public boolean canRead() {
741             return del.canRead ();
742         }
743
744         public PropertyEditor getPropertyEditor() {
745             return del.getPropertyEditor();
746         }
747
748         public boolean isHidden() {
749             return del.isHidden();
750         }
751
752         public T getValue() throws IllegalAccessException JavaDoc, InvocationTargetException {
753             return del.getValue ();
754         }
755
756         public void setExpert(boolean param) {
757             del.setExpert(param);
758         }
759
760         /** Delegates the set value and also saves the bean.
761          */

762         public void setValue(T val) throws IllegalAccessException JavaDoc, IllegalArgumentException JavaDoc, InvocationTargetException {
763             del.setValue (val);
764             t.scheduleSave();
765         }
766
767         public void setShortDescription(java.lang.String JavaDoc str) {
768             del.setShortDescription(str);
769         }
770
771         public boolean isExpert() {
772             return del.isExpert();
773         }
774
775         public boolean canWrite() {
776             return del.canWrite ();
777         }
778
779         public Class JavaDoc<T> getValueType() {
780             return del.getValueType();
781         }
782
783         public java.lang.String JavaDoc getDisplayName() {
784             return del.getDisplayName();
785         }
786
787         public java.util.Enumeration JavaDoc<String JavaDoc> attributeNames() {
788             return del.attributeNames();
789         }
790
791         public java.lang.String JavaDoc getShortDescription() {
792             return del.getShortDescription();
793         }
794
795         public java.lang.String JavaDoc getName() {
796             return del.getName();
797         }
798
799         public void setHidden(boolean param) {
800             del.setHidden(param);
801         }
802
803         public void setDisplayName(java.lang.String JavaDoc str) {
804             del.setDisplayName(str);
805         }
806
807         public boolean isPreferred() {
808             return del.isPreferred();
809         }
810
811         public java.lang.Object JavaDoc getValue(java.lang.String JavaDoc str) {
812             return del.getValue(str);
813         }
814
815         public void setPreferred(boolean param) {
816             del.setPreferred(param);
817         }
818
819         public boolean canIndexedRead () {
820             return del.canIndexedRead ();
821         }
822
823         public Class JavaDoc<InstanceDataObject> getElementType () {
824             return del.getElementType ();
825         }
826
827         public InstanceDataObject getIndexedValue (int index) throws
828         IllegalAccessException JavaDoc, IllegalArgumentException JavaDoc, InvocationTargetException {
829             return del.getIndexedValue (index);
830         }
831
832         public boolean canIndexedWrite () {
833             return del.canIndexedWrite ();
834         }
835
836         public void setIndexedValue (int indx, InstanceDataObject val) throws
837         IllegalAccessException JavaDoc, IllegalArgumentException JavaDoc, InvocationTargetException {
838             del.setIndexedValue (indx, val);
839             t.scheduleSave();
840         }
841
842         public PropertyEditor getIndexedPropertyEditor () {
843             return del.getIndexedPropertyEditor ();
844         }
845     } // end of I
846

847     /** Derived from BeanChildren and allow replace beancontext. */
848     private final static class InstanceChildren extends Children.Keys implements PropertyChangeListener {
849         java.lang.ref.WeakReference JavaDoc<PropertyChangeListener> dobjListener;
850         InstanceDataObject dobj;
851         Object JavaDoc bean;
852         ContextL contextL = null;
853         
854         public InstanceChildren(InstanceDataObject dobj) {
855             this.dobj = dobj;
856         }
857         
858         protected void addNotify () {
859             super.addNotify();
860             
861             PropertyChangeListener p = org.openide.util.WeakListeners.propertyChange(this, dobj);
862             dobjListener = new java.lang.ref.WeakReference JavaDoc<PropertyChangeListener>(p);
863             dobj.addPropertyChangeListener(p);
864             // attaches a listener to the bean
865
contextL = new ContextL (this);
866             propertyChange(null);
867         }
868         
869         protected void removeNotify () {
870             if (contextL != null && bean != null)
871                 ((BeanContext) bean).removeBeanContextMembershipListener (contextL);
872             contextL = null;
873             
874             PropertyChangeListener p = dobjListener.get();
875             if (p != null) {
876                 dobj.removePropertyChangeListener(p);
877                 dobjListener.clear();
878             }
879
880             setKeys (java.util.Collections.emptySet());
881         }
882         
883         public void propertyChange(PropertyChangeEvent evt) {
884             if (evt != null && !evt.getPropertyName().equals(InstanceDataObject.PROP_COOKIE)) return;
885             
886             if (contextL != null && bean != null)
887                 ((BeanContext) bean).removeBeanContextMembershipListener (contextL);
888             
889             try {
890                 InstanceCookie ic = dobj.getCookie(InstanceCookie.class);
891                 if (ic == null) {
892                     bean = null;
893                     return;
894                 }
895                 Class JavaDoc<?> clazz = ic.instanceClass();
896                 if (BeanContext.class.isAssignableFrom(clazz)) {
897                     bean = ic.instanceCreate();
898                 } else if (BeanContextProxy.class.isAssignableFrom(clazz)) {
899                     bean = ((BeanContextProxy) dobj.instanceCreate()).getBeanContextProxy();
900                 } else {
901                     bean = null;
902                 }
903             } catch (Exception JavaDoc ex) {
904                 bean = null;
905                 Exceptions.printStackTrace(ex);
906             }
907             if (bean != null) {
908                 // attaches a listener to the bean
909
((BeanContext) bean).addBeanContextMembershipListener (contextL);
910             }
911             updateKeys();
912         }
913         
914         private void updateKeys() {
915             if (bean == null) {
916                 setKeys(java.util.Collections.emptySet());
917             } else {
918                 setKeys(((BeanContext) bean).toArray());
919             }
920         }
921         
922         /** Create nodes for a given key.
923          * @param key the key
924          * @return child nodes for this key or null if there should be no
925          * nodes for this key
926          */

927         protected Node[] createNodes(Object JavaDoc key) {
928             Object JavaDoc ctx = bean;
929             if (bean == null) return new Node[0];
930             
931             try {
932                 if (key instanceof java.beans.beancontext.BeanContextSupport JavaDoc) {
933                     java.beans.beancontext.BeanContextSupport JavaDoc bcs = (java.beans.beancontext.BeanContextSupport JavaDoc)key;
934
935                     if (((BeanContext) ctx).contains (bcs.getBeanContextPeer())) {
936                         // sometimes a BeanContextSupport occures in the list of
937
// beans children even there is its peer. we think that
938
// it is desirable to hide the context if the peer is
939
// also present
940
return new Node[0];
941                     }
942                 }
943
944                 return new Node[] { new BeanContextNode<Object JavaDoc> (key, dobj) };
945             } catch (IntrospectionException ex) {
946                 // ignore the exception
947
return new Node[0];
948             }
949         }
950         
951         /** Context listener.
952         */

953         private static final class ContextL implements BeanContextMembershipListener {
954             /** weak reference to the BeanChildren object */
955             private java.lang.ref.WeakReference JavaDoc<InstanceChildren> ref;
956
957             /** Constructor */
958             ContextL (InstanceChildren bc) {
959                 ref = new java.lang.ref.WeakReference JavaDoc<InstanceChildren> (bc);
960             }
961
962             /** Listener method that is called when a bean is added to
963             * the bean context.
964             * @param bcme event describing the action
965             */

966             public void childrenAdded (BeanContextMembershipEvent bcme) {
967                 InstanceChildren bc = ref.get ();
968                 if (bc != null) {
969                     bc.updateKeys();
970                 }
971             }
972
973             /** Listener method that is called when a bean is removed to
974             * the bean context.
975             * @param bcme event describing the action
976             */

977             public void childrenRemoved (BeanContextMembershipEvent bcme) {
978                 InstanceChildren bc = ref.get ();
979                 if (bc != null) {
980                     bc.updateKeys ();
981                 }
982             }
983         }
984     }
985     
986     /** Creates BeanContextNode for each bean
987     */

988     private static class BeanFactoryImpl implements BeanChildren.Factory {
989         InstanceDataObject task;
990         public BeanFactoryImpl(InstanceDataObject task) {
991             this.task = task;
992         }
993         
994         /** @return bean node */
995         public Node createNode (Object JavaDoc bean) throws IntrospectionException {
996             return new BeanContextNode<Object JavaDoc> (bean, task);
997         }
998     }
999     
1000    private static class BeanContextNode<T> extends BeanNode<T> {
1001        public BeanContextNode(T bean, InstanceDataObject task) throws IntrospectionException {
1002            super(bean, getChildren(bean, task));
1003            changeSheet(getSheet(), task);
1004        }
1005        
1006        private void changeSheet(Sheet orig, InstanceDataObject task) {
1007            Sheet.Set props = orig.get (Sheet.PROPERTIES);
1008            if (props != null) {
1009                convertProps (props, props.getProperties(), task);
1010            }
1011
1012            props = orig.get(Sheet.EXPERT);
1013            if (props != null) {
1014                convertProps (props, props.getProperties(), task);
1015            }
1016        }
1017        private static Children getChildren (Object JavaDoc bean, InstanceDataObject task) {
1018            if (bean instanceof BeanContext)
1019                return new BeanChildren ((BeanContext)bean, new BeanFactoryImpl(task));
1020            if (bean instanceof BeanContextProxy) {
1021                java.beans.beancontext.BeanContextChild JavaDoc bch = ((BeanContextProxy)bean).getBeanContextProxy();
1022                if (bch instanceof BeanContext)
1023                    return new BeanChildren ((BeanContext)bch, new BeanFactoryImpl(task));
1024            }
1025            return Children.LEAF;
1026        }
1027        
1028        // #7925
1029
public boolean canDestroy() {
1030            return false;
1031        }
1032        
1033    }
1034    
1035    /** Property change listener to update the properties of the node and
1036    * also the name of the node (sometimes)
1037    */

1038    private final class PropL extends Object JavaDoc implements PropertyChangeListener {
1039        private boolean doNotListen = false;
1040        PropL() {}
1041        
1042        public void propertyChange(PropertyChangeEvent e) {
1043            if (doNotListen) return;
1044            firePropertyChange (e.getPropertyName (), e.getOldValue (), e.getNewValue ());
1045        }
1046        
1047        public void destroy() {
1048            doNotListen = true;
1049        }
1050    }
1051        
1052}
1053
Popular Tags