001: /*******************************************************************************
002: * Copyright (c) 2000, 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.ui.internal.ide.registry;
011:
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.Collections;
015: import java.util.Comparator;
016: import java.util.HashMap;
017: import java.util.HashSet;
018: import java.util.Iterator;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.Set;
022:
023: import org.eclipse.core.resources.IMarker;
024: import org.eclipse.core.runtime.CoreException;
025: import org.eclipse.core.runtime.IConfigurationElement;
026: import org.eclipse.core.runtime.Platform;
027: import org.eclipse.ui.IMarkerHelpRegistry;
028: import org.eclipse.ui.IMarkerResolution;
029: import org.eclipse.ui.IMarkerResolutionGenerator;
030: import org.eclipse.ui.IMarkerResolutionGenerator2;
031: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
032: import org.osgi.framework.Bundle;
033:
034: /**
035: * This class is a registry for marker help contexts and resolutions.
036: */
037: public class MarkerHelpRegistry implements IMarkerHelpRegistry {
038: /**
039: * Table of queries for marker F1 help.
040: */
041: private Map helpQueries = new HashMap();
042:
043: /**
044: * Sorted list of help queries. Used to ensure that the "most specific"
045: * query is tried first
046: */
047: private List sortedHelpQueries;
048:
049: /**
050: * Table of queries for marker resolutions
051: */
052: private Map resolutionQueries = new HashMap();
053:
054: /**
055: * Help context id attribute in configuration element
056: */
057: private static final String ATT_HELP = "helpContextId"; //$NON-NLS-1$
058:
059: /**
060: * Resolution class attribute name in configuration element
061: */
062: private static final String ATT_CLASS = "class"; //$NON-NLS-1$
063:
064: private class QueryComparator implements Comparator {
065: /*
066: * (non-Javadoc) Method declared on Object.
067: */
068: public boolean equals(Object o) {
069: if (!(o instanceof QueryComparator)) {
070: return false;
071: }
072: return true;
073: }
074:
075: /*
076: * (non-Javadoc) Method declared on Comparator.
077: */
078: public int compare(Object o1, Object o2) {
079: // more attribues come first
080: MarkerQuery q1 = (MarkerQuery) o1;
081: MarkerQuery q2 = (MarkerQuery) o2;
082:
083: int size1 = q1.getAttributes().length;
084: int size2 = q2.getAttributes().length;
085:
086: if (size1 > size2) {
087: return -1;
088: }
089: if (size1 == size2) {
090: return 0;
091: }
092: return 1;
093: }
094: }
095:
096: /*
097: * (non-Javadoc) Method declared on IMarkerHelpRegistry.
098: */
099: public String getHelp(IMarker marker) {
100: if (sortedHelpQueries == null) {
101: Set set = helpQueries.keySet();
102: sortedHelpQueries = new ArrayList(set.size());
103: sortedHelpQueries.addAll(set);
104: Collections.sort(sortedHelpQueries, new QueryComparator());
105: }
106:
107: // Return the first match (we assume there is only one)
108: for (Iterator iter = sortedHelpQueries.iterator(); iter
109: .hasNext();) {
110: MarkerQuery query = (MarkerQuery) iter.next();
111: MarkerQueryResult result = query.performQuery(marker);
112: if (result != null) {
113: // See if a matching result is registered
114: Map resultsTable = (Map) helpQueries.get(query);
115:
116: if (resultsTable.containsKey(result)) {
117:
118: Iterator elements = ((Collection) resultsTable
119: .get(result)).iterator();
120: while (elements.hasNext()) {
121: IConfigurationElement element = (IConfigurationElement) elements
122: .next();
123: // We have a match so return the help context id
124: return element.getAttribute(ATT_HELP);
125: }
126: }
127: }
128: }
129: return null;
130: }
131:
132: /*
133: * (non-Javadoc) Method declared on IMarkerHelpRegistry.
134: */
135: public boolean hasResolutions(IMarker marker) {
136: // Detect a match
137: for (Iterator iter = resolutionQueries.keySet().iterator(); iter
138: .hasNext();) {
139: MarkerQuery query = (MarkerQuery) iter.next();
140: MarkerQueryResult result = query.performQuery(marker);
141: if (result != null) {
142: // See if a matching result is registered
143: Map resultsTable = (Map) resolutionQueries.get(query);
144:
145: if (resultsTable.containsKey(result)) {
146:
147: Iterator elements = ((Collection) resultsTable
148: .get(result)).iterator();
149: while (elements.hasNext()) {
150: IConfigurationElement element = (IConfigurationElement) elements
151: .next();
152:
153: if (hasResolution(marker, element))
154: return true;
155: }
156: }
157: }
158: }
159: return false;
160: }
161:
162: /**
163: * Return whether or not this configuration element has a resolution for the
164: * marker.
165: *
166: * @param marker
167: * @param element
168: * @return boolean <code>true</code> if there is a resolution.
169: */
170: private boolean hasResolution(IMarker marker,
171: IConfigurationElement element) {
172: IMarkerResolutionGenerator generator = null;
173: if (Platform.getBundle(element.getNamespace()).getState() == Bundle.ACTIVE) {
174: // The element's plugin is loaded so we instantiate
175: // the resolution
176: try {
177: generator = (IMarkerResolutionGenerator) element
178: .createExecutableExtension(ATT_CLASS);
179: } catch (CoreException e) {
180: IDEWorkbenchPlugin
181: .log(
182: "Unable to instantiate resolution generator", e.getStatus()); //$NON-NLS-1$
183: }
184: if (generator != null) {
185: if (generator instanceof IMarkerResolutionGenerator2) {
186: if (((IMarkerResolutionGenerator2) generator)
187: .hasResolutions(marker)) {
188: return true;
189: }
190: } else {
191: IMarkerResolution[] resolutions = generator
192: .getResolutions(marker);
193: if (resolutions.length > 0) {
194: // there is at least one resolution
195: return true;
196: }
197: }
198: }
199: } else {
200: // The element's plugin in not loaded so we assume
201: // the generator will produce resolutions for the marker
202: return true;
203: }
204: return false;
205: }
206:
207: /* (non-Javadoc)
208: * @see org.eclipse.ui.IMarkerHelpRegistry#getResolutions(org.eclipse.core.resources.IMarker)
209: */
210: public IMarkerResolution[] getResolutions(IMarker marker) {
211: // Collect all matches
212: ArrayList resolutions = new ArrayList();
213: for (Iterator iter = resolutionQueries.keySet().iterator(); iter
214: .hasNext();) {
215: MarkerQuery query = (MarkerQuery) iter.next();
216: MarkerQueryResult result = query.performQuery(marker);
217: if (result != null) {
218: // See if a matching result is registered
219: Map resultsTable = (Map) resolutionQueries.get(query);
220:
221: if (resultsTable.containsKey(result)) {
222:
223: Iterator elements = ((Collection) resultsTable
224: .get(result)).iterator();
225: while (elements.hasNext()) {
226: IConfigurationElement element = (IConfigurationElement) elements
227: .next();
228:
229: IMarkerResolutionGenerator generator = null;
230: try {
231: generator = (IMarkerResolutionGenerator) element
232: .createExecutableExtension(ATT_CLASS);
233: } catch (CoreException e) {
234: IDEWorkbenchPlugin
235: .log(
236: "Unable to instantiate resolution generator", e.getStatus()); //$NON-NLS-1$
237: }
238: if (generator != null) {
239: IMarkerResolution[] generatedResolutions = generator
240: .getResolutions(marker);
241: for (int i = 0; i < generatedResolutions.length; i++) {
242: resolutions
243: .add(generatedResolutions[i]);
244: }
245: }
246:
247: }
248: }
249: }
250: }
251: return (IMarkerResolution[]) resolutions
252: .toArray(new IMarkerResolution[resolutions.size()]);
253: }
254:
255: /**
256: * Adds a help query to the registry.
257: *
258: * @param query
259: * a marker query
260: * @param result
261: * a result for the given query
262: * @param element
263: * the configuration element defining the result
264: */
265: public void addHelpQuery(MarkerQuery query,
266: MarkerQueryResult result, IConfigurationElement element) {
267:
268: addQuery(helpQueries, query, result, element);
269: }
270:
271: /**
272: * Adds a resolution query to the registry.
273: *
274: * @param query
275: * a marker query
276: * @param result
277: * a result for the given query
278: * @param element
279: * the configuration element defining the result
280: */
281: public void addResolutionQuery(MarkerQuery query,
282: MarkerQueryResult result, IConfigurationElement element) {
283:
284: addQuery(resolutionQueries, query, result, element);
285: }
286:
287: /**
288: * Adds a query to the given table.
289: *
290: * @param table
291: * the table to which the query is added
292: * @param query
293: * a marker query
294: * @param result
295: * a result for the given query
296: * @param element
297: * the configuration element defining the result
298: */
299: private void addQuery(Map table, MarkerQuery query,
300: MarkerQueryResult result, IConfigurationElement element) {
301:
302: // See if the query is already in the table
303: Map results = (Map) table.get(query);
304: if (results == null) {
305: // Create a new results table
306: results = new HashMap();
307:
308: // Add the query to the table
309: table.put(query, results);
310: }
311:
312: if (results.containsKey(result)) {
313: Collection currentElements = (Collection) results
314: .get(result);
315: currentElements.add(element);
316: } else {
317: Collection elements = new HashSet();
318: elements.add(element);
319:
320: // Add the new result
321: results.put(result, elements);
322: }
323: }
324: }
|