001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.text.java;
011:
012: import java.net.URL;
013: import java.util.ArrayList;
014: import java.util.Iterator;
015: import java.util.List;
016:
017: import org.eclipse.core.runtime.FileLocator;
018: import org.eclipse.core.runtime.IConfigurationElement;
019: import org.eclipse.core.runtime.IExtension;
020: import org.eclipse.core.runtime.IStatus;
021: import org.eclipse.core.runtime.InvalidRegistryObjectException;
022: import org.eclipse.core.runtime.Path;
023: import org.eclipse.core.runtime.Platform;
024: import org.eclipse.core.runtime.Status;
025: import org.eclipse.core.runtime.SubProgressMonitor;
026:
027: import org.eclipse.jface.action.LegacyActionTools;
028: import org.eclipse.jface.resource.ImageDescriptor;
029:
030: import org.eclipse.jdt.internal.corext.util.Messages;
031:
032: import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
033: import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer;
034:
035: import org.eclipse.jdt.internal.ui.JavaPlugin;
036:
037: import org.osgi.framework.Bundle;
038:
039: /**
040: * Describes a category extension to the "javaCompletionProposalComputer" extension point.
041: *
042: * @since 3.2
043: */
044: public final class CompletionProposalCategory {
045: /** The extension schema name of the icon attribute. */
046: private static final String ICON = "icon"; //$NON-NLS-1$
047:
048: private final String fId;
049: private final String fName;
050: private final IConfigurationElement fElement;
051: /** The image descriptor for this category, or <code>null</code> if none specified. */
052: private final ImageDescriptor fImage;
053:
054: private boolean fIsSeparateCommand = true;
055: private boolean fIsEnabled = true;
056: private boolean fIsIncluded = true;
057: private final CompletionProposalComputerRegistry fRegistry;
058:
059: private int fSortOrder = 0x10000;
060: private String fLastError = null;
061:
062: CompletionProposalCategory(IConfigurationElement element,
063: CompletionProposalComputerRegistry registry) {
064: fElement = element;
065: fRegistry = registry;
066: IExtension parent = (IExtension) element.getParent();
067: fId = parent.getUniqueIdentifier();
068: checkNotNull(fId, "id"); //$NON-NLS-1$
069: String name = parent.getLabel();
070: if (name == null)
071: fName = fId;
072: else
073: fName = name;
074:
075: String icon = element.getAttribute(ICON);
076: ImageDescriptor img = null;
077: if (icon != null) {
078: Bundle bundle = getBundle();
079: if (bundle != null) {
080: Path path = new Path(icon);
081: URL url = FileLocator.find(bundle, path, null);
082: img = ImageDescriptor.createFromURL(url);
083: }
084: }
085: fImage = img;
086:
087: }
088:
089: CompletionProposalCategory(String id, String name,
090: CompletionProposalComputerRegistry registry) {
091: fRegistry = registry;
092: fId = id;
093: fName = name;
094: fElement = null;
095: fImage = null;
096: }
097:
098: private Bundle getBundle() {
099: String namespace = fElement.getDeclaringExtension()
100: .getContributor().getName();
101: Bundle bundle = Platform.getBundle(namespace);
102: return bundle;
103: }
104:
105: /**
106: * Checks an element that must be defined according to the extension
107: * point schema.
108: *
109: * @param obj the element to be checked
110: * @param attribute the attribute
111: * @throws InvalidRegistryObjectException if <code>obj</code> is <code>null</code>
112: */
113: private void checkNotNull(Object obj, String attribute)
114: throws InvalidRegistryObjectException {
115: if (obj == null) {
116: Object[] args = { getId(),
117: fElement.getContributor().getName(), attribute };
118: String message = Messages
119: .format(
120: JavaTextMessages.CompletionProposalComputerDescriptor_illegal_attribute_message,
121: args);
122: IStatus status = new Status(IStatus.WARNING, JavaPlugin
123: .getPluginId(), IStatus.OK, message, null);
124: JavaPlugin.log(status);
125: throw new InvalidRegistryObjectException();
126: }
127: }
128:
129: /**
130: * Returns the identifier of the described extension.
131: *
132: * @return Returns the id
133: */
134: public String getId() {
135: return fId;
136: }
137:
138: /**
139: * Returns the name of the described extension.
140: *
141: * @return Returns the name
142: */
143: public String getName() {
144: return fName;
145: }
146:
147: /**
148: * Returns the name of the described extension
149: * without mnemonic hint in order to be displayed
150: * in a message.
151: *
152: * @return Returns the name
153: */
154: public String getDisplayName() {
155: return LegacyActionTools.removeMnemonics(fName);
156: }
157:
158: /**
159: * Returns the image descriptor of the described category.
160: *
161: * @return the image descriptor of the described category
162: */
163: public ImageDescriptor getImageDescriptor() {
164: return fImage;
165: }
166:
167: /**
168: * Sets the separate command state of the category.
169: *
170: * @param enabled the new enabled state.
171: */
172: public void setSeparateCommand(boolean enabled) {
173: fIsSeparateCommand = enabled;
174: }
175:
176: /**
177: * Returns the enablement state of the category.
178: *
179: * @return the enablement state of the category
180: */
181: public boolean isSeparateCommand() {
182: return fIsSeparateCommand;
183: }
184:
185: /**
186: * @param included the included
187: */
188: public void setIncluded(boolean included) {
189: fIsIncluded = included;
190: }
191:
192: /**
193: * @return included
194: */
195: public boolean isIncluded() {
196: return fIsIncluded;
197: }
198:
199: public boolean isEnabled() {
200: return fIsEnabled;
201: }
202:
203: public void setEnabled(boolean isEnabled) {
204: fIsEnabled = isEnabled;
205: }
206:
207: /**
208: * Returns <code>true</code> if the category contains any computers, <code>false</code>
209: * otherwise.
210: *
211: * @return <code>true</code> if the category contains any computers, <code>false</code>
212: * otherwise
213: */
214: public boolean hasComputers() {
215: List descriptors = fRegistry.getProposalComputerDescriptors();
216: for (Iterator it = descriptors.iterator(); it.hasNext();) {
217: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
218: .next();
219: if (desc.getCategory() == this )
220: return true;
221: }
222: return false;
223: }
224:
225: /**
226: * Returns <code>true</code> if the category contains any computers in the given partition, <code>false</code>
227: * otherwise.
228: *
229: * @param partition the partition
230: * @return <code>true</code> if the category contains any computers, <code>false</code>
231: * otherwise
232: */
233: public boolean hasComputers(String partition) {
234: List descriptors = fRegistry
235: .getProposalComputerDescriptors(partition);
236: for (Iterator it = descriptors.iterator(); it.hasNext();) {
237: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
238: .next();
239: if (desc.getCategory() == this )
240: return true;
241: }
242: return false;
243: }
244:
245: /**
246: * @return sortOrder
247: */
248: public int getSortOrder() {
249: return fSortOrder;
250: }
251:
252: /**
253: * @param sortOrder the sortOrder
254: */
255: public void setSortOrder(int sortOrder) {
256: fSortOrder = sortOrder;
257: }
258:
259: /**
260: * Safely computes completion proposals of all computers of this category through their
261: * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
262: * the contract described in {@link IJavaCompletionProposalComputer}, it is disabled.
263: *
264: * @param context the invocation context passed on to the extension
265: * @param partition the partition type where to invocation occurred
266: * @param monitor the progress monitor passed on to the extension
267: * @return the list of computed completion proposals (element type:
268: * {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
269: */
270: public List computeCompletionProposals(
271: ContentAssistInvocationContext context, String partition,
272: SubProgressMonitor monitor) {
273: fLastError = null;
274: List result = new ArrayList();
275: List descriptors = new ArrayList(fRegistry
276: .getProposalComputerDescriptors(partition));
277: for (Iterator it = descriptors.iterator(); it.hasNext();) {
278: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
279: .next();
280: if (desc.getCategory() == this )
281: result.addAll(desc.computeCompletionProposals(context,
282: monitor));
283: if (fLastError == null)
284: fLastError = desc.getErrorMessage();
285: }
286: return result;
287: }
288:
289: /**
290: * Safely computes context information objects of all computers of this category through their
291: * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
292: * the contract described in {@link IJavaCompletionProposalComputer}, it is disabled.
293: *
294: * @param context the invocation context passed on to the extension
295: * @param partition the partition type where to invocation occurred
296: * @param monitor the progress monitor passed on to the extension
297: * @return the list of computed context information objects (element type:
298: * {@link org.eclipse.jface.text.contentassist.IContextInformation})
299: */
300: public List computeContextInformation(
301: ContentAssistInvocationContext context, String partition,
302: SubProgressMonitor monitor) {
303: fLastError = null;
304: List result = new ArrayList();
305: List descriptors = new ArrayList(fRegistry
306: .getProposalComputerDescriptors(partition));
307: for (Iterator it = descriptors.iterator(); it.hasNext();) {
308: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
309: .next();
310: if (desc.getCategory() == this
311: && (isIncluded() || isSeparateCommand()))
312: result.addAll(desc.computeContextInformation(context,
313: monitor));
314: if (fLastError == null)
315: fLastError = desc.getErrorMessage();
316: }
317: return result;
318: }
319:
320: /**
321: * Returns the error message from the computers in this category.
322: *
323: * @return the error message from the computers in this category
324: */
325: public String getErrorMessage() {
326: return fLastError;
327: }
328:
329: /**
330: * Notifies the computers in this category of a proposal computation session start.
331: */
332: public void sessionStarted() {
333: List descriptors = new ArrayList(fRegistry
334: .getProposalComputerDescriptors());
335: for (Iterator it = descriptors.iterator(); it.hasNext();) {
336: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
337: .next();
338: if (desc.getCategory() == this )
339: desc.sessionStarted();
340: if (fLastError == null)
341: fLastError = desc.getErrorMessage();
342: }
343: }
344:
345: /**
346: * Notifies the computers in this category of a proposal computation session end.
347: */
348: public void sessionEnded() {
349: List descriptors = new ArrayList(fRegistry
350: .getProposalComputerDescriptors());
351: for (Iterator it = descriptors.iterator(); it.hasNext();) {
352: CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it
353: .next();
354: if (desc.getCategory() == this)
355: desc.sessionEnded();
356: if (fLastError == null)
357: fLastError = desc.getErrorMessage();
358: }
359: }
360:
361: }
|