Source: core/converter/pipeline-converter.js

var Converter = require("./converter").Converter,
    Promise = require("core/promise").Promise;

/**
 * Converter that chains a series of converters together
 *
 *
 * @class PipelineConverter
 * @extends Converter
 */
exports.PipelineConverter = Converter.specialize({


    /********************************************
     * Serialization
     */

    deserializeSelf: {
        value: function (deserializer) {
            var value;
            value = deserializer.getProperty("converters");
            if (value !== void 0) {
                this.converters = value;
            }
        }
    },

    serializeSelf: {
        value: function (serializer) {
            if (this.converters.length > 0) {
                serializer.setProperty("converters", this.converters);
            }
        }
    },

    /********************************************
     * Convert/Revert
     */

    /**
     * The converters to chain on convert()
     * @type {Converter[]}
     */
    converters: {
        value: undefined
    },


    convert: {
        value: function (value) {
            return this._convertWithConverterAtIndex(value, 0);
        }
    },

    _convertWithConverterAtIndex: {
        value: function (input, index) {
            var self = this,
                converter = this.converters[index],
                output = converter.convert(input),
                isFinalOutput = index === (this.converters.length - 1),
                isPromise = this._isThenable(output),
                result;

            index++;



            if (isFinalOutput) {
                result = isPromise ? output : Promise.resolve(output);
            } else if (isPromise) {
                result = output.then(function (value) {
                    return self._convertWithConverterAtIndex(value, index);
                });
            } else {
                result = this._convertWithConverterAtIndex(output, index);
            }

            return result;
        }
    },

    _isThenable: {
        value: function (value) {
            return !!(value && value.then && typeof value.then === "function");
        }
    },


    revert: {
        value: function (value) {
            return this._revertWithConverterAtIndex(value, this.converters.length - 1);
        }
    },

    _revertWithConverterAtIndex: {
        value: function (input, index) {
            var self = this,
                converter = this.converters[index],
                output = converter.revert(input),
                isFinalOutput = index === 0,
                isPromise = this._isThenable(output),
                result;

            index--;

            if (isFinalOutput) {
                result = isPromise ? output : Promise.resolve(output);
            } else if (isPromise) {
                result = output.then(function (value) {
                    return self._revertWithConverterAtIndex(value, index);
                });
            } else {
                result = this._revertWithConverterAtIndex(output, index);
            }

            return result;
        }
    }

});