//////////////////////////////////////////////////////////////////////////////// // Copyright 2013 Michael Schmalle - Teoti Graphix, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License // // Author: Michael Schmalle, Principal Architect // mschmalle at teotigraphix dot com //////////////////////////////////////////////////////////////////////////////// package com.teotigraphix.caustk.controller.command; import java.util.HashMap; import java.util.Map; import com.teotigraphix.caustic.core.CausticException; import com.teotigraphix.caustic.core.Dispatcher; import com.teotigraphix.caustic.core.IDispatcher; import com.teotigraphix.caustk.controller.ICaustkController; import com.teotigraphix.caustk.controller.command.ICommandHistory.OnClearComplete; import com.teotigraphix.caustk.controller.command.ICommandHistory.OnFastForwardComplete; import com.teotigraphix.caustk.controller.command.ICommandHistory.OnRewindComplete; public class CommandManager implements ICommandManager { private ICaustkController controller; private CommandHistory commandHistory; private Map<String, Class<?>> commands = new HashMap<String, Class<?>>(); private String applicationId; //---------------------------------- // dispatcher //---------------------------------- private IDispatcher dispatcher; public IDispatcher getDispatcher() { return dispatcher; } public CommandManager(ICaustkController controller) { this.controller = controller; applicationId = controller.getConfiguration().getApplicationId(); dispatcher = new Dispatcher(); commandHistory = new CommandHistory(dispatcher); } /** * Clears the {@link CommandHistory}. * * @see OnClearComplete */ @Override public void clearHistory() { commandHistory.clear(); } /** * An undo in the {@link ICommandHistory}. * * @see OnRewindComplete */ @Override public int undo() { try { return commandHistory.rewind(1); } catch (Exception e) { e.printStackTrace(); } return -1; } /** * An redo in the {@link ICommandHistory}. * * @see OnFastForwardComplete */ @Override public int redo() { try { return commandHistory.forward(1); } catch (Exception e) { e.printStackTrace(); } return -1; } /** * Adds a {@link ICommand} to the manager. * <p> * The <code>message</code> does not contain the controller head, the * controller/applicationId will automatically be appended. * * @param message The message key that links to the {@link ICommand}. * @param command The Class that will be instantiated. */ @Override public void put(String message, Class<?> command) { final String controllerMessage = returnControllerMessage(message); if (commands.containsKey(controllerMessage)) return; commands.put(controllerMessage, command); } public void remove(String message) { final String controllerMessage = returnControllerMessage(message); if (commands.containsKey(controllerMessage)) { commands.remove(controllerMessage); } } /** * Executes an {@link ICommand} against a registered message. * * @param message The message without the controller/applicationId. * @param args Arguments to pass to the created {@link OSCMessage} that will * be created. * @see #sendOSCCommand(OSCMessage) */ @Override public void execute(String message, Object... args) { try { OSCMessage result = OSCMessage.initialize(returnControllerMessage(message)); for (Object value : args) { result.add(value); } sendOSCCommand(result); } catch (CausticException e) { e.printStackTrace(); } } /** * Capable of sending inter-application messages. * <p> * Not for use within the same app API. */ public void sendOSCCommand(String message) throws CausticException { OSCMessage result = OSCMessage.initialize(message); sendOSCCommand(result); } /** * Executes an {@link ICommand} based on the message. * <p> * The message is forced to have the same {@link #applicationId} as this * instance. This method is not for inter-application communications, see * {@link #sendOSCCommand(String)}. * * @param message The command message without the controller/applicationId * @throws CausticException */ public void sendOSCCommand(OSCMessage message) throws CausticException { // This controller forces ALL messages to use it's root controller name // this will overwrite anything that is passed in //message.setController(applicationId); exectueCommand(message); } private void exectueCommand(OSCMessage message) { System.err.println(" OSC[" + message.toString() + "]"); String commandString = message.toCommandString(); Class<?> command = getCommand(commandString); // TODO should log these commands that cannot be found if (command == null) return; ICommand instance = null; try { instance = (ICommand)command.newInstance(); } catch (IllegalAccessException e) { message.setException(e); e.printStackTrace(); } catch (InstantiationException e) { message.setException(e); e.printStackTrace(); } // Exception thrown during instantiation (constructor) if (instance == null) return; if (instance instanceof CommandBase) ((CommandBase)instance).setContext(new CommandContext(controller, message)); try { if (instance instanceof IUndoCommand) { // this calls execute and adds to history stack commandHistory.execute((IUndoCommand)instance); } else if (instance instanceof ICommand) { // normal execute() instance.execute(); } } catch (CommandExecutionException e) { // if an undo command reaches here, it has NOT been added to history // TODO Figure out how controller will deal with CommandExecutionException // Log.e("Controller[" + getControllerName() + "]", e.getMessage() + " Cause:" // + e.getCause().toString()); e.printStackTrace(); message.setException(e); } } private Class<?> getCommand(String command) { return commands.get(command); } private String returnControllerMessage(String message) { return "/" + applicationId + "/" + message; } }