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