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.
This is a request for an API enhancement (or a request for suggestions on how to do without it). The templateWizardIterator file attribute is used to tell the TemplateWizard (in getIterator(FileObject)) that a given file has a given template iterator. This is fine for special-case wizards that should be associated with a particular template. But very often the author of a DataObject wishes to make a given iterator the *default* for all objects of that DataObject class. For example, *.group files have a standard GroupTemplateIterator, and Ant project files have a standard AntTemplateIterator which provides desirable basic improvements to the New... behavior for this object type. Same for the audioloader API example--the wizard for audio clips must prompt the user to record sounds. But there is no good way to do this. You can set the templateWizardIterator on all the instances of the file as a template that you know about (and convince other people to do this too, though then they have to keep track of whether your iterator changes name or something). To make it the default also for templates that the user creates, or those added by unknown modules, you can make the constructor of the DataObject, if it is a template, set the iterator; and also attach a listener so that if it becomes a template later, and it has no iterator, set its iterator to the default. But this has disadvantages: the code is messy and somewhat difficult to write; it dumps extra file attributes into .nbattrs files in the system file system on disk, where they accumulate even if the user has changed nothing, and will complicate upgrading the IDE because these attributes will be persistent; and if the file is on a read-only filesystem, it does not work at all (and there must be extra code to protect against this, cf. recently filed bug to utilities module re. GroupShadow). So suggest some way of declaring a default iterator for all DataObject's of some type. Maybe a cookie that the DataObject could provide giving its iterator; probably this would have been a better design to begin with, since it puts control over the iterator in the hands of the DataObject itself; however I cannot think of a way to do this that would be efficient (avoid overhead in both DataObject.<init> and .getCookie). Or a static registration method in TemplateWizard per DataObject representation class (bleah).
I sort of like your suggestion to implement the default Iterator as a cookie. It IS, in fact, a service provided by the DataObject (instantiation service). I think there will be almost no overhead - the DataObject are loaded and initialized anyway since NFT Wizard works on Template's DataObjects and creates them just to display templates' nodes. We can also implement getCookie() for Iterator cookie lazily.
Re. overhead, I was more speaking of regular objects that are not templates. I.e. adding overhead to *every* DataObject creation would be bad. So here is a possible solution using the cookie: - Define some cookie with a method to get a TemplateWizard.Iterator (or null to use the standard iterator). - Deprecate TemplateWizard.[gs]etIterator. - Change TemplateWizard to not call these methods, rather ask the DataObject for the iterator cookie and get the cookie. - Define an implementation of the cookie (support) which takes a DataObject as constructor and checks its primary file for the templateWizardIterator attribute. - Modify DataObject.getCookie() to check whether the cookie class == the class of the iterator cookie (or the support), and if so return a new support impl (do not try to cache it or use CookieSet, useless). Do this check after trying other possibilities (e.g. whether the DataObject is assignable to the cookie). This provides both a convenience (module authors need not explicitly implement it if they do not need a class-wide default) and backwards compatibility. Now e.g. GroupShadow could simply implement the cookie and implement its method to return a new instance of the desired iterator. The overhead for the IDE in general is a couple of JVM bytecodes (equality test for the class) per getCookie call resulting in null, which is probably acceptable overhead. Maybe long-term the default behavior in DataObject could be removed and modules forced to explicitly implement the iterator cookie or attach it somehow if they wanted to use it.
When I was designing the TemplateWizard I was thinking about having something like TemplateCookie, but I do not liked the IDE too much and moreover I wanted the TemplateWizard be separate from the rest as much as possible. When I realized that there is a need for default iterator then my first choice was to add a method: protected Iterator DataLoader.defaultIterator () I think that DataLoader is the right place for this, because you want to specify default behaviour for all instances of the same DataObject and that share exactly the DataLoader. If you need the default iterator, I would vote for this solution!?
Hmm, maybe, but it doesn't look like a method you would expect to find on DataLoader, and also using a cookie permits more flexibility--you might want to have a different default iterator depending on some characteristic of the object... (e.g. JavaDataObject may wish to provide one iterator for classes, another ones for interfaces).
*** Issue 9326 has been marked as a duplicate of this issue. ***
There is a cookie. NewTemplateAction.Cookie. It is not exactly what you want, but might be used (maybe temporily) to get the iterator!? Ugly, ugly...
Target milestone -> 3.3
Target milestone -> 3.3.1.
Yarda suggests on nbdev: --------%<--------- PS: I think that the whole issue slept because I prefered DataLoader.defaultIterator and others prefer Cookie. But introducing bunch of new classes (Cookie, Support, etc.) seems to me as big overkill to such simple task. And that is why: Do you realize that simplest solution is likely to make TemplateWizard.Iterator extends Node.Cookie and appropriatelly change TW.getIterator? --------%<--------- For an example of the workaround he also suggests: --------%<---------- Possible solution might be to find out when your data object turns into template (PROP_TEMPLATE is fired) and in such case use TemplateWizard.setIterator (....) on that object. --------%<---------- For an example see ant/src/org/apache/tools/ant/module/loader/AntProjectDataObject.java pre-1.7. In 1.7 I deleted the workaround because it seemed too clumsy and the iterator was not valuable enough to bother with it.
Worksaround: I've implemented a workaround so that generated templates would use the JarPackagerWizardIterator instead of the default interator. This is based on Yarda's suggestion as posted by Jesse. Might be useful to others trying to implement the same. Add the first few lines to the DataObject constructor and make sure the DataObject class implements PropertyChangeListener. // Until there is a fix for 8858 the creation of JarDataObject // must check the TemplateWizard also anytime the property // PROP_TEMPLATE is changed checkIterator(); addPropertyChangeListener(this); } /** * Handle property change notification. * Primarily this is a workaround for 8858 to catch a change in he * the setting of the template so the template iterator can be properly * set. */ public void propertyChange (PropertyChangeEvent ev) { String prop = ev.getPropertyName (); if (prop == null || prop.equals (DataObject.PROP_TEMPLATE)) { checkIterator(); } } /** * Until there is a fix for 8858 the TemplateWizard.Iterator will have to * to be set within the code. This is only true for templates. */ private void checkIterator() { FileObject prim = getPrimaryFile (); TemplateWizard.Iterator it = TemplateWizard.getIterator (this); if (isTemplate () && it == null && ! prim.isReadOnly ()) { try { TemplateWizard.setIterator (this, new JarContentsWizardIterator ()); } catch (IOException ioe) { TopManager.getDefault ().getErrorManager ().notify (ErrorManager.WARNING, ioe); } }
Guys can we agree on making TemplateWizard.Iterator extend cookie? The issue is here for long time and might be finally resolved...
FWIW I like the idea of making it a cookie... seems more consistent from an API perspective, can be done while preserving compatibility, etc. E.g.: 1. Make it extend cookie. 2. Deprecate TW.[gs]etIterator but leave impl alone. 3. Change TW to ask DataObject for the cookie. 4. Change DataObject.getCookie to check for clazz==TW.I.class and look for a file attribute to get it, by default. Subclasses can override.
Fine, that the cookie idea is accepted. But let me propose different level of changes: 1. Make it extend cookie. 2. Change TW.getIterator to first check the FileObject's attribute and if not set use DataObject.getCookie (TW.Iterator.class) or in oposite order 3. Change javadoc of setIterator to indicate that there is a different way how to add a cookie and maybe deprecate
OK, that has the advantage that no change to DataObject is required. (I was hoping to make getIterator also superfluous, so it could maybe be deleted in some future API cleanup. But it is only a static utility method, which are generally easy to deprecate & retain & make copies of.) I would recommend: look for cookie before file attribute; do deprecate setIterator.
On 31 Jan 2001 I opened issue 9326. It later got marked as a duplicate of this bug. The problem still exists that when a user enters invalid data on a new from template, the wizard closes without giving the user a chance to correct the problem. When can I expect a fix for this problem? It has been open for over a year and is is generating duplicate issues in our product, Forte for Java, which uses NetBeans.
Well it's marked for milestone 3 on the 3.4 dev cycle.
Jarda asked for this bug. Reassigning.
Ok, let's implement it.
Checking in openide-spec-vers.properties; /cvs/openide/openide-spec-vers.properties,v <-- openide-spec-vers.properties new revision: 1.52; previous revision: 1.51 done Processing log script arguments... More commits to come... Checking in api/doc/changes/apichanges.xml; /cvs/openide/api/doc/changes/apichanges.xml,v <-- apichanges.xml new revision: 1.56; previous revision: 1.55 done Processing log script arguments... More commits to come... Checking in src/org/openide/loaders/TemplateWizard.java; /cvs/openide/src/org/openide/loaders/TemplateWizard.java,v <-- TemplateWizard.java new revision: 1.51; previous revision: 1.50 done Processing log script arguments... More commits to come... RCS file: /cvs/openide/test/unit/src/org/openide/loaders/TemplateWizardTest.java,v done Checking in test/unit/src/org/openide/loaders/TemplateWizardTest.java; /cvs/openide/test/unit/src/org/openide/loaders/TemplateWizardTest.java,v <-- TemplateWizardTest.java initial revision: 1.1 done
verified
I changed order of returning values in TemplateWizard.getIterator() to save backward compatibility (consulted with Yarda) There was following serious problem in New Module Wizard x JAR content wizard: NMW creates jarContent file and declares its own TW.Iterator in layer. So trying New -> NetBeans Extensions -> IDE plugin, instead of NMW always appeared JAR wizard (from getCookie of JarDataObject)!
Resolved for 3.4.x or earlier, no new info since then -> closing.