⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smarttree.java

📁 JAVA开源LDAP浏览器jxplorer的源码!
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     *
     * @param s the source of data for initialising SmartNodes etc.
     */

    public void registerDataSource(DataSource s)
    {
        if (s == null) return;    // sanity check

        log.fine("registering data source for tree " + getName());
        treeDataSource = s;

        // Register ourselves as interested in *all* data events that pass through this data source...
        treeDataSource.addDataListener(this);

        //setRoot(rootDN);
    }

    /**
     * Returns the active data source that has been registered for the tree.
     *
     * @return the data source used by the tree.
     */

    public DataSource getDataSource()
    {
        return treeDataSource;
    }

    /**
     * Register a <code>DataSink</code>.
     * DataSinks are entities that are interested in
     * displaying the data corresponding to a particular
     * SmartNode (that is, the attributes of the node).  There
     * may be a number of such sinks in operation simultaneously.
     * This registration method adds a new data sink to the list
     * of active data sinks.
     *
     * @param s a new data sink to add to the list of active sinks.
     */

    public void registerDataSink(DataSink s)
    {
        treeDataSinks.addElement(s);
        if (s instanceof AttributeDisplay)
            registerPluggableEditorSource((AttributeDisplay) s);
    }

    /**
     * Quick Hack to clear out a tree preparitory to loading a new
     * one.  May need revisiting to do a neater data clean up.
     */
    public void clearTree()
    {
        root.removeAllChildren();
        setRoot(NODATA);
        treeModel.setRoot(root);
        treeModel.reload();
        clearEntry();
        for (int i = 0; i < treeDataSinks.size(); i++)
            ((DataSink) treeDataSinks.elementAt(i)).displayEntry(null, null);
    }


    /**
     * Takes a node, and adds a bunch of children.
     *
     * @param parent   the node to add the children too
     * @param children an enumeration of NameClassPair containing
     *                 the names of the child nodes
     */

    public void addCutting(SmartNode parent, NamingEnumeration children)
    {
        // sanity checks
        if (parent == null)
        {
            return;
        }
        if (children == null)
        {
            log.warning("null child list in addCutting...!");
            return;
        }

        if (children != null)
        {
            // Step 1: Clear any dummy nodes prior to adding real ones.
            if (parent.getChildCount() == 1 && ((SmartNode) parent.getChildAt(0)).isDummy())
            {
                parent.removeAllChildren();
            }
            // Step 2: Add new children (nb - there may be *zero* children to add, in which case parent is actually a leaf node
            while (children.hasMoreElements())
            {
                NameClassPair np = (NameClassPair) children.nextElement();

                SmartNode child;

                // &(*%& pointless bloody jndi; the one time it would be useful for them
                // to use 'Name' objects they use strings; in 'NameClassPair' no less. What a joke.

                DN temp = new DN(np.getName());
                child = new SmartNode(temp.getRDN(temp.size() - 1));

                if (parent.hasChild(child.toString()) == false)  // don't add a child twice!
                {
                    parent.add(child);
                    //treeModel.insertNodeInto(child, parent, parent.getChildCount());

                    // Step 3:  try to recover the object class list for the node to use.

                    if (np instanceof SearchResult)
                    {
                        doObjectClassSpecificHandling(child, ((SearchResult) np));
                    }

                }

                //XXX is it more efficient to work on nodes, then call nodeStructureChanged?
                //XXX i.e. parent.add(child);

                if (child.getAllowsChildren())
                //    treeModel.insertNodeInto(new SmartNode(), child, 0);
                    child.add(new SmartNode());

                //parent.add(child);
            }

            parent.sort();

            treeModel.nodeStructureChanged(parent);
        }
    }

    public void registerPluggableEditorSource(AttributeDisplay display)
    {
        pluggableEditorSource = display;
    }

    /**
     * HERE BE MAGIC
     * <p/>
     * In order for pluggable editors to truncate trees, special displays for aliases,
     * object class based icons, and object class based popup menus, we need special
     * handling for nodes where the object class is known.<p><
     * <p/>
     * This registers the object class with a node, and checks to see if any pluggable
     * editors are known corresponding to these object classes that are unique, and
     * have special requests (for icons/popup menus/etc.)<p>
     * <p/>
     * This is all optional stuff - the browser will work fine if these details are
     * not available, but more complex pluggable functionality will not be possible.
     *
     * @param child the smart node to register the object classes with
     * @param ocs   a search result containing the object class attribute (we hope).
     */

    protected void doObjectClassSpecificHandling(SmartNode child, SearchResult ocs)
    {
        if (ocs == null) return;                        // can't do anything.
        Attributes atts = ocs.getAttributes();

        if (atts == null || atts.size() == 0) return;   // still can't do anything.

        Attribute OC;

        try  // the usual fuss and bother to retrieve the object class attribute.  X500 does this so much better...
        {
            OC = atts.get("objectClass");
            if (OC == null)
                OC = atts.get("objectclass");

            if (OC == null) // there *may* only be one attribute, which *may* be a wierd capitalisation of object class...
            {
                Attribute test = (Attribute) atts.getAll().next();
                if ("objectclass".equals(test.getID().toLowerCase()))
                    OC = test;
            }

            if (OC == null)   // give up!  It doesn't have one.
                return;

            if ((OC instanceof DXAttribute) == false)
                OC = new DXAttribute(OC);
            OC = DXAttributes.getAllObjectClasses((DXAttribute) OC); // order it...

            doObjectClassSpecificHandling(child, OC);
        }
        catch (Exception e)
        {
            log.warning("Warning error doing object class specific handling for tree nodes: " + e);
        }
    }


    /**
     * HERE BE MAGIC
     * <p/>
     * In order for pluggable editors to truncate trees, special displays for aliases,
     * object class based icons, and object class based popup menus, we need special
     * handling for nodes where the object class is known.<p><
     * <p/>
     * This registers the object class with a node, and checks to see if any pluggable
     * editors are known corresponding to these object classes that are unique, and
     * have special requests (for icons/popup menus/etc.)<p>
     * <p/>
     * This is all optional stuff - the browser will work fine if these details are
     * not available, but more complex pluggable functionality will not be possible.
     *
     * @param child the smart node to register the object classes with
     * @param OC    objectclass attribute
     */
    protected void doObjectClassSpecificHandling(SmartNode child, Attribute OC)
    {
        if (OC instanceof DXAttribute == false)
            OC = new DXAttribute(OC);
        child.setTrueObjectClass((DXAttribute) OC);                   // and register it with smartnode

        // *** TRICKYNESS ***

        //
        // The code below looks for, and interogates, any pluggable editors
        // that are related to the node in order to determine any special
        // handling requirements such as custom popup menus, icons, or
        // subtree truncations.

        if (pluggableEditorSource != null)
        {
            PluggableEditor editor = pluggableEditorSource.getUniqueEditor(OC);

            if (editor != null)
            {

                if (editor.hideSubEntries(child.toString()))
                    child.setAllowsChildren(false);

                ImageIcon newIcon = editor.getTreeIcon(child.toString());
                if (newIcon != null)
                    child.setIcon(newIcon);

                if (editor.getPopupMenu(child.toString()) != null)
                    child.setPopupMenu(editor.getPopupMenu(child.toString()));
            }
        }
    }


    /**
     * Takes an entry, usually from a search result list, and adds it to
     * the tree, creating parent nodes if necessary.
     *
     * @param newDN the new DN to create a smart Node for, and add to the tree.
     */

    public SmartNode addNode(DN newDN)
    {
        if (newDN == null) return null;

        SmartNode parent, child = null;

        if (rootDN.toString().equals(NODATA))
        {
            setRoot("");  // the same as 'cn=World'
        }

        // Walk through the current newDN, creating new nodes
        // as necessary until we can add a new node corresponding to
        // the lowest RDN of the newDN.

        parent = root;
        RDN rdn;

        for (int i = 0; i < newDN.size(); i++)
        {
            rdn = newDN.getRDN(i);
            Enumeration children = parent.children();

            child = null;
            while (children.hasMoreElements())
            {
                child = (SmartNode) children.nextElement();

                if (child.isDummy())                // strip any dummy nodes en passent
                    parent.remove(child);
                else if (child.rdnEquals(rdn))      // and check if the node already exists (before overwritting it below)
                    break;

                child = null;
            }

            if (child == null)               // if the node doesn't exist...
            {
                child = new SmartNode(rdn);  // ... create it
                if (i < newDN.size() - 1)
                {
                    child.setStructural(true);
                }
                parent.add(child);           // ... add it to the parent
                parent.sort();
                treeModel.nodeStructureChanged(parent);

                parent = child;
            }
            else
            {
                parent = child;              // reset parent pointer for next turn around
                if (i == newDN.size() - 1)
                    child.setStructural(false);
            }
        }
//		setSelectionPath(treeModel.getPathForDN(newDN));	//TE: make sure its selected.		
		
        return parent;
    }


    /**
     * Refresh the display of a given volatile dn or node.
     */

    public void refresh(DN dn)
    {
        if (dn != null)		//TE: make sure the dn is not null.
        {
            treeDataSource.getChildren(dn);
        }
    }


    /**
     * Forces a refresh of the Editor Pane.  Currently is used by the tab listener in
     * JXplorer for when the user changes tabs the correct entry display is updated
     * depending on the entry selected in the tree of the tab that is selected.
     * (see Bug 2243).
     * .
     */

    public void refreshEditorPane()
    {
        //TE: was...	if(entry!=null && treeDataSource!=null)
        pluggableEditorSource.refreshEditors(entry, treeDataSource);
    }


    /**
     * Gets the DN of the currently selected tree node (or the root Node,
     * if no node is selected).
     *
     * @return DN the distinguished name of the current SmartNode.
     */

    public DN getCurrentDN()
    {
        return (currentDN == null) ? rootDN : currentDN;
    }


    /**
     * Displays a null entry in the table editor and the html view.
     * Intended to be used if an entry has been deleted.
     */

    public void clearEntry()
    {
        setEntry(null);
        pluggableEditorSource.displayEntry(null, treeDataSource);
    }


    /**
     * removes everything except the root DN node(s), and
     * sets things up as they were in the beginning, the
     * point being to force the tree to reload from the
     * data source, which has changed independantly of the
     * tree...
     */

    public void collapse()
    {

        String dn = rootDN.toString();

        if (dn.equals(NODATA)) return;  // don't bother!

        try
        {
            NamingEnumeration en = treeDataSource.getChildren(rootDN).getEnumeration();

            if (en != null)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -