4acbeff22888a41530c8bf6d5911139f9214ed66
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / java / hover / JavaEditorTextHoverDescriptor.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.internal.ui.text.java.hover;
13
14 import java.text.Collator;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.StringTokenizer;
20
21 import net.sourceforge.phpdt.ui.PreferenceConstants;
22 import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
23 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
24 import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
25
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IConfigurationElement;
28 import org.eclipse.core.runtime.IExtensionRegistry;
29 import org.eclipse.core.runtime.IStatus;
30 import org.eclipse.core.runtime.Platform;
31 import org.eclipse.core.runtime.Status;
32 import org.eclipse.jface.text.Assert;
33 import org.eclipse.swt.SWT;
34 import org.osgi.framework.Bundle;
35
36 /**
37  * Describes a Java editor text hover.
38  * 
39  * @since 2.1
40  */
41 public class JavaEditorTextHoverDescriptor implements Comparable {
42
43         private static final String JAVA_EDITOR_TEXT_HOVER_EXTENSION_POINT = "net.sourceforge.phpeclipse.phpEditorTextHovers"; //$NON-NLS-1$
44
45         private static final String HOVER_TAG = "hover"; //$NON-NLS-1$
46
47         private static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
48
49         private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
50
51         private static final String LABEL_ATTRIBUTE = "label"; //$NON-NLS-1$
52
53         private static final String ACTIVATE_PLUG_IN_ATTRIBUTE = "activate"; //$NON-NLS-1$
54
55         private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
56
57         public static final String NO_MODIFIER = "0"; //$NON-NLS-1$
58
59         public static final String DISABLED_TAG = "!"; //$NON-NLS-1$
60
61         public static final String VALUE_SEPARATOR = ";"; //$NON-NLS-1$
62
63         private int fStateMask;
64
65         private String fModifierString;
66
67         private boolean fIsEnabled;
68
69         private IConfigurationElement fElement;
70
71         /**
72          * Returns all Java editor text hovers contributed to the workbench.
73          */
74         public static JavaEditorTextHoverDescriptor[] getContributedHovers() {
75                 IExtensionRegistry registry = Platform.getExtensionRegistry();
76                 IConfigurationElement[] elements = registry
77                                 .getConfigurationElementsFor(JAVA_EDITOR_TEXT_HOVER_EXTENSION_POINT);
78                 JavaEditorTextHoverDescriptor[] hoverDescs = createDescriptors(elements);
79                 initializeFromPreferences(hoverDescs);
80                 return hoverDescs;
81         }
82
83         /**
84          * Computes the state mask for the given modifier string.
85          * 
86          * @param modifiers
87          *            the string with the modifiers, separated by '+', '-', ';', ','
88          *            or '.'
89          * @return the state mask or -1 if the input is invalid
90          */
91         public static int computeStateMask(String modifiers) {
92                 if (modifiers == null)
93                         return -1;
94
95                 if (modifiers.length() == 0)
96                         return SWT.NONE;
97
98                 int stateMask = 0;
99                 StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
100                                 ",;.:+-* "); //$NON-NLS-1$
101                 while (modifierTokenizer.hasMoreTokens()) {
102                         int modifier = EditorUtility
103                                         .findLocalizedModifier(modifierTokenizer.nextToken());
104                         if (modifier == 0 || (stateMask & modifier) == modifier)
105                                 return -1;
106                         stateMask = stateMask | modifier;
107                 }
108                 return stateMask;
109         }
110
111         /**
112          * Creates a new Java Editor text hover descriptor from the given
113          * configuration element.
114          */
115         private JavaEditorTextHoverDescriptor(IConfigurationElement element) {
116                 Assert.isNotNull(element);
117                 fElement = element;
118         }
119
120         /**
121          * Creates the Java editor text hover.
122          */
123         public IJavaEditorTextHover createTextHover() {
124                 String pluginId = fElement.getDeclaringExtension().getNamespace();
125                 boolean isHoversPlugInActivated = Platform.getBundle(pluginId)
126                                 .getState() == Bundle.ACTIVE;
127                 if (isHoversPlugInActivated || canActivatePlugIn()) {
128                         try {
129                                 return (IJavaEditorTextHover) fElement
130                                                 .createExecutableExtension(CLASS_ATTRIBUTE);
131                         } catch (CoreException x) {
132                                 PHPeclipsePlugin.log(new Status(IStatus.ERROR, PHPeclipsePlugin
133                                                 .getPluginId(), 0, JavaHoverMessages
134                                                 .getString("JavaTextHover.createTextHover"), null)); //$NON-NLS-1$
135                         }
136                 }
137
138                 return null;
139         }
140
141         // ---- XML Attribute accessors
142         // ---------------------------------------------
143
144         /**
145          * Returns the hover's id.
146          */
147         public String getId() {
148                 return fElement.getAttribute(ID_ATTRIBUTE);
149         }
150
151         /**
152          * Returns the hover's class name.
153          */
154         public String getHoverClassName() {
155                 return fElement.getAttribute(CLASS_ATTRIBUTE);
156         }
157
158         /**
159          * Returns the hover's label.
160          */
161         public String getLabel() {
162                 String label = fElement.getAttribute(LABEL_ATTRIBUTE);
163                 if (label != null)
164                         return label;
165
166                 // Return simple class name
167                 label = getHoverClassName();
168                 int lastDot = label.lastIndexOf('.');
169                 if (lastDot >= 0 && lastDot < label.length() - 1)
170                         return label.substring(lastDot + 1);
171                 else
172                         return label;
173         }
174
175         /**
176          * Returns the hover's description.
177          * 
178          * @return the hover's description or <code>null</code> if not provided
179          */
180         public String getDescription() {
181                 return fElement.getAttribute(DESCRIPTION_ATTRIBUTE);
182         }
183
184         public boolean canActivatePlugIn() {
185                 return Boolean.valueOf(
186                                 fElement.getAttribute(ACTIVATE_PLUG_IN_ATTRIBUTE))
187                                 .booleanValue();
188         }
189
190         public boolean equals(Object obj) {
191                 if (obj == null || !obj.getClass().equals(this.getClass())
192                                 || getId() == null)
193                         return false;
194                 return getId().equals(((JavaEditorTextHoverDescriptor) obj).getId());
195         }
196
197         public int hashCode() {
198                 return getId().hashCode();
199         }
200
201         /*
202          * Implements a method from IComparable
203          */
204         public int compareTo(Object o) {
205                 return Collator.getInstance().compare(getLabel(),
206                                 ((JavaEditorTextHoverDescriptor) o).getLabel());
207         }
208
209         // /**
210         // * @param descriptor a JavaEditorTextHoverDescriptor
211         // * @return <code>true</code> if this contributed hover depends on the
212         // other one
213         // */
214         // public boolean dependsOn(JavaEditorTextHoverDescriptor descriptor) {
215         // if (descriptor == null)
216         // return false;
217         //              
218         // IPluginDescriptor thisPluginDescriptor=
219         // fElement.getDeclaringExtension().getDeclaringPluginDescriptor();
220         // IPluginDescriptor otherPluginDescriptor=
221         // descriptor.fElement.getDeclaringExtension().getDeclaringPluginDescriptor();
222         // return dependsOn(thisPluginDescriptor, otherPluginDescriptor);
223         // }
224
225         // private boolean dependsOn(IPluginDescriptor descriptor0,
226         // IPluginDescriptor descriptor1) {
227         //
228         // IPluginRegistry registry= Platform.getPluginRegistry();
229         // IPluginPrerequisite[] prerequisites=
230         // descriptor0.getPluginPrerequisites();
231         //
232         // for (int i= 0; i < prerequisites.length; i++) {
233         // IPluginPrerequisite prerequisite= prerequisites[i];
234         // String id= prerequisite.getUniqueIdentifier();
235         // IPluginDescriptor descriptor= registry.getPluginDescriptor(id);
236         //                      
237         // if (descriptor != null && (descriptor.equals(descriptor1) ||
238         // dependsOn(descriptor, descriptor1)))
239         // return true;
240         // }
241         //              
242         // return false;
243         // }
244
245         private static JavaEditorTextHoverDescriptor[] createDescriptors(
246                         IConfigurationElement[] elements) {
247                 List result = new ArrayList(elements.length);
248                 for (int i = 0; i < elements.length; i++) {
249                         IConfigurationElement element = elements[i];
250                         if (HOVER_TAG.equals(element.getName())) {
251                                 JavaEditorTextHoverDescriptor desc = new JavaEditorTextHoverDescriptor(
252                                                 element);
253                                 result.add(desc);
254                         }
255                 }
256                 Collections.sort(result);
257                 return (JavaEditorTextHoverDescriptor[]) result
258                                 .toArray(new JavaEditorTextHoverDescriptor[result.size()]);
259         }
260
261         private static void initializeFromPreferences(
262                         JavaEditorTextHoverDescriptor[] hovers) {
263                 String compiledTextHoverModifiers = PHPeclipsePlugin.getDefault()
264                                 .getPreferenceStore().getString(
265                                                 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
266
267                 StringTokenizer tokenizer = new StringTokenizer(
268                                 compiledTextHoverModifiers, VALUE_SEPARATOR);
269                 HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
270
271                 while (tokenizer.hasMoreTokens()) {
272                         String id = tokenizer.nextToken();
273                         if (tokenizer.hasMoreTokens())
274                                 idToModifier.put(id, tokenizer.nextToken());
275                 }
276
277                 String compiledTextHoverModifierMasks = PHPeclipsePlugin.getDefault()
278                                 .getPreferenceStore().getString(
279                                                 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
280
281                 tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
282                                 VALUE_SEPARATOR);
283                 HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
284
285                 while (tokenizer.hasMoreTokens()) {
286                         String id = tokenizer.nextToken();
287                         if (tokenizer.hasMoreTokens())
288                                 idToModifierMask.put(id, tokenizer.nextToken());
289                 }
290
291                 for (int i = 0; i < hovers.length; i++) {
292                         String modifierString = (String) idToModifier
293                                         .get(hovers[i].getId());
294                         boolean enabled = true;
295                         if (modifierString == null)
296                                 modifierString = DISABLED_TAG;
297
298                         if (modifierString.startsWith(DISABLED_TAG)) {
299                                 enabled = false;
300                                 modifierString = modifierString.substring(1);
301                         }
302
303                         if (modifierString.equals(NO_MODIFIER))
304                                 modifierString = ""; //$NON-NLS-1$
305
306                         hovers[i].fModifierString = modifierString;
307                         hovers[i].fIsEnabled = enabled;
308                         hovers[i].fStateMask = computeStateMask(modifierString);
309                         if (hovers[i].fStateMask == -1) {
310                                 // Fallback: use stored modifier masks
311                                 try {
312                                         hovers[i].fStateMask = Integer
313                                                         .parseInt((String) idToModifierMask.get(hovers[i]
314                                                                         .getId()));
315                                 } catch (NumberFormatException ex) {
316                                         hovers[i].fStateMask = -1;
317                                 }
318                                 // Fix modifier string
319                                 int stateMask = hovers[i].fStateMask;
320                                 if (stateMask == -1)
321                                         hovers[i].fModifierString = ""; //$NON-NLS-1$
322                                 else
323                                         hovers[i].fModifierString = EditorUtility
324                                                         .getModifierString(stateMask);
325                         }
326                 }
327         }
328
329         /**
330          * Returns the configured modifier getStateMask for this hover.
331          * 
332          * @return the hover modifier stateMask or -1 if no hover is configured
333          */
334         public int getStateMask() {
335                 return fStateMask;
336         }
337
338         /**
339          * Returns the modifier String as set in the preference store.
340          * 
341          * @return the modifier string
342          */
343         public String getModifierString() {
344                 return fModifierString;
345         }
346
347         /**
348          * Returns whether this hover is enabled or not.
349          * 
350          * @return <code>true</code> if enabled
351          */
352         public boolean isEnabled() {
353                 return fIsEnabled;
354         }
355
356         /**
357          * Returns this hover descriptors configuration element.
358          * 
359          * @return the configuration element
360          * @since 3.0
361          */
362         public IConfigurationElement getConfigurationElement() {
363                 return fElement;
364         }
365 }