/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.core.internal.command; import java.util.List; import java.util.regex.Matcher; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.osgi.util.NLS; import org.xmind.core.command.ICommand; import org.xmind.core.command.ICommandHandler; import org.xmind.core.command.ICommandService; import org.xmind.core.command.IReturnValueConsumer; import org.xmind.core.command.ReturnValue; import org.xmind.core.command.binary.IBinaryStore; import org.xmind.core.internal.command.XMindCommandHandlerRegistry.CommandHandlerDescriptor; /** * This implementation of command service delegates command execution to * specific command handlers. * * @author Frank Shaka */ public class XMindCommandService implements ICommandService { private static final String[] NO_MATCH_GROUPS = new String[0]; XMindCommandService() { } public IStatus execute(IProgressMonitor monitor, ICommand command, IReturnValueConsumer returnValueConsumer) { if (monitor == null) monitor = new NullProgressMonitor(); monitor.beginTask(null, 100); monitor.subTask(NLS.bind(Messages.XMindCommandService_ExcutingCommand, command)); IProgressMonitor executeMonitor = new SubProgressMonitor(monitor, 90); IStatus returnValue = executeCommand(executeMonitor, command); if (!executeMonitor.isCanceled()) executeMonitor.done(); try { monitor.subTask(Messages.XMindCommandService_ConsumingValue); IProgressMonitor consumeMonitor = new SubProgressMonitor(monitor, 10); consumeCommand(consumeMonitor, command, returnValue, returnValueConsumer); if (!consumeMonitor.isCanceled()) consumeMonitor.done(); if (!monitor.isCanceled()) monitor.done(); return returnValue; } finally { if (returnValue != null && returnValue instanceof ReturnValue) { Object value = ((ReturnValue) returnValue).getValue(); if (value instanceof IBinaryStore) { ((IBinaryStore) value).clear(); } } } } private IStatus executeCommand(IProgressMonitor monitor, ICommand command) { monitor.beginTask(null, 100); monitor.subTask(Messages.XMindCommandService_SearchHandler_Message); List<CommandHandlerDescriptor> handlerDescriptors = XMindCommandHandlerRegistry .getInstance().findMatchedHandlerDescriptors(command); if (handlerDescriptors.isEmpty()) { monitor.done(); return new Status( IStatus.WARNING, XMindCommandPlugin.PLUGIN_ID, CODE_NO_HANDLERS, NLS.bind( Messages.XMindCommandService_SearchHandlersError_Message, command), null); } if (monitor.isCanceled()) return Status.CANCEL_STATUS; monitor.worked(10); monitor.subTask(NLS.bind( Messages.XMindCommandService_HandingCommand_Message, command)); SubProgressMonitor handlersMonitor = new SubProgressMonitor(monitor, 80); IStatus returnValue = handleCommand(handlersMonitor, command, handlerDescriptors); if (returnValue != null && !returnValue.isOK() && returnValue.getSeverity() != IStatus.CANCEL) { Logger.log(returnValue); } else if (returnValue == null) { Logger.log("Command not handled: " + command, null); //$NON-NLS-1$ returnValue = new Status( IStatus.WARNING, XMindCommandPlugin.PLUGIN_ID, CODE_NOT_HANDLED, NLS.bind( Messages.XMindCommandService_CommandHandledError_Message, command), null); } if (monitor.isCanceled()) return Status.CANCEL_STATUS; handlersMonitor.done(); monitor.done(); return returnValue; } protected IStatus handleCommand(SubProgressMonitor monitor, ICommand command, List<CommandHandlerDescriptor> handlerDescriptors) { IStatus returnValue = null; try { monitor.beginTask(null, handlerDescriptors.size()); for (CommandHandlerDescriptor handlerDescriptor : handlerDescriptors) { ICommandHandler handler = handlerDescriptor.getHandler(); if (handler != null) { SubProgressMonitor handlerMonitor = new SubProgressMonitor( monitor, 1); returnValue = handler.execute(handlerMonitor, command, getMatchGroups(handlerDescriptor, command)); if (monitor.isCanceled()) return Status.CANCEL_STATUS; handlerMonitor.done(); if (returnValue != null) break; } } } catch (Throwable e) { return new Status( IStatus.ERROR, XMindCommandPlugin.PLUGIN_ID, NLS.bind( Messages.XMindCommandService_InvokingCommandError_Message, e.toString()), e); } if (monitor.isCanceled()) return Status.CANCEL_STATUS; monitor.done(); return returnValue; } private String[] getMatchGroups(CommandHandlerDescriptor handlerDescriptor, ICommand command) { Matcher matcher = handlerDescriptor.match(command.getCommandName()); if (!matcher.find()) return NO_MATCH_GROUPS; int total = matcher.groupCount(); if (total <= 0) return NO_MATCH_GROUPS; String[] groups = new String[total]; for (int i = 0; i < total; i++) { groups[i] = matcher.group(i + 1); } return groups; } private void consumeCommand(IProgressMonitor monitor, ICommand command, IStatus returnValue, IReturnValueConsumer returnValueConsumer) { if (returnValueConsumer != null) { try { IStatus consumed = returnValueConsumer.consumeReturnValue( monitor, returnValue); if (!monitor.isCanceled() && consumed != null && !consumed.isOK() && consumed.getSeverity() != IStatus.CANCEL) { Logger.log(consumed); } } catch (Throwable e) { Logger.log("Error occurred while consuming return value.", //$NON-NLS-1$ e); } } } }