The basic question I asked paulweb515 is as follows:

You're writing an extension point. You want an id and a label, as well as lots of other stuff / methods. So you make an interface for it that others must implement.

public interface IPackageType {
    public String getId();
    public String getLabel();
    public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);
    public int getSupportFor (IProject project);
}


In your extension point, you require a class, but you also want to require the id and label. What is the best way to do it?

paulweb515 had 3 suggestions:
<paulweb515> rawblem: I've seen 3 common usages
<paulweb515> rawblem: 1) Tell you users to implement IPackageType that has setId(*) as well as getId(*) ... then you can set your user's data when you create the executable extension

If you just let the extender implement IChef, he'll be filling in id and label twice, once in the extension point, and once in API.
So paulweb suggests setters, but that's not a great idea because then anyone who gets a reference to your object can
change the ID and label. Obviously that's a glaring error.

<paulweb515> rawblem: 2) Like ViewPart, create an abstract base class that they must use instead of just an interface.  ViewPart uses setInitializationData(*) to store the config element for the client to use in a protected  method, and extracts id, label etc into the base abstract class ... but they're private, and it only provides public final String getId() so they can't change it

This sounds like the best way, I'll look at it momentarily.

<paulweb515> or 3) don't store the ID in the object, have that ID be part of an association that your extension point knows.

Not exactly the best way, because then given an IChef, you cannot get his id or label.


Things I've done in the past:
   Let the user extend AbstractPackageDelegate, then when loading the extension points, do as follows:
  
public class AbstractPackageDelegate {
    public abstract IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);
    public abstract int getSupportFor (IProject project);
}

public class PackageTypeWrapper implements IPackageType {
          private AbstractPackageDelegate delegate;
          private IConfigurationElement element;
          public PackageTypeWrapper(IConfigurationElement element) {
                    this.element = element;
                    delegate = element.createExecutableExtension("class");
          }
          public String getId() { return element.getAttribute("id"); }
          public String getLabel() { return element.getAttribute("label"); }
         
         public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor) {
                    return delegate.createDefaultConfiguration(project, monitor);
         }
         public int getSupportFor (IProject project) {
                   return delegate.getSupportFor(project);
         }
}

The problem with this example, in this specific IPackageType example, is that in JarPackageType, marshall uses the following code:
        jar.setPackageType(this);

In the above example, "this", isnt an IPackageType. It's an incomplete piece of an IPackageType that will need to be wrapped.
A possible fix is:
         public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor) {
                    IPackage obj = delegate.createDefaultConfiguration(project, monitor);
                    obj.setPackageType(this);
                    return obj;
         }
... but clearly that's not ideal or intuitive.


//***** Paulweb's option 2 *********//
public abstract class AbstractPackageType implements IPackageType {
    private String id;
    private String label;
    private boolean initailized = false;
    public void setInitializationData(IConfigurationElement el) {
        if( !initialized) {
             id = el.getAttribute("id");
             label = el.getAttribute("label");
        }
    }
   
    public String getId() { return id; }
    public String getLabel() { return label; }
   
    public abstract int getSupportFor (IProject project);
    public abstract IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);
}

// creation
AbstractPackageType extender = (AbstractPackageType)configElement.createExecutableExtension("class");
extender.setInitializationData(configElement);

In this way, all users who get a reference to the IPackageType can get the id and label, but no users can change it arbitrarily.
Someone could still theoretically write their extension of AbstractPackageType to override the setInitializationData and make it
easy to change, but at least then it's the extender willfully allowing it to happen, instead of our abstract class having a public setter for all to use.


All are welcome to give forth their suggestions or other best practices they use WRT extension points ;) 
I'll probably be using a methodology similar to the one paulweb515 suggested.

- Rob