001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.ant.freeform.ui;
043:
044: import java.beans.PropertyChangeEvent;
045: import java.io.File;
046: import java.util.HashSet;
047: import java.util.Set;
048: import java.util.SortedSet;
049: import java.util.TreeSet;
050: import org.netbeans.api.project.Project;
051: import org.netbeans.api.project.ProjectManager;
052: import org.netbeans.junit.NbTestCase;
053: import org.netbeans.modules.ant.freeform.FreeformProjectGenerator;
054: import org.netbeans.modules.ant.freeform.FreeformProjectType;
055: import org.netbeans.modules.ant.freeform.TestBase;
056: import org.netbeans.modules.ant.freeform.spi.support.Util;
057: import org.netbeans.spi.project.support.ant.AntProjectHelper;
058: import org.netbeans.spi.project.support.ant.EditableProperties;
059: import org.netbeans.spi.project.ui.LogicalViewProvider;
060: import org.openide.filesystems.FileObject;
061: import org.openide.filesystems.FileUtil;
062: import org.openide.loaders.DataObject;
063: import org.openide.modules.ModuleInfo;
064: import org.openide.nodes.Children;
065: import org.openide.nodes.Node;
066: import org.openide.nodes.NodeEvent;
067: import org.openide.nodes.NodeListener;
068: import org.openide.nodes.NodeMemberEvent;
069: import org.openide.nodes.NodeReorderEvent;
070: import org.w3c.dom.Document;
071: import org.openide.util.Lookup;
072: import org.w3c.dom.Element;
073: import org.w3c.dom.NodeList;
074:
075: // XXX testRootNodeDisplayNameChange
076:
077: /**
078: * Test {@link View}: changes in children etc.
079: * @author Jesse Glick
080: */
081: public class ViewTest extends TestBase {
082:
083: public ViewTest(String name) {
084: super (name);
085: }
086:
087: private LogicalViewProvider lvp;
088:
089: protected void setUp() throws Exception {
090: super .setUp();
091: ModuleInfo info = Lookup.getDefault().lookup(ModuleInfo.class);
092: lvp = extsrcroot.getLookup().lookup(LogicalViewProvider.class);
093: assertNotNull("found a LogicalViewProvider", lvp);
094: }
095:
096: public void testViewItemBasic() throws Exception {
097: Node root = lvp.createLogicalView();
098: assertEquals("lookup has project", extsrcroot, root.getLookup()
099: .lookup(Project.class));
100: Children ch = root.getChildren();
101: Node[] kids = ch.getNodes(true);
102: assertEquals("two child nodes", 2, kids.length);
103: // Do not check anything about #1, since it is provided by java/freeform.
104: assertEquals("correct code name #2", "nbproject/project.xml",
105: kids[1].getName());
106: assertEquals("correct display name #2", "project.xml", kids[1]
107: .getDisplayName());
108: assertEquals(
109: "correct cookie #2",
110: DataObject
111: .find(egdirFO
112: .getFileObject("extsrcroot/proj/nbproject/project.xml")),
113: kids[1].getLookup().lookup(DataObject.class));
114: }
115:
116: public void testViewItemChanges() throws Exception {
117: Node root = lvp.createLogicalView();
118: Children ch = root.getChildren();
119: Node[] kids = ch.getNodes(true);
120: assertEquals("two child nodes", 2, kids.length);
121: assertEquals("correct code name #1", "../src", kids[0]
122: .getName());
123: assertEquals("correct code name #2", "nbproject/project.xml",
124: kids[1].getName());
125: TestNL l = new TestNL();
126: root.addNodeListener(l);
127: Element data = extsrcroot.getPrimaryConfigurationData();
128: Element view = Util.findElement(data, "view",
129: FreeformProjectType.NS_GENERAL);
130: assertNotNull("have <view>", view);
131: Element items = Util.findElement(view, "items",
132: FreeformProjectType.NS_GENERAL);
133: assertNotNull("have <items>", items);
134: Element sourceFolder = Util.findElement(items, "source-folder",
135: FreeformProjectType.NS_GENERAL);
136: assertNotNull("have <source-folder>", sourceFolder);
137: Element location = Util.findElement(sourceFolder, "location",
138: FreeformProjectType.NS_GENERAL);
139: assertNotNull("have <location>", location);
140: NodeList nl = location.getChildNodes();
141: assertEquals("one child", 1, nl.getLength());
142: location.removeChild(nl.item(0));
143: location.appendChild(location.getOwnerDocument()
144: .createTextNode("../src2"));
145: Element sourceFile = Util.findElement(items, "source-file",
146: FreeformProjectType.NS_GENERAL);
147: assertNotNull("have <source-file>", sourceFile);
148: items.removeChild(sourceFile);
149: extsrcroot.putPrimaryConfigurationData(data);
150: // children keys are updated asynchronously. give them a time
151: Thread.sleep(500);
152: assertFalse("got some changes in children", l.probeChanges()
153: .isEmpty());
154: kids = ch.getNodes(true);
155: assertEquals("one child node", 1, kids.length);
156: assertEquals("correct code name #1", "../src2", kids[0]
157: .getName());
158: assertEquals("correct display name #1", "External Sources",
159: kids[0].getDisplayName());
160: assertEquals("correct cookie #1", DataObject.find(egdirFO
161: .getFileObject("extsrcroot/src2")), kids[0].getLookup()
162: .lookup(DataObject.class));
163: }
164:
165: public void testFindPath() throws Exception {
166: // Do not test packages style - provided only by java/freeform.
167: LogicalViewProvider lvp2 = simple.getLookup().lookup(
168: LogicalViewProvider.class);
169: assertNotNull(lvp2);
170: Node root = lvp2.createLogicalView();
171: doTestFindPathPositive(lvp2, root, simple, "xdocs/foo.xml");
172: doTestFindPathPositive(lvp2, root, simple, "xdocs");
173: doTestFindPathPositive(lvp2, root, simple, "build.properties");
174: doTestFindPathPositive(lvp2, root, simple, "build.xml");
175: doTestFindPathNegative(lvp2, root, simple,
176: "nbproject/project.xml");
177: doTestFindPathNegative(lvp2, root, simple, "nbproject");
178: }
179:
180: public static void doTestFindPathPositive(LogicalViewProvider lvp,
181: Node root, Project project, String path) throws Exception {
182: FileObject file = project.getProjectDirectory().getFileObject(
183: path);
184: assertNotNull("found " + path, file);
185: DataObject d = DataObject.find(file);
186: Node nDO = lvp.findPath(root, d);
187: Node nFO = lvp.findPath(root, file);
188: assertNotNull("found node for " + path, nDO);
189: assertNotNull("found node for " + path, nFO);
190: assertEquals("correct node", d, nDO.getLookup().lookup(
191: DataObject.class));
192: //not exactly fullfilling the contract:
193: assertEquals("correct node", d, nFO.getLookup().lookup(
194: DataObject.class));
195: }
196:
197: public static void doTestFindPathNegative(LogicalViewProvider lvp,
198: Node root, Project project, String path) throws Exception {
199: FileObject file = project.getProjectDirectory().getFileObject(
200: path);
201: assertNotNull("found " + path, file);
202: DataObject d = DataObject.find(file);
203: Node n = lvp.findPath(root, d);
204: assertNull("did not find node for " + path, n);
205: }
206:
207: public static void doTestIncludesExcludes(NbTestCase test,
208: String style, String appearanceEverything,
209: String appearanceIncludesExcludes,
210: String appearanceExcludes, String appearanceFloating)
211: throws Exception {
212: FolderNodeFactory.synchronous = true;
213: test.clearWorkDir();
214: File d = test.getWorkDir();
215: AntProjectHelper helper = FreeformProjectGenerator
216: .createProject(d, d, "prj", null);
217: Project p = ProjectManager.getDefault().findProject(
218: helper.getProjectDirectory());
219: FileUtil.createData(new File(d, "s/relevant/included/file"));
220: FileUtil.createData(new File(d, "s/relevant/excluded/file"));
221: FileUtil.createData(new File(d, "s/ignored/file"));
222: Element data = Util.getPrimaryConfigurationData(helper);
223: Document doc = data.getOwnerDocument();
224: Element items = (Element) data.getElementsByTagName("items")
225: .item(0);
226: items.removeChild(items.getElementsByTagName("source-file")
227: .item(0)); // build.xml
228: Element sf = (Element) items.appendChild(doc.createElementNS(
229: Util.NAMESPACE, "source-folder"));
230: sf.setAttribute("style", style);
231: sf.appendChild(doc.createElementNS(Util.NAMESPACE, "location"))
232: .appendChild(doc.createTextNode("s"));
233: Util.putPrimaryConfigurationData(helper, data);
234: ProjectManager.getDefault().saveProject(p);
235: Node r = p.getLookup().lookup(LogicalViewProvider.class)
236: .createLogicalView();
237: assertEquals(appearanceEverything, expand(r));
238: // Now configure includes and excludes.
239: EditableProperties ep = new EditableProperties();
240: ep.put("includes", "relevant/");
241: ep.put("excludes", "**/excluded/");
242: helper.putProperties("config.properties", ep);
243: data = Util.getPrimaryConfigurationData(helper);
244: doc = data.getOwnerDocument();
245: data.getElementsByTagName("properties").item(0).appendChild(
246: doc.createElementNS(Util.NAMESPACE, "property-file"))
247: .appendChild(doc.createTextNode("config.properties"));
248: Util.putPrimaryConfigurationData(helper, data);
249: ProjectManager.getDefault().saveProject(p);
250: data = Util.getPrimaryConfigurationData(helper);
251: doc = data.getOwnerDocument();
252: sf = (Element) data.getElementsByTagName("source-folder").item(
253: 0);
254: sf.appendChild(doc.createElementNS(Util.NAMESPACE, "includes"))
255: .appendChild(doc.createTextNode("${includes}"));
256: sf.appendChild(doc.createElementNS(Util.NAMESPACE, "excludes"))
257: .appendChild(doc.createTextNode("${excludes}"));
258: Util.putPrimaryConfigurationData(helper, data);
259: ProjectManager.getDefault().saveProject(p);
260: assertEquals(appearanceIncludesExcludes, expand(r));
261: // Now change them.
262: ep = helper.getProperties("config.properties");
263: ep.remove("includes");
264: helper.putProperties("config.properties", ep);
265: ProjectManager.getDefault().saveProject(p);
266: assertEquals(appearanceExcludes, expand(r));
267: // Also check floating includes.
268: ep = helper.getProperties("config.properties");
269: ep.put("includes", "relevant/included/");
270: helper.putProperties("config.properties", ep);
271: ProjectManager.getDefault().saveProject(p);
272: assertEquals(appearanceFloating, expand(r));
273: }
274:
275: public void testIncludesExcludes() throws Exception {
276: doTestIncludesExcludes(
277: this ,
278: "tree",
279: "prj{s{ignored{file} relevant{excluded{file} included{file}}}}",
280: "prj{s{relevant{included{file}}}}",
281: "prj{s{ignored{file} relevant{included{file}}}}",
282: "prj{s{relevant{included{file}}}}");
283: }
284:
285: private static String expand(Node n) {
286: Node[] kids = n.getChildren().getNodes(true);
287: String nm = n.getDisplayName();
288: if (kids.length == 0) {
289: return nm;
290: } else {
291: SortedSet<String> under = new TreeSet<String>();
292: for (Node kid : kids) {
293: under.add(expand(kid));
294: }
295: StringBuilder b = new StringBuilder(nm).append('{');
296: boolean first = true;
297: for (String s : under) {
298: if (first) {
299: first = false;
300: } else {
301: b.append(' ');
302: }
303: b.append(s);
304: }
305: return b.append('}').toString();
306: }
307: }
308:
309: private static final class TestNL implements NodeListener {
310: private final Set<String> changes = new HashSet<String>();
311:
312: public TestNL() {
313: }
314:
315: public synchronized void childrenRemoved(NodeMemberEvent ev) {
316: changes.add("childrenRemoved");
317: }
318:
319: public synchronized void childrenAdded(NodeMemberEvent ev) {
320: changes.add("childrenAdded");
321: }
322:
323: public synchronized void childrenReordered(NodeReorderEvent ev) {
324: changes.add("childrenReordered");
325: }
326:
327: public synchronized void nodeDestroyed(NodeEvent ev) {
328: changes.add("nodeDestroyed");
329: }
330:
331: public synchronized void propertyChange(
332: PropertyChangeEvent propertyChangeEvent) {
333: changes.add(propertyChangeEvent.getPropertyName());
334: }
335:
336: /** Get a set of all change event names since the last call. Clears set too. */
337: public synchronized Set<String> probeChanges() {
338: Set<String> _changes = new HashSet<String>(changes);
339: changes.clear();
340: return _changes;
341: }
342: }
343:
344: }
|