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.netbeans.modules.xml.tree.nodes;

import java.io.*;
import java.awt.Image;
import java.awt.Component;
import java.awt.datatransfer.*;
import java.util.List;
import java.beans.*;
import java.lang.ref.*;

import org.openide.*;
import org.openide.loaders.*;
import org.openide.actions.*;
import org.openide.util.actions.*;
import org.openide.nodes.*;
import org.openide.explorer.propertysheet.editors.*;
import org.openide.util.datatransfer.*;
import org.openide.util.HelpCtx;
import org.openide.util.Utilities;

import org.netbeans.tax.*;
import org.netbeans.tax.io.*;
import org.netbeans.modules.xml.core.*;
import org.netbeans.modules.xml.core.cookies.*;
import org.netbeans.modules.xml.tree.children.*;
import org.netbeans.modules.xml.tree.nodes.*;
import org.netbeans.modules.xml.tree.settings.*;
import org.netbeans.modules.xml.tree.lib.GuiUtil;
import org.netbeans.modules.xml.tax.cookies.TreeDocumentCookie;
import org.netbeans.modules.xml.tax.cookies.TreeEditorCookie;


/**
 * DataNode that proxies a lot of functionality to actual root bean node.
 * It updates state according to bean PROP_STATUS and ...
 *
 * @author  Libor Kramolis
 * @author  Petr Kuzel
 * @version 0.2
 */
public abstract class AbstractDataNode extends DataNode implements TreeObjectNode, DataNodeCookie, NodeViewType.Provider {
    /** */
    public static final String PROP_ROOT_NODE = "rootNode"; // NOI18N

    private static final String XML_STATUS    = "status"; // NOI18N

    /** Last cached document cookie. */
    private TreeDocumentCookie documentCookie;
    
    /** Last cached document status. */
    private int status;

    /** 
     * Reference to root node allowing garbage collection of TAX model for 
     * collapsed nodes. Actual value can be accessed as getRootNode().
     * We do not need to listen to garbage collection as we listen at editor cookie status.
     */
    private Reference rootRef;

    /** */
    public static final String NODE_VIEW_TYPE_ATTRIBUTE = "org.netbeans.modules.xml.tree.settings.NodeViewType"; // NOI18N
    /** */
    private NodeViewType nodeViewType;


    //!!! where does it listen on PROP_NODE_VIEW_TYPE?
    // listen on bean editor STATUS
    private InnerListener listener;


    //
    // init
    //

    /** */
    protected AbstractDataNode(XMLDataObjectLook dataObject) {
        super ((DataObject)dataObject, new DataObjectChildren ((TreeEditorCookie)dataObject.getCookie (TreeEditorCookie.class)));

        init (dataObject);
    }


    /** */
    private void init (XMLDataObjectLook dataObject) {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::init: status " + ((TreeEditorCookie)dataObject.getCookie (TreeEditorCookie.class)).getStatus()); // NOI18N

        documentCookie = null;
        status = -1;
        rootRef = null;
        listener = new InnerListener();
                
        TreeEditorCookie cake = (TreeEditorCookie) dataObject.getCookie (TreeEditorCookie.class);
        cake.addPropertyChangeListener (listener);

        updateIconBase();

        getCookieSet().add ((DataNodeCookie)this);

        updateShortDescription();
        initNodeViewType();
    }


    //
    // from TreeObjectNode
    //

    /**
     * @return related tree object.
     */
    public final TreeObject getTreeObject () {
        try {
            return (TreeObject)getDocumentRoot();
        } catch (Exception e) {
            return null;
        }        
    }


    //
    // itself
    //

    /** Get the associated xml data object.
     * ({@link #getDataObject} is protected; this provides access to it.)
     * @return the data object
     */
    public final XMLDataObjectLook getXMLDataObjectLook () {
        return (XMLDataObjectLook)getDataObject();
    }


    /**
     */
    protected final TreeDocumentRoot getDocumentRoot () throws IOException, TreeException {
        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null) {
            return (TreeDocumentRoot)rootNode.getTreeObject();
        }
        return null;
    }
  
    
    /**
     */
    protected final DataObjectChildren getDataObjectChildren () {
        return (DataObjectChildren)getChildren();
    }


    //
    // ShortDescription
    //

    /**
     */
    private void updateShortDescription () {
        setShortDescription (createShortDescription());
    }
    
    /**
     */
    private String createShortDescription () {
        StringBuffer sb = new StringBuffer ();

        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            sb.append (rootNode.getShortDescription());
        } else {
            sb.append (getNodeDescription());

            int status = ((TreeEditorCookie)getXMLDataObjectLook().getCookie (TreeEditorCookie.class)).getStatus();
            
            if (status == TreeEditorCookie.STATUS_NOT) {
                sb.append (' ').append (Util.THIS.getString ("TEXT_PART_not_parsed_yet"));
            } else if (status == TreeEditorCookie.STATUS_ERROR) {
                sb.append (' ').append (Util.THIS.getString ("TEXT_PART_error"));
            }
        }

        return sb.toString();
    }

    abstract protected String getNodeDescription ();


    //
    // icon
    //
    
    /**
     */
    public final Image getIcon (int type) {
        Image icon = super.getIcon (type);

        int status = ((TreeEditorCookie)getXMLDataObjectLook().getCookie (TreeEditorCookie.class)).getStatus();
        if ( status == TreeEditorCookie.STATUS_ERROR ) {
            Image errorBadge = Utilities.loadImage ("org/netbeans/modules/xml/tree/resources/errorbadge.gif");
            icon = Utilities.mergeImages (icon, errorBadge, 8, 8);
        }
        return icon;
    }

    /**
     */
    public final Image getOpenedIcon (int type) {
        return getIcon (type);
    }

    /**
     */
    protected final void updateIconBase () {
        fireIconChange ();
        fireOpenedIconChange ();        
    }


    //
    // from DataNodeCookie
    //

    /**
     */
    public final DataNode getDataNode () {
        String thisClassName = this.getClass().getName();
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode [ " + thisClassName + " ] ::getDataNode: this = " + this); // NOI18N

        return this;
    }


    public HelpCtx getHelpCtx() {
        return new HelpCtx (this.getClass());
    }


    //
    // Node, Document
    //

    /**
     */
    abstract protected AbstractRootNode createRootNode (TreeDocumentRoot documentRoot);

    /**
     */
    protected final void updateNode () {
        TreeDocumentCookie newDocumentCookie = (TreeDocumentCookie)getDataObject().getCookie (TreeDocumentCookie.class);
        int newStatus = ((TreeEditorCookie)getDataObject().getCookie (TreeEditorCookie.class)).getStatus();

        if ( Util.THIS.isLoggable() ) /* then */ {
            Util.THIS.debug ("AbstractDataNode::updateNode: status " + newStatus); // NOI18N
            Util.THIS.debug ("                ::updateNode:  OLD  documentCookie = " + this.documentCookie); // NOI18N
            Util.THIS.debug ("                ::updateNode: *new* DocumentCookie = " + newDocumentCookie); // NOI18N
        }

        if ( this.documentCookie != newDocumentCookie ) {
            this.documentCookie = newDocumentCookie;
            if (documentCookie == null) {
                setRootNode (null);
            } else {
                setRootNode (createRootNode (documentCookie.getDocumentRoot()));
            }
        }

        if ( status != newStatus ) {
            this.status = newStatus;

            updateSheet();
            updateShortDescription();
            updateIconBase();
        }
    }

    /**
     * Access weak root node property, may return null.
     */
    public final AbstractRootNode getRootNode () {
        Object rootNode = rootRef == null ? null : rootRef.get();
        return (AbstractRootNode) rootNode;
    }

    /**
     * Set new root node firing PROP_ROOT_NODE property.
     */
    protected final void setRootNode (AbstractRootNode newRootNode) {
        
        AbstractRootNode rootNode = getRootNode();
        
        if ( Util.THIS.isLoggable() ) /* then */ {
            Util.THIS.debug ("AbstractDataNode::setRootNode:  OLD  rootNode = " + rootNode); // NOI18N
            Util.THIS.debug ("                ::setRootNode: *new* rootNode = " + newRootNode); // NOI18N
        }

        if ( rootNode == newRootNode ) {
            return;
        }
        
        AbstractRootNode oldRootNode = (AbstractRootNode) rootNode;
        
        if (newRootNode != null) {
            this.rootRef = new WeakReference(newRootNode);
        } else {
            this.rootRef = null;
        }
        
        if ( oldRootNode != null ) {
            oldRootNode.setDataNode (null);
        }
        if ( newRootNode != null ) {
            newRootNode.setDataNode (this);
        }

        if ( oldRootNode != null ) {
            oldRootNode.removePropertyChangeListener (listener);
//             oldRootNode.removeNodeListener (listener);
        }
        if ( newRootNode != null ) {
            newRootNode.setNodeViewType (this.getNodeViewType());
            newRootNode.addPropertyChangeListener (listener);
//             newRootNode.addNodeListener (listener);
        }

        firePropertyChange (PROP_ROOT_NODE, oldRootNode, newRootNode);
    }



    //
    // Sheet
    //

    /**
     */
    protected final void updateSheet () {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("--> AbstractDataNode.updateSheet"); // NOI18N
        
        setSheet (createSheet());
    }

    /** Create the property sheet.
     * Subclasses may want to override this and add additional properties.
     * @return the sheet
     */
    protected Sheet createSheet () {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("--> AbstractDataNode.createSheet"); // NOI18N
        
        Sheet sheet = super.createSheet();

        sheet.put (updatePropertiesSheetSet (sheet));
        sheet.put (createXMLSheetSet());
        Sheet.Set viewSet = createViewSheetSet();
        if ( viewSet != null ) {
            sheet.put (viewSet);
        }
        
        return sheet;
    }
    
    /** To a standard properties sheet set add short description. */
    private Sheet.Set updatePropertiesSheetSet (Sheet sheet) {
        Sheet.Set propSet = sheet.get (Sheet.PROPERTIES);
        if (propSet == null)
            propSet = sheet.createPropertiesSet();
            
        return propSet;
    }


    /** Creates new XML sheet set from TreeDocumentRoot properties. */
    protected Sheet.Set createXMLSheetSet () {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("--> AbstractDataNode.createXMLSheetSet"); // NOI18N
        
        Sheet.Set xmlSet = new Sheet.Set ();
        xmlSet.setName ("__NAME__");

        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            Node.PropertySet[] propertySets = rootNode.getPropertySets();
            for (int i = 0; i < propertySets.length; i++) {
                if (Sheet.PROPERTIES.equals (propertySets[i].getName())) {
                    xmlSet.put (propertySets[i].getProperties());
                    break;
                }
            }
        } else {
            int status = ((TreeEditorCookie)getXMLDataObjectLook().getCookie (TreeEditorCookie.class)).getStatus();
            switch (status) {
            case TreeEditorCookie.STATUS_NOT: // not parsed yet
                xmlSet.put (new PropertySupport.ReadOnly
                    (XML_STATUS,
                     String.class,
                     Util.THIS.getString ("PROP_xmlStatus"),
                     Util.THIS.getString ("HINT_xmlStatus")) {
                        public Object getValue() {
                            return Util.THIS.getString ("MSG_not_parsed_yet");
                        }
                    });
                break;
            case TreeEditorCookie.STATUS_ERROR:
                xmlSet.put (new PropertySupport.ReadOnly 
                    (XML_STATUS,
                     String.class,
                     Util.THIS.getString ("PROP_xmlStatus"),
                     Util.THIS.getString ("HINT_xmlStatus")) {
                        public Object getValue () {
                            return Util.THIS.getString ("MSG_parsing_error");
                        }
                    });
                break;
            }
        }
        
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("<--                 .createXMLSheetSet: return = " + xmlSet); // NOI18N
        
        return xmlSet;
    }

    /**
     */
    protected Sheet.Set createViewSheetSet () {
        Sheet.Set viewSet = null;

        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            viewSet = rootNode.getViewSheetSet();
        }

        return viewSet;
    }

    
    //
    // Customizer
    //

    /**
     */
    public final boolean hasCustomizer () {
        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            return rootNode.hasCustomizer();
        }

        return false;
    }

    /**
     */
    public final Component getCustomizer () {
        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            return rootNode.getCustomizer();
        }

        return null;
    }


    //
    // from NodeViewType.Provider
    //

    /**
     */
    public NodeViewType getNodeViewType () {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::getNodeViewType: this = " + this); // NOI18N
        if ( nodeViewType != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::getNodeViewType: nodeViewType.name = " + nodeViewType.getName()); // NOI18N
        }
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::getNodeViewType: nodeViewType = " + nodeViewType); // NOI18N

//          if ( (nodeViewType != null) &&
//               NodeViewType.isValid (nodeViewType) ) {
        if ( nodeViewType != null ) {
            return nodeViewType;
        }

        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::getNodeViewType: use DEFAULT value!"); // NOI18N

        return TreeEditSettings.getDefault().getDefaultNodeViewType();
    }
    
    /**
     */
    public final void setNodeViewType (NodeViewType nodeViewType) {
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::setNodeViewType: this = " + this); // NOI18N
        if ( nodeViewType != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::setNodeViewType: NEW nodeViewType.name = " + nodeViewType.getName()); // NOI18N
        }
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::setNodeViewType: NEW nodeViewType = " + nodeViewType); // NOI18N

        if (this.nodeViewType == nodeViewType)
            return;

        NodeViewType oldNodeViewType = this.nodeViewType;
        this.nodeViewType = nodeViewType;

        if ( oldNodeViewType != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::setNodeViewType: OLD nodeViewType.name = " + oldNodeViewType.getName()); // NOI18N
        }
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::setNodeViewType: OLD nodeViewType = " + oldNodeViewType); // NOI18N

        saveNodeViewType();

        firePropertyChange (PROP_NODE_VIEW_TYPE, oldNodeViewType, this.nodeViewType);
    }

    /**
     */
    private void updateNodeViewType () {
        AbstractRootNode rootNode = getRootNode();

        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::updateNodeViewType: this = " + this); // NOI18N
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::updateNodeViewType: rootNode = " + rootNode); // NOI18N

        if ( rootNode != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::updateNodeViewType: rawNodeViewType = " + rootNode.getRawNodeViewType()); // NOI18N

            setNodeViewType (rootNode.getRawNodeViewType());
        }        
    }

    /**
     */
    private void initNodeViewType () {
        Object value = getDataObject().getPrimaryFile().getAttribute (NODE_VIEW_TYPE_ATTRIBUTE);

        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::initNodeViewType: this = " + this); // NOI18N
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::initNodeViewType: value = " + value); // NOI18N

        if ( value instanceof ServiceType.Handle ) {
            nodeViewType = (NodeViewType)((ServiceType.Handle)value).getServiceType();
        } else {
            nodeViewType = NodeViewType.getValid ((NodeViewType)value);
        }

        if ( nodeViewType != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::initNodeViewType: NEW nodeViewType.name = " + nodeViewType.getName()); // NOI18N
        }
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("                ::initNodeViewType: NEW nodeViewType = " + nodeViewType); // NOI18N
    }

    /**
     */
    private void saveNodeViewType () {
        if ( this.nodeViewType != null ) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::saveNodeViewType: nodeViewType.name = " + this.nodeViewType.getName()); // NOI18N
        }
        if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::saveNodeViewType: nodeViewType = " + this.nodeViewType); // NOI18N

        try {
            Object value = null;
            if ( this.nodeViewType != null ) {
                value = new ServiceType.Handle (this.nodeViewType);
            }
            getDataObject().getPrimaryFile().setAttribute (NODE_VIEW_TYPE_ATTRIBUTE, value);
        } catch (IOException ioe) {
            // ... will not be persistent!
            ErrorManager.getDefault().notify (ErrorManager.INFORMATIONAL, ioe);
        }        
    }


    //
    // NewTypes
    //


    /** Support for new types that can be created in this node.
     * @return array of new type operations that are allowed
     */
    public final NewType[] getNewTypes () {
        AbstractRootNode rootNode = getRootNode();
        if ( rootNode == null ) {
            return new NewType[0];
        }

        return rootNode.getNewTypes();
    }
    
    //
    // clipboard
    //

    /**
     */
    protected void createPasteTypes (Transferable t, List s) {
        AbstractRootNode rootNode = getRootNode();
        if ( rootNode != null ) {
            rootNode.createPasteTypes (t, s);
        }
    }


    //
    // class InnerListener
    //

    /**
     * class InnerListener listen on
     */
    private class InnerListener implements /*NodeListener,*/ PropertyChangeListener {

        /** */
        public void propertyChange (PropertyChangeEvent pche) {
            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("AbstractDataNode::InnerListener::propertyChange: propertyName = '" + pche.getPropertyName() + "'"); // NOI18N

            if (TreeEditorCookie.PROP_STATUS.equals (pche.getPropertyName())) {
//                  || DataObject.PROP_COOKIE.equals (pche.getPropertyName()) ) {
                AbstractDataNode.this.updateNode();
            } else if ( NodeViewType.Provider.PROP_NODE_VIEW_TYPE.equals (pche.getPropertyName()) ) {
                AbstractDataNode.this.updateNodeViewType();
            } else if (TreeDocument.PROP_ENCODING.equals (pche.getPropertyName())
		       || TreeDocument.PROP_VERSION.equals (pche.getPropertyName())
		       || TreeDocument.PROP_STANDALONE.equals (pche.getPropertyName())) {
                AbstractDataNode.this.updateSheet();
            }
        }

        /** Does nothing.
         * @param ev event describing the action
         */
        public void childrenAdded (NodeMemberEvent ev) {
        }

        /** Does nothing.
         * @param ev event describing the action
         */
        public void childrenRemoved (NodeMemberEvent ev) {
        }

        /** Does nothing.
         * @param ev event describing the action
         */
        public void childrenReordered (NodeReorderEvent ev) {
        }

        /* Does nothing.
         * @param ev event describing the node
         */
        public final void nodeDestroyed (NodeEvent ev) {
//             AbstractDataNode.this.originalDestroyed(); //!!!
        }
            
    } // class InnerListener

}
... 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.