airbug/bugcore

View on GitHub
libraries/bugcore/js/src/core/Arr.js

Summary

Maintainability
A
3 hrs
Test Coverage
/*
 * Copyright (c) 2016 airbug Inc. http://airbug.com
 *
 * bugcore may be freely distributed under the MIT license.
 */


//-------------------------------------------------------------------------------
// Annotations
//-------------------------------------------------------------------------------

//@Export('Arr')

//@Require('ArrayIterator')
//@Require('Class')
//@Require('Exception')
//@Require('IArrayable')
//@Require('IIndexValueIterable')
//@Require('IStreamable')
//@Require('Obj')
//@Require('Stream')
//@Require('Suppliers')
//@Require('TypeUtil')


//-------------------------------------------------------------------------------
// Context
//-------------------------------------------------------------------------------

require('bugpack').context("*", function(bugpack) {

    //-------------------------------------------------------------------------------
    // BugPack
    //-------------------------------------------------------------------------------

    var ArrayIterator           = bugpack.require('ArrayIterator');
    var Class                   = bugpack.require('Class');
    var Exception               = bugpack.require('Exception');
    var IArrayable              = bugpack.require('IArrayable');
    var IIndexValueIterable     = bugpack.require('IIndexValueIterable');
    var IStreamable             = bugpack.require('IStreamable');
    var Obj                     = bugpack.require('Obj');
    var Stream                  = bugpack.require('Stream');
    var Suppliers               = bugpack.require('Suppliers');
    var TypeUtil                = bugpack.require('TypeUtil');


    //-------------------------------------------------------------------------------
    // Declare Class
    //-------------------------------------------------------------------------------

    /**
     * @class
     * @extends {Obj}
     * @implements {IIndexValueIterable.<V>}
     * @implements {IStreamable.<V>}
     * @template V
     */
    var Arr = Class.extend(Obj, /** @lends {Arr.prototype} */{

        _name: "Arr",


        //-------------------------------------------------------------------------------
        // Constructor
        //-------------------------------------------------------------------------------

        /**
         * @constructs
         */
        _constructor: function() {

            this._super();


            //-------------------------------------------------------------------------------
            // Private Properties
            //-------------------------------------------------------------------------------

            /**
             * @private
             * @type {Array.<V>}
             */
            this.array  = null;
        },


        //-------------------------------------------------------------------------------
        // Init Methods
        //-------------------------------------------------------------------------------

        /**
         * @param {(IArrayable.<V> | Array.<V>)=} items
         * @return {Arr}
         */
        init: function(items) {
            var _this = this._super();

            if (_this) {
                if (TypeUtil.isArray(items)) {
                    this.array = items;
                } else if (Class.doesImplement(items, IArrayable)) {
                    this.array = items.toArray();
                } else {
                    throw new Exception("IllegalArgument", {}, "'items' must either be an Array or implement IArrayable");
                }
            }
            return _this;
        },


        //-------------------------------------------------------------------------------
        // Getters and Setters
        //-------------------------------------------------------------------------------

        /**
         * @return {Array.<V>}
         */
        getArray: function() {
            return this.array;
        },


        //-------------------------------------------------------------------------------
        // Public Methods
        //-------------------------------------------------------------------------------

        /**
         * @param {V} item
         */
        add: function(item) {
            this.array.push(item);
        },

        /**
         * @param {(Array.<V> | IIterable.<V>)} items
         */
        addAll: function(items) {
            var _this = this;
            items.forEach(function(item) {
                _this.add(item);
            });
        },


        //-------------------------------------------------------------------------------
        // IIndexValueIterable Implementation
        //-------------------------------------------------------------------------------

        /**
         * NOTE BRN: If a value is modified in one iteration and then visited at a later time, its value in the loop is
         * its value at that later time. A value that is deleted before it has been visited will not be visited later.
         * Values added to the Collection over which iteration is occurring may either be visited or omitted from iteration.
         *
         * @param {function(V, number)} func
         */
        forEach: function(func) {
            var iterator = this.iterator();
            while (iterator.hasNext()) {
                var index = iterator.nextIndex();
                func(this.array[index], index);
            }
        },

        /**
         * NOTE BRN: If a value is modified in one iteration and then visited at a later time, its value in the loop is
         * its value at that later time. A value that is deleted before it has been visited will not be visited later.
         * Values added to the Collection over which iteration is occurring may either be visited or omitted from iteration.
         *
         * @param {function(number, V)} func
         */
        forIn: function(func) {
            var iterator = this.iterator();
            while (iterator.hasNext()) {
                var index = iterator.nextIndex();
                func(index, this.array[index]);
            }
        },

        /**
         * NOTE BRN: If a value is modified in one iteration and then visited at a later time, its value in the loop is
         * its value at that later time. A value that is deleted before it has been visited will not be visited later.
         * Values added to the Collection over which iteration is occurring may either be visited or omitted from iteration.
         *
         * @return {IIndexValueIterator.<V>}
         */
        iterator: function() {
            return new ArrayIterator(this.array);
        },


        //-------------------------------------------------------------------------------
        // IStreamable Implementation
        //-------------------------------------------------------------------------------

        /**
         * @return {Stream.<I>}
         */
        stream: function() {
            return Stream.newStream(Suppliers.iterable(this));
        },


        //-------------------------------------------------------------------------------
        // Obj Methods
        //-------------------------------------------------------------------------------

        /**
         * @param {boolean=} deep
         * @return {Arr.<I>}
         */
        clone: function(deep) {
            var cloneArr = new Arr();
            if (deep) {
                this.forEach(function(item) {
                    cloneArr.add(Obj.clone(item, true));
                });
            } else {
                cloneArr.addAll(this);
            }
            return cloneArr;
        }
    });


    //-------------------------------------------------------------------------------
    // Implement Interfaces
    //-------------------------------------------------------------------------------

    Class.implement(Arr, IIndexValueIterable);
    Class.implement(Arr, IStreamable);


    //-------------------------------------------------------------------------------
    // Exports
    //-------------------------------------------------------------------------------

    bugpack.export('Arr', Arr);
});