This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 72441
Collapse All | Expand All

(-)apichanges.xml (+19 lines)
Lines 81-86 Link Here
81
    <!-- ACTUAL CHANGES BEGIN HERE: -->
81
    <!-- ACTUAL CHANGES BEGIN HERE: -->
82
82
83
    <changes>
83
    <changes>
84
        <change id="NodeFactory">
85
            <api name="general"/>
86
            <summary>Ability to construct project node's children from multiple sources.</summary>
87
            <version major="1" minor="17"/>
88
            <date day="24" month="8" year="2006"/>
89
            <author login="mkleint"/>
90
            <compatibility addition="yes" binary="compatible" deletion="no" deprecation="no" modification="no" semantic="compatible" source="compatible">
91
            </compatibility>
92
            <description>
93
                Added way to declaratively layout the subnodes of the project node, allowing 3rd party contributions 
94
                to project's Logical/Projects View.
95
                The project's node is constructed based on layer folder content. This api change provides just 
96
                the infrastructure, the actual extension point location is up to the project type implementations.
97
            </description>
98
            <class package="org.netbeans.spi.project.ui.support" name="NodeFactory"/>
99
            <class package="org.netbeans.spi.project.ui.support" name="NodeList"/>
100
            <class package="org.netbeans.spi.project.ui.support" name="NodeFactorySupport"/>
101
            <issue number="72441"/>
102
        </change>
84
103
85
        <change id="CompositeCategoryProvider">
104
        <change id="CompositeCategoryProvider">
86
            <api name="general"/>
105
            <api name="general"/>
(-)nbproject/project.properties (-1 / +1 lines)
Lines 15-21 Link Here
15
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
15
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
16
# Microsystems, Inc. All Rights Reserved.
16
# Microsystems, Inc. All Rights Reserved.
17
17
18
spec.version.base=1.16.0
18
spec.version.base=1.17.0
19
is.autoload=true
19
is.autoload=true
20
javadoc.arch=${basedir}/arch.xml
20
javadoc.arch=${basedir}/arch.xml
21
javadoc.apichanges=${basedir}/apichanges.xml
21
javadoc.apichanges=${basedir}/apichanges.xml
(-)src/org/netbeans/spi/project/ui/support/NodeFactory.java (+55 lines)
Added Link Here
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.netbeans.spi.project.ui.support;
21
22
import org.netbeans.api.project.Project;
23
import org.openide.nodes.Node;
24
25
/**
26
 * Factory interface for distributed creation of project node's children. Implementation
27
 * instances are assumed to be registered in layers at a location specific for the particular
28
 * project type. Project types wanting to make use of NodeFactory can use the 
29
 * {@link org.netbeans.spi.project.ui.support.NodeFactorySupport#createCompositeChildren}
30
 * method to create the Project nodes's children.
31
 * 
32
<pre>
33
public class FooBarLogicalViewProvider implements LogicalViewProvider {
34
    public Node createLogicalView() {
35
        return new FooBarRootNode(NodeFactorySupport.createCompositeChildren("Projects/org-foo-bar-project/Nodes");
36
    }
37
  
38
}
39
</pre>
40
 * @author RichUnger
41
 * @since org.netbeans.modules.projectuiapi 1.17
42
 */
43
public interface NodeFactory {
44
    
45
    /** 
46
     * Create a list of children nodes for the given project. If the list is to be static,
47
     * use the {@link org.netbeans.spi.project.ui.support.NodeFactorySupport#fixedNodeList}
48
     * @return never return null, if the project is not relevant to the NodeFactory,
49
     * use {@link org.netbeans.spi.project.ui.support.NodeFactorySupport#emptyNodeList} empty value.
50
     */ 
51
    NodeList createNodes(Project p);
52
    
53
//    Node findPath(Project p, Node root, Object target);
54
    
55
}
(-)src/org/netbeans/spi/project/ui/support/NodeFactorySupport.java (+215 lines)
Added Link Here
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.netbeans.spi.project.ui.support;
21
22
import java.io.IOException;
23
import java.util.ArrayList;
24
import java.util.Arrays;
25
import java.util.Collections;
26
import java.util.Enumeration;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Map;
31
import javax.swing.event.ChangeEvent;
32
import javax.swing.event.ChangeListener;
33
import org.netbeans.api.project.Project;
34
import org.openide.ErrorManager;
35
import org.openide.cookies.InstanceCookie;
36
import org.openide.filesystems.FileAttributeEvent;
37
import org.openide.filesystems.FileChangeListener;
38
import org.openide.filesystems.FileEvent;
39
import org.openide.filesystems.FileObject;
40
import org.openide.filesystems.FileRenameEvent;
41
import org.openide.filesystems.Repository;
42
import org.openide.loaders.DataFolder;
43
import org.openide.loaders.DataObject;
44
import org.openide.loaders.DataObjectNotFoundException;
45
import org.openide.loaders.FolderLookup;
46
import org.openide.loaders.InstanceDataObject;
47
import org.openide.nodes.Children;
48
import org.openide.nodes.Node;
49
import org.openide.util.Lookup;
50
import org.openide.util.LookupEvent;
51
import org.openide.util.LookupListener;
52
53
/**
54
 * Support class for creating Project node's children nodes from NodeFactory instances
55
 * in layers.
56
 * @author mkleint
57
 * @since org.netbeans.modules.projectuiapi 1.17
58
 */
59
public class NodeFactorySupport {
60
    
61
    /**
62
     * Creates a new instance of NodeFactorySupport
63
     */
64
    private NodeFactorySupport() {
65
    }
66
    
67
    /**
68
     * create Node' Children instance that works on top of NodeFactory instances
69
     * in the layers.
70
     */
71
    public static Children createCompositeChildren(Project project, String folderPath) {
72
        return new DelegateChildren(project, folderPath);
73
    }
74
    /**
75
     * Utility method for creating a non variable NodeList instance.
76
     */
77
    public static NodeList fixedNodeList(Node[] nodes) {
78
        return new FixedNodeList(nodes);
79
    }
80
    
81
    /**
82
     * Utility method to create empty NodeList instance. Useful in case when a particular project instance is not
83
     * relevant to the NodeFactory
84
     */
85
    public static NodeList emptyNodeList() {
86
        return new FixedNodeList(new Node[0]);
87
    }
88
    
89
    
90
    private static class FixedNodeList implements  NodeList {
91
        
92
        private List nodes;
93
        
94
        FixedNodeList(Node[] nds) {
95
            nodes = Arrays.asList(nds);
96
        }
97
        public List keys() {
98
            return nodes;
99
        }
100
        
101
        public void addChangeListener(ChangeListener l) { }
102
        
103
        public void removeChangeListener(ChangeListener l) { }
104
        
105
        public Node node(Object key) {
106
            return (Node)key;
107
        }
108
        
109
        public void addNotify() {
110
        }
111
        
112
        public void removeNotify() {
113
        }
114
    }
115
    
116
    static class DelegateChildren extends Children.Keys implements LookupListener, ChangeListener {
117
        
118
        private String folderPath;
119
        private Project project;
120
        private List nodeLists = new ArrayList();
121
        private List factories = new ArrayList();
122
        private Lookup.Result result;
123
        
124
        public DelegateChildren(Project proj, String path) {
125
            folderPath = path;
126
            project = proj;
127
        }
128
        
129
        // protected for tests..
130
        protected Lookup createLookup() {
131
            FileObject root = Repository.getDefault().getDefaultFileSystem().findResource(folderPath);
132
            DataFolder folder = DataFolder.findFolder(root);
133
            return new FolderLookup(folder).getLookup();
134
        }
135
        
136
        protected Node[] createNodes(Object key) {
137
            NodeList lst = (NodeList)key;
138
            Iterator it = lst.keys().iterator();
139
            List toRet = new ArrayList();
140
            while (it.hasNext()) {
141
                Object elem = it.next();
142
                Node nd = lst.node(elem);
143
                if (nd != null) {
144
                    toRet.add(nd);
145
                }
146
            }
147
            return (Node[])toRet.toArray(new Node[toRet.size()]);
148
        }
149
        
150
        protected void addNotify() {
151
            super.addNotify();
152
            result = createLookup().lookup(new Lookup.Template(NodeFactory.class));
153
            Iterator it = result.allInstances().iterator();
154
            while (it.hasNext()) {
155
                NodeFactory factory = (NodeFactory) it.next();
156
                NodeList lst = factory.createNodes(project);
157
                assert lst != null;
158
                nodeLists.add(lst);
159
                lst.addNotify();
160
                lst.addChangeListener(this);
161
                factories.add(factory);
162
            }
163
            result.addLookupListener(this);
164
            setKeys(nodeLists);
165
        }
166
        
167
        protected void removeNotify() {
168
            super.removeNotify();
169
            setKeys(Collections.EMPTY_LIST);
170
            Iterator it = nodeLists.iterator();
171
            while (it.hasNext()) {
172
                NodeList elem = (NodeList) it.next();
173
                elem.removeChangeListener(this);
174
                elem.removeNotify();
175
            }
176
            nodeLists.clear();
177
            factories.clear();
178
            if (result != null) {
179
                result.removeLookupListener(this);
180
                result = null;
181
            }
182
        }
183
        
184
        public void stateChanged(ChangeEvent e) {
185
            refreshKey(e.getSource());
186
        }
187
188
        public void resultChanged(LookupEvent ev) {
189
            Iterator it = result.allInstances().iterator();
190
            int index = 0;
191
            while (it.hasNext()) {
192
                NodeFactory factory = (NodeFactory) it.next();
193
                if (!factories.contains(factory)) {
194
                    factories.add(index, factory);
195
                    NodeList lst = factory.createNodes(project);
196
                    assert lst != null;
197
                    nodeLists.add(index, lst);
198
                    lst.addNotify();
199
                    lst.addChangeListener(this);
200
                } else {
201
                    while (!factory.equals(factories.get(index))) {
202
                        factories.remove(index);
203
                        NodeList lst = (NodeList)nodeLists.remove(index);
204
                        lst.removeNotify();
205
                        lst.removeChangeListener(this);                            
206
                    }
207
                }
208
                index++;
209
            }
210
            setKeys(nodeLists);
211
        }
212
        
213
    }
214
    
215
}
(-)src/org/netbeans/spi/project/ui/support/NodeList.java (+62 lines)
Added Link Here
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.netbeans.spi.project.ui.support;
21
22
import java.util.List;
23
import javax.swing.event.ChangeListener;
24
import org.openide.nodes.Node;
25
26
/**
27
 * A <code>Children.Keys</code>-like abstration for use in 
28
 * {@link org.netbeans.spi.project.ui.support.NodeFactory}
29
 * instances. For utility methods of creating a <code>NodeList</code> instance, see
30
 * {@link org.netbeans.spi.project.ui.support.NodeFactorySupport}
31
32
 * @author mkleint
33
 * @since org.netbeans.modules.projectuiapi 1.17
34
 */
35
public interface NodeList {
36
    /**
37
     * child keys for which we later create a  {@link org.openide.nodes.Node}
38
     * in the node() method. If the change set of keys changes based on external
39
     *  events, fire a <code>ChangeEvent</code> to notify the parent Node.
40
     */
41
    List keys();
42
    /**
43
     * add a change listener, primarily to be used by the infrastructure
44
     */
45
    void addChangeListener(ChangeListener l); // change in keys()
46
    /**
47
     * remove a change listener, primarily to be used by the infrastructure
48
     */
49
    void removeChangeListener(ChangeListener l);
50
    /**
51
     * create Node for a given key, equal in semantics to <code>Children.Keys.createNode()</code>
52
     */
53
    Node node(Object key);
54
    /**
55
     * callback from Children instance of the parent node, equal in semantics to <code>Children.addNotify()</code>
56
     */
57
    void addNotify();
58
    /**
59
     * callback from Children instance of the parent node, equal in semantics to <code>Children.removeNotify()</code>
60
     */
61
    void removeNotify();
62
}
(-)test/unit/src/org/netbeans/spi/project/ui/support/NodeFactorySupportTest.java (+146 lines)
Added Link Here
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.netbeans.spi.project.ui.support;
21
22
import com.sun.org.apache.bcel.internal.generic.LOOKUPSWITCH;
23
import junit.framework.TestCase;
24
import junit.framework.*;
25
import java.io.IOException;
26
import java.util.ArrayList;
27
import java.util.Arrays;
28
import java.util.Collections;
29
import java.util.Enumeration;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import javax.swing.event.ChangeEvent;
35
import javax.swing.event.ChangeListener;
36
import org.netbeans.api.project.Project;
37
import org.netbeans.junit.MockServices;
38
import org.openide.ErrorManager;
39
import org.openide.cookies.InstanceCookie;
40
import org.openide.filesystems.FileAttributeEvent;
41
import org.openide.filesystems.FileChangeListener;
42
import org.openide.filesystems.FileEvent;
43
import org.openide.filesystems.FileObject;
44
import org.openide.filesystems.FileRenameEvent;
45
import org.openide.filesystems.Repository;
46
import org.openide.loaders.DataFolder;
47
import org.openide.loaders.DataObject;
48
import org.openide.loaders.DataObjectNotFoundException;
49
import org.openide.loaders.FolderLookup;
50
import org.openide.loaders.InstanceDataObject;
51
import org.openide.nodes.AbstractNode;
52
import org.openide.nodes.Children;
53
import org.openide.nodes.Node;
54
import org.openide.util.Lookup;
55
import org.openide.util.LookupEvent;
56
import org.openide.util.LookupListener;
57
import org.openide.util.lookup.AbstractLookup;
58
import org.openide.util.lookup.InstanceContent;
59
60
/**
61
 *
62
 * @author mkleint
63
 */
64
public class NodeFactorySupportTest extends TestCase {
65
    
66
    public NodeFactorySupportTest(String testName) {
67
        super(testName);
68
    }
69
70
    protected void setUp() throws Exception {
71
    }
72
73
    protected void tearDown() throws Exception {
74
    }
75
76
    /**
77
     * Test of createCompositeChildren method, of class org.netbeans.spi.project.ui.support.NodeFactorySupport.
78
     */
79
    public void testCreateCompositeChildren() {
80
        System.out.println("createCompositeChildren");
81
        InstanceContent ic = new InstanceContent();
82
        TestDelegates dels = new TestDelegates(ic);
83
        Node node1 = new AbstractNode(Children.LEAF);
84
        Node node2 = new AbstractNode(Children.LEAF);
85
        Node node3 = new AbstractNode(Children.LEAF);
86
        Node node4 = new AbstractNode(Children.LEAF);
87
        node1.setName("node1");
88
        node2.setName("node2");
89
        node3.setName("node3");
90
        node4.setName("node4");
91
        NodeFactory fact1 = new TestNodeFactory(node1);
92
        NodeFactory fact2 = new TestNodeFactory(node2);
93
        NodeFactory fact3 = new TestNodeFactory(node3);
94
        NodeFactory fact4 = new TestNodeFactory(node4);
95
        List col = new ArrayList();
96
        col.add(fact1);
97
        col.add(fact2);
98
        ic.set(col, null);
99
        
100
        Node[] nds = dels.getNodes();
101
        assertEquals(nds[0], node1);
102
        assertEquals(nds[1], node2);
103
        
104
        col.add(0, fact4);
105
        col.add(fact3);
106
        col.remove(fact2);
107
        ic.set(col, null);
108
        nds = dels.getNodes();
109
        assertEquals(nds[0], node4);
110
        assertEquals(nds[1], node1);
111
        assertEquals(nds[2], node3);
112
        
113
    }
114
115
   private class TestNodeFactory implements NodeFactory {
116
       
117
       Node node;
118
       public TestNodeFactory(Node node) {
119
           this.node = node;
120
       }
121
        public NodeList createNodes(Project p) {
122
            return NodeFactorySupport.fixedNodeList(new Node[] {node});
123
        }
124
   }
125
   
126
   private class TestDelegates extends NodeFactorySupport.DelegateChildren  {
127
       public AbstractLookup.Content content;
128
       TestDelegates(AbstractLookup.Content cont) {
129
           super(null, null);
130
           content = cont;
131
       }
132
       
133
       protected Lookup createLookup() {
134
           return new AbstractLookup(content);
135
       }
136
       
137
       public void addNotify() {
138
           super.addNotify();
139
       }
140
       
141
       public void removeNotify() {
142
           super.removeNotify();
143
       }
144
   }
145
    
146
}

Return to bug 72441