    /**
     * @author Ed Spencer
     * @class Ext.data.Operation
     * @extends Object
     *
     * <p>Represents a single read or write operation performed by a {@link Ext.data.proxy.Proxy Proxy}.
     * Operation objects are used to enable communication between Stores and Proxies. Application
     * developers should rarely need to interact with Operation objects directly.</p>
     *
     * <p>Several Operations can be batched together in a {@link Ext.data.Batch batch}.</p>
     *
     */
    Ext.define('Ext.data.Operation', {
        /**
         * @cfg {Boolean} synchronous True if this Operation is to be executed synchronously (defaults to true). This
         * property is inspected by a {@link Ext.data.Batch Batch} to see if a series of Operations can be executed in
         * parallel or not.
         */
        synchronous: true,

        /**
         * @cfg {String} action The action being performed by this Operation. Should be one of 'create', 'read', 'update' or 'destroy'
         */
        action: undefined,

        /**
         * @cfg {Array} filters Optional array of filter objects. Only applies to 'read' actions.
         */
        filters: undefined,

        /**
         * @cfg {Array} sorters Optional array of sorter objects. Only applies to 'read' actions.
         */
        sorters: undefined,

        /**
         * @cfg {Object} group Optional grouping configuration. Only applies to 'read' actions where grouping is desired.
         */
        group: undefined,

        /**
         * @cfg {Number} start The start index (offset), used in paging when running a 'read' action.
         */
        start: undefined,

        /**
         * @cfg {Number} limit The number of records to load. Used on 'read' actions when paging is being used.
         */
        limit: undefined,

        /**
         * @cfg {Ext.data.Batch} batch The batch that this Operation is a part of (optional)
         */
        batch: undefined,

        /**
         * Read-only property tracking the start status of this Operation. Use {@link #isStarted}.
         * @property started
         * @type Boolean
         * @private
         */
        started: false,

        /**
         * Read-only property tracking the run status of this Operation. Use {@link #isRunning}.
         * @property running
         * @type Boolean
         * @private
         */
        running: false,

        /**
         * Read-only property tracking the completion status of this Operation. Use {@link #isComplete}.
         * @property complete
         * @type Boolean
         * @private
         */
        complete: false,

        /**
         * Read-only property tracking whether the Operation was successful or not. This starts as undefined and is set to true
         * or false by the Proxy that is executing the Operation. It is also set to false by {@link #setException}. Use
         * {@link #wasSuccessful} to query success status.
         * @property success
         * @type Boolean
         * @private
         */
        success: undefined,

        /**
         * Read-only property tracking the exception status of this Operation. Use {@link #hasException} and see {@link #getError}.
         * @property exception
         * @type Boolean
         * @private
         */
        exception: false,

        /**
         * The error object passed when {@link #setException} was called. This could be any object or primitive.
         * @property error
         * @type Mixed
         * @private
         */
        error: undefined,

        /**
         * Creates new Operation object.
         * @param {Object} config (optional) Config object.
         */
        constructor: function(config) {
            Ext.apply(this, config || {});
        },

        /**
         * Marks the Operation as started
         */
        setStarted: function() {
            this.started = true;
            this.running = true;
        },

        /**
         * Marks the Operation as completed
         */
        setCompleted: function() {
            this.complete = true;
            this.running  = false;
        },

        /**
         * Marks the Operation as successful
         */
        setSuccessful: function() {
            this.success = true;
        },

        /**
         * Marks the Operation as having experienced an exception. Can be supplied with an option error message/object.
         * @param {Mixed} error Optional error string/object
         */
        setException: function(error) {
            this.exception = true;
            this.success = false;
            this.running = false;
            this.error = error;
        },

        /**
         * Returns true if this Operation encountered an exception (see also {@link #getError})
         * @return {Boolean} True if there was an exception
         */
        hasException: function() {
            return this.exception === true;
        },

        /**
         * Returns the error string or object that was set using {@link #setException}
         * @return {Mixed} The error object
         */
        getError: function() {
            return this.error;
        },

        /**
         * Returns an array of Ext.data.Model instances as set by the Proxy.
         * @return {Array} Any loaded Records
         */
        getRecords: function() {
            var resultSet = this.getResultSet();

            return (resultSet === undefined ? this.records : resultSet.records);
        },

        /**
         * Returns the ResultSet object (if set by the Proxy). This object will contain the {@link Ext.data.Model model} instances
         * as well as meta data such as number of instances fetched, number available etc
         * @return {Ext.data.ResultSet} The ResultSet object
         */
        getResultSet: function() {
            return this.resultSet;
        },

        /**
         * Returns true if the Operation has been started. Note that the Operation may have started AND completed,
         * see {@link #isRunning} to test if the Operation is currently running.
         * @return {Boolean} True if the Operation has started
         */
        isStarted: function() {
            return this.started === true;
        },

        /**
         * Returns true if the Operation has been started but has not yet completed.
         * @return {Boolean} True if the Operation is currently running
         */
        isRunning: function() {
            return this.running === true;
        },

        /**
         * Returns true if the Operation has been completed
         * @return {Boolean} True if the Operation is complete
         */
        isComplete: function() {
            return this.complete === true;
        },

        /**
         * Returns true if the Operation has completed and was successful
         * @return {Boolean} True if successful
         */
        wasSuccessful: function() {
            return this.isComplete() && this.success === true;
        },

        /**
         * @private
         * Associates this Operation with a Batch
         * @param {Ext.data.Batch} batch The batch
         */
        setBatch: function(batch) {
            this.batch = batch;
        },

        /**
         * Checks whether this operation should cause writing to occur.
         * @return {Boolean} Whether the operation should cause a write to occur.
         */
        allowWrite: function() {
            return this.action != 'read';
        }
    });