3 * Created on 16-feb-2004
6 package com.quantum.extensions;
7 import java.util.Vector;
9 import org.eclipse.core.runtime.CoreException;
10 import org.eclipse.core.runtime.IConfigurationElement;
11 import org.eclipse.core.runtime.IExtension;
12 import org.eclipse.core.runtime.IExtensionPoint;
13 import org.eclipse.core.runtime.IPluginRegistry;
14 import org.eclipse.core.runtime.Platform;
15 import org.eclipse.ui.IViewPart;
16 import org.eclipse.ui.WorkbenchException;
17 import org.w3c.dom.Document;
19 import com.quantum.view.bookmark.BookmarkView;
20 import com.quantum.view.tableview.TableView;
23 * Extension processing logic for the <code>functions</code> extension-point.
24 * Extract specific information about each function. Create callback
25 * function object when required.
30 public class ProcessServiceMembers {
33 * The fully-qualified name of the functions extension-point for this plug-in.
35 private static final String EXTENSION_POINT_METADATA =
36 "com.quantum.Quantum.metadata";
37 private static final String EXTENSION_POINT_DATA =
38 "com.quantum.Quantum.data";
41 * Name of the XML attribute designating a metadata actor label.
43 private static final String FUNCTION_NAME_ATTRIBUTE = "label";
46 * Name of the XML attribute designating the fully-qualified name
47 * of the implementation class of a function.
49 private static final String CLASS_ATTRIBUTE = "class";
52 * Perform initial extension processing for the members of the
53 * <code>functions</code> extension-point. Make calls to the user interface
54 * module to add the functions of an extension to the UI functions grid.
55 * For each function, a virtual proxy callback object is created and handed
56 * to the user interface module. The proxy class is a nested top-level
57 * class and is therefore known at compile time. The actual (real) callback
58 * objects configured into extensions are instantiated and initialized in
59 * a lazy fashion by the proxy callback objects.
61 * @param grid The UI functions grid exposing the functions configured
62 * into <code>functions</code> extensions.
65 public static void process(IViewPart view, Vector extensionActions) throws WorkbenchException {
67 extensionActions.clear();
69 IPluginRegistry registry = Platform.getPluginRegistry();
71 // We have two different extension points, we choose the needed one based
72 // on the view that calls this function.
73 // Our two extension points have the same attributes, so the only change is the name
74 // If the implementation differed more, we should probably make two different functions
75 if (view instanceof BookmarkView)
76 extPointId = EXTENSION_POINT_METADATA;
77 else if (view instanceof TableView)
78 extPointId = EXTENSION_POINT_DATA;
82 IExtensionPoint extensionPoint =
83 registry.getExtensionPoint(extPointId);
84 if (extensionPoint == null) {
85 throw new WorkbenchException(
86 "unable to resolve extension-point: " + extPointId);
88 IConfigurationElement[] members =
89 extensionPoint.getConfigurationElements();
92 for (int m = 0; m < members.length; m++) {
93 IConfigurationElement member = members[m];
94 // Get the label of the extender plugin and the ID of the extension.
95 IExtension extension = member.getDeclaringExtension();
97 extension.getDeclaringPluginDescriptor().getLabel();
98 if (pluginLabel == null) {
99 pluginLabel = "[unnamed plugin]";
101 // Get the name of the operation implemented by the service.
102 // The operation name is a service attribute in the extension's XML specification.
103 String functionName = member.getAttribute(FUNCTION_NAME_ATTRIBUTE);
104 if (functionName == null) {
105 functionName = "[unnamed function]";
107 String label = pluginLabel + "/" + functionName;
108 // Add a row to support this operation to the UI grid.
109 IQuantumExtension proxy = null;
110 if (view instanceof BookmarkView)
111 proxy = (IMetadataExtension) new MetadataFunctionProxy(member);
112 else if (view instanceof TableView)
113 proxy = (IDataExtension) new DataFunctionProxy(member);
114 //grid.addFunction(proxy, functionName, label);
115 extensionActions.add(new ExtensionAction(view, label, label, proxy));
120 * Virtual proxy class for function invokation.
121 * Members of this class support lazy processing by fronting the real
122 * implementations of arithmetic functions configured into extensions.
124 private static class MetadataFunctionProxy implements IMetadataExtension {
125 // The "real" implementation of the function.
126 private IMetadataExtension delegate = null;
127 // The configured state of the extension element representing this arithmetic function.
128 private IConfigurationElement element;
129 // Whether this function has been invoked before.
130 // Used for lazy evaluation of the service.
131 private boolean invoked = false;
134 * Construct a virtual proxy to stand in place of an extension function.
135 * The constructor simply keeps track of an arithmetic function's configured state
136 * without at this time instantiating the implementation of the function.
138 * @param element The configuration of this arithmetic function.
140 public MetadataFunctionProxy(IConfigurationElement element) {
141 this.element = element;
145 * Compute the function value.
146 * The proxy computation first instantiates the implementation
147 * of the function, if this is the first time the function is called,
148 * and then delegates to that implementation. The instantiation and
149 * initialization of the delegate implementation uses the standard
150 * callback object instantiation and initialization methods of Eclipse.
152 * @see com.bolour.sample.eclipse.service.ui.IFunction#compute(long)
154 public final void run(Document doc) {
156 getDelegate().run(doc);
157 } catch (Exception e) {
158 // TODO Auto-generated catch block
164 * Instantiate and initialize the implementation of the function if
165 * this is the first time the proxy has been called.
167 * @return The implementation delegate (same as the instance variable <code>delegate</code>.
168 * @throws Exception If the callback object is misconfigured.
170 private final IMetadataExtension getDelegate() throws Exception {
177 element.createExecutableExtension(CLASS_ATTRIBUTE);
178 if (!(callback instanceof IMetadataExtension)) {
181 + callback.getClass().getName()
182 + "' is not an IFunction";
183 System.err.println(message);
184 throw new ClassCastException(message);
186 delegate = (IMetadataExtension) callback;
187 } catch (CoreException ex) {
188 System.err.println(ex.getMessage());
189 ex.printStackTrace();
191 } catch (Error err) {
192 System.err.println(err.getMessage());
193 err.printStackTrace();
200 * Virtual proxy class for function invokation.
201 * Members of this class support lazy processing by fronting the real
202 * implementations of arithmetic functions configured into extensions.
204 private static class DataFunctionProxy implements IDataExtension {
205 // The "real" implementation of the function.
206 private IDataExtension delegate = null;
207 // The configured state of the extension element representing this arithmetic function.
208 private IConfigurationElement element;
209 // Whether this function has been invoked before.
210 // Used for lazy evaluation of the service.
211 private boolean invoked = false;
214 * Construct a virtual proxy to stand in place of an extension function.
215 * The constructor simply keeps track of an arithmetic function's configured state
216 * without at this time instantiating the implementation of the function.
218 * @param element The configuration of this arithmetic function.
220 public DataFunctionProxy(IConfigurationElement element) {
221 this.element = element;
225 * Compute the function value.
226 * The proxy computation first instantiates the implementation
227 * of the function, if this is the first time the function is called,
228 * and then delegates to that implementation. The instantiation and
229 * initialization of the delegate implementation uses the standard
230 * callback object instantiation and initialization methods of Eclipse.
232 * @see com.bolour.sample.eclipse.service.ui.IFunction#compute(long)
234 public final void run(Document doc) {
236 getDelegate().run(doc);
237 } catch (Exception e) {
238 // TODO Auto-generated catch block
244 * Instantiate and initialize the implementation of the function if
245 * this is the first time the proxy has been called.
247 * @return The implementation delegate (same as the instance variable <code>delegate</code>.
248 * @throws Exception If the callback object is misconfigured.
250 private final IDataExtension getDelegate() throws Exception {
257 element.createExecutableExtension(CLASS_ATTRIBUTE);
258 if (!(callback instanceof IDataExtension)) {
261 + callback.getClass().getName()
262 + "' is not an IFunction";
263 System.err.println(message);
264 throw new ClassCastException(message);
266 delegate = (IDataExtension) callback;
267 } catch (CoreException ex) {
268 System.err.println(ex.getMessage());
269 ex.printStackTrace();
271 } catch (Error err) {
272 System.err.println(err.getMessage());
273 err.printStackTrace();