KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > text > AnnotationProviderTest


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
21 package org.openide.text;
22
23 import java.io.IOException JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Set JavaDoc;
27 import org.netbeans.junit.NbTestCase;
28 import org.openide.actions.CopyAction;
29 import org.openide.actions.CutAction;
30 import org.openide.actions.DeleteAction;
31 import org.openide.actions.FileSystemAction;
32 import org.openide.actions.OpenAction;
33 import org.openide.actions.PasteAction;
34 import org.openide.actions.PropertiesAction;
35 import org.openide.actions.RenameAction;
36 import org.openide.actions.SaveAsTemplateAction;
37 import org.openide.actions.ToolsAction;
38 import org.openide.cookies.CloseCookie;
39 import org.openide.cookies.EditCookie;
40 import org.openide.cookies.EditorCookie;
41 import org.openide.cookies.OpenCookie;
42 import org.openide.cookies.PrintCookie;
43 import org.openide.cookies.SaveCookie;
44 import org.openide.filesystems.FileLock;
45 import org.openide.filesystems.FileObject;
46 import org.openide.filesystems.FileStateInvalidException;
47 import org.openide.filesystems.FileSystem;
48 import org.openide.filesystems.Repository;
49 import org.openide.loaders.DataFolder;
50 import org.openide.loaders.DataNode;
51 import org.openide.loaders.DataObject;
52 import org.openide.loaders.DataObjectExistsException;
53 import org.openide.loaders.ExtensionList;
54 import org.openide.loaders.MultiDataObject;
55 import org.openide.loaders.MultiFileLoader;
56 import org.openide.loaders.UniFileLoader;
57 import org.openide.nodes.Children;
58 import org.openide.nodes.CookieSet;
59 import org.openide.nodes.Node;
60 import org.openide.util.HelpCtx;
61 import org.openide.util.Lookup;
62 import org.openide.util.LookupListener;
63 import org.openide.util.NbBundle;
64 import org.openide.util.actions.SystemAction;
65 import org.openide.windows.CloneableOpenSupport;
66
67 public class AnnotationProviderTest extends NbTestCase {
68     
69     public AnnotationProviderTest(String JavaDoc s) {
70         super(s);
71     }
72     
73     private FileSystem fs;
74     
75     protected void setUp() throws Exception JavaDoc {
76         System.setProperty("org.openide.util.Lookup", "org.openide.text.AnnotationProviderTest$Lkp");
77         
78         clearWorkDir ();
79         org.openide.filesystems.LocalFileSystem lfs = new org.openide.filesystems.LocalFileSystem ();
80         lfs.setRootDirectory (getWorkDir ());
81         fs = lfs;
82     }
83     
84     public void testAnnotationProviderIsCalledCorrectly() throws Exception JavaDoc {
85         Object JavaDoc o = Lookup.getDefault().lookup(AnnotationProvider.class);
86         if(o == null) {
87             fail("No annotation provider found");
88         }
89         
90         FileObject fo = fs.getRoot().createData("test", "txt");
91
92         DataObject data = DataObject.find(fo);
93         
94         EditorCookie ec = (EditorCookie)data.getCookie(EditorCookie.class);
95         
96         ConsistencyCheckProvider.called = 0;
97         ec.open();
98         
99         CloneableEditorSupport ces = (CloneableEditorSupport)ec;
100         
101         assertEquals("Provider called exactly once", 1, ConsistencyCheckProvider.called);
102         assertEquals("Consistent lookup content", data.getPrimaryFile(), ConsistencyCheckProvider.inLkp);
103
104         Line l1 = ces.getLineSet().getCurrent(0);
105         assertEquals("Exactly one annotation attached", 1, l1.getAnnotationCount());
106         
107         ec.close();
108         // XXX
109
Line l2 = ces.getLineSet().getCurrent(0);
110         assertEquals ("Lines are the same", l1, l2);
111         assertEquals("Exactly one annotation attached after close", 1, l2.getAnnotationCount());
112
113         ConsistencyCheckProvider.called = 0;
114         ec.open();
115         // XXX
116
assertEquals("Provider not called during reopen", 0, ConsistencyCheckProvider.called);
117         assertEquals("Exactly one annotation attached after reopen", 1, ces.getLineSet().getCurrent(0).getAnnotationCount());
118     }
119
120     public void testContextLookupIsConsistentAfterMove() throws Exception JavaDoc {
121         // Prepare the data object (to initialize the lookup)
122
FileObject fo = fs.getRoot().createData("test2", "txt");
123         DataObject data = DataObject.find(fo);
124         EditorCookie ec = (EditorCookie)data.getCookie(EditorCookie.class);
125
126         // now move it (the lookup should update itself)
127
FileObject fld = fs.getRoot().createFolder("folder1");
128         DataFolder df = DataFolder.findFolder(fld);
129         data.move(df);
130
131         // now open the editor (invoke AnnotationProviders)
132
// and check the lookup
133
ec.open();
134         assertEquals("Consistent lookup content", data.getPrimaryFile(), ConsistencyCheckProvider.inLkp);
135     }
136     
137     private void forceGC () {
138         for (int i = 0; i < 5; i++) {
139             System.gc ();
140         }
141     }
142     
143     public void testContextLookupFiresDuringMove() throws Exception JavaDoc {
144         // Prepare the data object (to initialize the lookup)
145
FileObject fo = fs.getRoot().createData("test3", "txt");
146         DataObject data = DataObject.find(fo);
147         EditorCookie ec = (EditorCookie)data.getCookie(EditorCookie.class);
148
149         // open the editor and check the lookup before move
150
ec.open();
151         assertEquals("Lookup content consistent before move", data.getPrimaryFile(), ConsistencyCheckProvider.inLkp);
152
153         forceGC ();
154         
155         // now move the file
156
ConsistencyCheckProvider.called = 0;
157         FileObject fld = fs.getRoot().createFolder("folder1");
158         DataFolder df = DataFolder.findFolder(fld);
159         data.move(df);
160
161         forceGC ();
162         
163         // check the result
164
assertEquals("Lookup fires one change during move", 1, ConsistencyCheckProvider.changes);
165         assertEquals("Lookup content consistent after move", data.getPrimaryFile(), ConsistencyCheckProvider.inLkp);
166     }
167     
168     public static class ConsistencyCheckProvider implements AnnotationProvider, LookupListener {
169         
170         private static Set JavaDoc myLines = new HashSet JavaDoc();
171         private static int called;
172         private static FileObject inLkp;
173         private Lookup.Result result;
174         private static int changes;
175         
176         public void annotate(org.openide.text.Line.Set set, org.openide.util.Lookup context) {
177             result = context.lookupResult(FileObject.class);
178             result.addLookupListener(this);
179             inLkp= (FileObject)result.allInstances().iterator().next();
180             called++;
181
182             Line act = set.getCurrent(0);
183             
184             myLines.add(act);
185             act.addAnnotation(new MyAnnotation());
186             
187         }
188         
189         public void resultChanged(org.openide.util.LookupEvent ev) {
190             changes++;
191             inLkp= (FileObject)result.allInstances().iterator().next();
192         }
193         
194     }
195
196     
197     // below is only irrelevant support stuff
198

199     private static class MyAnnotation extends Annotation {
200         
201         public String JavaDoc getAnnotationType() {
202             return "nowhere";
203         }
204         
205         public String JavaDoc getShortDescription() {
206             return "Test annotation";
207         }
208         
209     }
210     
211     protected boolean runInEQ() {
212         return true;
213     }
214     
215     //
216
// Code from text module
217
//
218

219
220     public static final class TXTDataLoader extends UniFileLoader {
221
222         /** Generated serial version UID. */
223         static final long serialVersionUID =-3658061894653334886L;
224
225         /** file attribute which forces a file to be considered a text file */
226         static final String JavaDoc ATTR_IS_TEXT_FILE = "org.netbeans.modules.text.IsTextFile"; // NOI18N
227

228
229         /** Creates new <code>TXTDataLoader</code>. */
230         public TXTDataLoader() {
231             super("org.netbeans.modules.text.TXTDataObject"); // NOI18N
232
}
233
234         /** Does initialization. Initializes extension list. */
235         protected void initialize () {
236             super.initialize();
237
238             ExtensionList ext = new ExtensionList();
239             ext.addExtension("txt"); // NOI18N
240
ext.addExtension("doc"); // NOI18N
241
ext.addExtension("me"); // for read.me files // NOI18N
242
ext.addExtension("policy"); // NOI18N
243
ext.addExtension("mf"); // for manifest.mf files // NOI18N
244
ext.addExtension("MF"); // -""- // NOI18N
245
ext.addExtension("log"); // log files are nice to be readable // NOI18N
246
setExtensions(ext);
247         }
248
249         /** Gets default display name. Overrides superclass method. */
250         protected String JavaDoc defaultDisplayName() {
251             return NbBundle.getBundle(TXTDataLoader.class).getString("PROP_TXTLoader_Name");
252         }
253
254         /** Gets default system actions. Overrides superclass method. */
255         protected SystemAction[] defaultActions() {
256             return new SystemAction[] {
257                 SystemAction.get(OpenAction.class),
258                 SystemAction.get (FileSystemAction.class),
259                 null,
260                 SystemAction.get(CutAction.class),
261                 SystemAction.get(CopyAction.class),
262                 SystemAction.get(PasteAction.class),
263                 null,
264                 SystemAction.get(DeleteAction.class),
265                 SystemAction.get(RenameAction.class),
266                 null,
267                 SystemAction.get(SaveAsTemplateAction.class),
268                 null,
269                 SystemAction.get(ToolsAction.class),
270                 SystemAction.get(PropertiesAction.class),
271             };
272         }
273
274         /** Check whether a file is recognized.
275          * It will be if the extension matches, or if it is marked to be a text file. */

276         protected FileObject findPrimaryFile (FileObject fo) {
277             boolean isSysFile;
278             try {
279                 isSysFile = fo.getFileSystem () == Repository.getDefault ().getDefaultFileSystem ();
280             } catch (FileStateInvalidException fsie) {
281                 // Never mind.
282
isSysFile = false;
283             }
284             if (! isSysFile && Boolean.TRUE.equals (fo.getAttribute (ATTR_IS_TEXT_FILE)))
285                 return fo;
286             return super.findPrimaryFile (fo);
287         }
288
289         /** Creates new <code>TXTDataObject</code> for specified <code>FileObject</code>.
290          * @param fo FileObject
291          * @return new TXTDataObject
292          */

293         protected MultiDataObject createMultiObject(final FileObject fo)
294         throws IOException JavaDoc {
295             return new TXTDataObject(fo, this);
296         }
297
298     } // end of TXTDataLoader
299

300     
301     public static final class TXTDataObject extends MultiDataObject implements CookieSet.Factory {
302
303         /** Generated Serialized Version UID */
304         static final long serialVersionUID = 4795737295255253334L;
305
306         /** Editor support for text data object. */
307         private transient TXTEditorSupport editorSupport;
308
309
310         /** Constructor. */
311         public TXTDataObject(final FileObject obj, final MultiFileLoader loader) throws DataObjectExistsException {
312             super(obj, loader);
313
314             getCookieSet().add(TXTEditorSupport.class, this);
315         }
316
317
318         /** Implements <code>CookieSet.Factory</code> interface. */
319         public Node.Cookie createCookie(Class JavaDoc clazz) {
320             if(clazz.isAssignableFrom(TXTEditorSupport.class))
321                 return getEditorSupport();
322             else
323                 return null;
324         }
325
326         // Accessibility from TXTEditorSupport:
327
CookieSet getCookieSet0() {
328             return getCookieSet();
329         }
330
331         /** Gets editor support for this data object. */
332         private TXTEditorSupport getEditorSupport() {
333             if(editorSupport == null) {
334                 synchronized(this) {
335                     if(editorSupport == null)
336                         editorSupport = new TXTEditorSupport(this);
337                 }
338             }
339
340             return editorSupport;
341         }
342
343         /** Provides node that should represent this data object. When a node for representation
344          * in a parent is requested by a call to getNode (parent) it is the exact copy of this node
345          * with only parent changed. This implementation creates instance <code>DataNode</code>.
346          * <p>
347          * This method is called only once.
348          *
349          * @return the node representation for this data object
350          * @see DataNode
351          */

352         protected Node createNodeDelegate () {
353             return new TXTNode(this);
354         }
355
356         /** Help context for this object.
357          * @return help context
358          */

359         public HelpCtx getHelpCtx () {
360             return new HelpCtx (TXTDataObject.class);
361         }
362
363
364         /** Text node implementation.
365          * Leaf node, default action opens editor or instantiates template.
366          * Icons redefined.
367          */

368         public static final class TXTNode extends DataNode {
369             /** Icon base for the TXTNode node */
370             private static final String JavaDoc TXT_ICON_BASE = "org/netbeans/modules/text/txtObject"; // NOI18N
371

372             /** Constructs node. */
373             public TXTNode (final DataObject dataObject) {
374                 super(dataObject, Children.LEAF);
375                 setIconBase(TXT_ICON_BASE);
376             }
377
378             /** Overrides default action from DataNode. */
379             public SystemAction getDefaultAction () {
380                 SystemAction result = super.getDefaultAction();
381                 return result == null ? SystemAction.get(OpenAction.class) : result;
382             }
383         } // End of nested class TXTNode.
384

385     } // TXTDataObject
386

387     
388     public static final class TXTEditorSupport extends DataEditorSupport
389     implements OpenCookie, EditCookie, EditorCookie.Observable, PrintCookie, CloseCookie {
390
391         /** SaveCookie for this support instance. The cookie is adding/removing
392          * data object's cookie set depending on if modification flag was set/unset. */

393         private final SaveCookie saveCookie = new SaveCookie() {
394             /** Implements <code>SaveCookie</code> interface. */
395             public void save() throws IOException JavaDoc {
396                 TXTEditorSupport.this.saveDocument();
397                 TXTEditorSupport.this.getDataObject().setModified(false);
398             }
399         };
400
401
402         /** Constructor. */
403         TXTEditorSupport(TXTDataObject obj) {
404             super(obj, new Environment(obj));
405
406             setMIMEType("text/plain"); // NOI18N
407
}
408
409         /**
410          * Overrides superclass method. Adds adding of save cookie if the document has been marked modified.
411          * @return true if the environment accepted being marked as modified
412          * or false if it has refused and the document should remain unmodified
413          */

414         protected boolean notifyModified () {
415             if (!super.notifyModified())
416                 return false;
417
418             addSaveCookie();
419
420             return true;
421         }
422
423         /** Overrides superclass method. Adds removing of save cookie. */
424         protected void notifyUnmodified () {
425             super.notifyUnmodified();
426
427             removeSaveCookie();
428         }
429
430         /** Helper method. Adds save cookie to the data object. */
431         private void addSaveCookie() {
432             TXTDataObject obj = (TXTDataObject)getDataObject();
433
434             // Adds save cookie to the data object.
435
if(obj.getCookie(SaveCookie.class) == null) {
436                 obj.getCookieSet0().add(saveCookie);
437                 obj.setModified(true);
438             }
439         }
440
441         /** Helper method. Removes save cookie from the data object. */
442         private void removeSaveCookie() {
443             TXTDataObject obj = (TXTDataObject)getDataObject();
444
445             // Remove save cookie from the data object.
446
Node.Cookie cookie = obj.getCookie(SaveCookie.class);
447
448             if(cookie != null && cookie.equals(saveCookie)) {
449                 obj.getCookieSet0().remove(saveCookie);
450                 obj.setModified(false);
451             }
452         }
453
454
455         /** Nested class. Environment for this support. Extends
456          * <code>DataEditorSupport.Env</code> abstract class.
457          */

458
459         private static class Environment extends DataEditorSupport.Env
460         {
461             private static final long serialVersionUID = 3499855082262173256L;
462
463             /** Constructor. */
464             public Environment(TXTDataObject obj) {
465                 super(obj);
466             }
467
468
469             /** Implements abstract superclass method. */
470             protected FileObject getFile() {
471                 return getDataObject().getPrimaryFile();
472             }
473
474             /** Implements abstract superclass method.*/
475             protected FileLock takeLock() throws IOException JavaDoc {
476                 return ((TXTDataObject)getDataObject()).getPrimaryEntry().takeLock();
477             }
478
479             /**
480              * Overrides superclass method.
481              * @return text editor support (instance of enclosing class)
482              */

483             public CloneableOpenSupport findCloneableOpenSupport() {
484                 return (TXTEditorSupport)getDataObject().getCookie(TXTEditorSupport.class);
485             }
486         } // End of nested Environment class.
487

488     } // TXTEditorSupport
489

490     
491     private static class MyPool extends org.openide.loaders.DataLoaderPool {
492         protected java.util.Enumeration JavaDoc loaders() {
493             return Collections.enumeration(Collections.singleton(
494                 TXTDataLoader.getLoader(TXTDataLoader.class)
495             ));
496         }
497         
498     }
499     
500     public static class Lkp extends org.openide.util.lookup.AbstractLookup {
501         public Lkp () {
502             this (new org.openide.util.lookup.InstanceContent ());
503         }
504         
505         private Lkp (org.openide.util.lookup.InstanceContent ic) {
506             super (ic);
507             
508             ic.add (new MyPool ());
509             ic.add (new ConsistencyCheckProvider ());
510         }
511     }
512 }
513
Popular Tags