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.

Bug 193549

Summary: @ProjectFactory.Registration
Product: projects Reporter: Jaroslav Tulach <jtulach>
Component: Generic InfrastructureAssignee: Jaroslav Tulach <jtulach>
Status: RESOLVED WONTFIX    
Severity: normal CC: apireviews, jglick
Priority: P3 Keywords: API_REVIEW_FAST
Version: 6.x   
Hardware: All   
OS: All   
Issue Type: ENHANCEMENT Exception Reporter:
Attachments: @ProjectRegistration
@ProjectFactory.Registration and its usage in maven

Description Jaroslav Tulach 2010-12-17 13:19:51 UTC
More and more projects are moving away from @AntBasedProjectRegistration (like CND as a result of implementing bug 193249) and we need a declarative way to avoid doing the same things multiple times.

I'd like to propose @ProjectFactory.Registration (sort of similar to first patch attached to bug 153655: http://bugzilla-attachments-153655.netbeans.org/bugzilla/attachment.cgi?id=74022) that would allow each provider of a project to annotate its factory method:

@ProjectFactory.Registration(
  relativeFile={ "nbproject/project.xml" },
  mimeType="text/xml+antproject",
  iconBase="...."
)
public static Project create(FileObject fo) throws IOException {
}

The above would generate an implementation of ProjectFactory2 that would implement isProject(FileObject dir) as follows:

if at least one of the dir.getFileObject(relativeFile[i]) exists and has appropriate mimeType (if the mimetype is specified), then return true. return false otherwise.

Implementation of loadProject would delegate to the factory method.
Comment 1 Jaroslav Tulach 2010-12-26 10:38:08 UTC
Created attachment 104500 [details]
@ProjectRegistration

There are two problems with the previous patch. There is no support for saveProject and no ProjectState is passed to the factory method.
Comment 2 Jaroslav Tulach 2010-12-26 15:02:31 UTC
Implementation that handles ProjectState and saveProject:
http://hg.netbeans.org/ergonomics/rev/185ba0da2385
Its usage in 
http://hg.netbeans.org/ergonomics/rev/ea89235cffb7

Is this enhancement suitable for 7.0?
Comment 3 Jesse Glick 2011-01-05 22:07:41 UTC
[JG01] I see no purpose for the mimeType attribute. Delete it unless there is a clear use case.


[JG02] The overall structure of the annotation seems more complicated than necessary. The usage of Flushable is also unnecessarily novel. A simpler suggestion is for the client to still implement ProjectFactory{,2} but register the factory using a new annotation rather than @ServiceProvider:

@ProjectFactory.Registration(iconBase="...", relativeFile="pom.xml")
public class MavenFactory implements ProjectFactory2 {
  // loadProject, isProject, isProject2, saveProject as usual
}

This would just register a proxy PF2 which implements isProject{,2} based on the metadata and returns quickly from loadProject for inappropriate dirs. If and when loadProject is called with a matching dir, the real factory is loaded and henceforth all method calls delegate to it.

This style:

1. Bypasses the need for the Flushable trick.

2. Affords more flexibility once class loading has already been triggered. For example, you could return a different icon from isProject2 if doing so is cheap enough. (Compare @ActionRegistration on an always-enabled Action instance.)

3. Provides the quickest migration path for existing PF{,2} impls.

4. Makes for a trivial annotation processor: one call to instanceAttribute.
Comment 4 Jaroslav Tulach 2011-01-07 10:05:32 UTC
Re. JG01 the mime attribute would allow CND to recognize nbproject/project.xml file, and not get triggered until there is the necessary content - e.g. correct project type declaration.

Re. JG02 - I was hoping to get away from the current style of registration and simplify it a bit. However I agree that Flushable contract is not nice.
Comment 5 Jesse Glick 2011-01-07 15:02:40 UTC
(In reply to comment #4)
> Re. JG01 the mime attribute would allow CND to recognize nbproject/project.xml
> file, and not get triggered until there is the necessary content - e.g. correct
> project type declaration.

What would the MIME type be other than text/xml?
Comment 6 Jaroslav Tulach 2011-01-07 20:23:21 UTC
There is a need to scan content of the files to find out whether it form a valid project of this type or not. This is certainly true for Maven's pom.xml (and the support for Java/JavaEE/Scala, etc.), for Ruby (as it uses nbproject/project.xml) and possibly also for cnd.

I can define my own way of looking into the file, but rather I'd like to reuse a standard.

We have one standard, efficient and declarative way of looking into any file. The one used during mime resolution. Thus I want to reuse it.

So to answer your question, the mime type would be something like text/xml+cnd-project. Of course only if CND defines appropriate mime resolver to scan the content of the file and recognize it as such mimetype.
Comment 7 Jesse Glick 2011-01-07 20:44:42 UTC
(In reply to comment #6)
> There is a need to scan content of the files to find out whether it form a
> valid project of this type or not. This is certainly true for Maven's pom.xml
> (and the support for Java/JavaEE/Scala, etc.)

No, these all produce NbMavenProjectImpl; pom.xml need not be opened to recognize a Maven project.

> We have one standard, efficient and declarative way of looking into any file.
> The one used during mime resolution. Thus I want to reuse it.
> 
> So to answer your question, the mime type would be something like
> text/xml+cnd-project. Of course only if CND defines appropriate mime resolver
> to scan the content of the file and recognize it as such mimetype.

I guess in this case text/xml+cnd-project will not be used for anything else, so it will become a regular XMLDataObject and have the normal validate actions etc.?
Comment 8 Jaroslav Tulach 2012-01-17 11:11:09 UTC
Created attachment 114960 [details]
@ProjectFactory.Registration and its usage in maven
Comment 9 Jaroslav Tulach 2012-01-17 11:13:08 UTC
Simplified to refer only to requiredFile and be applicable only to ProjectFactory. I'd like to integrate on Jan 24, 2012.
Comment 10 Jesse Glick 2012-01-18 19:35:13 UTC
[JG03] GenericProjectFactory.saveProject should call delegate(). Possibly does not matter, but more clearly right.


[JG04] GPF.isProject does not call delegate.isProject at all, which is rather confusing. In the case of NbMavenProjectFactory, it means that the customized isProject is ignored except when used internally as part of loadProject; NbMPF.iP could as well throw an assertion error or unconditionally return true, and move that logic into loadProject. I would recommend that GPF.isProject call delegate.iP when fo != null && delegate != null, but if not it should at least be clearly documented that PF.iP will never be called (contrary to current Javadoc "all operations are delegated to it").


[JG05] The default value of iconBase clashes with the fact that GPF.isProject2 expects iconBase to be non-null. PM.Result does support a null icon but we would not want to encourage this (ProjectChooserAccessory in this case simply forces loading of the project). The Javadoc says the factory may implement PF2 _or_ specify an iconBase, but this is broken: (a) the processor does not check that either is true; (b) when the delegate has not yet been loaded, iconBase is still needed (though a fix of JG04 may change that).


[JG06] Processor buglets: iconBase should be passed through validateResource; roundEnv.processingOver should be checked; pr == null should be checked; instanceFile or instanceAttribute should use long form with annotation name.


[JG07] Test should not call Lookup.getDefault().lookup(ModuleInfo.class). Use MockLookup.setLayersAndInstances().


[JG08] Would like to see more than one usage: AntBasedProjectFactorySingleton, MakeBasedProjectFactorySingleton, GrailsProjectFactory?
Comment 11 Jaroslav Tulach 2013-09-10 08:12:35 UTC
Seems like ergonomics are happy with .properties specification of important files and otherwise there was no need for this annotation. Closing for now.