baja/obj/Simple.js

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

/**
 * Defines {@link baja.Simple}.
 * 
 * @module baja/obj/Simple
 */
define(["bajaScript/sys",
        "bajaScript/baja/obj/Value"], function (
         baja,
         Value) {
  
  'use strict';
  
  var subclass = baja.subclass,
      callSuper = baja.callSuper,
      bajaHasType = baja.hasType;
  
  /**
   * Represents `baja:Simple` in BajaScript.
   * 
   * `Simple`s are immutable and represent primitive data types in Niagara. 
   * They are the basic building blocks of the architecture. Simples contain 
   * no slots themselves but do contain an implicit data value that can be 
   * encoded and decoded in a `String` format.
   * 
   * `Simple`s must be immutable and under no circumstances should there be 
   * any attempt to modify the contents of a Simple.
   * 
   * All `Simple`s must conform to the following conventions... 
   * 
   * * Define a `DEFAULT` instance on the `Simple` constructor.
   * * Define a `make` method.
   * * Define a `decodeFromString` method on the Object's instance that takes a 
   *   `String` and returns an instance of the `Simple`.
   * * Define an `encodeToString` method on the Object's instance that encodes 
   *   the value to a `String`.
   *   
   * Since this Constructor represents an abstract class, it should never
   * be directly used to create a new object.
   *
   * @class
   * @alias baja.Simple
   * @extends baja.Value
   */
  var Simple = function Simple() { 
    callSuper(Simple, this, arguments);
  };
  
  subclass(Simple, Value);
  
  /**
   * Equality test.
   *
   * @param obj
   * @returns {Boolean}
   */
  Simple.prototype.equals = function (obj) {
    // Comparing in via encodeToString is ok because most Simples
    // lazily cache their string encoding (since they're all immutable)    
    return bajaHasType(obj) && 
           obj.getType().equals(this.getType()) && 
           obj.encodeToString() === this.encodeToString();
  };

 /**
  * Returns the String representation of this object.
  *
  * @see baja.Object#toString
  *
  * @param {Object} [cx] optional context information to be used when
  * formatting the string
  *
  * @returns {String|Promise.<String>} a string (if no context passed), or
  * either a string or a Promise (if context passed).
  */
  Simple.prototype.toString = function (cx) {
    return this.encodeToString();
  };

  /**
   * The string encoding of certain Simples may include Type information, or
   * other data that may be require asynchronous operations to decode. BOX is
   * designed to handle these situations when decoding data from the station,
   * but when user code needs to decode string-encoded Simples directly, prefer
   * this method as it gives the individual Simple a chance to import Types,
   * etc. to ensure that the decoded Simple is fully correct.
   *
   * The default implementation just returns `decodeFromString` directly.
   *
   * @param {string} str
   * @param {baja.comm.Batch} [batch] optional batch to use
   * @returns {baja.Simple|Promise.<baja.Simple>} may return the Simple instance
   * directly, or a Promise resolving to same - so wrap in `Promise.resolve()`
   * if unsure.
   */
  Simple.prototype.decodeAsync = function (str, batch) {
    return this.decodeFromString(str);
  };

  /**
   * @returns {String} the string encoding of the Simple, by default
   */
  Simple.prototype.valueOf = function () {
    return this.encodeToString();
  };

  /**
   * Every Simple implementation must have an `encodeToString` function.
   * 
   * @function 
   * @name baja.Simple#encodeToString
   * @abstract
   * @returns {string}
   */

  /**
   * Every Simple implementation must have a `decodeFromString` function.
   *
   * @function
   * @name baja.Simple#decodeFromString
   * @abstract
   * @param {string} str
   * @returns {baja.Simple}
   */

  /**
   * Every Simple implementation must have a `make` function. It can take
   * any arbitrary arguments. When constructing the Simple with `baja.$`, any
   * additional arguments will be passed to `make()`, with the following special
   * cases:
   *
   * - When _no_ arguments are passed, `baja.$` will return the `DEFAULT`
   *   instance.
   * - When _one_ argument is passed and it is a string, `baja.$` will use
   *   `decodeFromString()` to create the instance.
   *
   * @function
   * @name baja.Simple#make
   * @abstract
   * @returns {baja.Simple}
   * @example
   * //in the Simple declaration:
   * MySimple.prototype.make = function (a, b, c) {
   *   var mySimple = new MySimple();
   *   mySimple.a = a;
   *   mySimple.b = b;
   *   mySimple.c = c;
   *   return mySimple;
   * };
   * 
   * //when constructing:
   * var mySimple = baja.$('myModule:MySimple', 'a', 'b', 'c');
   */

  return Simple;
});