FilesystemsLoadersBridge

(Difference between revisions)
m
(Proposal)
Line 4: Line 4:
A lot of editor modules have a dependency on DataSystems API, but don't actually need DataObjects per se.
A lot of editor modules have a dependency on DataSystems API, but don't actually need DataObjects per se.
 +
 +
== Unresoved Issues ==
 +
 +
# DataObjects maintain identity after rename and move, FileObjects do not. So far there is nothing adressing this in this proposal. Is the identity loss unimportant?
== General use cases ==
== General use cases ==

Revision as of 08:53, 8 March 2012

Contents

Proposal

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.

Unresoved Issues

  1. DataObjects maintain identity after rename and move, FileObjects do not. So far there is nothing adressing this in this proposal. Is the identity loss unimportant?

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.

DataObject.find(FileObject).getCookie().

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.

5. JTextComponent/Document/FileObject -> Unique ID

The idea here is to use DataObject as a key in a Map to make sure all the editor clones get the same data (eg. csl.api/spi.editor.hints AnnotationHolder.java). The map is usually a cache.


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-#4). They also care in some cases about some way of guaranteeing uniqueness for the given opened resource (#5).

Advantages

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) {
     try{
       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)

5. Most caches will be able to switch to using the primary FileObjects as the map key. The regression is that on file renames the cache value gets invalidated (which didn't happen with DataObjects) and will have to be recomputed.

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