/**
 * * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Generated by Apache Flex Cross-Compiler from XMLList.as
 * XMLList
 *
 * @fileoverview
 *
 * @suppress {checkTypes|accessControls}
 */

goog.provide('XMLList');

goog.require('QName');
goog.require('XML');
goog.require('org.apache.flex.utils.Language');



/**
 * @constructor
 */
XMLList = function() {
  
  this._xmlArray = [];
  this.addIndex(0);
};


/**
 * @private
 * @type {Array}
 */
XMLList.prototype._xmlArray;


/**
 * @private
 * @param {number} idx
 */
XMLList.prototype.addIndex = function(idx) {
  var self = this;
  var /** @type {Function} */ __localFn0__ = function() {
    return self._xmlArray[idx];
  }
  var /** @type {Function} */ __localFn1__ = function(newValue) {
    if (idx >= self._xmlArray.length)
      self.appendChild(newValue);
    else
      self.replaceChildAt(idx, newValue);
  }
  var /** @type {string} */ idxStr = "" + idx;
  Object.defineProperty(this, idxStr, {"get":__localFn0__, "set":__localFn1__, enumerable:true, configurable:true});
};


/**
 * @export
 * @param {XML} child
 */
XMLList.prototype.appendChild = function(child) {
  this._xmlArray[this._xmlArray.length] = child;
  this.addIndex(this._xmlArray.length);
  do {
    if (!this._targetObject)
      break;
    if (!this._targetProperty) {
      this._targetObject.appendChild(child);
      break;
    }
    var /** @type {XMLList} */ objToAppend = this._targetObject.child(this._targetProperty);
    if (!objToAppend.length()) {
      this._targetObject.appendChild(child);
      break;
    }
    this._targetObject.insertChildAfter(objToAppend[objToAppend.length() - 1], child);
  } while (false);
};


/**
 * Calls the attribute() method of each XML object and returns an XMLList object of the results.
 * 
 * @asparam attributeName
 * @asreturn 
 * 
 * @export
 * @param {*} attributeName
 * @return {XMLList}
 */
XMLList.prototype.attribute = function(attributeName) {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].attribute(attributeName);
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Calls the attributes() method of each XML object and returns an XMLList object of attributes for each XML object.
 * 
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.attributes = function() {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].attributes();
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Calls the child() method of each XML object and returns an XMLList object that contains the results in order.
 * 
 * @asparam propertyName
 * @asreturn 
 * 
 * @export
 * @param {Object} propertyName
 * @return {XMLList}
 */
XMLList.prototype.child = function(propertyName) {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ propNum = parseInt(propertyName, 10);
  if (propNum.toString() == propertyName) {
    if (propNum >= 0 && propNum < this._xmlArray.length) {
      retVal.appendChild(this._xmlArray[propNum]);
      retVal.targetObject = this._xmlArray[propNum];
    }
    return retVal;
  }
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].child(propertyName);
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Calls the children() method of each XML object and returns an XMLList object that contains the results.
 * 
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.children = function() {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].children();
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Calls the comments() method of each XML object and returns an XMLList of comments.
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.comments = function() {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].comments();
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * @export
 * @param {*} list
 * @return {XMLList}
 */
XMLList.prototype.concat = function(list) {
  if (org.apache.flex.utils.Language.is(list, XML)) {
    var /** @type {XMLList} */ newList = new XMLList();
    newList.appendChild(list);
    list = newList;
  }
  if (!org.apache.flex.utils.Language.is(list, XMLList))
    throw new TypeError("invalid type");
  var /** @type {XML} */ item;
  var /** @type {number} */ len = Number(list.length());
  var /** @type {number} */ i = 0;
  while (i < len)
    this.appendChild(list[i++]);
  return this;
};


/**
 * Checks whether the XMLList object contains an XML object that is equal to the given value parameter.
 * 
 * @asparam value
 * @asreturn 
 * 
 * @export
 * @param {XML} value
 * @return {boolean}
 */
XMLList.prototype.contains = function(value) {
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    if (this._xmlArray[i].contains(value))
      return true;
  }
  return false;
};


/**
 * Returns a copy of the given XMLList object.
 * 
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.copy = function() {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++)
    retVal.appendChild(this._xmlArray[i].copy());
  return retVal;
};


/**
 * Returns all descendants (children, grandchildren, great-grandchildren, and so on) of the XML object that have the given name parameter.
 * 
 * @asparam name
 * @asreturn 
 * 
 * @export
 * @param {Object=} name
 * @return {XMLList}
 */
XMLList.prototype.descendants = function(name) {
  name = typeof name !== 'undefined' ? name : "*";
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].descendants(name);
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Calls the elements() method of each XML object.
 * 
 * @asparam name
 * @asreturn 
 * 
 * @export
 * @param {Object=} name
 * @return {XMLList}
 */
XMLList.prototype.elements = function(name) {
  name = typeof name !== 'undefined' ? name : "*";
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].elements(name);
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * @export
 * @return {Array}
 */
XMLList.prototype.elementNames = function() {
  var /** @type {Array} */ retVal = [];
  var /** @type {number} */ i = 0;
  var /** @type {number} */ len = Number(this._xmlArray.length);
  while (i < len)
    retVal.push(i++);
  return retVal;
};


/**
 * @export
 * @param {*} list
 * @return {boolean}
 */
XMLList.prototype.equals = function(list) {
  return false;
};


/**
 * @export
 * @param {Function} callback
 * @return {XMLList}
 */
XMLList.prototype.filter = function(callback) {
  var /** @type {XMLList} */ list = new XMLList();
  for (var /** @type {number} */ i = 0; i < this._xmlArray.length; i++) {
    if (callback(this._xmlArray[i]))
      list.appendChild(this._xmlArray[i]);
  }
  list.targetObject = this._targetObject;
  list.targetProperty = this._targetProperty;
  return list;
};


/**
 * @export
 * @return {boolean}
 */
XMLList.prototype.hasComplexContent = function() {
  if (this._xmlArray.length == 0)
    return false;
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 1; i < len; i++) {
    if (this._xmlArray[i].hasComplexContent())
      return true;
  }
  return false;
};


/**
 * @export
 * @override
 */
XMLList.prototype.hasOwnProperty = function(propertyName) {
  if (parseInt(propertyName, 10).toString() == propertyName) {
    return parseInt(propertyName, 10) < this._xmlArray.length;
  }
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 1; i < len; i++) {
    if (this._xmlArray[i].hasOwnProperty(propertyName))
      return true;
  }
  return false;
};


/**
 * Checks whether the XMLList object contains simple content.
 * 
 * @asreturn 
 * 
 * @export
 * @return {boolean}
 */
XMLList.prototype.hasSimpleContent = function() {
  if (this._xmlArray.length == 0)
    return true;
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 1; i < len; i++) {
    if (this._xmlArray[i].hasComplexContent())
      return false;
  }
  return true;
};


/**
 * Returns the number of items in the XMLList.
 * 
 * @asreturn 
 * 
 * @export
 * @return {number}
 */
XMLList.prototype.length = function() {
  return this._xmlArray.length;
};


/**
 * @export
 * @return {QName}
 */
XMLList.prototype.name = function() {
  if (this._xmlArray.length == 1)
    return this._xmlArray[0].name();
  return null;
};


/**
 * Merges adjacent text nodes and eliminates empty text nodes for each of the following:
 * all text nodes in the XMLList, all the XML objects contained in the XMLList, and the descendants of all the XML objects in the XMLList.
 * 
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.normalize = function() {
  return this;
};


/**
 * Returns the parent of the XMLList object if all items in the XMLList object have the same parent.
 * 
 * @asreturn 
 * 
 * @export
 * @return {Object}
 */
XMLList.prototype.parent = function() {
  if (this._xmlArray.length == 0)
    return undefined;
  var /** @type {XML} */ retVal = this._xmlArray[0].parent();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 1; i < len; i++) {
    if (this._xmlArray[i].parent() != retVal)
      return undefined;
  }
  return retVal;
};


/**
 * @export
 * @param {*} rightHand
 * @return {*}
 */
XMLList.prototype.plus = function(rightHand) {
  if (org.apache.flex.utils.Language.is(rightHand, XML) || org.apache.flex.utils.Language.is(rightHand, XMLList)) {
    var /** @type {XMLList} */ list = new XMLList();
    list.concat(this);
    list.concat(rightHand);
    if (org.apache.flex.utils.Language.is(rightHand, XML))
      list.targetObject = rightHand; else {
      list.targetObject = rightHand.targetObject;
      list.targetProperty = rightHand.targetProperty;
    }
    return list;
  }
  if (org.apache.flex.utils.Language.is(rightHand, String))
    return this.toString() + rightHand;
  if (org.apache.flex.utils.Language.is(rightHand, Number) && isNaN(rightHand))
    return NaN;
  if (isNaN(Number(this.toString())) || isNaN(Number(rightHand.toString())))
    return this.toString() + rightHand.toString();
  return Number(this.toString()) + rightHand;
};


/**
 * If a name parameter is provided, lists all the children of the XMLList object that contain processing instructions with that name.
 * 
 * @asparam name
 * @asreturn 
 * 
 * @export
 * @param {string=} name
 * @return {XMLList}
 */
XMLList.prototype.processingInstructions = function(name) {
  name = typeof name !== 'undefined' ? name : "*";
  var /** @type {XMLList} */ retVal = new XMLList();
  if (!name)
    return retVal;
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    if (this._xmlArray[i].nodeKind() != "processing-instruction")
      continue;
    if (name == "*") {
      retVal.appendChild(this._xmlArray[i]);
    }
    else if (name == this._xmlArray[i].localName)
      retVal.appendChild(this._xmlArray[i]);
  }
  return retVal;
};


/**
 * @export
 * @param {*} child
 */
XMLList.prototype.removeChild = function(child) {
  var /** @type {number} */ i;
  var /** @type {number} */ len;
  if (org.apache.flex.utils.Language.is(child, XMLList)) {
    len = Number(child.length());
    for (i = 0; i < len; i++) {
      this.removeChild(child[i]);
    }
  } else if (org.apache.flex.utils.Language.is(child, XML)) {
    len = this._xmlArray.length - 1;
    for (i = len; i >= 0; i--) {
      if (this._xmlArray[i] == child) {
        this._xmlArray.splice(i, 1);
      }
    }
  }
};


/**
 * @export
 * @param {number} idx
 */
XMLList.prototype.removeChildAt = function(idx) {
  if (idx >= 0 && idx < this._xmlArray.length)
    this._xmlArray.splice(idx, 1);
};


/**
 * @private
 * @param {number} idx
 * @param {*} child
 */
XMLList.prototype.replaceChildAt = function(idx, child) {
  var /** @type {number} */ i;
  var /** @type {XML} */ childToReplace = this._xmlArray[idx];
  if (childToReplace && this._targetObject) {
    this._targetObject.replaceChildAt(childToReplace.childIndex(), child);
  }
  if (org.apache.flex.utils.Language.is(child, XML)) {
    this._xmlArray[idx] = child;
  } else if (org.apache.flex.utils.Language.is(child, XMLList)) {
    var /** @type {number} */ len = Number(child.length());
    for (i = 0; i < len; i++) {
      if (i == 0)
        this._xmlArray[idx] = child[i];
      else
        this._xmlArray.splice(idx + i, 0, child[i]);
    }
  }
  while (idx++ < this._xmlArray.length) {
    if (!this.hasOwnProperty(idx))
      this.addIndex(idx);
  }
};


/**
 * @private
 * @type {*}
 */
XMLList.prototype._targetObject;


/**
 * @private
 * @type {*}
 */
XMLList.prototype._targetProperty;


/**
 * @export
 * @param {*} attr
 * @param {string} value
 */
XMLList.prototype.setAttribute = function(attr, value) {
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++)
    this._xmlArray[i].setAttribute(attr, value);
};


/**
 * @export
 * @param {*} elementName
 * @param {Object} elements
 */
XMLList.prototype.setChild = function(elementName, elements) {
  if (this._xmlArray.length == 1)
    this._xmlArray[0].setChild(elementName, elements);
};


/**
 * Calls the text() method of each XML object and returns an XMLList object that contains the results.
 * 
 * @asreturn 
 * 
 * @export
 * @return {XMLList}
 */
XMLList.prototype.text = function() {
  var /** @type {XMLList} */ retVal = new XMLList();
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {XMLList} */ list = this._xmlArray[i].text();
    if (list.length())
      retVal.concat(list);
  }
  return retVal;
};


/**
 * Returns the string representation of this object, formatted according to locale-specific conventions.
 * 
 * @asreturn 
 * 
 * @export
 * @override
 */
XMLList.prototype.toLocaleString = function() {
  var /** @type {Array} */ retVal = [];
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {string} */ str = org.apache.flex.utils.Language.string(this._xmlArray[i].toLocaleString());
    if (str)
      retVal.push(str);
  }
  return retVal.join("");
};


/**
 * Returns a string representation of all the XML objects in an XMLList object.
 * 
 * @asreturn 
 * 
 * @export
 * @return {string}
 */
XMLList.prototype.toString = function() {
  var /** @type {Array} */ retVal = [];
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {string} */ str = org.apache.flex.utils.Language.string(this._xmlArray[i].toString());
    if (str)
      retVal.push(str);
  }
  return retVal.join("\n");
};


/**
 * Returns a string representation of all the XML objects in an XMLList object.
 * 
 * @asreturn 
 * 
 * @export
 * @return {string}
 */
XMLList.prototype.toXMLString = function() {
  var /** @type {Array} */ retVal = [];
  var /** @type {number} */ len = Number(this._xmlArray.length);
  for (var /** @type {number} */ i = 0; i < len; i++) {
    var /** @type {string} */ str = org.apache.flex.utils.Language.string(this._xmlArray[i].toXMLString());
    if (str)
      retVal.push(str);
  }
  return retVal.join("\n");
};


/**
 * Returns the XMLList object.
 * 
 * @asreturn 
 * 
 * @export
 * @override
 */
XMLList.prototype.valueOf = function() {
  return this;
};


Object.defineProperties(XMLList.prototype, /** @lends {XMLList.prototype} */ {
/** @export */
targetObject: {
get: /** @this {XMLList} */ function() {
  return this._targetObject;
},
set: /** @this {XMLList} */ function(value) {
  this._targetObject = value;
}},
/** @export */
targetProperty: {
get: /** @this {XMLList} */ function() {
  return this._targetProperty;
},
set: /** @this {XMLList} */ function(value) {
  this._targetProperty = value;
}}}
);


/**
 * Metadata
 *
 * @type {Object.<string, Array.<Object>>}
 */
XMLList.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'XMLList', qName: 'XMLList'}] };


/**
 * Prevent renaming of class. Needed for reflection.
 */
goog.exportSymbol('XMLList', XMLList);



/**
 * Reflection
 *
 * @return {Object.<string, Function>}
 */
XMLList.prototype.FLEXJS_REFLECTION_INFO = function () {
  return {
    variables: function () {
      return {
      };
    },
    accessors: function () {
      return {
        'targetObject': { type: '*', declaredBy: 'XMLList'},
        'targetProperty': { type: '*', declaredBy: 'XMLList'}
      };
    },
    methods: function () {
      return {
        'XMLList': { type: '', declaredBy: 'XMLList'},
        'appendChild': { type: 'void', declaredBy: 'XMLList'},
        'attribute': { type: 'XMLList', declaredBy: 'XMLList'},
        'attributes': { type: 'XMLList', declaredBy: 'XMLList'},
        'child': { type: 'XMLList', declaredBy: 'XMLList'},
        'children': { type: 'XMLList', declaredBy: 'XMLList'},
        'comments': { type: 'XMLList', declaredBy: 'XMLList'},
        'concat': { type: 'XMLList', declaredBy: 'XMLList'},
        'contains': { type: 'Boolean', declaredBy: 'XMLList'},
        'copy': { type: 'XMLList', declaredBy: 'XMLList'},
        'descendants': { type: 'XMLList', declaredBy: 'XMLList'},
        'elements': { type: 'XMLList', declaredBy: 'XMLList'},
        'elementNames': { type: 'Array', declaredBy: 'XMLList'},
        'equals': { type: 'Boolean', declaredBy: 'XMLList'},
        'filter': { type: 'XMLList', declaredBy: 'XMLList'},
        'hasComplexContent': { type: 'Boolean', declaredBy: 'XMLList'},
        'hasOwnProperty': { type: 'Boolean', declaredBy: 'XMLList'},
        'hasSimpleContent': { type: 'Boolean', declaredBy: 'XMLList'},
        'length': { type: 'int', declaredBy: 'XMLList'},
        'name': { type: 'QName', declaredBy: 'XMLList'},
        'normalize': { type: 'XMLList', declaredBy: 'XMLList'},
        'parent': { type: 'Object', declaredBy: 'XMLList'},
        'plus': { type: '*', declaredBy: 'XMLList'},
        'processingInstructions': { type: 'XMLList', declaredBy: 'XMLList'},
        'removeChild': { type: 'void', declaredBy: 'XMLList'},
        'removeChildAt': { type: 'void', declaredBy: 'XMLList'},
        'setAttribute': { type: 'void', declaredBy: 'XMLList'},
        'setChild': { type: 'void', declaredBy: 'XMLList'},
        'text': { type: 'XMLList', declaredBy: 'XMLList'},
        'toLocaleString': { type: 'String', declaredBy: 'XMLList'},
        'toString': { type: 'String', declaredBy: 'XMLList'},
        'toXMLString': { type: 'String', declaredBy: 'XMLList'},
        'valueOf': { type: '*', declaredBy: 'XMLList'}
      };
    }
  };
};