alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.loaders;

import java.awt.Image;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyEditor;
import java.beans.beancontext.BeanContext;
import java.beans.beancontext.BeanContextProxy;
import java.beans.beancontext.BeanContextMembershipEvent;
import java.beans.beancontext.BeanContextMembershipListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.IOException;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.openide.*;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.*;
import org.openide.loaders.*;
import org.openide.util.*;
import org.openide.nodes.*;

/** Node to represent a .settings, .ser or .instance file.
 *
 * @author  Jaroslav Tulach, Jan Pokorsky
 */
final class InstanceNode extends DataNode {
    
    /** icon base */
    private static final String INSTANCE_ICON_BASE =
        "org/openide/loaders/instanceObject"; // NOI18N
    
    /** File extension for xml settings. */
    private static final String XML_EXT = "settings"; //NOI18N
    
    /** listener for properties */
    private PropL propertyChangeListener = null;
    private PropertyChangeListener dobjListener;
    private boolean isSheetCreated = false;
    /** bean info is not used only if the file specifies 
     * 
     */
    private boolean noBeanInfo = false;

    /** Constructor */
    public InstanceNode (InstanceDataObject obj) {
        this (obj,  Boolean.FALSE.equals (obj.getPrimaryFile ().getAttribute ("beaninfo"))); // NOI18N
    }
     
    /** @param obj the object to use
     * @param noBeanInfo info to use
     */
    private InstanceNode (InstanceDataObject obj, boolean noBeanInfo) {
        super (obj, getChildren(obj, noBeanInfo));
        
        initIconBase();

        this.noBeanInfo = noBeanInfo;
        
        if (!noBeanInfo && !getDataObject().getPrimaryFile().hasExt(XML_EXT)) {
            initName();
        }
        
        // listen on the cookie change of the instance data object
        dobjListener = new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals(DataObject.PROP_COOKIE)) {
                    if (propertyChangeListener != null) {
                        propertyChangeListener.destroy();
                        propertyChangeListener = null;
                    }
                    if (InstanceNode.this.noBeanInfo || ic() == null) {
                       initIconBase();
                    } else {
                       fireIconChange();
                    }
                    fireNameChange(null, null);
                    fireDisplayNameChange(null, null);
                    fireShortDescriptionChange(null, null);
                    if (isSheetCreated) setSheet(createSheet());
                }
            }
        };
        obj.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(dobjListener, obj));
    }
    
    /** initialize the icon base according to state of the settings instance (valid/broken) */
    private void initIconBase() {
        InstanceCookie.Of ic = ic();
        String iconBase = INSTANCE_ICON_BASE;
        if (ic == null) {//XXX && io.instanceOf(XMLSettingsSupport.BrokenSettings.class)) {
            iconBase = "org/openide/loaders/instanceBroken"; // NOI18N
        }
        setIconBase(iconBase);
    }
    
    private static Children getChildren(DataObject dobj, boolean noBeanInfo) {
        if (noBeanInfo) {
            return Children.LEAF;
        }
        InstanceCookie inst = (InstanceCookie)dobj.getCookie(InstanceCookie.class);
        if (inst == null) return Children.LEAF;
        try {
            Class clazz = inst.instanceClass();
            if (BeanContext.class.isAssignableFrom(clazz) ||
                BeanContextProxy.class.isAssignableFrom(clazz)) {
                return new InstanceChildren ((InstanceDataObject) dobj);
            } else {
                return Children.LEAF;
            }
        } catch (Exception ex) {
            return Children.LEAF;
        }
    }
    
    /** Getter for instance data object.
     * @return instance data object
     */
    private InstanceDataObject i () {
        return (InstanceDataObject)getDataObject ();
    }
    
    private InstanceCookie.Of ic () {
        return (InstanceCookie.Of) getDataObject().getCookie(InstanceCookie.Of.class);
    }

    /** Find an icon for this node (in the closed state).
    * @param type constant from {@link java.beans.BeanInfo}
    * @return icon to use to represent the node
    */
    public Image getIcon (int type) {
        if (noBeanInfo) return super.getIcon(type);
        Image img = null;
        try {
            DataObject dobj = getDataObject();
            img = dobj.getPrimaryFile().getFileSystem().getStatus().
                annotateIcon (img, type, dobj.files ());
        } catch (FileStateInvalidException e) {
            // no fs, do nothing
        }
        
        if (img == null) img = initIcon(type);
        if (img == null) img = super.getIcon(type);
        return img;
    }

    /** Find an icon for this node (in the open state).
    * This icon is used when the node may have children and is expanded.
    *
    * @param type constant from {@link java.beans.BeanInfo}
    * @return icon to use to represent the node when open
    */
    public Image getOpenedIcon (int type) {
        return getIcon (type);
    }

    /** try to register PropertyChangeListener to instance to fire its changes.*/
    private void initPList () {
        try {
            InstanceCookie ic = ic();
            if (ic == null) return;
            BeanInfo info = Utilities.getBeanInfo(ic.instanceClass());
            java.beans.EventSetDescriptor[] descs = info.getEventSetDescriptors();
            Method setter = null;
            for (int i = 0; descs != null && i < descs.length; i++) {
                setter = descs[i].getAddListenerMethod();
                if (setter != null && setter.getName().equals("addPropertyChangeListener")) { // NOI18N
                    Object bean = ic.instanceCreate();
                    propertyChangeListener = new PropL();
                    setter.invoke(bean, new Object[] {org.openide.util.WeakListeners.propertyChange(propertyChangeListener, bean)});
                }
            }
        } catch (Exception ex) {
        } catch (LinkageError ex) {
            // #30650 - catch also LinkageError.
            // Ignoring exception the same way as the Exception handler above.
        }
    }
    
    private Image initIcon (int type) {
        Image beanInfoIcon = null;
        try {
            InstanceCookie ic = ic();
            if (ic == null) return null;
            Class clazz = ic.instanceClass();
            //Fixed bug #5610
            //Class javax.swing.JToolBar$Separator does not have icon
            //we will use temporarily icon from javax.swing.JSeparator
            //New icon is requested.

            String className = clazz.getName ();
            BeanInfo bi;
            if (
                className.equals ("javax.swing.JSeparator") ||  // NOI18N
                className.equals ("javax.swing.JToolBar$Separator") // NOI18N
            ) {
                Class clazzTmp = Class.forName ("javax.swing.JSeparator"); // NOI18N
                bi = Utilities.getBeanInfo (clazzTmp);
            } else {
                bi = Utilities.getBeanInfo (clazz);
            }

            if (bi != null) {
                beanInfoIcon = bi.getIcon (type);
                if (beanInfoIcon != null) {
                    beanInfoIcon = toBufferedImage(beanInfoIcon, true);
                }
            }
            // Also specially handle action instances.
            if (beanInfoIcon == null && Action.class.isAssignableFrom(clazz)) {
                Action action = (Action)ic.instanceCreate();
                Icon icon = (Icon)action.getValue(Action.SMALL_ICON);
                // [PENDING] not very pretty, but there is no good way to
                // get an Image from an Icon that I know of
                if (icon instanceof ImageIcon) {
                    beanInfoIcon = ((ImageIcon)icon).getImage();
                } else {
                    beanInfoIcon = Utilities.loadImage("org/openide/loaders/empty.gif", true); // NOI18N
                }
            }
        } catch (Exception e) {
            // Problem ==>> use default icon
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, e);
        } catch (LinkageError e) {
            // #30650 - catch also LinkageError.
            // Problem ==>> use default icon
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, e);
        }

        return beanInfoIcon;
    }

    /** try to initialize display name.
    */
    private void initName() {
        try {
            InstanceCookie ic = ic();
            if (ic == null) return;
            Class clazz = ic.instanceClass();
        
        String className = clazz.getName ();
        if (className.equals ("javax.swing.JSeparator") || // NOI18N
            className.equals ("javax.swing.JToolBar$Separator")) { // NOI18N
                
            setDisplayName (NbBundle.getMessage (InstanceDataObject.class,
                "LBL_separator_instance")); // NOI18N
            return;
        }
        // Also specially handle action instances.
        if (Action.class.isAssignableFrom(clazz)) {
            Action action = (Action)ic.instanceCreate();
            // Set node's display name.
            String name = (String)action.getValue(Action.NAME);
            
            // #31227 - some action does not implement its name properly.
            // Throw exception with the name of the class.
            if (name == null) {
                ErrorManager.getDefault().log(ErrorManager.WARNING,
                    "Please attach following information to the issue " + // NOI18N
                    ": " + // NOI18N
                    "action " + className + " does not implement SystemAction.getName() or Action.getValue(NAME) properly. It returns null!"); // NOI18N
                setDisplayName(className);
                return;
            }
            
            int amper = name.indexOf ((char) '&');
            if (amper != -1)
                name = name.substring (0, amper) + name.substring (amper + 1);
            if (name.endsWith ("...")) // NOI18N
                name = name.substring (0, name.length () - 3);
            name = name.trim ();
            setDisplayName (name);
            return;
        }
        } catch (Exception e) {
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, e);
            setDisplayName(getDataObject().getName());
            return;
        }
    }
    
    /** Try to get display name of the bean.
     */
    private String getNameForBean() {
        try {
            InstanceCookie ic = ic();
            if (ic == null) {
                // it must be unrecognized setting
                return NbBundle.getMessage(InstanceNode.class,
                    "LBL_BrokenSettings"); //NOI18N
            }
            Class clazz = ic.instanceClass();
            Method nameGetter;
            Class[] param = new Class [0];
            try {
                nameGetter = clazz.getMethod ("getName", param); // NOI18N
                if (nameGetter.getReturnType () != String.class) throw new NoSuchMethodException ();
            } catch (NoSuchMethodException e) {
                try {
                    nameGetter = clazz.getMethod ("getDisplayName", param); // NOI18N
                    if (nameGetter.getReturnType () != String.class) throw new NoSuchMethodException ();
                } catch (NoSuchMethodException ee) {
                    return null;
                }
            }
            Object bean = ic.instanceCreate();
            return (String) nameGetter.invoke (bean, null);
        } catch (Exception ex) {
            return null;
        }
    }
    
    /** try to find setter setName/setDisplayName, if none declared return null */
    private Method getDeclaredSetter() {
        Method nameSetter = null;
        try {
            InstanceCookie ic = ic();
            if (ic == null) return null;
            Class clazz = ic.instanceClass();
            Class[] param = new Class[] {String.class};
            // find the setter for the name
            try {
                nameSetter = clazz.getMethod ("setName", param); // NOI18N
            } catch (NoSuchMethodException e) {
                nameSetter = clazz.getMethod ("setDisplayName", param); // NOI18N
            }
        } catch (Exception ex) {
        }
        return nameSetter;
    }
    
    public void setName(String name) {
        if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) {
            super.setName(name);
            return ;
        }
        String old = getNameImpl();
        if (old != null && old.equals(name)) return;
        InstanceCookie ic = ic();
        if (ic == null) {
            super.setName(name);
            return;
        }
        
        Method nameSetter = getDeclaredSetter();
        if (nameSetter != null) {
            try {
                Object bean = ic.instanceCreate();
                nameSetter.invoke(bean, new Object[] {name});
                i().scheduleSave();
            } catch (Exception ex) {
            }
        }
        super.setName(name);
    }
    
    /** Get the display name for the node.
     * A filesystem may {@link org.openide.filesystems.FileSystem#getStatus specially alter} this.
     * @return the desired name
    */
    public String getDisplayName () {
        String name = (String) getDataObject().getPrimaryFile().
            getAttribute(InstanceDataObject.EA_NAME);
        if (name == null) {
            try {
                String def = "\b"; // NOI18N
                FileSystem.Status fsStatus = getDataObject().getPrimaryFile().
                    getFileSystem().getStatus();
                name = fsStatus.annotateName(def, getDataObject().files());
                if (name.indexOf(def) < 0) {
                    return name;
                } else {
                    name = getNameForBean();
                    if (name != null) {
                        name = fsStatus.annotateName (name, getDataObject().files());
                    } else {
                        name = super.getDisplayName();
                    }
                }
            } catch (FileStateInvalidException e) {
                // no fs, do nothing
            }
        }
        return name;
    }
    
    /** try to get name by colling getter on the instance. */
    private String getNameImpl() {
        String name;
        name = getNameForBean();
        if (name == null) name = getName();

        return name;
    }
    
    protected Sheet createSheet () {
        Sheet orig;
    
        if (getDataObject ().getPrimaryFile ().hasExt ("ser") || // NOI18N
            getDataObject ().getPrimaryFile ().hasExt (XML_EXT)) {
            orig = new Sheet();
            changeSheet (orig);
        } else {
            // just instance file, change here
            orig = super.createSheet ();
            Sheet.Set props = orig.get (Sheet.PROPERTIES);
            final InstanceCookie ic = ic();
            if (ic == null) {
                props.put (new PropertySupport.ReadOnly (
                    "className", String.class, // NOI18N
                    NbBundle.getMessage (InstanceDataObject.class, "PROP_instance_class"), // NOI18N
                    NbBundle.getMessage (InstanceDataObject.class, "HINT_instance_class") // NOI18N
                ) {
                    public Object getValue () {
                        return ic.instanceName ();
                    }
                });
            }
        }
        
        isSheetCreated = true;
        return orig;
    }
        
        
    private void changeSheet (Sheet orig) {
        Sheet.Set props = orig.get (Sheet.PROPERTIES);

        try {
            InstanceCookie ic = ic();
            if (ic == null) return;
            // properties
            BeanInfo beanInfo = Utilities.getBeanInfo (ic.instanceClass ());
            BeanNode.Descriptor descr = BeanNode.computeProperties (ic.instanceCreate (), beanInfo);
            initPList();

            props = Sheet.createPropertiesSet();
            if (descr.property != null) {
                convertProps (props, descr.property, i ());
            }
            orig.put (props);

            if (descr.expert != null && descr.expert.length != 0) {
                Sheet.Set p = Sheet.createExpertSet();
                convertProps (p, descr.expert, i ());
                orig.put (p);
            }
        } catch (ClassNotFoundException ex) {
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ex);
        } catch (IOException ex) {
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ex);
        } catch (IntrospectionException ex) {
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ex);
        } catch (LinkageError ex) {
            // #30650 - catch also LinkageError.
            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ex);
        }
    }
    
    
    /** Method that converts properties of an object.
     * @param set set to add properties to
     * @param arr array of Node.Property and Node.IndexedProperty
     * @param ido IDO providing task to invoke when a property changes
     */
    private static final void convertProps (
        Sheet.Set set, Node.Property[] arr, InstanceDataObject ido
    ) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] instanceof Node.IndexedProperty) {
                set.put (new I ((Node.IndexedProperty)arr[i], ido));
            } else {
                set.put (new P (arr[i], ido));
            }
        }
    }        
    
    /** The method creates a BufferedImage which represents the same Image as the
     * parameter but consumes less memory.
     */
    private static final java.awt.Image toBufferedImage(Image img, boolean load) {
        // load the image
        if (load) {
            new javax.swing.ImageIcon(img);
        }
        
        java.awt.image.BufferedImage rep = createBufferedImage();
        java.awt.Graphics g = rep.createGraphics();
        g.drawImage(img, 0, 0, null);
        g.dispose();
        img.flush();
        return rep;
    }

    /** Creates BufferedImage 16x16 and Transparency.BITMASK */
    private static final java.awt.image.BufferedImage createBufferedImage() {
        java.awt.image.ColorModel model = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().
                                          getDefaultScreenDevice().getDefaultConfiguration().getColorModel(java.awt.Transparency.BITMASK);
        java.awt.image.BufferedImage buffImage = new java.awt.image.BufferedImage(model,
                model.createCompatibleWritableRaster(16, 16), model.isAlphaPremultiplied(), null);
        return buffImage;
    }
    
    /** Indicate whether the node may be renamed.
     * @return tests {@link DataObject#isRenameAllowed}
     */
    public boolean canRename() {
        if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canRename();
        return getDeclaredSetter() != null;
    }
    
    /** Indicate whether the node may be destroyed.
     * @return tests {@link DataObject#isDeleteAllowed}
     */
    public boolean canDestroy() {
        if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canDestroy();
        try {
            InstanceCookie ic = ic();
            if (ic == null) return true;
            Class clazz = ic.instanceClass();
            return (!SharedClassObject.class.isAssignableFrom(clazz));
        } catch (Exception ex) {
            return false;
        }
    }
    
    public boolean canCut() {
        if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canCut();
        try {
            InstanceCookie ic = ic();
            if (ic == null) return false;
            Class clazz = ic.instanceClass();
            return (!SharedClassObject.class.isAssignableFrom(clazz));
        } catch (Exception ex) {
            return false;
        }
    }
    
    public boolean canCopy() {
        if (!getDataObject().getPrimaryFile().hasExt(XML_EXT)) return super.canCopy();
        try {
            InstanceCookie ic = ic();
            if (ic == null) return false;
            Class clazz = ic.instanceClass();
//XXX            if (XMLSettingsSupport.BrokenSettings.class.isAssignableFrom(clazz))
//                return false;
            return (!SharedClassObject.class.isAssignableFrom(clazz));
        } catch (Exception ex) {
            return false;
        }
    }
    
    /** Gets the short description of this feature. */
    public String getShortDescription() {
        if (noBeanInfo) return super.getShortDescription();
        
        try {
            InstanceCookie ic = ic();
            if (ic == null) {
                // it must be unrecognized instance
                return getDataObject().getPrimaryFile().toString();
            }
            
            Class clazz = ic.instanceClass();
            java.beans.BeanDescriptor bd = Utilities.getBeanInfo(clazz).getBeanDescriptor();
            String desc = bd.getShortDescription();
            return (desc.equals(bd.getName()))? getDisplayName(): desc;
        } catch (Exception ex) {
            return super.getShortDescription();
        } catch (LinkageError ex) {
            // #30650 - catch also LinkageError.
            return super.getShortDescription();
        }
    }
    
    /* do not want CustomizeBean to be invoked on double-click */
    public Action getPreferredAction() {
        return null;
    }
    
    //
    // inner classes - properties
    //
    
    /** A property that delegates every call to original property
     * but when modified, also starts a saving task.
     */
    private static final class P extends Node.Property {
        /** delegate */
        private Node.Property del;
        /** task to executed */
        private InstanceDataObject t;

        public P (Node.Property del, InstanceDataObject t) {
            super (del.getValueType ());
            this.del = del;
            this.t = t;
        }

        public void setName(java.lang.String str) {
            del.setName(str);
        }

        public void restoreDefaultValue() throws IllegalAccessException, InvocationTargetException {
            del.restoreDefaultValue();
        }

        public void setValue(java.lang.String str, java.lang.Object obj) {
            del.setValue(str, obj);
        }

        public boolean supportsDefaultValue() {
            return del.supportsDefaultValue();
        }

        public boolean canRead() {
            return del.canRead ();
        }

        public PropertyEditor getPropertyEditor() {
            return del.getPropertyEditor();
        }

        public boolean isHidden() {
            return del.isHidden();
        }

        public Object getValue() throws IllegalAccessException, InvocationTargetException {
            return del.getValue ();
        }

        public void setExpert(boolean param) {
            del.setExpert(param);
        }

        /** Delegates the set value and also saves the bean.
         */
        public void setValue(Object val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            del.setValue (val);
            t.scheduleSave();
        }

        public void setShortDescription(java.lang.String str) {
            del.setShortDescription(str);
        }

        public boolean isExpert() {
            return del.isExpert();
        }

        public boolean canWrite() {
            return del.canWrite ();
        }

        public Class getValueType() {
            return del.getValueType();
        }

        public java.lang.String getDisplayName() {
            return del.getDisplayName();
        }

        public java.util.Enumeration attributeNames() {
            return del.attributeNames();
        }

        public java.lang.String getShortDescription() {
            return del.getShortDescription();
        }

        public java.lang.String getName() {
            return del.getName();
        }

        public void setHidden(boolean param) {
            del.setHidden(param);
        }

        public void setDisplayName(java.lang.String str) {
            del.setDisplayName(str);
        }

        public boolean isPreferred() {
            return del.isPreferred();
        }

        public java.lang.Object getValue(java.lang.String str) {
            return del.getValue(str);
        }

        public void setPreferred(boolean param) {
            del.setPreferred(param);
        }

    } // end of P

    /** A property that delegates every call to original property
     * but when modified, also starts a saving task.
     */
    private static final class I extends Node.IndexedProperty {
        /** delegate */
        private Node.IndexedProperty del;
        /** task to executed */
        private InstanceDataObject t;

        public I (Node.IndexedProperty del, InstanceDataObject t) {
            super (del.getValueType (), del.getElementType ());
            this.del = del;
            this.t = t;
        }

        public void setName(java.lang.String str) {
            del.setName(str);
        }

        public void restoreDefaultValue() throws IllegalAccessException, InvocationTargetException {
            del.restoreDefaultValue();
        }

        public void setValue(java.lang.String str, java.lang.Object obj) {
            del.setValue(str, obj);
        }

        public boolean supportsDefaultValue() {
            return del.supportsDefaultValue();
        }

        public boolean canRead() {
            return del.canRead ();
        }

        public PropertyEditor getPropertyEditor() {
            return del.getPropertyEditor();
        }

        public boolean isHidden() {
            return del.isHidden();
        }

        public Object getValue() throws IllegalAccessException, InvocationTargetException {
            return del.getValue ();
        }

        public void setExpert(boolean param) {
            del.setExpert(param);
        }

        /** Delegates the set value and also saves the bean.
         */
        public void setValue(Object val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            del.setValue (val);
            t.scheduleSave();
        }

        public void setShortDescription(java.lang.String str) {
            del.setShortDescription(str);
        }

        public boolean isExpert() {
            return del.isExpert();
        }

        public boolean canWrite() {
            return del.canWrite ();
        }

        public Class getValueType() {
            return del.getValueType();
        }

        public java.lang.String getDisplayName() {
            return del.getDisplayName();
        }

        public java.util.Enumeration attributeNames() {
            return del.attributeNames();
        }

        public java.lang.String getShortDescription() {
            return del.getShortDescription();
        }

        public java.lang.String getName() {
            return del.getName();
        }

        public void setHidden(boolean param) {
            del.setHidden(param);
        }

        public void setDisplayName(java.lang.String str) {
            del.setDisplayName(str);
        }

        public boolean isPreferred() {
            return del.isPreferred();
        }

        public java.lang.Object getValue(java.lang.String str) {
            return del.getValue(str);
        }

        public void setPreferred(boolean param) {
            del.setPreferred(param);
        }

        public boolean canIndexedRead () {
            return del.canIndexedRead ();
        }

        public Class getElementType () {
            return del.getElementType ();
        }

        public Object getIndexedValue (int index) throws
        IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            return del.getIndexedValue (index);
        }

        public boolean canIndexedWrite () {
            return del.canIndexedWrite ();
        }

        public void setIndexedValue (int indx, Object val) throws
        IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            del.setIndexedValue (indx, val);
            t.scheduleSave();
        }

        public PropertyEditor getIndexedPropertyEditor () {
            return del.getIndexedPropertyEditor ();
        }
    } // end of I
    
    /** Derived from BeanChildren and allow replace beancontext. */
    private final static class InstanceChildren extends Children.Keys implements PropertyChangeListener {
        java.lang.ref.WeakReference dobjListener;
        InstanceDataObject dobj;
        Object bean;
        ContextL contextL = null;
        
        public InstanceChildren(InstanceDataObject dobj) {
            this.dobj = dobj;
        }
        
        protected void addNotify () {
            super.addNotify();
            
            PropertyChangeListener p = org.openide.util.WeakListeners.propertyChange(this, dobj);
            dobjListener = new java.lang.ref.WeakReference(p);
            dobj.addPropertyChangeListener(p);
            // attaches a listener to the bean
            contextL = new ContextL (this);
            propertyChange(null);
        }
        
        protected void removeNotify () {
            if (contextL != null && bean != null)
                ((BeanContext) bean).removeBeanContextMembershipListener (contextL);
            contextL = null;
            
            PropertyChangeListener p = (PropertyChangeListener) dobjListener.get();
            if (p != null) {
                dobj.removePropertyChangeListener(p);
                dobjListener.clear();
            }

            setKeys (java.util.Collections.EMPTY_SET);
        }
        
        public void propertyChange(PropertyChangeEvent evt) {
            if (evt != null && !evt.getPropertyName().equals(InstanceDataObject.PROP_COOKIE)) return;
            
            if (contextL != null && bean != null)
                ((BeanContext) bean).removeBeanContextMembershipListener (contextL);
            
            try {
                InstanceCookie ic = (InstanceCookie) dobj.getCookie(InstanceCookie.class);
                if (ic == null) {
                    bean = null;
                    return;
                }
                Class clazz = ic.instanceClass();
                if (BeanContext.class.isAssignableFrom(clazz)) {
                    bean = ic.instanceCreate();
                } else if (BeanContextProxy.class.isAssignableFrom(clazz)) {
                    bean = ((BeanContextProxy) dobj.instanceCreate()).getBeanContextProxy();
                } else {
                    bean = null;
                }
            } catch (Exception ex) {
                bean = null;
                ErrorManager.getDefault().notify(ex);
            }
            if (bean != null) {
                // attaches a listener to the bean
                ((BeanContext) bean).addBeanContextMembershipListener (contextL);
            }
            updateKeys();
        }
        
        private void updateKeys() {
            if (bean == null) {
                setKeys(java.util.Collections.EMPTY_SET);
            } else {
                setKeys(((BeanContext) bean).toArray());
            }
        }
        
        /** Create nodes for a given key.
         * @param key the key
         * @return child nodes for this key or null if there should be no
         *   nodes for this key
         */
        protected Node[] createNodes(Object key) {
            Object ctx = bean; 
            if (bean == null) return new Node[0];
            
            try {
                if (key instanceof java.beans.beancontext.BeanContextSupport) {
                    java.beans.beancontext.BeanContextSupport bcs = (java.beans.beancontext.BeanContextSupport)key;

                    if (((BeanContext) ctx).contains (bcs.getBeanContextPeer())) {
                        // sometimes a BeanContextSupport occures in the list of
                        // beans children even there is its peer. we think that
                        // it is desirable to hide the context if the peer is
                        // also present
                        return new Node[0];
                    }
                }

                return new Node[] { new BeanContextNode (key, dobj) };
            } catch (IntrospectionException ex) {
                // ignore the exception
                return new Node[0];
            }
        }
        
        /** Context listener.
        */
        private static final class ContextL implements BeanContextMembershipListener {
            /** weak reference to the BeanChildren object */
            private java.lang.ref.WeakReference ref;

            /** Constructor */
            ContextL (InstanceChildren bc) {
                ref = new java.lang.ref.WeakReference (bc);
            }

            /** Listener method that is called when a bean is added to
            * the bean context.
            * @param bcme event describing the action
            */
            public void childrenAdded (BeanContextMembershipEvent bcme) {
                InstanceChildren bc = (InstanceChildren)ref.get ();
                if (bc != null) {
                    bc.updateKeys();
                }
            }

            /** Listener method that is called when a bean is removed to
            * the bean context.
            * @param bcme event describing the action
            */
            public void childrenRemoved (BeanContextMembershipEvent bcme) {
                InstanceChildren bc = (InstanceChildren)ref.get ();
                if (bc != null) {
                    bc.updateKeys ();
                }
            }
        }
    }
    
    /** Creates BeanContextNode for each bean
    */
    private static class BeanFactoryImpl implements BeanChildren.Factory {
        InstanceDataObject task;
        public BeanFactoryImpl(InstanceDataObject task) {
            this.task = task;
        }
        
        /** @return bean node */
        public Node createNode (Object bean) throws IntrospectionException {
            return new BeanContextNode (bean, task);
        }
    }
    
    private static class BeanContextNode extends BeanNode {
        public BeanContextNode(Object bean, InstanceDataObject task) throws IntrospectionException {
            super(bean, getChildren(bean, task));
            changeSheet(getSheet(), task);
        }
        
        private void changeSheet(Sheet orig, InstanceDataObject task) {
            Sheet.Set props = orig.get (Sheet.PROPERTIES);
            if (props != null) {
                convertProps (props, props.getProperties(), task);
            }

            props = orig.get(Sheet.EXPERT);
            if (props != null) {
                convertProps (props, props.getProperties(), task);
            }
        }
        private static Children getChildren (Object bean, InstanceDataObject task) {
            if (bean instanceof BeanContext)
                return new BeanChildren ((BeanContext)bean, new BeanFactoryImpl(task));
            if (bean instanceof BeanContextProxy) {
                java.beans.beancontext.BeanContextChild bch = ((BeanContextProxy)bean).getBeanContextProxy();
                if (bch instanceof BeanContext)
                    return new BeanChildren ((BeanContext)bch, new BeanFactoryImpl(task));
            }
            return Children.LEAF;
        }
        
        // #7925
        public boolean canDestroy() {
            return false;
        }
        
    }
    
    /** Property change listener to update the properties of the node and
    * also the name of the node (sometimes)
    */
    private final class PropL extends Object implements PropertyChangeListener {
        private boolean doNotListen = false;
        PropL() {}
        
        public void propertyChange(PropertyChangeEvent e) {
            if (doNotListen) return;
            firePropertyChange (e.getPropertyName (), e.getOldValue (), e.getNewValue ());
        }
        
        public void destroy() {
            doNotListen = true;
        }
    }
        
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.