Source: src/main/javascript/oracle/oj/ojrowexpander/MergedNodeSet.js

Oracle® JavaScript Extension Toolkit (JET)
1.1.2

E65298-01

/**
 * Copyright (c) 2014, Oracle and/or its affiliates.
 * All rights reserved.
 */
 
/**
 * Combines two NodeSets together into one.
 * @param {Object} nodeSet1 the first node set
 * @param {Object} nodeSet2 the second node set
 * @param {Object} mergeAt the row key on the first node set where the second node set is merge to 
 * @constructor
 * @export
 */
oj.MergedNodeSet = function(nodeSet1, nodeSet2, mergeAt)
{
    this.m_nodeSet1 = nodeSet1;
    this.m_nodeSet2 = nodeSet2;
    this.m_mergeAt = this._findIndex(mergeAt);
};

/**
 * Retrieve the index of the key within the first node set
 * Which is going to be the index where the two node set merge
 * @param {Object} key the key to find the index
 * @return {number} the index of the key within the first node set, if index is not found, then the last index of the first node set is returned.
 * @private
 */
oj.MergedNodeSet.prototype._findIndex = function(key)
{
    var start, end, i, rowKey;

    start = this.m_nodeSet1.getStart();
    end = start + this.m_nodeSet1.getCount();
    for (i=start; i<end; i++)
    {
        rowKey = this.m_nodeSet1.getMetadata(i)['key'];
        if (key === rowKey)
        {
            return i;
        }
    }

    // if the point cannot be found, the merge happens at the end
    return (end-1);
};

/**
 * Gets the parent
 * @return {Object} the key of the parent.
 * @export
 */
oj.MergedNodeSet.prototype.getParent = function()
{
    // returns the parent of the top node set
    return this.m_nodeSet1.getParent();
};

/**
 * Gets the start index of the result set.  
 * @return {number} the start index of the result set.  
 * @export
 */
oj.MergedNodeSet.prototype.getStart = function()
{
    // returns the start of the top node set
    return this.m_nodeSet1.getStart();
};

/**
 * Gets the actual count of the result set.  
 * @return {number} the actual count of the result set.  
 * @export
 */
oj.MergedNodeSet.prototype.getCount = function()
{
    // return the total count of both node sets
    return this.m_nodeSet1.getCount() + this.m_nodeSet2.getCount();
};

/**
 * Gets the data of the specified index.  An error is throw when 1) the range is not yet available and
 * 2) the index specified is out of bounds. 
 * @param {number} index the index of the node/row in which we want to retrieve the data from.  
 * @return {Object} the data for the specified index.
 * @export
 */
oj.MergedNodeSet.prototype.getData = function(index)
{
    var result, set, relIndex;

    result = this._getRelativeIndex(index);
    set = result['set'];
    relIndex = result['index'];

    return set.getData(relIndex);
};

/**
 * Gets the metadata of the specified index.  An error is throw when 1) the range is not yet available and 
 * 2) the index specified is out of bounds. 
 * The metadata that the data source must return are:
 *  1) key - Object, the key of the node/row.
 *  2) state - state of the node, valid values are 'expanded', 'collapsed', 'leaf'. 
 *  3) depth - number, the depth of the node/row. 
 * @param {number} index the index of the node/row in which we want to retrieve the metadata from.  
 * @return {Object} the metadata object for the specific index.
 * @export
 */
oj.MergedNodeSet.prototype.getMetadata = function(index)
{
    var result, set, relIndex;

    result = this._getRelativeIndex(index);
    set = result['set'];
    relIndex = result['index'];

    return set.getMetadata(relIndex);
};

/**
 * Calculate the relative index to the appropriate node set based on where the
 * merge point is.
 * @private
 */
oj.MergedNodeSet.prototype._getRelativeIndex = function(index)
{
    if (index <= this.m_mergeAt)
    {
        return {'set': this.m_nodeSet1, 'index': index};
    }
    else
    {
        var count = this.m_nodeSet2.getCount();
        var end = this.m_mergeAt + count;
        if (index > end)
        {
            // first set
            return {'set': this.m_nodeSet1, 'index': index - count};
        }   
        else
        {
            // second set
            return {'set': this.m_nodeSet2, 'index': index - (this.m_mergeAt+1)};
        }
    }
};