I would like to suggest a new Filesystems API bridge towards DataSystems API and some standard util method to get the primary FileObject for a given Document.

A lot of editor modules have a dependency on DataSystems API, but don't actually need DataObjects per se.

General use cases

There are a couple of "mappings" that DataSystems API users seems to need:

1. Document -> Cookie.

This is basically handled by reading the Document property Document.StreamDescriptionProperty which is usually an instance of DataObject. Afterwards we call DataObject.getCookie.

2. FileObject -> Cookie.


3. JTextComponent -> Cookie.

JTextComponent.getDocument which then uses the logic from #1.

4. Document -> FileObject.

Document.StreamDescriptionProperty then DataObject.getPrimaryFile() -- it's quite rare to care about the non-primary files.

So except the modules that actually implement a DataObject/DataLoaders, almost nobody cares about the DataObject and the DataSystems API.

What modules need is a way to get some Cookie or FileObject given a JTextComponent/Document/File/FileObject.


1. Get rid of all the copy-paste code. A lot of modules have various similar code for the operations mentioned above or little util methods that do this.

2. Show the actual importance of the DataSystems API. I think the API seems much more important than it is because so many modules have a dependency on it. Since most modules also have a dependency on FileSystems API, this new change will just get rid of the DataSystems API dependency.

3. Decouple the editors from DataSystems API and the disk. (This is actually the most important aspect to me.) If we start decoupling modules from DataSystems API via the Bridge, it becomes simpler to use them in more creative ways.

API Proposal

openide.filesystems introduces a friend contract with openide.loaders:

 public interface FileObjectLookupFactory {
   Lookup getLookup(FileObject fo);

FileObject becomes a Lookup.Provider using the FileObjectLookupFactory:

 @Override public Lookup getLookup() {
   FileObjectLookupFactory f = Lookup.getDefault().lookup(FileObjectLookupFactory.class);
   return f != null ? f.getLookup(this) : Lookups.singleton(this);

openide.loaders provides the default FileObjectLookupFactory implementation:

 @ServiceProvider(service= FileObjectLookupFactory.class)
 public class FileObjectDataObjectBridge implements FileObjectLookupFactory {
   public Lookup getLookup(FileObject fo) {
       return DataObject.find(fo).getLookup();
     }catch(DataObjectNotFoundException donfe){
       //TODO: also log exception?
       return Lookups.singleton(fo);

In editor/ NbEditorUtilities we remove of update getFileObject and add

 public static FileObject getPrimaryFileObject(Document doc) {
      Object o = doc.getProperty(Document.StreamDescriptionProperty);
      if (o instanceof Lookup.Provider) {
          return ((Lookup.Provider) o).getLookup().lookup(FileObject.class);
      } else {
          return null;
 public static FileObject getPrimaryFileObject(JTextComponent text) {
   return getPrimaryFileObject(text.getDocument());

-- this will work because both FileObject and DataObject are Lookup.Provider-s now so there is no need to do an instanceof FileObject.

General use cases evolution

The use cases above become:

1. NbEditorUtilities.getPrimaryFileObject(doc).getLookup().lookup(SomeCookie.class)

2. fo.getLookup().lookup(SomeCookie.class)

3. NbEditorUtilities.getPrimaryFileObject(textComponent).getLookup().lookup(SomeCookie.class)

4. NbEditorUtilities.getPrimaryFileObject(doc)

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo