<commit_before>/*jslint browser: true, maxerr: 50, indent: 4 */
/**
 * Model classes and functions for the FormDesigner
 */
if (typeof formdesigner === 'undefined') {
    var formdesigner = {};
}



/**
 * A regular tree (with any amount of leafs per node)
 * @param tType - is this a DataElement tree or a controlElement tree (use 'data' or 'control' for this argument, respectively)
 * tType defaults to 'data'
 */
var Tree = function (tType) {
    var that = {}, rootNode, treeType = tType;
    if (!treeType) {
        treeType = 'data';
    }

    /**
     * Children is a list of objects.
     * @param children - optional
     * @param value - that value object that this node should contain (should be a Mug)
     */
    var Node = function (children, value) {
        var that = {}, isRootNode = false, 
            nodeValue = value;
        that.value = value;

        children = children || [];
        that.children = children;

        that.getChildren = function () {
            return children;
        };

        that.getValue = function () {
            return nodeValue;
        };

        that.setValue = function (val) {
            nodeValue = val;
            _(that.children).each(function (child) {
                child.getValue().parentMug = val;
            });
        };

        /**
         * DOES NOT CHECK TO SEE IF NODE IS IN TREE ALREADY!
         * Adds child to END of children!
         */
        that.addChild = function (node) {
            if (!children) {
                children = [];
            }
            children.push(node);
        };

        /**
         * Insert child at the given index (0 means first)
         * if index > children.length, will insert at end.
         * -ve index will result in child being added to first of children list.
         */
        that.insertChild = function (node, index) {
            if (node === null) {
                return null;
            }

            if (index < 0) {
                index = 0;
            }

            children.splice(index, 0, node);
        };

        /**
         * Given a mug, finds the node that the mug belongs to.
         * if it is not the current node, will recursively look through 
         * children node (depth first search)
         */
        that.getNodeFromValue = function (value) {
            if (value === null) {
                return null;
            }
            var valueIsFn = _.isFunction(value),
                retVal,
                thisVal = this.getValue();

            if ((!valueIsFn && thisVal === value && thisVal !== ' ') ||
                (valueIsFn && value(thisVal)))
            {
                return this;
            } else {
                for (var i = 0; i < children.length; i++) {
                    retVal = children[i].getNodeFromValue(value);
                    if (retVal) {
                        return retVal;
                    }
                }
            }
            return null; //we haven't found what we're looking for
        };
        that.getNodeFromMug = that.getNodeFromValue;

        that.getMugFromUFID = function (ufid) {
            var node = that.getNodeFromValue(function (value) {
                return value.ufid === ufid;
            });
            
            return node ? node.getValue() : null;
        };

        that.removeChild = function (node) {
            var childIdx = children.indexOf(node);
            if (childIdx !== -1) { //if arg node is a member of the children list
                children.splice(childIdx, 1); //remove it
            }

            return node;
        };

        /**
         * Finds the parentNode of the specified node (recursively going through the tree/children of this node)
         * Returns the parent if found, else null.
         */
        that.findParentNode = function (node) {
            var i, parent = null;
            if (!children || children.length === 0) {
                return null;
            }
            if (children.indexOf(node) !== -1) {
                return this;
            }

            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    parent = children[i].findParentNode(node);
                    if (parent !== null) {
                        return parent;
                    }
                }
            }
            return parent;
        };

        /**
         * An ID used during prettyPrinting of the Node. (a human readable value for the node)
         */
        that.getID = function () {
            var id;
            if (this.isRootNode) {
                id = formdesigner.controller.form.formID;
                if (id) {
                    return id;
                } else {
                    return 'RootNode';
                }
            }
            var mug = this.getValue();
            if (treeType === 'data') {
                return this.getValue().getDataElementID();
            } else if (treeType === 'control') {
                return formdesigner.util.getMugDisplayName(this.getValue());
            } else {
                throw 'Tree does not have a specified treeType! Default is "data" so must have been forcibly removed!';
            }
        };

        /**
         * Get all children MUG TYPES of this node (not recursive, only the top level).
         * Return a list of Mug objects, or empty list for no children.
         */
        that.getChildrenMugs = function () {
            var i, retList = [];
            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    retList.push(children[i].getValue());
                }
            }
            return retList;
        };


        //that.toString = function () {
            //return this.getID();
        //};

        that.prettyPrint = function () {
            var arr = [], i;
            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    arr.push(children[i].prettyPrint());
                }
            }
            if (!children || children.length === 0) {
                return this.getID();
            } else {
                return '' + this.getID() + '[' + arr + ']';
            }
        };

        /**
         * calls the given function on each node (the node
         * is given as the only argument to the given function)
         * and appends the result (if any) to a flat list
         * (the store argument) which is then returned
         * @param nodeFunc
         * @param store
         */
        that.treeMap = function (nodeFunc, store, afterChildFunc) {
            var result, child;
            result = nodeFunc(this); //call on self
            if(result){
                store.push(result);
            }
            for(child in this.getChildren()){
                if(this.getChildren().hasOwnProperty(child)){
                    this.getChildren()[child].treeMap(nodeFunc, store, afterChildFunc); //have each children also perform the func
                }
            }
            if(afterChildFunc){
                afterChildFunc(this, result);
            }
            return store; //return the results
        };

        /**
         * See docs @ Tree.validateTree()
         */
        var validateTree = function () {
            var validationErrors, thisMug, i, childResult;
            if(!this.getValue()){
                throw 'Tree contains node with no values!'
            }
            if (!this.getValue().isValid()) {
                return false;
            }

            for (i in this.getChildren()) {
                if (this.getChildren().hasOwnProperty(i)) {
                    childResult = this.getChildren()[i].validateTree();
                    if(!childResult){
                        return false;
                    }
                }
            }

            //If we got this far, everything checks out.
            return true;


        }
        that.validateTree = validateTree;

        return that;
    };

    var init = function (type) {
        rootNode = new Node(null, ' ');
        rootNode.isRootNode = true;
        treeType = type || 'data';
    }(treeType);
    that.rootNode = rootNode;

    that.getParentNode = function (node) {
        if (this.rootNode === node) { //special case:
            return this.rootNode;
        } else { //regular case
            return this.rootNode.findParentNode(node);
        }
    };

    /**
     * Given a mug, finds the node that the mug belongs to (in this tree).
     * Will return null if nothing is found.
     */
    that.getNodeFromMug = function (mug) {
        return rootNode.getNodeFromMug(mug);
    };

    /**
     * Removes a node (and all it's children) from the tree (regardless of where it is located in the
     * tree) and returns it.
     *
     * If no such node is found in the tree (or node is null/undefined)
     * null is returned.
     */
    var removeNodeFromTree = function (node) {
        if (!node) {
            return null;
        }
        if (!that.getNodeFromMug(node.getValue())) {
            return null;
        } //node not in tree
        var parent = that.getParentNode(node);
        if (parent) {
            parent.removeChild(node);
            return node;
        } else {
            return null;
        }
    };

    /**
     * Insert a Mug as a child to the node containing parentMug.
     *
     * Will MOVE the mug to the new location in the tree if it is already present!
     * @param mug - the Mug to be inserted into the Tree
     * @param position - position relative to the refMug. Can be 'null', 'before', 'after' or 'into'
     * @param refMug - reference Mug.
     *
     * if refMug is null, will default to the last child of the root node.
     * if position is null, will default to 'after'.  If 'into' is specified, mug will be inserted
     * as a ('after') child of the refMug.
     *
     * If an invalid move is specified, no operation will occur.
     */
    that.insertMug = function (mug, position, refMug) {
        var refNode, refNodeSiblings, refNodeIndex, refNodeParent, node;

        if (position !== null && typeof position !== 'string') {
            throw "position argument must be a string or null! Can be 'after', 'before' or 'into'";
        }
        if (!position) {
            position = 'after';
        }

        if (!refMug || (!refMug.controlElement && treeType === 'control')) {
            refNode = rootNode;
            position = 'into';
        } else {
            refNode = this.getNodeFromMug(refMug);
        }

        //remove it from tree if it already exists
        node = removeNodeFromTree(this.getNodeFromMug(mug)); 
        if (!node) {
            node = new Node(null, mug);
        }

        if (position !== 'into') {
            refNodeParent = that.getParentNode(refNode);
            refNodeSiblings = refNodeParent.getChildren();
            refNodeIndex = refNodeSiblings.indexOf(refNode);
            mug.parentMug = refNodeParent.getValue();
        } else {
            mug.parentMug = refMug;
        }

        switch (position) {
            case 'before':<commit_msg>fix inserting a hidden value<commit_after>/*jslint browser: true, maxerr: 50, indent: 4 */
/**
 * Model classes and functions for the FormDesigner
 */
if (typeof formdesigner === 'undefined') {
    var formdesigner = {};
}



/**
 * A regular tree (with any amount of leafs per node)
 * @param tType - is this a DataElement tree or a controlElement tree (use 'data' or 'control' for this argument, respectively)
 * tType defaults to 'data'
 */
var Tree = function (tType) {
    var that = {}, rootNode, treeType = tType;
    if (!treeType) {
        treeType = 'data';
    }

    /**
     * Children is a list of objects.
     * @param children - optional
     * @param value - that value object that this node should contain (should be a Mug)
     */
    var Node = function (children, value) {
        var that = {}, isRootNode = false, 
            nodeValue = value;
        that.value = value;

        children = children || [];
        that.children = children;

        that.getChildren = function () {
            return children;
        };

        that.getValue = function () {
            return nodeValue;
        };

        that.setValue = function (val) {
            nodeValue = val;
            _(that.children).each(function (child) {
                child.getValue().parentMug = val;
            });
        };

        /**
         * DOES NOT CHECK TO SEE IF NODE IS IN TREE ALREADY!
         * Adds child to END of children!
         */
        that.addChild = function (node) {
            if (!children) {
                children = [];
            }
            children.push(node);
        };

        /**
         * Insert child at the given index (0 means first)
         * if index > children.length, will insert at end.
         * -ve index will result in child being added to first of children list.
         */
        that.insertChild = function (node, index) {
            if (node === null) {
                return null;
            }

            if (index < 0) {
                index = 0;
            }

            children.splice(index, 0, node);
        };

        /**
         * Given a mug, finds the node that the mug belongs to.
         * if it is not the current node, will recursively look through 
         * children node (depth first search)
         */
        that.getNodeFromValue = function (value) {
            if (value === null) {
                return null;
            }
            var valueIsFn = _.isFunction(value),
                retVal,
                thisVal = this.getValue();

            if ((!valueIsFn && thisVal === value && thisVal !== ' ') ||
                (valueIsFn && value(thisVal)))
            {
                return this;
            } else {
                for (var i = 0; i < children.length; i++) {
                    retVal = children[i].getNodeFromValue(value);
                    if (retVal) {
                        return retVal;
                    }
                }
            }
            return null; //we haven't found what we're looking for
        };
        that.getNodeFromMug = that.getNodeFromValue;

        that.getMugFromUFID = function (ufid) {
            var node = that.getNodeFromValue(function (value) {
                return value.ufid === ufid;
            });
            
            return node ? node.getValue() : null;
        };

        that.removeChild = function (node) {
            var childIdx = children.indexOf(node);
            if (childIdx !== -1) { //if arg node is a member of the children list
                children.splice(childIdx, 1); //remove it
            }

            return node;
        };

        /**
         * Finds the parentNode of the specified node (recursively going through the tree/children of this node)
         * Returns the parent if found, else null.
         */
        that.findParentNode = function (node) {
            var i, parent = null;
            if (!children || children.length === 0) {
                return null;
            }
            if (children.indexOf(node) !== -1) {
                return this;
            }

            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    parent = children[i].findParentNode(node);
                    if (parent !== null) {
                        return parent;
                    }
                }
            }
            return parent;
        };

        /**
         * An ID used during prettyPrinting of the Node. (a human readable value for the node)
         */
        that.getID = function () {
            var id;
            if (this.isRootNode) {
                id = formdesigner.controller.form.formID;
                if (id) {
                    return id;
                } else {
                    return 'RootNode';
                }
            }
            var mug = this.getValue();
            if (treeType === 'data') {
                return this.getValue().getDataElementID();
            } else if (treeType === 'control') {
                return formdesigner.util.getMugDisplayName(this.getValue());
            } else {
                throw 'Tree does not have a specified treeType! Default is "data" so must have been forcibly removed!';
            }
        };

        /**
         * Get all children MUG TYPES of this node (not recursive, only the top level).
         * Return a list of Mug objects, or empty list for no children.
         */
        that.getChildrenMugs = function () {
            var i, retList = [];
            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    retList.push(children[i].getValue());
                }
            }
            return retList;
        };


        //that.toString = function () {
            //return this.getID();
        //};

        that.prettyPrint = function () {
            var arr = [], i;
            for (i in children) {
                if (children.hasOwnProperty(i)) {
                    arr.push(children[i].prettyPrint());
                }
            }
            if (!children || children.length === 0) {
                return this.getID();
            } else {
                return '' + this.getID() + '[' + arr + ']';
            }
        };

        /**
         * calls the given function on each node (the node
         * is given as the only argument to the given function)
         * and appends the result (if any) to a flat list
         * (the store argument) which is then returned
         * @param nodeFunc
         * @param store
         */
        that.treeMap = function (nodeFunc, store, afterChildFunc) {
            var result, child;
            result = nodeFunc(this); //call on self
            if(result){
                store.push(result);
            }
            for(child in this.getChildren()){
                if(this.getChildren().hasOwnProperty(child)){
                    this.getChildren()[child].treeMap(nodeFunc, store, afterChildFunc); //have each children also perform the func
                }
            }
            if(afterChildFunc){
                afterChildFunc(this, result);
            }
            return store; //return the results
        };

        /**
         * See docs @ Tree.validateTree()
         */
        var validateTree = function () {
            var validationErrors, thisMug, i, childResult;
            if(!this.getValue()){
                throw 'Tree contains node with no values!'
            }
            if (!this.getValue().isValid()) {
                return false;
            }

            for (i in this.getChildren()) {
                if (this.getChildren().hasOwnProperty(i)) {
                    childResult = this.getChildren()[i].validateTree();
                    if(!childResult){
                        return false;
                    }
                }
            }

            //If we got this far, everything checks out.
            return true;


        }
        that.validateTree = validateTree;

        return that;
    };

    var init = function (type) {
        rootNode = new Node(null, ' ');
        rootNode.isRootNode = true;
        treeType = type || 'data';
    }(treeType);
    that.rootNode = rootNode;

    that.getParentNode = function (node) {
        if (this.rootNode === node) { //special case:
            return this.rootNode;
        } else { //regular case
            return this.rootNode.findParentNode(node);
        }
    };

    /**
     * Given a mug, finds the node that the mug belongs to (in this tree).
     * Will return null if nothing is found.
     */
    that.getNodeFromMug = function (mug) {
        return rootNode.getNodeFromMug(mug);
    };

    /**
     * Removes a node (and all it's children) from the tree (regardless of where it is located in the
     * tree) and returns it.
     *
     * If no such node is found in the tree (or node is null/undefined)
     * null is returned.
     */
    var removeNodeFromTree = function (node) {
        if (!node) {
            return null;
        }
        if (!that.getNodeFromMug(node.getValue())) {
            return null;
        } //node not in tree
        var parent = that.getParentNode(node);
        if (parent) {
            parent.removeChild(node);
            return node;
        } else {
            return null;
        }
    };

    /**
     * Insert a Mug as a child to the node containing parentMug.
     *
     * Will MOVE the mug to the new location in the tree if it is already present!
     * @param mug - the Mug to be inserted into the Tree
     * @param position - position relative to the refMug. Can be 'null', 'before', 'after' or 'into'
     * @param refMug - reference Mug.
     *
     * if refMug is null, will default to the last child of the root node.
     * if position is null, will default to 'after'.  If 'into' is specified, mug will be inserted
     * as a ('after') child of the refMug.
     *
     * If an invalid move is specified, no operation will occur.
     */
    that.insertMug = function (mug, position, refMug) {
        var refNode, refNodeSiblings, refNodeIndex, refNodeParent, node;

        if (position !== null && typeof position !== 'string') {
            throw "position argument must be a string or null! Can be 'after', 'before' or 'into'";
        }
        if (!position) {
            position = 'after';
        }

        if (!refMug || refMug === ' ' || 
            (!refMug.controlElement && treeType === 'control'))
        {
            refNode = rootNode;
            position = 'into';
        } else {
            refNode = this.getNodeFromMug(refMug);
        }

        //remove it from tree if it already exists
        node = removeNodeFromTree(this.getNodeFromMug(mug)); 
        if (!node) {
            node = new Node(null, mug);
        }

        if (position !== 'into') {
            refNodeParent = that.getParentNode(refNode);
            refNodeSiblings = refNodeParent.getChildren();
            refNodeIndex = refNodeSiblings.indexOf(refNode);
            mug.parentMug = refNodeParent.getValue();
        } else {
            mug.parentMug = refMug;
        }

        switch (position) {
            case 'before':
{'fraction_non_alphanumeric': 0.10476910757184803, 'fraction_numerical': 0.001156686537948216, 'mean_word_length': 1.39776, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7094323', 'n_tokens_mistral': 5960, 'n_tokens_neox': 5725, 'n_words': 1844}