| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.help.internal.context; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.help.AbstractContextProvider; |
| import org.eclipse.help.IContext; |
| import org.eclipse.help.internal.HelpPlugin; |
| |
| /* |
| * Manages all context-sensitive help data for the help system. |
| */ |
| public class ContextManager { |
| |
| private static final String EXTENSION_POINT_ID_CONTEXT = HelpPlugin.PLUGIN_ID + ".contexts"; //$NON-NLS-1$ |
| private static final String ELEMENT_NAME_CONTEXT_PROVIDER = "contextProvider"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_NAME_CLASS = "class"; //$NON-NLS-1$ |
| |
| private Map<String, List<AbstractContextProvider>> providersByPluginId; |
| private Map<String, List<String>> contextIDsByPluginId; |
| private List<AbstractContextProvider> globalProviders; |
| |
| public ContextManager() |
| { |
| if (HelpPlugin.DEBUG_CONTEXT) |
| checkContextProviders(); |
| } |
| |
| /* |
| * Returns the Context for the given id and locale. |
| */ |
| public IContext getContext(String contextId, String locale) { |
| |
| |
| if (HelpPlugin.DEBUG_CONTEXT && contextId != null) { |
| System.out.println("ContextManager.getContext(\"" + contextId + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| // ask the providers |
| int index = contextId.lastIndexOf('.'); |
| if (index != -1) { |
| String pluginId = contextId.substring(0, index); |
| Iterator<AbstractContextProvider> iter = getContextProviders(pluginId).iterator(); |
| while (iter.hasNext()) { |
| AbstractContextProvider provider = iter.next(); |
| try { |
| IContext context = provider.getContext(contextId, locale); |
| if (context != null) { |
| if (HelpPlugin.DEBUG_CONTEXT) { |
| System.out.println("ContextManager.getContext found context, description = \"" + context.getText() + '"'); //$NON-NLS-1$ |
| } |
| return new Context(context, contextId); |
| } |
| } |
| catch (Throwable t) { |
| // log and skip |
| String msg = "Error querying context provider (" + provider.getClass().getName() + ") with context Id: " + contextId; //$NON-NLS-1$ //$NON-NLS-2$ |
| HelpPlugin.logError(msg, t); |
| } |
| } |
| } |
| |
| if (HelpPlugin.DEBUG_CONTEXT) { |
| System.out.println("ContextManager.getContext - no context found"); //$NON-NLS-1$ |
| |
| String id = contextId; |
| ArrayList<String> potentialMatches = new ArrayList<>(); |
| if ((index = contextId.lastIndexOf('.'))>-1) |
| id = contextId.substring(index+1); |
| |
| String warning = "Registered Context Provider IDs:\n"; //$NON-NLS-1$ |
| Iterator<String> iter = contextIDsByPluginId.keySet().iterator(); |
| warning+="--------------------------------\n"; //$NON-NLS-1$ |
| while (iter.hasNext()) { |
| String pluginID = iter.next(); |
| List<String> contextIDList = contextIDsByPluginId.get(pluginID); |
| for (int c = 0; c < contextIDList.size(); c++) { |
| if (contextIDList.get(c).equalsIgnoreCase(id)) { |
| potentialMatches.add(pluginID+'.'+contextIDList.get(c)); |
| break; |
| } |
| } |
| |
| warning+=pluginID+' '+contextIDList.toString()+'\n'; |
| } |
| warning+="--------------------------------"; //$NON-NLS-1$ |
| System.out.println(warning); |
| |
| if (!potentialMatches.isEmpty()) |
| System.out.println("The ID searched is "+contextId+". Did you mean to call setHelp with:\n"+potentialMatches); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| return null; |
| } |
| |
| /* |
| * Returns all registered context providers (potentially cached) for the |
| * given plug-in id. |
| */ |
| private List<AbstractContextProvider> getContextProviders(String pluginId) { |
| if (providersByPluginId == null) { |
| loadContextProviders(); |
| } |
| List<AbstractContextProvider> list = new ArrayList<>(); |
| List<AbstractContextProvider> forPlugin = providersByPluginId.get(pluginId); |
| if (forPlugin != null) { |
| list.addAll(forPlugin); |
| } |
| list.addAll(globalProviders); |
| return list; |
| } |
| |
| /* |
| * Finds and instantiates all registered context-sensitive help providers. |
| */ |
| private void loadContextProviders() { |
| providersByPluginId = new HashMap<>(); |
| globalProviders = new ArrayList<>(); |
| |
| IExtensionRegistry registry = Platform.getExtensionRegistry(); |
| IConfigurationElement[] elements = registry.getConfigurationElementsFor(EXTENSION_POINT_ID_CONTEXT); |
| for (int i=0;i<elements.length;++i) { |
| IConfigurationElement elem = elements[i]; |
| if (elem.getName().equals(ELEMENT_NAME_CONTEXT_PROVIDER)) { |
| try { |
| AbstractContextProvider provider = (AbstractContextProvider)elem.createExecutableExtension(ATTRIBUTE_NAME_CLASS); |
| String[] plugins = provider.getPlugins(); |
| if (plugins != null) { |
| for (int j=0;j<plugins.length;++j) { |
| List<AbstractContextProvider> list = providersByPluginId.get(plugins[j]); |
| if (list == null) { |
| list = new ArrayList<>(); |
| providersByPluginId.put(plugins[j], list); |
| } |
| list.add(provider); |
| } |
| } else { |
| globalProviders.add(provider); |
| } |
| } |
| catch (CoreException e) { |
| // log and skip |
| String msg = "Error instantiating context-sensitive help provider class \"" + elem.getAttribute(ATTRIBUTE_NAME_CLASS) + '"'; //$NON-NLS-1$ |
| HelpPlugin.logError(msg, e); |
| } |
| } |
| } |
| } |
| |
| /* |
| * Method only called when debugging context |
| * sensitive help. |
| * |
| * Checks to see if there are any duplicate ids |
| * |
| */ |
| private void checkContextProviders() |
| { |
| contextIDsByPluginId = new Hashtable<>(); |
| Hashtable<String, Context> contextByContextID = new Hashtable<>(); |
| |
| if (providersByPluginId == null) { |
| loadContextProviders(); |
| } |
| |
| Iterator<String> i = providersByPluginId.keySet().iterator(); |
| |
| while (i.hasNext()) |
| { |
| String pluginID = i.next(); |
| List<AbstractContextProvider> providers = providersByPluginId.get(pluginID); |
| |
| for (int p = 0; p < providers.size(); p++) { |
| ContextFileProvider provider = (ContextFileProvider)providers.get(p); |
| Map<String, Context>[] maps = provider.getPluginContexts(pluginID, Platform.getNL()); |
| |
| for (int m = 0; m < maps.length; m++) { |
| Iterator<String> i2 = maps[m].keySet().iterator(); |
| while (i2.hasNext()) { |
| String contextID = i2.next(); |
| String fullID = pluginID+'.'+contextID; |
| Context currentContext = maps[m].get(contextID); |
| |
| if (!contextByContextID.containsKey(fullID)) { |
| contextByContextID.put(fullID,currentContext); |
| } else if (HelpPlugin.DEBUG_CONTEXT) { |
| Context initialContext = contextByContextID.get(fullID); |
| String error = "Context Help ID '"+contextID+"' is found in multiple context files in plugin '"+pluginID+"'\n"+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| " Description 1: "+initialContext.getText()+'\n'+ //$NON-NLS-1$ |
| " Description 2: "+currentContext.getText(); //$NON-NLS-1$ |
| |
| System.out.println(error); |
| } |
| |
| List<String> list = contextIDsByPluginId.get(pluginID); |
| if (list==null){ |
| list = new ArrayList<>(); |
| contextIDsByPluginId.put(pluginID,list); |
| } |
| list.add(contextID); |
| } |
| } |
| } |
| } |
| } |
| } |