baja/tag/ComponentTags.js

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

/**
 * @module baja/tag/ComponentTags
 */
define([ "bajaScript/sys",
        "bajaScript/baja/ord/SlotPath",
        "bajaScript/baja/comp/Flags",
        "bajaScript/baja/tag/Id",
        "bajaScript/baja/tag/Tag" ], function (
        baja,
        SlotPath,
        Flags,
        Id,
        Tag) {
  
  "use strict";

  var escapedColon;
     
  /**
   * Tags is used to access the direct tags on a Component instance.
   *
   * @class
   * @alias module:baja/tag/ComponentTags
   *
   * @param {baja.Component} owner The Component instance owner.
   */  
  var ComponentTags = function ComponentTags(owner) {
    this.$owner = owner;
  };

  /**
   * @returns {Boolean} Returns true if there are no Tag objects.
   */
  ComponentTags.prototype.isEmpty = function () {
    return this.getAll().length === 0;
  };

  function tagFromSlot(owner, slot) {
    slot = owner.getSlot(slot);
    return slot ? new Tag(ComponentTags.slotToQname(slot), owner.get(slot)) : null;
  }

  /**
   * Get the value of the Tag with the given id if it exists.
   * 
   * @param {String|module:baja/tag/Id} id The Id
   * used for the search. This can be an Id or a qname for an Id.
   * @returns The value for the tag if it exists or else null.
   */
  ComponentTags.prototype.get = function (id) {
    var slotName = ComponentTags.idToSlotName(id),
        tag = this.isTaggableSlot(slotName) ? tagFromSlot(this.$owner, slotName) : null;

    return tag ? tag.getValue() : null;
  };

  /**
   * Returns true if a Tag with the specified Id (or qname) is found.
   * 
   * @param  {String|module:baja/tag/Id} id The Id
   * used for the search. This can be an Id or a qname for an Id.
   * @returns {Boolean} Returns true if found.
   */
  ComponentTags.prototype.contains = function (id) {
    return this.get(id) !== null;
  };

  /**
   * Returns a copy of the contained Tags array.
   * 
   * @returns {Array<module:baja/tag/Tag>} An array of Tag objects.
   */
  ComponentTags.prototype.getAll = function () {
    var tags = [],
        that = this,
        owner = that.$owner;

    owner
      .getSlots()
      .filter(function (slot) {
        // Filter to all taggable Slots
        return that.isTaggableSlot(slot);
      })
      .each(function (slot) {
        // Create a tag for each valid Slot.
        tags.push(tagFromSlot(owner, slot));
      });

    return tags;
  };

  /**
   * Returns true if the specified Slot is taggable.
   * 
   * @param {baja.Slot|String} slot The Slot (or slot name) that's tested
   * to see if it's a taggable Slot.
   * @returns {Boolean} Returns true if the Slot is taggable.
   */
  ComponentTags.prototype.isTaggableSlot = function (slot) {
    var owner = this.$owner,
        flags,
        valid,
        colon;

    slot = owner.getSlot(slot);
    flags = (slot && owner.getFlags(slot)) || 0;

    valid =  
      slot && 
      slot.isProperty() && 
      !owner.get(slot).getType().isComponent() &&
      (flags & Flags.TRANSIENT) !== Flags.TRANSIENT &&
      (flags & Flags.METADATA) === Flags.METADATA;

    if (!valid) {
      return false;
    }

    escapedColon = escapedColon || baja.SlotPath.escape(":");

    colon = slot.getName().indexOf(escapedColon);
    return colon === -1 ? true : slot.getName().indexOf(escapedColon, colon + 1) === -1;
  };

  /**
   * Return a Slot name from the specified Id.
   * 
   * @param  {String|module:baja/tag/Id} id The Id or 
   * qname name to create the Slot name from.
   * 
   * @returns {String} The Slot Name.
   */
  ComponentTags.idToSlotName = function (id) {
    return SlotPath.escape(id.toString());
  };

  /**
   * Returns a qname from a Slot.
   *
   * @param {baja.Slot} slot The Slot to create the Id from.
   * 
   * @returns {String}
   */
  ComponentTags.slotToQname = function (slot) {
    return SlotPath.unescape(slot.getName());
  };

  /**
   * Returns a qname from a Slot name.
   *
   * @param {String} slotName The slot name to create the Id from.
   * 
   * @returns {String}
   */
  ComponentTags.slotNameToQname = function (slotName) {
    return SlotPath.unescape(slotName);
  };

  return ComponentTags;
});