/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.ui.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.part.MultiPageEditorSite;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.wst.sse.ui.internal.extension.ActionDescriptor;
import org.eclipse.wst.sse.ui.internal.extension.IExtendedEditorActionProxyForDelayLoading;
import org.eclipse.wst.sse.ui.internal.extension.RegistryReader;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;


/**
 * This class reads the registry for extensions that plug into 'editorActions'
 * extension point.
 */

public class ExtendedEditorActionBuilder extends RegistryReader {

	public class ExtendedContributor implements IExtendedContributor, IMenuListener {
		private IExtendedSimpleEditor activeExtendedEditor = null;

		private List cache;
		private Map map = new HashMap();
		private IMenuManager menuBar = null;

		private Set menus = new HashSet();

		public ExtendedContributor(List cache) {
			this.cache = cache;
		}

		private IExtendedSimpleEditor computeExtendedEditor(final IEditorPart editor) {
			IExtendedSimpleEditor simpleEditor = null;
			if (editor instanceof IExtendedSimpleEditor) {
				simpleEditor = (IExtendedSimpleEditor) editor;
			}
			if (editor != null && simpleEditor == null) {
				final ISourceEditingTextTools tools = (ISourceEditingTextTools) editor.getAdapter(ISourceEditingTextTools.class);
				if (tools != null) {
					simpleEditor = new IExtendedSimpleEditor() {
						public int getCaretPosition() {
							return tools.getCaretOffset();
						}

						public IDocument getDocument() {
							return tools.getDocument();
						}

						public IEditorPart getEditorPart() {
							return tools.getEditorPart();
						}

						public Point getSelectionRange() {
							ITextSelection selection = tools.getSelection();
							return new Point(selection.getOffset(), selection.getOffset() + selection.getLength());
						}

					};
				}
			}
			return simpleEditor;
		}

		public void contributeToMenu(IMenuManager menu) {
			menuBar = menu;
			long time0 = System.currentTimeMillis();
			for (int i = 0; i < cache.size(); i++) {
				Object obj = cache.get(i);
				if (obj instanceof IConfigurationElement) {
					IConfigurationElement menuElement = (IConfigurationElement) obj;
					if ((menuElement.getName()).equals(TAG_MENU)) {
						contributeMenu(menuElement, menu, true);
						if (debugMenu)
							System.out.println(getClass().getName() + "#contributeToMenu() added: " + menuElement.getAttribute(ATT_ID)); //$NON-NLS-1$
					}
				}
				else if (obj instanceof ActionDescriptor) {
					try {
						ActionDescriptor ad = (ActionDescriptor) obj;
						IMenuManager mm = contributeMenuAction(ad, menu, true, false);
						if (mm != null) {
							map.put(ad.getContributionItem(), mm);
							mm.addMenuListener(this);
							menus.add(mm);
							if (debugMenu)
								System.out.println(getClass().getName() + "#contributeToMenu() added: " + ad.getId()); //$NON-NLS-1$
						}
					}
					catch (Exception e) {
						Logger.logException("contributing to menu", e); //$NON-NLS-1$
					}
				}
			}
			if (debugContributeTime)
				System.out.println(getClass().getName() + "#contributeToMenu(): ran in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		public void contributeToPopupMenu(IMenuManager menu) {
			long time0 = System.currentTimeMillis();
			for (int i = 0; i < cache.size(); i++) {
				Object obj = cache.get(i);
				if (obj instanceof IConfigurationElement) {
					IConfigurationElement menuElement = (IConfigurationElement) obj;
					if ((menuElement.getName()).equals(TAG_POPUPMENU)) {
						contributeMenu(menuElement, menu, true);
					}
				}
				else if (obj instanceof ActionDescriptor) {
					try {
						ActionDescriptor ad = (ActionDescriptor) obj;
						IAction a = ad.getAction();
						if (a instanceof IExtendedEditorAction) {
							// uncaught exceptions could cause the menu to not
							// be shown
							try {
								if (((ad.getPopupMenuPath() != null) || (ad.getPopupMenuGroup() != null)) && (a instanceof IExtendedEditorActionProxyForDelayLoading)) {
								    ((IExtendedEditorActionProxyForDelayLoading)a).realize();
								}

								IExtendedEditorAction eea = (IExtendedEditorAction) a;
								eea.setActiveExtendedEditor(activeExtendedEditor);
								eea.update();
								if (eea.isVisible()) {
									IMenuManager parent = contributeMenuAction(ad, menu, true, true);
									if (debugPopup && parent != null)
										System.out.println(getClass().getName() + "#contributeToPopupMenu() added: " + ad.getId()); //$NON-NLS-1$
								}
							}
							catch (Exception e) {
								Logger.logException(e);
							}

						}
						else {
							IMenuManager parent = contributeMenuAction(ad, menu, true, true);
							if (debugPopup && parent != null)
								System.out.println(getClass().getName() + "#contributeToPopupMenu() added: " + ad.getId()); //$NON-NLS-1$
						}
					}
					catch (Exception e) {
						Logger.logException("contributing to popup", e); //$NON-NLS-1$
					}
				}
			}
			if (debugContributeTime)
				System.out.println(getClass().getName() + "#contributeToPopupMenu(): ran in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		public void contributeToStatusLine(IStatusLineManager manager) {
			// nothing from here
		}

		public void contributeToToolBar(IToolBarManager manager) {
			long time0 = System.currentTimeMillis();
			for (int i = 0; i < cache.size(); i++) {
				Object obj = cache.get(i);
				if (obj instanceof ActionDescriptor) {
					try {
						ActionDescriptor ad = (ActionDescriptor) obj;
						IAction a = ad.getAction();
						if (a instanceof IExtendedEditorAction) {
							if (((ad.getToolbarPath() != null) || (ad.getToolbarGroup() != null)) && (a instanceof IExtendedEditorActionProxyForDelayLoading)) {
							    ((IExtendedEditorActionProxyForDelayLoading)a).realize();
							}
							IExtendedEditorAction eea = (IExtendedEditorAction) a;
							eea.setActiveExtendedEditor(activeExtendedEditor);
							eea.update();
							if (eea.isVisible()) {
								boolean contributed = contributeToolbarAction(ad, manager, true);
								if (debugToolbar && contributed)
									System.out.println(getClass().getName() + "#contributeToToolBar() added: " + ad.getId()); //$NON-NLS-1$
							}
							else {
								if (debugToolbar)
									System.out.println(getClass().getName() + "#contributeToToolBar(): [skipped] " + ad.getId()); //$NON-NLS-1$
							}
						}
						else {
							boolean contributed = contributeToolbarAction(ad, manager, true);
							if (debugToolbar && contributed)
								System.out.println(getClass().getName() + "#contributeToToolBar() added: " + ad.getId()); //$NON-NLS-1$
						}
					}
					catch (Exception e) {
						Logger.logException("contributing to toolbar", e); //$NON-NLS-1$
					}
				}
			}
			if (debugContributeTime)
				System.out.println(getClass().getName() + "#contributeToToolBar(): ran in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		public void dispose() {
			Iterator it = menus.iterator();
			while (it.hasNext()) {
				Object o = it.next();
				if (o instanceof IMenuManager) {
					((IMenuManager) o).removeMenuListener(this);
				}
			}
		}

		public void init(IActionBars bars, IWorkbenchPage page) {
			// nothing from here
		}

		public void menuAboutToShow(IMenuManager menu) {
			// slows down the menu and interferes with it for other editors;
			// optimize on visibility
			IEditorSite site = null;
			boolean activeEditorIsVisible = false;

			if (activeExtendedEditor != null && activeExtendedEditor.getEditorPart() != null)
				site = activeExtendedEditor.getEditorPart().getEditorSite();
			if (site == null)
				return;

			// Eclipse bug 48784 - [MPE] ClassCast exception Workbench page
			// isPartVisiable for MultiPageSite
			if (site instanceof MultiPageEditorSite) {
				Object multiPageEditor = ((MultiPageEditorSite) site).getMultiPageEditor();
				activeEditorIsVisible = multiPageEditor.equals(site.getPage().getActiveEditor()) || multiPageEditor.equals(site.getPage().getActivePart());
			}
			else {
				activeEditorIsVisible = site.getWorkbenchWindow().getPartService().getActivePart().equals(activeExtendedEditor.getEditorPart());
			}
			// due to a delay class loading, don't return now
//			if (!activeEditorIsVisible)
//				return;

			IContributionItem[] items = menu.getItems();
			if (items == null || items.length == 0)
				return;

			for (int i = 0; i < items.length; ++i) {
				// add menu listener to submenu
				if (items[i] instanceof IMenuManager) {
					((IMenuManager) items[i]).addMenuListener(this);
					menus.add(items[i]);
				}
			}

			Set keys = map.keySet();
			Iterator it = keys.iterator();
			boolean needActionContributionItemUpdate = false;
			while (it.hasNext()) {
				IContributionItem item = (IContributionItem) it.next();
				IMenuManager mm = (IMenuManager) map.get(item);
				if (menu.getId() != null && menu.getId().equals(mm.getId()) && item instanceof ActionContributionItem) {
					try {
						IAction action = ((ActionContributionItem) item).getAction();

						if (action instanceof IExtendedEditorActionProxyForDelayLoading) {
						    IExtendedEditorActionProxyForDelayLoading eea = (IExtendedEditorActionProxyForDelayLoading)action;
						    if (eea.isRealized() == false) {
						        eea.realize();
						        needActionContributionItemUpdate = true;
						    }
						}

						if (activeEditorIsVisible || needActionContributionItemUpdate) {
							if (action instanceof IUpdate) {
								((IUpdate) action).update();
							}
						}

						if (activeEditorIsVisible || needActionContributionItemUpdate) {
							boolean visible = true;
							if (action instanceof IExtendedEditorAction) {
								visible = ((IExtendedEditorAction) action).isVisible();
							}
							item.setVisible(visible);
						}

						if (needActionContributionItemUpdate) {
						    ((ActionContributionItem)item).update();
						}

					}
					catch (Exception e) {
						Logger.logException("updating actions", e); //$NON-NLS-1$
					}
				}
			}
			if (activeEditorIsVisible || needActionContributionItemUpdate) {
			    if (needActionContributionItemUpdate) {
			        // the action is realized so that need to update the menu w/
			        // force set to true
			        menu.update(true);
			    } else {
			        menu.update(false);
			    }
			}
		}

		public void setActiveEditor(IEditorPart editor) {
			activeExtendedEditor = computeExtendedEditor(editor);
			IKeyBindingService svc = (editor != null) ? editor.getEditorSite().getKeyBindingService() : null;
			for (int i = 0; i < cache.size(); i++) {
				Object obj = cache.get(i);
				if (obj instanceof ActionDescriptor) {
					ActionDescriptor ad = (ActionDescriptor) obj;
					try {
						IAction action = ad.getAction();
						if (action instanceof IExtendedEditorAction) {
							((IExtendedEditorAction) action).setActiveExtendedEditor(activeExtendedEditor);
							((IExtendedEditorAction) action).update();
							// update visibility right now so that the menu
							// will show/hide properly
							if (!((IExtendedEditorAction) action).isVisible() && ad.getContributionItem() != null)
								ad.getContributionItem().setVisible(false);
							if (svc != null && action.getActionDefinitionId() != null) {
								svc.registerAction(action);
							}
						}
					}
					catch (Exception e) {
						Logger.logException("setting active editor on actions", e); //$NON-NLS-1$
					}
				}
			}

			if (menuBar != null && editor != null) {
				// Class clz = editor.getClass();
				// while (clz != null) {
				// if (clz.getName().equals(targetID)) {
				// contributeToMenu(menuBar);
				// break;
				// }
				// clz = clz.getSuperclass();
				// }
				if (targetIDs.contains(editor.getEditorSite().getId())) {
					contributeToMenu(menuBar);
				}
			}

			updateToolbarActions();
		}

		public void updateToolbarActions() {
			for (int i = 0; i < cache.size(); i++) {
				Object obj = cache.get(i);
				if (obj instanceof ActionDescriptor) {
					try {
						ActionDescriptor ad = (ActionDescriptor) obj;
						if (ad.getToolbarPath() != null) {
							IAction action = ad.getAction();
							if (action instanceof IUpdate) {
								((IUpdate) action).update();
							}
						}
					}
					catch (Exception e) {
						Logger.logException("updating toolbar actions", e); //$NON-NLS-1$
					}
				}
			}
		}
	}

	public static final String ATT_ID = "id"; //$NON-NLS-1$
	public static final String ATT_LABEL = "label"; //$NON-NLS-1$
	public static final String ATT_NAME = "name"; //$NON-NLS-1$
	public static final String ATT_PATH = "path"; //$NON-NLS-1$

	public static final String ATT_TARGET_ID = "targetID"; //$NON-NLS-1$
	protected final static boolean debugContributeTime = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/extendededitoractionbuilder/contributetime")); //$NON-NLS-1$  //$NON-NLS-2$

	protected final static boolean debugMenu = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/extendededitoractionbuilder/debugmenu")); //$NON-NLS-1$  //$NON-NLS-2$;
	protected final static boolean debugPopup = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/extendededitoractionbuilder/debugpopup")); //$NON-NLS-1$  //$NON-NLS-2$;
	protected final static boolean debugReadTime = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/extendededitoractionbuilder/readtime")); //$NON-NLS-1$  //$NON-NLS-2$
	protected final static boolean debugToolbar = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/extendededitoractionbuilder/debugtoolbar")); //$NON-NLS-1$  //$NON-NLS-2$;

	private static final String EXTENDED_EDITOR = "extendedEditor"; //$NON-NLS-1$

	public static final String PL_EXTENDED_EDITOR_ACTIONS = "extendedEditorActions"; //$NON-NLS-1$

	public static final String PLUGIN_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$
	public static final String TAG_ACTION = "action"; //$NON-NLS-1$

	public static final String TAG_CONTRIBUTION_TYPE = "editorContribution"; //$NON-NLS-1$

	public static final String TAG_MENU = "menu"; //$NON-NLS-1$
	public static final String TAG_POPUPMENU = "popupmenu"; //$NON-NLS-1$
	public static final String TAG_RULERMENU = "rulermenu"; //$NON-NLS-1$
	public static final String TAG_SEPARATOR = "separator"; //$NON-NLS-1$

	protected List readingCache;

	protected String targetContributionTag;
	protected List targetIDs;

	/**
	 * The constructor.
	 */
	public ExtendedEditorActionBuilder() {
		super();
	}

	/**
	 * Creates a menu from the information in the menu configuration element
	 * and adds it into the provided menu manager. If 'appendIfMissing' is
	 * true, and menu path slot is not found, it will be created and menu will
	 * be added into it. Otherwise, add operation will fail.
	 */
	protected void contributeMenu(IConfigurationElement menuElement, IMenuManager mng, boolean appendIfMissing) {
		// Get config data.
		String id = menuElement.getAttribute(ATT_ID);
		String label = menuElement.getAttribute(ATT_LABEL);
		String path = menuElement.getAttribute(ATT_PATH);
		if (label == null) {
			Logger.log(Logger.ERROR, "Invalid Menu Extension (label == null): " + id); //$NON-NLS-1$
			return;
		}

		// Calculate menu path and group.
		String group = null;
		if (path != null) {
			int loc = path.lastIndexOf('/');
			if (loc != -1) {
				group = path.substring(loc + 1);
				path = path.substring(0, loc);
			}
			else {
				// assume that path represents a slot
				// so actual path portion should be null
				group = path;
				path = null;
			}
		}

		// Find parent menu.
		IMenuManager parent = mng;
		if (path != null) {
			parent = mng.findMenuUsingPath(path);
			if (parent == null) {
				// Logger.log("Invalid Menu Extension (Path is invalid): " +
				// id);//$NON-NLS-1$
				return;
			}
			// IMenuManager.findMenuUsingPath() returns invisible menu item if
			// the manager can't find
			// the specified path and create new MenuManager for it.
			// I don't know this is a specification or bug.
			// Anyway, to ensure the menu can be visible, setVisible(true)
			// needs to be called.
			parent.setVisible(true);
		}

		// Find reference group.
		if (group == null)
			group = IWorkbenchActionConstants.MB_ADDITIONS;
		IContributionItem sep = parent.find(group);
		if (sep == null) {
			if (appendIfMissing)
				parent.add(new Separator(group));
			else {
				Logger.log(Logger.ERROR, "Invalid Menu Extension (Group is invalid): " + id); //$NON-NLS-1$
				return;
			}
		}

		// If the menu does not exist create it.
		IMenuManager newMenu = parent.findMenuUsingPath(id);
		if (newMenu == null)
			newMenu = new MenuManager(label, id);

		// Create separators.
		IConfigurationElement[] children = menuElement.getChildren(TAG_SEPARATOR);
		for (int i = 0; i < children.length; i++) {
			contributeSeparator(newMenu, children[i]);
		}

		// Add new menu
		try {
			parent.insertAfter(group, newMenu);
		}
		catch (IllegalArgumentException e) {
			Logger.log(Logger.ERROR, "Invalid Menu Extension (Group is missing): " + id); //$NON-NLS-1$
		}
	}

	/**
	 * Contributes action from action descriptor into the provided menu
	 * manager.
	 */
	protected IMenuManager contributeMenuAction(ActionDescriptor ad, IMenuManager menu, boolean appendIfMissing, boolean popupmenu) {
		if (ad.getContributionItem() == null || ad.getAction() == null)
			return null;

		// Get config data.
		String mpath = popupmenu ? ad.getPopupMenuPath() : ad.getMenuPath();
		String mgroup = popupmenu ? ad.getPopupMenuGroup() : ad.getMenuGroup();
		if (mpath == null && mgroup == null)
			return null;

		// Find parent menu.
		IMenuManager parent = menu;
		if (mpath != null) {
			parent = parent.findMenuUsingPath(mpath);
			if (parent == null) {
				// Logger.log("Invalid Menu Extension (Path is invalid): " +
				// ad.getId()); //$NON-NLS-1$
				return null;
			}
			// IMenuManager.findMenuUsingPath() returns invisible menu item if
			// the manager can't find
			// the specified path and create new MenuManager for it.
			// I don't know this is a specification or bug.
			// Anyway, to ensure the menu can be visible, setVisible(true)
			// needs to be called.
			parent.setVisible(true);
		}

		// First remove existing menu item
		IContributionItem item = parent.find(ad.getId());
		if (item != null) {
			parent.remove(ad.getId());
		}

		// Find reference group.
		if (mgroup == null)
			mgroup = IWorkbenchActionConstants.MB_ADDITIONS;
		IContributionItem sep = parent.find(mgroup);
		if (sep == null) {
			if (appendIfMissing)
				parent.add(sep = new Separator(mgroup));
			else {
				Logger.log(Logger.ERROR, "Invalid Menu Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
				return null;
			}
		}

		// Add action.
		try {
			if (popupmenu) {
				// Context menu need a newly created contribution item
				if (sep != null && sep.isGroupMarker())
					parent.appendToGroup(sep.getId(), ad.getAction());
				else
					parent.insertAfter(mgroup, ad.getAction());
			}
			else {
				// Normal menu need to add existing contribution item to
				// remove it from menu listener
				if (sep != null && sep.isGroupMarker())
					parent.appendToGroup(sep.getId(), ad.getContributionItem());
				else
					parent.insertAfter(mgroup, ad.getContributionItem());
			}
		}
		catch (IllegalArgumentException e) {
			Logger.log(Logger.ERROR, "Invalid Menu Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
			parent = null;
		}

		return parent;
	}

	/**
	 * Creates a named menu separator from the information in the
	 * configuration element. If the separator already exists do not create a
	 * second.
	 */
	protected boolean contributeSeparator(IMenuManager menu, IConfigurationElement element) {
		String id = element.getAttribute(ATT_NAME);
		if (id == null || id.length() <= 0)
			return false;
		IContributionItem sep = menu.find(id);
		if (sep != null)
			return false;
		menu.add(new Separator(id));
		return true;
	}

	/**
	 * Contributes action from the action descriptor into the provided tool
	 * bar manager.
	 */
	protected boolean contributeToolbarAction(ActionDescriptor ad, IToolBarManager toolbar, boolean appendIfMissing) {
		if (ad.getContributionItem() == null || ad.getAction() == null)
			return false;

		// Get config data.
		String tpath = ad.getToolbarPath();
		String tgroup = ad.getToolbarGroup();
		if (tpath == null && tgroup == null)
			return false;

		// First remove existing toolbar item
		IContributionItem item = toolbar.find(ad.getId());
		if (item != null) {
			toolbar.remove(ad.getId());
		}

		// Find reference group.
		if (tgroup == null)
			tgroup = IWorkbenchActionConstants.MB_ADDITIONS;
		IContributionItem sep = toolbar.find(tgroup);
		if (sep == null) {
			if (appendIfMissing)
				toolbar.add(new Separator(tgroup));
			else {
				Logger.log(Logger.ERROR, "Invalid Toolbar Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
				return false;
			}
		}

		// Add action to tool bar.
		try {
			if (sep != null && sep.isGroupMarker())
				toolbar.appendToGroup(sep.getId(), ad.getAction());
			else
				toolbar.insertAfter(tgroup, ad.getAction());
		}
		catch (IllegalArgumentException e) {
			Logger.log(Logger.ERROR, "Invalid Toolbar Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
			return false;
		}
		return true;
	}

	/**
	 * This factory method returns a new ActionDescriptor for the
	 * configuration element. It should be implemented by subclasses.
	 */
	protected ActionDescriptor createActionDescriptor(IConfigurationElement element) {
		ActionDescriptor ad = null;
		try {
			ad = new ActionDescriptor(element);
			// these cases like "class not found" are handled
			// at lower level, so no action if formed. In that
			// case, we also don't want to form an action descriptor.
			if ((ad != null) && (ad.getAction() == null)) {
				ad = null;
			}
		}
		catch (Exception e) {
			Logger.traceException(EXTENDED_EDITOR, e);
			ad = null;
		}
		return ad;
	}

	/**
	 * Returns the name of the part ID attribute that is expected in the
	 * target extension.
	 */
	protected String getTargetID(IConfigurationElement element) {
		String value = element.getAttribute(ATT_TARGET_ID);
		return value != null ? value : "???"; //$NON-NLS-1$
	}

	/**
	 * Reads editor contributor if specified directly in the 'editor'
	 * extension point, and all external contributions for this editor's ID
	 * registered in 'editorActions' extension point.
	 */
	public IExtendedContributor readActionExtensions(String editorId) {
		return readActionExtensions(new String[]{editorId});
	}

	/**
	 * Reads editor contributor if specified directly in the 'editor'
	 * extension point, and all external contributions for this editor's ID
	 * registered in 'editorActions' extension point.
	 */
	public IExtendedContributor readActionExtensions(String[] ids) {
		long time0 = System.currentTimeMillis();
		ExtendedContributor ext = null;
		readContributions(ids, TAG_CONTRIBUTION_TYPE, PL_EXTENDED_EDITOR_ACTIONS);
		if (debugReadTime) {
			String idlist = ""; //$NON-NLS-1$
			if (ids.length > 0) {
				for (int i = 0; i < ids.length; i++) {
					idlist += ids[i];
					if (i < ids.length - 1)
						idlist += ","; //$NON-NLS-1$
				}
			}
			System.out.println(getClass().getName() + "#readActionExtensions(" + idlist + "): read in " + (System.currentTimeMillis() - time0) + "ms [" + (readingCache != null ? readingCache.size() : 0) + " contributions]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		}
		if (readingCache != null) {
			ext = new ExtendedContributor(readingCache);
			readingCache = null;
		}
		return ext;
	}

	/**
	 * Reads the contributions from the registry for the provided workbench
	 * part and the provided extension point IDs.
	 */
	protected void readContributions(String[] ids, String tag, String extensionPoint) {
		readingCache = null;
		targetIDs = Arrays.asList(ids);
		targetContributionTag = tag;
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		readRegistry(registry, PLUGIN_ID, extensionPoint);
	}

	/**
	 * Implements abstract method to handle the provided XML element in the
	 * registry.
	 */
	protected boolean readElement(IConfigurationElement element) {
		String tag = element.getName();
		if (tag.equals(targetContributionTag)) {
			String id = getTargetID(element);
			if (id == null || !targetIDs.contains(id)) {
				// This is not of interest to us - don't go deeper
				return true;
			}
		}
		else if (tag.equals(TAG_MENU)) {
			if (readingCache == null)
				readingCache = new ArrayList();
			readingCache.add(element);
			return true; // just cache the element - don't go into it
		}
		else if (tag.equals(TAG_POPUPMENU)) {
			if (readingCache == null)
				readingCache = new ArrayList();
			readingCache.add(element);
			return true; // just cache the element - don't go into it
		}
		else if (tag.equals(TAG_RULERMENU)) {
			if (readingCache == null)
				readingCache = new ArrayList();
			readingCache.add(element);
			return true; // just cache the element - don't go into it
		}
		else if (tag.equals(TAG_ACTION)) {
			if (readingCache == null)
				readingCache = new ArrayList();
			ActionDescriptor ad = createActionDescriptor(element);
			if (ad != null)
				readingCache.add(ad);
			return true; // just cache the action - don't go into
		}
		else {
			return false;
		}

		readElementChildren(element);
		return true;
	}
}
