baja/ord/OrdQueryList.js

/**
 * @copyright 2015 Tridium, Inc. All Rights Reserved.
 * @author Gareth Johnson
 */

/**
 * Defines {@link baja.OrdQueryList}.
 * @module baja/ord/OrdQueryList
 */
define([
  "bajaScript/sys",
  "bajaScript/baja/ord/OrdQueryListCursor" ], function (
   baja,
   OrdQueryListCursor) {
  
  "use strict";
  
  var subclass = baja.subclass,
      bajaDef = baja.def,
      BaseBajaObj = baja.BaseBajaObj;
  
  /**
   * ORD Query List.
   * 
   * Used to hold a list of OrdQueries.
   *
   * @class
   * @alias baja.OrdQueryList
   * @extends baja.BaseBajaObj
   *
   * @see baja.OrdQuery
   *
   * @param {Array.<baja.OrdQuery>} [queries] an array of ORD queries.
   */  
  var OrdQueryList = function OrdQueryList(queries) {  
    this.$queries = queries || [];
  };
  
  subclass(OrdQueryList, BaseBajaObj);
  
  /**
   * Add an ORD Query to the List
   *
   * @param {baja.OrdQuery} query 
   */
  OrdQueryList.prototype.add = function (query) {
    this.$queries.push(query);
  };
  
  /**
   * Is the list empty?
   *
   * @returns {Boolean}
   */
  OrdQueryList.prototype.isEmpty = function () {
    return this.$queries.length === 0;
  };
  
  /**
   * @private
   * @returns {boolean} true if this list contains an unknown ORD scheme
   */
  OrdQueryList.prototype.hasUnknown = function () {
    var queries = this.$queries;
    for (var i = 0, len = queries.length; i < len; ++i) {
      if (queries[i].getScheme() instanceof baja.UnknownScheme) {
        return true;
      }
    }
    return false;
  };

  /**
   * @returns {boolean} false if this list contains an ORD scheme that cannot be
   * resolved in the client
   * @since Niagara 4.10
   */
  OrdQueryList.prototype.isClientResolvable = function () {
    var queries = this.$queries;
    for (var i = 0, len = queries.length; i < len; ++i) {
      if (!queries[i].getScheme().isClientResolvable()) {
        return false;
      }
    }
    return true;
  };
  
  /**
   * Returns a Cursor for use with the ORD Query List.
   *
   * @returns {module:baja/ord/OrdQueryListCursor}
   */
  OrdQueryList.prototype.getCursor = function () {
    return new OrdQueryListCursor(this);
  };
  
  function normalizeOrdQueryList(list, hasUnknownSchemes, cx) {
    var i;
    for (i = 0; i < list.$queries.length; ++i) {

      if ((!hasUnknownSchemes || list.$queries[i].getSchemeName() === 'view') && list.$queries[i].normalize(list, i, cx)) {
        return true;
      }
    }
    return false;
  }
  
  /**
   * Normalize the ORD Query List.
   * 
   * @private
   *
   * @param {Object} [cx] As of Niagara 4.13, this optional parameter can be
   * specified to provide additional context information for this normalize
   * call. For example, if the OrdQuery.RESOLVING_ORD_CX object is passed in,
   * then this normalize call is happening at ORD resolution time.
   *
   * @returns {baja.OrdQueryList} returns itself.
   */
  OrdQueryList.prototype.normalize = function (cx) {

    //Limit the normalize to ViewQueries if there's unknown client ORD Schemes
    for (;;) {
      if (!normalizeOrdQueryList(this, this.hasUnknown(), cx)) {
        break;
      }
    }

    return this;
  };

  /**
   * Deletes the queries at the given index and the one after, then inserts the
   * given query in their place.
   * 
   * @param {number} index
   * @param {baja.OrdQuery} query
   * @since Niagara 4.10
   */
  OrdQueryList.prototype.merge = function (index, query) {
    this.$queries.splice(index, 2, query);
  };

  /**
   * @param {number} indexA
   * @param {number} indexB
   * @returns {boolean} true if the queries at both indexes exist and are the
   * same scheme
   * @since Niagara 4.10
   */
  OrdQueryList.prototype.isSameScheme = function (indexA, indexB) {
    var queries = this.$queries;
    var schemeA = queries[indexA];
    var schemeB = queries[indexB];
    return !!(schemeA && schemeB && (schemeA.getSchemeName() === schemeB.getSchemeName()));

  };
  
  /**
   * Return String representation of the ORD Query List.
   *
   * @param {Number} [length=size()] number of queries to include in the string 
   * @returns {String}
   */
  OrdQueryList.prototype.toString = function (length) {
    length = bajaDef(length, this.$queries.length);
    var a = [], i;
    for (i = 0; i < length; ++i) {
      a.push(this.$queries[i].toString());
    }
    return a.join("|");
  };
  
  /**
   * Return the query object at the specified index.
   *
   * @param {Number|String} index or scheme name.
   * @returns {baja.OrdQuery} query (or null if can't be found).
   */
  OrdQueryList.prototype.get = function (index) {
    var to = typeof index,
        queries = this.$queries,
        i,
        q;
        
    if (to === "number") {
      // Get via index
      q = queries[index];
    } else if (to === "string") {
      // Search via scheme name
      for (i = 0; i < queries.length; ++i) {
        if (queries[i].getSchemeName() === index) {
          q = queries[i];
          break;
        }
      }
    }
    
    return q || null;
  };
    
  /**
   * Set an ORD query object at the given index.
   *
   * @param {Number} index 
   * @param {baja.OrdQuery} query
   */
  OrdQueryList.prototype.set = function (index, query) {
    if (index < 0 || index > this.$queries.length) {
      throw new Error("Invalid index (" + index + ")");
    }
    this.$queries[index] = query;
  };
  
  /**
   * Remove the entry at the specified index and return it.
   *
   * @param {Number} index 
   * @returns {baja.OrdQuery} query
   */
  OrdQueryList.prototype.remove = function (index) {
    var query = null;
    if (index >= 0 && index < this.$queries.length) {
      query = this.$queries.splice(index, 1)[0];
    }
    return query;
  };
  
  /**
   * Return the size of the query list.
   * 
   * @returns {Number} size of the list.
   */
  OrdQueryList.prototype.size = function () {
    return this.$queries.length;
  };
  
  return OrdQueryList;
});