/*
* BasicAction.java
* Transform
*
* Copyright (c) 2009-2010 Flagstone Software Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Flagstone Software Ltd. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.flagstone.transform.action;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import com.flagstone.transform.coder.Context;
import com.flagstone.transform.coder.SWFEncoder;
/**
* BasicAction represents all the actions that can be encoded using a single
* byte-code.
*
* Where appropriate the description for an action contains a simple example
* showing the order of arguments on the stack and any result: e.g. 3, 2 -> 1.
* Here 3 and 2 are the numbers on the stack with 2 being the top-most. When the
* action is executed the numbers are popped off and the result to the right of
* the arrow is the result is pushed onto the stack.
*
* <h1>Notes:</h1>
* <p>
* FSPush is used to push literals onto the Stack. See also FSRegisterCopy which
* copies the value on top of the Stack to one of the Flash Player's internal
* registers.
* </p>
*
* <p>
* Arithmetic add is supported by two actions. INTEGER_ADD was introduced in
* Flash 4. It was replaced in Flash 5 by the more flexible ADD action which is
* able to add any two numbers and also concatenate strings. If a string and a
* number are added then the number is converted to its string representation
* before concatenation.
* </p>
*
* <p>
* For comparison, Flash 4 introduced INTEGER_LESS and INTEGER_EQUALS for
* comparing numbers and STRING_LESS and STRING_EQUALS for comparing strings.
* They were superseded in Flash 5 by LESS and EQUALS which work with either
* strings or numbers.
* </p>
*/
public enum BasicAction implements Action {
/** Signals the end of a list of actions. */
END(ActionTypes.END),
/** Move to the next frame. */
NEXT_FRAME(ActionTypes.NEXT_FRAME),
/** Move to the previous frame. */
PREV_FRAME(ActionTypes.PREV_FRAME),
/** Start playing the movie or movie clip. */
PLAY(ActionTypes.PLAY),
/** Stop playing the movie or movie clip. */
STOP(ActionTypes.STOP),
/** Toggle the movie between high and low quality. */
TOGGLE_QUALITY(ActionTypes.TOGGLE_QUALITY),
/** Stop playing all sounds. */
STOP_SOUNDS(ActionTypes.STOP_SOUNDS),
/** Add two integers. */
INTEGER_ADD(ActionTypes.INTEGER_ADD),
/** Subtract two integers. */
SUBTRACT(ActionTypes.SUBTRACT),
/** Multiply two numbers. */
MULTIPLY(ActionTypes.MULTIPLY),
/** Divide two numbers. */
DIVIDE(ActionTypes.DIVIDE),
/** Test whether two integers are equal. */
INTEGER_EQUALS(ActionTypes.INTEGER_EQUALS),
/** Test where one number is less than another. */
INTEGER_LESS(ActionTypes.INTEGER_LESS),
/** Logically and two values together. */
LOGICAL_AND(ActionTypes.LOGICAL_AND),
/** Logically invert a value. */
LOGICAL_NOT(ActionTypes.LOGICAL_NOT),
/** Logically or two values together. */
LOGICAL_OR(ActionTypes.LOGICAL_OR),
/** Test whether two strings are equal. */
STRING_EQUALS(ActionTypes.STRING_EQUALS),
/** Get the length of an ASCII string. */
STRING_LENGTH(ActionTypes.STRING_LENGTH),
/** Substring. */
STRING_EXTRACT(ActionTypes.STRING_EXTRACT),
/** Pop value from the top of the stack. */
POP(ActionTypes.POP),
/** Convert a value to an integer. */
TO_INTEGER(ActionTypes.TO_INTEGER),
/** Get the value of a variable. */
GET_VARIABLE(ActionTypes.GET_VARIABLE),
/** Set the value of a variable. "x", 3 -> */
SET_VARIABLE(ActionTypes.SET_VARIABLE),
/** Execute the following actions with the named movie clip. */
SET_TARGET_2(ActionTypes.SET_TARGET_2),
/** Concatenate two strings. */
STRING_ADD(ActionTypes.STRING_ADD),
/** Push the value of the specified property on the stack. */
GET_PROPERTY(ActionTypes.GET_PROPERTY),
/** Set the value of a property. */
SET_PROPERTY(ActionTypes.SET_PROPERTY),
/** Duplicate a movie clip on the display list. */
CLONE_SPRITE(ActionTypes.CLONE_SPRITE),
/** Delete a movie clip. */
REMOVE_SPRITE(ActionTypes.REMOVE_SPRITE),
/** Append value to debugging window. */
TRACE(ActionTypes.TRACE),
/** Start dragging the mouse. */
START_DRAG(ActionTypes.START_DRAG),
/** Stop dragging the mouse. */
END_DRAG(ActionTypes.END_DRAG),
/** Test where one string is less than another. */
STRING_LESS(ActionTypes.STRING_LESS),
/** Throw an exception. */
THROW(ActionTypes.THROW),
/** Casts the type of an object. */
CAST(ActionTypes.CAST),
/** Identifies a class implements a defined interface. */
IMPLEMENTS(ActionTypes.IMPLEMENTS),
/** FSCommand2 function. */
FS_COMMAND2(ActionTypes.FS_COMMAND2),
/** Push a random number onto the stack. */
RANDOM_NUMBER(ActionTypes.RANDOM_NUMBER),
/** Get the length of an multi-byte string. */
MB_STRING_LENGTH(ActionTypes.MB_STRING_LENGTH),
/** Convert the first character of a string to its ASCII value. */
CHAR_TO_ASCII(ActionTypes.CHAR_TO_ASCII),
/** Convert the ASCII value to the equivalent character. */
ASCII_TO_CHAR(ActionTypes.ASCII_TO_CHAR),
/** Return the elapsed time since the start of the movie. */
GET_TIME(ActionTypes.GET_TIME),
/** Substring of a multi-byte string. */
MB_STRING_EXTRACT(ActionTypes.MB_STRING_EXTRACT),
/** Convert the first character of string to its Unicode value. */
MB_CHAR_TO_ASCII(ActionTypes.MB_CHAR_TO_ASCII),
/** Convert a Unicode value to the equivalent character. */
MB_ASCII_TO_CHAR(ActionTypes.MB_ASCII_TO_CHAR),
/** Delete a variable. */
DELETE_VARIABLE(ActionTypes.DELETE_VARIABLE),
/** Delete an object or variable. */
DELETE(ActionTypes.DELETE),
/** Create and set a variable. */
INIT_VARIABLE(ActionTypes.INIT_VARIABLE),
/** Execute a function. */
EXECUTE_FUNCTION(ActionTypes.EXECUTE_FUNCTION),
/** Return control from a function. */
RETURN(ActionTypes.RETURN),
/** Calculate the modulus of two numbers. */
MODULO(ActionTypes.MODULO),
/** Construct an instance of a built-in object. */
NAMED_OBJECT(ActionTypes.NAMED_OBJECT),
/** Create a new variable. */
NEW_VARIABLE(ActionTypes.NEW_VARIABLE),
/** Create a new array. */
NEW_ARRAY(ActionTypes.NEW_ARRAY),
/** Define a new class. */
NEW_OBJECT(ActionTypes.NEW_OBJECT),
/** Return the type of an object or value. */
GET_TYPE(ActionTypes.GET_TYPE),
/** Return the path to the current movie clip. */
GET_TARGET(ActionTypes.GET_TARGET),
/** Enumerate through the attributes of an object. */
ENUMERATE(ActionTypes.ENUMERATE),
/** Add two numbers. */
ADD(ActionTypes.ADD),
/** Test where one value is less than another. */
LESS(ActionTypes.LESS),
/** Test where one value is equal to another. */
EQUALS(ActionTypes.EQUALS),
/** Converts the string value to a number. */
TO_NUMBER(ActionTypes.TO_NUMBER),
/** Converts the value to a string. */
TO_STRING(ActionTypes.TO_STRING),
/** Duplicate the value at the top of the stack. */
DUPLICATE(ActionTypes.DUPLICATE),
/** Swap the top two values on the stack. */
SWAP(ActionTypes.SWAP),
/** Get the value of an object's attribute. */
GET_ATTRIBUTE(ActionTypes.GET_ATTRIBUTE),
/** Set the value of an object's attribute. */
SET_ATTRIBUTE(ActionTypes.SET_ATTRIBUTE),
/** Increment a number. */
INCREMENT(ActionTypes.INCREMENT),
/** Decrement a number. */
DECREMENT(ActionTypes.DECREMENT),
/** Execute a method. */
EXECUTE_METHOD(ActionTypes.EXECUTE_METHOD),
/** Define a new method for an object. */
NEW_METHOD(ActionTypes.NEW_METHOD),
/** Tests whether an object can be created using the constructor. */
INSTANCEOF(ActionTypes.INSTANCEOF),
/** Enumerate through the attributes of an object. */
ENUMERATE_OBJECT(ActionTypes.ENUMERATE_OBJECT),
/** Bitwise and tow numbers. */
BITWISE_AND(ActionTypes.BITWISE_AND),
/** Bitwise or tow numbers.*/
BITWISE_OR(ActionTypes.BITWISE_OR),
/** Bitwise exclusive-or two numbers. */
BITWISE_XOR(ActionTypes.BITWISE_XOR),
/** Shift a number left. */
SHIFT_LEFT(ActionTypes.SHIFT_LEFT),
/** Arithmetically shift a number right. */
ARITH_SHIFT_RIGHT(ActionTypes.ARITH_SHIFT_RIGHT),
/** Shift a number right. -1, 30 -> 3 */
SHIFT_RIGHT(ActionTypes.SHIFT_RIGHT),
/** Test whether type and value of two objects are equal. */
STRICT_EQUALS(ActionTypes.STRICT_EQUALS),
/** Test whether a number is greater than another. */
GREATER(ActionTypes.GREATER),
/** Test whether a string is greater than another. */
STRING_GREATER(ActionTypes.STRING_GREATER),
/** Identifies that a class inherits from a class. */
EXTENDS(ActionTypes.EXTENDS);
/**
* Table used to store instances of Basic Actions so only one object is
* created for each type of action decoded.
*/
private static final Map<Integer, BasicAction> TABLE
= new LinkedHashMap<Integer, BasicAction>();
static {
for (final BasicAction action : values()) {
TABLE.put(action.type, action);
}
}
/**
* Returns the BasicAction for a given type.
*
* @param actionType
* the type that identifies the action when it is encoded.
*
* @return a shared instance of the object representing a given action type.
*/
public static BasicAction fromInt(final int actionType) {
return TABLE.get(actionType);
}
/** Type used to identify the action when it is encoded. */
private final int type;
/**
* Constructor used to create instances for each type of action.
*
* @param actionType the value representing the action when it is encoded.
*/
private BasicAction(final int actionType) {
type = actionType;
}
/** {@inheritDoc} */
@Override
public BasicAction copy() {
return this;
}
/** {@inheritDoc} */
@Override
public int prepareToEncode(final Context context) {
return 1;
}
/** {@inheritDoc} */
@Override
public void encode(final SWFEncoder coder, final Context context)
throws IOException {
coder.writeByte(type);
}
}