/******************************************************************************* * Copyright (c) 2001, 2007 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.isBundleActive() == true && 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; } }