001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 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.ui.texteditor;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.osgi.framework.Bundle;
018:
019: import org.eclipse.core.resources.IMarker;
020: import org.eclipse.core.resources.IResource;
021: import org.eclipse.core.resources.IWorkspace;
022: import org.eclipse.core.resources.IWorkspaceRunnable;
023: import org.eclipse.core.resources.ResourcesPlugin;
024: import org.eclipse.core.runtime.CoreException;
025: import org.eclipse.core.runtime.IConfigurationElement;
026: import org.eclipse.core.runtime.IExtension;
027: import org.eclipse.core.runtime.IExtensionPoint;
028: import org.eclipse.core.runtime.ILog;
029: import org.eclipse.core.runtime.IProgressMonitor;
030: import org.eclipse.core.runtime.Platform;
031:
032: import org.eclipse.ui.PlatformUI;
033:
034: /**
035: * Utility class for accessing marker attributes. The static methods provided
036: * on this class provide internal exception handling (unexpected
037: * <code>CoreException</code>s are logged to workbench).
038: * <p>
039: * This class provides static methods only; it is not intended to be
040: * instantiated or subclassed by clients.
041: * </p>
042: */
043: public final class MarkerUtilities {
044:
045: /**
046: * Internal marker super type hierarchy cache.
047: * TODO this cache is currently unbound, i.e. only limited by the number of marker types
048: */
049: private static class MarkerTypeHierarchy {
050:
051: private Map fTypeMap;
052: private Map fSuperTypesCache = new HashMap();
053:
054: public String[] getSuperTypes(String typeName) {
055: String[] cachedTypes = (String[]) fSuperTypesCache
056: .get(typeName);
057: if (cachedTypes == null) {
058: cachedTypes = computeSuperTypes(typeName);
059: fSuperTypesCache.put(typeName, cachedTypes);
060: }
061: return cachedTypes;
062: }
063:
064: private String[] computeSuperTypes(String typeName) {
065: ArrayList types = new ArrayList();
066: appendAll(types, getDirectSuperTypes(typeName));
067: int index = 0;
068: while (index < types.size()) {
069: String type = (String) types.get(index++);
070: appendAll(types, getDirectSuperTypes(type));
071: }
072:
073: String[] super Types = new String[types.size()];
074: types.toArray(super Types);
075: return super Types;
076: }
077:
078: private String[] getDirectSuperTypes(String typeName) {
079: return (String[]) getTypeMap().get(typeName);
080: }
081:
082: private void appendAll(List list, Object[] objects) {
083: if (objects == null)
084: return;
085: for (int i = 0; i < objects.length; i++) {
086: Object o = objects[i];
087: if (!list.contains(o))
088: list.add(o);
089: }
090: }
091:
092: private Map getTypeMap() {
093: if (fTypeMap == null)
094: fTypeMap = readTypes();
095: return fTypeMap;
096: }
097:
098: private Map readTypes() {
099: HashMap allTypes = new HashMap();
100: IExtensionPoint point = Platform.getExtensionRegistry()
101: .getExtensionPoint(ResourcesPlugin.PI_RESOURCES,
102: ResourcesPlugin.PT_MARKERS);
103: if (point != null) {
104: IExtension[] extensions = point.getExtensions();
105: for (int i = 0; i < extensions.length; i++) {
106: IExtension extension = extensions[i];
107: ArrayList types = new ArrayList();
108: IConfigurationElement[] configElements = extension
109: .getConfigurationElements();
110: for (int j = 0; j < configElements.length; ++j) {
111: IConfigurationElement element = configElements[j];
112: if (element.getName().equalsIgnoreCase("super")) { //$NON-NLS-1$
113: String type = element.getAttribute("type"); //$NON-NLS-1$
114: if (type != null) {
115: types.add(type);
116: }
117: }
118: }
119: String[] super Types = new String[types.size()];
120: types.toArray(super Types);
121: allTypes.put(extension.getUniqueIdentifier(),
122: super Types);
123: }
124: }
125: return allTypes;
126: }
127: }
128:
129: private static MarkerTypeHierarchy fgMarkerTypeHierarchy;
130:
131: /**
132: * Don't allow instantiation.
133: */
134: private MarkerUtilities() {
135: }
136:
137: /**
138: * Returns the ending character offset of the given marker.
139: *
140: * @param marker the marker
141: * @return the ending character offset, or <code>-1</code> if not set
142: * @see IMarker#CHAR_END
143: * @see IMarker#getAttribute(java.lang.String, int)
144: */
145: public static int getCharEnd(IMarker marker) {
146: return getIntAttribute(marker, IMarker.CHAR_END, -1);
147: }
148:
149: /**
150: * Returns the starting character offset of the given marker.
151: *
152: * @param marker the marker
153: * @return the starting character offset, or <code>-1</code> if not set
154: * @see IMarker#CHAR_START
155: * @see IMarker#getAttribute(java.lang.String,int)
156: */
157: public static int getCharStart(IMarker marker) {
158: return getIntAttribute(marker, IMarker.CHAR_START, -1);
159: }
160:
161: /**
162: * Returns the specified attribute of the given marker as an integer.
163: * Returns the given default if the attribute value is not an integer.
164: *
165: * @param marker the marker
166: * @param attributeName the name of the attribute
167: * @param defaultValue the default value
168: * @return the attribute's value or the default value
169: * if the attribute does not exist or isn't an int
170: */
171: private static int getIntAttribute(IMarker marker,
172: String attributeName, int defaultValue) {
173: if (marker.exists())
174: return marker.getAttribute(attributeName, defaultValue);
175: return defaultValue;
176: }
177:
178: /**
179: * Returns the line number of the given marker.
180: *
181: * @param marker the marker
182: * @return the line number, or <code>-1</code> if not set
183: * @see IMarker#LINE_NUMBER
184: * @see IMarker#getAttribute(java.lang.String,int)
185: */
186: public static int getLineNumber(IMarker marker) {
187: return getIntAttribute(marker, IMarker.LINE_NUMBER, -1);
188: }
189:
190: /**
191: * Returns the priority of the given marker.
192: *
193: * @param marker the marker
194: * @return the priority, or <code>IMarker.PRIORITY_NORMAL</code> if not set
195: * @see IMarker#PRIORITY
196: * @see IMarker#PRIORITY_NORMAL
197: * @see IMarker#getAttribute(java.lang.String,int)
198: */
199: public static int getPriority(IMarker marker) {
200: return getIntAttribute(marker, IMarker.PRIORITY,
201: IMarker.PRIORITY_NORMAL);
202: }
203:
204: /**
205: * Returns the severity of the given marker.
206: *
207: * @param marker the marker
208: * @return the priority, or <code>IMarker.SEVERITY_INFO</code> if not set
209: * @see IMarker#SEVERITY
210: * @see IMarker#SEVERITY_INFO
211: * @see IMarker#getAttribute(java.lang.String,int)
212: */
213: public static int getSeverity(IMarker marker) {
214: return getIntAttribute(marker, IMarker.SEVERITY,
215: IMarker.SEVERITY_INFO);
216: }
217:
218: /**
219: * Handles a core exception which occurs when accessing marker attributes.
220: *
221: * @param e the core exception
222: */
223: private static void handleCoreException(CoreException e) {
224: Bundle bundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
225: ILog log = Platform.getLog(bundle);
226: log.log(e.getStatus());
227: }
228:
229: /**
230: * Returns whether the given marker is of the given type (either directly or indirectly).
231: *
232: * @param marker the marker to be checked
233: * @param type the reference type
234: * @return <code>true</code>if maker is an instance of the reference type
235: */
236: public static boolean isMarkerType(IMarker marker, String type) {
237: if (marker != null) {
238: try {
239: return marker.exists() && marker.isSubtypeOf(type);
240: } catch (CoreException x) {
241: handleCoreException(x);
242: }
243: }
244: return false;
245: }
246:
247: /**
248: * Returns the marker type of the given marker or <code>null</code> if
249: * the type could not be determined.
250: *
251: * @param marker the marker
252: * @return the marker type
253: * @since 3.0
254: */
255: public static String getMarkerType(IMarker marker) {
256: try {
257: return marker.getType();
258: } catch (CoreException x) {
259: handleCoreException(x);
260: }
261: return null;
262: }
263:
264: /**
265: * Returns the message associated with the given marker.
266: *
267: * @param marker the marker
268: * @return the message associated with the marker or <code>null</code>
269: * @since 3.0
270: */
271: public static String getMessage(IMarker marker) {
272: return marker.getAttribute(IMarker.MESSAGE, null);
273: }
274:
275: /**
276: * Sets the ending character offset of the given marker.
277: *
278: * @param marker the marker
279: * @param charEnd the ending character offset
280: * @see IMarker#CHAR_END
281: * @see IMarker#setAttribute(java.lang.String,int)
282: */
283: public static void setCharEnd(IMarker marker, int charEnd) {
284: setIntAttribute(marker, IMarker.CHAR_END, charEnd);
285: }
286:
287: /**
288: * Sets the ending character offset in the given map using the standard
289: * marker attribute name as the key.
290: *
291: * @param map the map (key type: <code>String</code>, value type:
292: * <code>Object</code>)
293: * @param charEnd the ending character offset
294: * @see IMarker#CHAR_END
295: */
296: public static void setCharEnd(Map map, int charEnd) {
297: map.put(IMarker.CHAR_END, new Integer(charEnd));
298: }
299:
300: /**
301: * Sets the starting character offset of the given marker.
302: *
303: * @param marker the marker
304: * @param charStart the starting character offset
305: * @see IMarker#CHAR_START
306: * @see IMarker#setAttribute(java.lang.String,int)
307: */
308: public static void setCharStart(IMarker marker, int charStart) {
309: setIntAttribute(marker, IMarker.CHAR_START, charStart);
310: }
311:
312: /**
313: * Sets the starting character offset in the given map using the standard
314: * marker attribute name as the key.
315: *
316: * @param map the map (key type: <code>String</code>, value type:
317: * <code>Object</code>)
318: * @param charStart the starting character offset
319: * @see IMarker#CHAR_START
320: */
321: public static void setCharStart(Map map, int charStart) {
322: map.put(IMarker.CHAR_START, new Integer(charStart));
323: }
324:
325: /**
326: * Sets the specified attribute of the given marker as an integer.
327: *
328: * @param marker the marker
329: * @param attributeName the attribute name
330: * @param value the int value
331: */
332: private static void setIntAttribute(IMarker marker,
333: String attributeName, int value) {
334: try {
335: if (marker.exists())
336: marker.setAttribute(attributeName, value);
337: } catch (CoreException e) {
338: handleCoreException(e);
339: }
340: }
341:
342: /**
343: * Sets the line number of the given marker.
344: *
345: * @param marker the marker
346: * @param lineNum the line number
347: * @see IMarker#LINE_NUMBER
348: * @see IMarker#setAttribute(java.lang.String,int)
349: */
350: public static void setLineNumber(IMarker marker, int lineNum) {
351: setIntAttribute(marker, IMarker.LINE_NUMBER, lineNum);
352: }
353:
354: /**
355: * Sets the line number in the given map using the standard marker attribute
356: * name as the key.
357: *
358: * @param map the map (key type: <code>String</code>, value type:
359: * <code>Object</code>)
360: * @param lineNum the line number
361: * @see IMarker#LINE_NUMBER
362: */
363: public static void setLineNumber(Map map, int lineNum) {
364: map.put(IMarker.LINE_NUMBER, new Integer(lineNum));
365: }
366:
367: /**
368: * Sets the message in the given map using the standard marker attribute name
369: * as the key.
370: *
371: * @param map the map (key type: <code>String</code>, value type:
372: * <code>Object</code>)
373: * @param message the message
374: * @see IMarker#MESSAGE
375: */
376: public static void setMessage(Map map, String message) {
377: map.put(IMarker.MESSAGE, message);
378: }
379:
380: /**
381: * Creates a marker on the given resource with the given type and attributes.
382: * <p>
383: * This method modifies the workspace (progress is not reported to the user).</p>
384: *
385: * @param resource the resource
386: * @param attributes the attribute map (key type: <code>String</code>,
387: * value type: <code>Object</code>)
388: * @param markerType the type of marker
389: * @throws CoreException if this method fails
390: * @see IResource#createMarker(java.lang.String)
391: */
392: public static void createMarker(final IResource resource,
393: final Map attributes, final String markerType)
394: throws CoreException {
395:
396: IWorkspaceRunnable r = new IWorkspaceRunnable() {
397: public void run(IProgressMonitor monitor)
398: throws CoreException {
399: IMarker marker = resource.createMarker(markerType);
400: marker.setAttributes(attributes);
401: }
402: };
403:
404: resource.getWorkspace().run(r, null, IWorkspace.AVOID_UPDATE,
405: null);
406: }
407:
408: /**
409: * Returns the list of super types for the given marker.
410: * The list is a depth first list and maintains the sequence in which
411: * the super types are listed in the marker specification.
412: *
413: * @param markerType the marker's type
414: * @return a depth-first list of all super types of the given marker type
415: */
416: public static String[] getSuperTypes(String markerType) {
417: if (fgMarkerTypeHierarchy == null)
418: fgMarkerTypeHierarchy = new MarkerTypeHierarchy();
419: return fgMarkerTypeHierarchy.getSuperTypes(markerType);
420: }
421: }
|