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 8858

Summary: templateWizardIterator file attribute inconvenient to automate
Product: platform Reporter: Jesse Glick <jglick>
Component: Dialogs&WizardsAssignee: Jaroslav Tulach <jtulach>
Status: CLOSED FIXED    
Severity: enhancement CC: dsimonek, jerilockhart, jtulach, mkleint, raccah, rbrinkley
Priority: P3 Keywords: API
Version: 3.x   
Hardware: PC   
OS: Linux   
Issue Type: ENHANCEMENT Exception Reporter:
Bug Depends on:    
Bug Blocks: 18430, 23349, 23350, 23351, 23859    

Description Jesse Glick 2000-12-11 12:34:00 UTC
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).
Comment 1 Svata Dedic 2000-12-11 12:41:59 UTC
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.
Comment 2 Jesse Glick 2000-12-11 13:43:59 UTC
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.
Comment 3 Jaroslav Tulach 2000-12-13 11:51:59 UTC
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!?
Comment 4 Jesse Glick 2000-12-13 12:02:59 UTC
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).
Comment 5 David Strupl 2001-03-05 14:12:06 UTC
*** Issue 9326 has been marked as a duplicate of this issue. ***
Comment 6 Jaroslav Tulach 2001-03-06 07:53:27 UTC
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...
Comment 7 Jan Chalupa 2001-05-06 08:11:50 UTC
Target milestone -> 3.3
Comment 8 Jan Chalupa 2001-11-27 13:02:56 UTC
Target milestone -> 3.3.1.
Comment 9 Jesse Glick 2001-12-21 16:55:15 UTC
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.
Comment 10 brinkley 2001-12-21 20:08:49 UTC
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);
           }
       }
Comment 11 Jaroslav Tulach 2002-01-07 08:51:46 UTC
Guys can we agree on making TemplateWizard.Iterator extend cookie? The
issue is here for long time and might be finally resolved...
Comment 12 Jesse Glick 2002-01-07 12:06:16 UTC
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.
Comment 13 Jaroslav Tulach 2002-01-09 09:16:02 UTC
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

Comment 14 Jesse Glick 2002-01-09 09:54:59 UTC
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.
Comment 15 Jeri Lockhart 2002-04-10 18:42:00 UTC
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.   
Comment 16 Jesse Glick 2002-04-10 20:27:58 UTC
Well it's marked for milestone 3 on the 3.4 dev cycle.
Comment 17 Petr Hrebejk 2002-04-22 14:57:08 UTC
Jarda asked for this bug. Reassigning.
Comment 18 Jaroslav Tulach 2002-04-23 09:16:47 UTC
Ok, let's implement it.
Comment 19 Jaroslav Tulach 2002-04-23 10:18:26 UTC
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
Comment 20 Jan Zajicek 2002-04-26 16:09:26 UTC
verified
Comment 21 akemr 2002-06-27 14:58:29 UTC
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)!
Comment 22 Quality Engineering 2003-07-01 16:12:56 UTC
Resolved for 3.4.x or earlier, no new info since then -> closing.