docs: function Attribute(args, arg2) {
    var splitTypes; // For String(30) type
    if (false === (this instanceof Attribute)) throw new Error('new operator required');
    if (typeof args == 'string') {
      var quickName = args;
      args = {};
      args.name = quickName;
      if (typeof arg2 == 'string') {
        args.type = arg2;
      }
    }
    args = args || {};
    this.name = args.name || null;
    this.label = args.label || args.name;
    if (this.label)
      this.label = this.label.charAt(0).toUpperCase() + this.label.slice(1);
    this.type = args.type || 'String';
    splitTypes = function (str) { // for String(30) remove right of (
      var tmpSplit = str.split('(');
      tmpSplit[1] = parseInt(tmpSplit[1]);
      return tmpSplit;
    }(this.type);
    this.type = splitTypes[0];
    this.hint = args.hint || {};
    if (args.hidden !== undefined)
      this.hidden = args.hidden;
    this.validationRule = args.validationRule || {};
    var unusedProperties = [];
    var standardProperties = ['name', 'type', 'label', 'hint', 'hidden', 'value', 'validationRule'];
    switch (this.type) {
      case 'ID':
        unusedProperties = getInvalidProperties(args, standardProperties);
        this.value = args.value || null;
        break;
      case 'String':
        unusedProperties = getInvalidProperties(args, standardProperties.concat(['placeHolder', 'quickPick', 'size']));
        this.size = splitTypes[1] ? splitTypes[1] : typeof args.size == 'number' ? args.size : args.size || 50;
        this.value = args.value || null;
        if (args.quickPick)
          this.quickPick = args.quickPick;
        this.placeHolder = args.placeHolder || null;
        break;
      case 'Date':
        unusedProperties = getInvalidProperties(args, standardProperties.concat('placeHolder'));
        this.value = args.value || null;
        this.placeHolder = args.placeHolder || null;
        break;
      case 'Boolean':
        unusedProperties = getInvalidProperties(args, standardProperties);
        if (args.value === false)
          this.value = false;
        else
          this.value = args.value || null;
        break;
      case 'Number':
        unusedProperties = getInvalidProperties(args, standardProperties.concat('placeHolder'));
        if (args.value === 0)
          this.value = 0;
        else
          this.value = args.value || null;
        this.placeHolder = args.placeHolder || null;
        break;
      case 'Model':
        unusedProperties = getInvalidProperties(args, standardProperties);
        this.value = args.value || null;
        if (this.value instanceof Attribute.ModelID)
          this.modelType = this.value.modelType;
        break;
      case 'Group':
        unusedProperties = getInvalidProperties(args, standardProperties);
        this.value = args.value || null;
        break;
      case 'Table':
        unusedProperties = getInvalidProperties(args, standardProperties.concat('group'));
        this.value = args.value || null;
        this.group = args.group || null;
        break;
      case 'Object':
        unusedProperties = getInvalidProperties(args, standardProperties);
        this.value = args.value || null;
        break;
      default:
        break;
    }
    var errorList = this.getObjectStateErrors(); // before leaving make sure valid Attribute
    for (var i = 0; i < unusedProperties.length; i++) errorList.push('invalid property: ' + unusedProperties[i]);
    if (errorList.length > 1) throw new Error('error creating Attribute: multiple errors');
    if (errorList.length) throw new Error('error creating Attribute: ' + errorList[0]);
  
    // Validations done
    this._eventListeners = [];
    this._errorConditions = {};
  }