baja/ord/BogScheme.js

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

/**
 * Defines {@link baja.BogScheme}.
 * @module baja/ord/BogScheme
 */
define([ "bajaScript/sys",
        "bajaScript/baja/ord/OrdQuery",
        "bajaScript/baja/ord/OrdScheme",
        "bajaScript/baja/ord/OrdTarget",
        "bajaScript/baja/boxcs/BogSpace",
        "bajaPromises" ], function (
        baja, 
        OrdQuery, 
        OrdScheme, 
        OrdTarget,
        BogSpace,
        Promise) {
  
  "use strict";
  
  var subclass = baja.subclass,
      callSuper = baja.callSuper;
  
  /**
   * Bog ORD Scheme.
   * 
   * This scheme resolves to a history space.
   *
   * @class
   * @alias baja.BogScheme
   * @extends baja.OrdScheme
   * @private
   */    
  var BogScheme = function BogScheme() {
    callSuper(BogScheme, this, arguments);
  };

  BogScheme.$spaceCache = {}; // Caches resolved spaces.
  BogScheme.$promiseCache = {}; // Caches promises that should resolve to spaces.
  
  subclass(BogScheme, OrdScheme);
  
  /**
   * Default Bog ORD Scheme instance.
   * @private
   * @type {baja.BogScheme}
   */
  BogScheme.DEFAULT = new BogScheme();
  
  /**
   * Called when an ORD is resolved.
   *
   * @private
   *
   * @see baja.OrdScheme#resolve
   *
   * @param {module:baja/ord/OrdTarget} target  the current ORD Target.
   * @param {baja.OrdQuery} query  the ORD Query used in resolving the ORD.
   * @param {module:baja/ord/OrdQueryListCursor} cursor  the ORD Query List 
   * cursor used for helping to asynchronously resolve the ORD.
   * @param {Object} options  options used for resolving an ORD.
   * @returns {Promise} Resolved with the BOG Space.
   */
  BogScheme.prototype.resolve = function (target, query, cursor, options) {
    var newTarget = new OrdTarget(target),
        file = target.getObject(),
        navOrdStr = file.getNavOrd().toString(),
        space,
        cb,
        batch,
        promise,
        spaceCache = BogScheme.$spaceCache,
        promiseCache = BogScheme.$promiseCache;

    function ok() {
      newTarget.object = spaceCache[navOrdStr];
      cursor.resolveNext(newTarget, options);
    }

    function fail(err) {
      options.callback.fail(err);
    }

    if (spaceCache[navOrdStr]) {
      ok();
      promise = Promise.resolve();
    } else if (promiseCache[navOrdStr]) {
      promise = promiseCache[navOrdStr];
      promise.then(ok, fail);
    } else {
      // TODO: handle file rename or removed nav events.
      
      space = new BogSpace(file.getFileName(), 
        file.getOrdInSession().toString() + "|bog:", baja.nav.localhost);

      batch = new baja.comm.Batch();
      space.init(batch);

      cb = new baja.comm.Callback();
      batch.addCallback(cb);

      promiseCache[navOrdStr] = promise = cb.promise().then(function () {
          delete promiseCache[navOrdStr];
          spaceCache[navOrdStr] = space;
          ok();
        }, function (err) {
          delete promiseCache[navOrdStr];
          fail(err);
        });

      batch.commit();
    }

    return promise;
  };
  
  /**
   * Return an ORD Query for the scheme.
   *
   * @returns {baja.OrdQuery}
   */
  BogScheme.prototype.parse = function (schemeName, body) {
    return new OrdQuery({
      scheme: this,
      schemeName: schemeName,
      body: body,
      isHost: false,
      isSession: false
    });
  };

  return BogScheme;
});