<br>The basic question I asked paulweb515 is as follows:<br><br>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.
<br><br>public interface IPackageType {<br> public String getId();<br> public String getLabel();<br> public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);<br> public int getSupportFor (IProject project);
<br>}<br><br><br>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? <br><br>paulweb515 had 3 suggestions: <br><span style="font-style: italic;"><paulweb515> rawblem: I've seen 3 common usages
</span><br style="font-style: italic;"><span style="font-style: italic;">
<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</span><br style="font-style: italic;">
<br>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. <br>So paulweb suggests setters, but that's not a great idea because then anyone who gets a reference to your object can
<br>change the ID and label. Obviously that's a glaring error. <br><br><span style="font-style: italic;"><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
</span><br style="font-style: italic;"><br>This sounds like the best way, I'll look at it momentarily.<br><br style="font-style: italic;"><span style="font-style: italic;"><paulweb515> or 3) don't store the ID in the object, have that ID be part of an association that your extension point knows.
<br></span><br>Not exactly the best way, because then given an IChef, you cannot get his id or label. <br><br><br>Things I've done in the past: <br> Let the user extend AbstractPackageDelegate, then when loading the extension points, do as follows:
<br> <br>public class AbstractPackageDelegate {<br> public abstract IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);<br>
public abstract int getSupportFor (IProject project);<br>
}<br><br>public class PackageTypeWrapper implements IPackageType {<br> private AbstractPackageDelegate delegate;<br> private IConfigurationElement element;<br> public PackageTypeWrapper(IConfigurationElement element) {
<br> this.element = element;<br> delegate = element.createExecutableExtension("class");<br>
}<br> public String getId() { return element.getAttribute("id"); }<br>
public String getLabel() { return element.getAttribute("label"); }<br>
<br> public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor) {<br> return delegate.createDefaultConfiguration(project, monitor);<br> }<br>
public int getSupportFor (IProject project) {<br> return delegate.getSupportFor(project);<br> }<br>
}<br><br>The problem with this example, in this specific IPackageType example, is that in JarPackageType, marshall uses the following code: <br> jar.setPackageType(this);<br><br>In the above example, "this", isnt an IPackageType. It's an incomplete piece of an IPackageType that will need to be wrapped.
<br>A possible fix is: <br> public IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor) {<br>
IPackage obj = delegate.createDefaultConfiguration(project, monitor);<br> obj.setPackageType(this);<br> return obj;<br>
}<br>
... but clearly that's not ideal or intuitive. <br><br><br>//***** Paulweb's option 2 *********//<br>public abstract class AbstractPackageType implements IPackageType {<br> private String id;<br> private String label;
<br> private boolean initailized = false;<br> public void setInitializationData(IConfigurationElement el) {<br> if( !initialized) {<br> id = el.getAttribute("id");<br> label =
el.getAttribute("label");<br> }<br> }<br> <br> public String getId() { return id; }<br> public String getLabel() { return label; }<br> <br> public abstract int getSupportFor (IProject project);
<br> public abstract IPackage createDefaultConfiguration(IProject project, IProgressMonitor monitor);<br>}<br><br>// creation<br>AbstractPackageType extender = (AbstractPackageType)configElement.createExecutableExtension("class");
<br>extender.setInitializationData(configElement);<br><br>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. <br>Someone could still theoretically write their extension of AbstractPackageType to override the setInitializationData and make it
<br>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. <br><br><br>All are welcome to give forth their suggestions or other best practices they use WRT extension points ;)
<br>I'll probably be using a methodology similar to the one paulweb515 suggested. <br><br>- Rob<br><br>