You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ft...@apache.org on 2015/09/17 17:28:56 UTC

[41/51] [abbrv] [partial] git commit: [flex-falcon] [refs/heads/JsToAs] - Added GCL extern.

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/fastdatanode.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/fastdatanode.js b/externs/GCL/externs/goog/datasource/fastdatanode.js
new file mode 100644
index 0000000..c14750f
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/fastdatanode.js
@@ -0,0 +1,814 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview
+ * Efficient implementation of DataNode API.
+ *
+ * The implementation consists of three concrete classes for modelling
+ * DataNodes with different characteristics: FastDataNode,
+ * FastPrimitiveDataNode and FastListNode.
+ *
+ * FastDataNode is for bean-like or map-like objects that consists of
+ * key/value mappings and where the primary access pattern is by key.
+ *
+ * FastPrimitiveDataNode wraps primitives like strings, boolean, and numbers.
+ *
+ * FastListNode is for array-like data nodes. It also supports key-based
+ * lookups if the data nodes have an "id" property or if child nodes are
+ * explicitly added by name. It is most efficient if these features are not
+ * used.
+ *
+ * FastDataNodes can be constructed from JSON-like objects via the function
+ * goog.ds.FastDataNode.fromJs.
+
+ */
+
+goog.provide('goog.ds.AbstractFastDataNode');
+goog.provide('goog.ds.FastDataNode');
+goog.provide('goog.ds.FastListNode');
+goog.provide('goog.ds.PrimitiveFastDataNode');
+
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNodeList');
+goog.require('goog.ds.EmptyNodeList');
+goog.require('goog.string');
+
+/*
+ * Implementation note: In order to reduce the number of objects,
+ * FastDataNode stores its key/value mappings directly in the FastDataNode
+ * object iself (instead of a separate map). To make this work we have to
+ * sure that there are no name clashes with other attribute names used by
+ * FastDataNode (like dataName and parent). This is especially difficult in
+ * the light of automatic renaming by the JavaScript compiler. For this reason,
+ * all internal attributes start with "__" so that they are not renamed
+ * by the compiler.
+ */
+
+/**
+ * Creates a new abstract data node.
+ * @param {string} dataName Name of the datanode.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @constructor
+ * @extends {goog.ds.DataNodeList}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.AbstractFastDataNode = function(dataName, opt_parent) {
+  if (!dataName) {
+    throw Error('Cannot create a fast data node without a data name');
+  }
+  this['__dataName'] = dataName;
+  this['__parent'] = opt_parent;
+};
+
+
+/**
+ * Return the name of this data node.
+ * @return {string} Name of this data noden.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.getDataName = function() {
+  return this['__dataName'];
+};
+
+
+/**
+ * Set the name of this data node.
+ * @param {string} value Name.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.setDataName = function(value) {
+  this['__dataName'] = value;
+};
+
+
+/**
+ * Get the path leading to this data node.
+ * @return {string} Data path.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.getDataPath = function() {
+  var parentPath;
+  if (this['__parent']) {
+    parentPath = this['__parent'].getDataPath() + goog.ds.STR_PATH_SEPARATOR;
+  } else {
+    parentPath = '';
+  }
+  return parentPath + this.getDataName();
+};
+
+
+
+/**
+ * Creates a new fast data node, using the properties of root.
+ * @param {Object} root JSON-like object to initialize data node from.
+ * @param {string} dataName Name of this data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ */
+goog.ds.FastDataNode = function(root, dataName, opt_parent) {
+  goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+  this.extendWith(root);
+};
+goog.inherits(goog.ds.FastDataNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Add all attributes of object to this data node.
+ * @param {Object} object Object to add attributes from.
+ * @protected
+ */
+goog.ds.FastDataNode.prototype.extendWith = function(object) {
+  for (var key in object) {
+    this[key] = object[key];
+  }
+};
+
+
+/**
+ * Creates a new FastDataNode structure initialized from object. This will
+ * return an instance of the most suitable sub-class of FastDataNode.
+ *
+ * You should not modify object after creating a fast data node from it
+ * or assume that changing object changes the data node. Doing so results
+ * in undefined behaviour.
+ *
+ * @param {Object|number|boolean|string} object Object to initialize data
+ *     node from.
+ * @param {string} dataName Name of data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of data node.
+ * @return {!goog.ds.AbstractFastDataNode} Data node representing object.
+ */
+goog.ds.FastDataNode.fromJs = function(object, dataName, opt_parent) {
+  if (goog.isArray(object)) {
+    return new goog.ds.FastListNode(object, dataName, opt_parent);
+  } else if (goog.isObject(object)) {
+    return new goog.ds.FastDataNode(object, dataName, opt_parent);
+  } else {
+    return new goog.ds.PrimitiveFastDataNode(object || !!object,
+                                             dataName,
+                                             opt_parent);
+  }
+};
+
+
+/**
+ * Static instance of an empty list.
+ * @type {!goog.ds.EmptyNodeList}
+ * @private
+ */
+goog.ds.FastDataNode.emptyList_ = new goog.ds.EmptyNodeList();
+
+
+/**
+ * Not supported for normal FastDataNodes.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.set = function(value) {
+  throw new Error('Not implemented yet');
+};
+
+
+/** @override */
+goog.ds.FastDataNode.prototype.getChildNodes = function(opt_selector) {
+  if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+    return this;
+  } else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
+    var child = this.getChildNode(opt_selector);
+    return child ? new goog.ds.FastListNode([child], '') :
+        new goog.ds.EmptyNodeList();
+  } else {
+    throw Error('Unsupported selector: ' + opt_selector);
+  }
+};
+
+
+/**
+ * Makes sure that a named child is wrapped in a data node structure.
+ * @param {string} name Name of child to wrap.
+ * @private
+ */
+goog.ds.FastDataNode.prototype.wrapChild_ = function(name) {
+  var child = this[name];
+  if (child != null && !child.getDataName) {
+    this[name] = goog.ds.FastDataNode.fromJs(this[name], name, this);
+  }
+};
+
+
+/**
+ * Get a child node by name.
+ * @param {string} name Name of child node.
+ * @param {boolean=} opt_create Whether to create the child if it does not
+ * exist.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getChildNode = function(name, opt_create) {
+  this.wrapChild_(name);
+  // this[name] always is a data node object, so using "||" is fine.
+  var child = this[name] || null;
+  if (child == null && opt_create) {
+    child = new goog.ds.FastDataNode({}, name, this);
+    this[name] = child;
+  }
+  return child;
+};
+
+
+/**
+ * Sets a child node. Creates the child if it does not exist.
+ *
+ * Calling  this function makes any child nodes previously obtained for name
+ * invalid. You should not use these child nodes but instead obtain a new
+ * instance by calling getChildNode.
+ *
+ * @override
+ */
+goog.ds.FastDataNode.prototype.setChildNode = function(name, value) {
+  if (value != null) {
+    this[name] = value;
+  } else {
+    delete this[name];
+  }
+  goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath() +
+      goog.ds.STR_PATH_SEPARATOR + name);
+  return null;
+};
+
+
+/**
+ * Returns the value of a child node. By using this method you can avoid
+ * the need to create PrimitiveFastData nodes.
+ * @param {string} name Name of child node.
+ * @return {Object} Value of child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getChildNodeValue = function(name) {
+  var child = this[name];
+  if (child != null) {
+    return (child.getDataName ? child.get() : child);
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns false for
+ * instances of FastDataNode but may return true for subclasses.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.isList = function() {
+  return false;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {!Object} Javascript object representation of this data node.
+ */
+goog.ds.FastDataNode.prototype.getJsObject = function() {
+  var result = {};
+  for (var key in this) {
+    if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+      result[key] = (this[key]['__dataName'] ? this[key].getJsObject() :
+          this[key]);
+    }
+  }
+  return result;
+};
+
+
+/**
+ * Creates a deep copy of this data node.
+ * @return {goog.ds.FastDataNode} Clone of this data node.
+ */
+goog.ds.FastDataNode.prototype.clone = function() {
+  return /** @type {!goog.ds.FastDataNode} */(goog.ds.FastDataNode.fromJs(
+      this.getJsObject(), this.getDataName()));
+};
+
+
+/*
+ * Implementation of goog.ds.DataNodeList for FastDataNode.
+ */
+
+
+/**
+ * Adds a child to this data node.
+ * @param {goog.ds.DataNode} value Child node to add.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.add = function(value) {
+  this.setChildNode(value.getDataName(), value);
+};
+
+
+/**
+ * Gets the value of this data node (if called without opt_key) or
+ * gets a child node (if called with opt_key).
+ * @param {string=} opt_key Name of child node.
+ * @return {*} This data node or a child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.get = function(opt_key) {
+  if (!goog.isDef(opt_key)) {
+    // if there is no key, DataNode#get was called
+    return this;
+  } else {
+    return this.getChildNode(opt_key);
+  }
+};
+
+
+/**
+ * Gets a child node by index. This method has a complexity of O(n) where
+ * n is the number of children. If you need a faster implementation of this
+ * method, you should use goog.ds.FastListNode.
+ * @param {number} index Index of child node (starting from 0).
+ * @return {goog.ds.DataNode} Child node at specified index.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getByIndex = function(index) {
+  var i = 0;
+  for (var key in this) {
+    if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+      if (i == index) {
+        this.wrapChild_(key);
+        return this[key];
+      }
+      ++i;
+    }
+  }
+  return null;
+};
+
+
+/**
+ * Gets the number of child nodes. This method has a complexity of O(n) where
+ * n is the number of children. If you need a faster implementation of this
+ * method, you should use goog.ds.FastListNode.
+ * @return {number} Number of child nodes.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getCount = function() {
+  var count = 0;
+  for (var key in this) {
+    if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+      ++count;
+    }
+  }
+  // maybe cache this?
+  return count;
+};
+
+
+/**
+ * Sets a child node.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.setNode = function(name, value) {
+  this.setChildNode(name, value);
+};
+
+
+/**
+ * Removes a child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.removeNode = function(name) {
+  delete this[name];
+  return false;
+};
+
+
+
+/**
+ * Creates a new data node wrapping a primitive value.
+ * @param {number|boolean|string} value Value the value to wrap.
+ * @param {string} dataName name Name of this data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ * @final
+ */
+goog.ds.PrimitiveFastDataNode = function(value, dataName, opt_parent) {
+  this.value_ = value;
+  goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+};
+goog.inherits(goog.ds.PrimitiveFastDataNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Returns the value of this data node.
+ * @return {(boolean|number|string)} Value of this data node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.get = function() {
+  return this.value_;
+};
+
+
+/**
+ * Sets this data node to a new value.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.set = function(value) {
+  if (goog.isArray(value) || goog.isObject(value)) {
+    throw Error('can only set PrimitiveFastDataNode to primitive values');
+  }
+  this.value_ = value;
+  goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+};
+
+
+/**
+ * Returns child nodes of this data node. Always returns an unmodifiable,
+ * empty list.
+ * @return {!goog.ds.DataNodeList} (Empty) list of child nodes.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNodes = function() {
+  return goog.ds.FastDataNode.emptyList_;
+};
+
+
+/**
+ * Get a child node by name. Always returns null.
+ * @param {string} name Name of child node.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNode = function(name) {
+  return null;
+};
+
+
+/**
+ * Returns the value of a child node. Always returns null.
+ * @param {string} name Name of child node.
+ * @return {Object} Value of child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNodeValue = function(name) {
+  return null;
+};
+
+
+/**
+ * Not supported by primitive data nodes.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.setChildNode =
+    function(name, value) {
+  throw Error('Cannot set a child node for a PrimitiveFastDataNode');
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns false for
+ * instances of PrimitiveFastDataNode.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.isList = function() {
+  return false;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {*} Javascript object representation of this data node.
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getJsObject = function() {
+  return this.value_;
+};
+
+
+/**
+ * Creates a new list node from an array.
+ * @param {Array<?>} values values hold by this list node.
+ * @param {string} dataName name of this node.
+ * @param {goog.ds.DataNode=} opt_parent parent of this node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ * @final
+ */
+// TODO(arv): Use interfaces when available.  This implements DataNodeList
+// as well.
+goog.ds.FastListNode = function(values, dataName, opt_parent) {
+  this.values_ = [];
+  for (var i = 0; i < values.length; ++i) {
+    var name = values[i].id || ('[' + i + ']');
+    this.values_.push(goog.ds.FastDataNode.fromJs(values[i], name, this));
+    if (values[i].id) {
+      if (!this.map_) {
+        this.map_ = {};
+      }
+      this.map_[values[i].id] = i;
+    }
+  }
+  goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+};
+goog.inherits(goog.ds.FastListNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Not supported for FastListNodes.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.FastListNode.prototype.set = function(value) {
+  throw Error('Cannot set a FastListNode to a new value');
+};
+
+
+/**
+ * Returns child nodes of this data node. Currently, only supports
+ * returning all children.
+ * @return {!goog.ds.DataNodeList} List of child nodes.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNodes = function() {
+  return this;
+};
+
+
+/**
+ * Get a child node by name.
+ * @param {string} key Name of child node.
+ * @param {boolean=} opt_create Whether to create the child if it does not
+ * exist.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNode = function(key, opt_create) {
+  var index = this.getKeyAsNumber_(key);
+  if (index == null && this.map_) {
+    index = this.map_[key];
+  }
+  if (index != null && this.values_[index]) {
+    return this.values_[index];
+  } else if (opt_create) {
+    this.setChildNode(key, {});
+    return this.getChildNode(key);
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * Returns the value of a child node.
+ * @param {string} key Name of child node.
+ * @return {*} Value of child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNodeValue = function(key) {
+  var child = this.getChildNode(key);
+  return (child ? child.get() : null);
+};
+
+
+/**
+ * Tries to interpret key as a numeric index enclosed by square brakcets.
+ * @param {string} key Key that should be interpreted as a number.
+ * @return {?number} Numeric index or null if key is not of the form
+ *  described above.
+ * @private
+ */
+goog.ds.FastListNode.prototype.getKeyAsNumber_ = function(key) {
+  if (key.charAt(0) == '[' && key.charAt(key.length - 1) == ']') {
+    return Number(key.substring(1, key.length - 1));
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * Sets a child node. Creates the child if it does not exist. To set
+ * children at a certain index, use a key of the form '[index]'. Note, that
+ * you can only set values at existing numeric indices. To add a new node
+ * to this list, you have to use the add method.
+ *
+ * Calling  this function makes any child nodes previously obtained for name
+ * invalid. You should not use these child nodes but instead obtain a new
+ * instance by calling getChildNode.
+ *
+ * @override
+ */
+goog.ds.FastListNode.prototype.setChildNode = function(key, value) {
+  var count = this.values_.length;
+  if (value != null) {
+    if (!value.getDataName) {
+      value = goog.ds.FastDataNode.fromJs(value, key, this);
+    }
+    var index = this.getKeyAsNumber_(key);
+    if (index != null) {
+      if (index < 0 || index >= this.values_.length) {
+        throw Error('List index out of bounds: ' + index);
+      }
+      this.values_[key] = value;
+    } else {
+      if (!this.map_) {
+        this.map_ = {};
+      }
+      this.values_.push(value);
+      this.map_[key] = this.values_.length - 1;
+    }
+  } else {
+    this.removeNode(key);
+  }
+  var dm = goog.ds.DataManager.getInstance();
+  dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + key);
+  if (this.values_.length != count) {
+    this.listSizeChanged_();
+  }
+  return null;
+};
+
+
+/**
+ * Fire data changes that are appropriate when the size of this list changes.
+ * Should be called whenever the list size has changed.
+ * @private
+ */
+goog.ds.FastListNode.prototype.listSizeChanged_ = function() {
+  var dm = goog.ds.DataManager.getInstance();
+  dm.fireDataChange(this.getDataPath());
+  dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+      'count()');
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns true.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.FastListNode.prototype.isList = function() {
+  return true;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {!Object} Javascript object representation of this data node.
+ */
+goog.ds.FastListNode.prototype.getJsObject = function() {
+  var result = [];
+  for (var i = 0; i < this.values_.length; ++i) {
+    result.push(this.values_[i].getJsObject());
+  }
+  return result;
+};
+
+
+/*
+ * Implementation of goog.ds.DataNodeList for FastListNode.
+ */
+
+
+/**
+ * Adds a child to this data node
+ * @param {goog.ds.DataNode} value Child node to add.
+ * @override
+ */
+goog.ds.FastListNode.prototype.add = function(value) {
+  if (!value.getDataName) {
+    value = goog.ds.FastDataNode.fromJs(value,
+        String('[' + (this.values_.length) + ']'), this);
+  }
+  this.values_.push(value);
+  var dm = goog.ds.DataManager.getInstance();
+  dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+      '[' + (this.values_.length - 1) + ']');
+  this.listSizeChanged_();
+};
+
+
+/**
+ * Gets the value of this data node (if called without opt_key) or
+ * gets a child node (if called with opt_key).
+ * @param {string=} opt_key Name of child node.
+ * @return {Array|goog.ds.DataNode} Array of child nodes (if called without
+ *     opt_key), or a named child node otherwise.
+ * @override
+ */
+goog.ds.FastListNode.prototype.get = function(opt_key) {
+  // if there are no arguments, DataNode.get was called
+  if (!goog.isDef(opt_key)) {
+    return this.values_;
+  } else {
+    return this.getChildNode(opt_key);
+  }
+};
+
+
+/**
+ * Gets a child node by (numeric) index.
+ * @param {number} index Index of child node (starting from 0).
+ * @return {goog.ds.DataNode} Child node at specified index.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getByIndex = function(index) {
+  var child = this.values_[index];
+  return (child != null ? child : null); // never return undefined
+};
+
+
+/**
+ * Gets the number of child nodes.
+ * @return {number} Number of child nodes.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getCount = function() {
+  return this.values_.length;
+};
+
+
+/**
+ * Sets a child node.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.setNode = function(name, value) {
+  throw Error('Setting child nodes of a FastListNode is not implemented, yet');
+};
+
+
+/**
+ * Removes a child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.removeNode = function(name) {
+  var index = this.getKeyAsNumber_(name);
+  if (index == null && this.map_) {
+    index = this.map_[name];
+  }
+  if (index != null) {
+    this.values_.splice(index, 1);
+    if (this.map_) {
+      var keyToDelete = null;
+      for (var key in this.map_) {
+        if (this.map_[key] == index) {
+          keyToDelete = key;
+        } else if (this.map_[key] > index) {
+          --this.map_[key];
+        }
+      }
+      if (keyToDelete) {
+        delete this.map_[keyToDelete];
+      }
+    }
+    var dm = goog.ds.DataManager.getInstance();
+    dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+        '[' + index + ']');
+    this.listSizeChanged_();
+  }
+  return false;
+};
+
+
+/**
+ * Returns the index of a named child nodes. This method only works if
+ * this list uses mixed name/indexed lookup, i.e. if its child node have
+ * an 'id' attribute.
+ * @param {string} name Name of child node to determine index of.
+ * @return {number} Index of child node named name.
+ */
+goog.ds.FastListNode.prototype.indexOf = function(name) {
+  var index = this.getKeyAsNumber_(name);
+  if (index == null && this.map_) {
+    index = this.map_[name];
+  }
+  if (index == null) {
+    throw Error('Cannot determine index for: ' + name);
+  }
+  return /** @type {number} */(index);
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsdatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsdatasource.js b/externs/GCL/externs/goog/datasource/jsdatasource.js
new file mode 100644
index 0000000..ccd469e
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsdatasource.js
@@ -0,0 +1,462 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview An implementation of DataNode for wrapping JS data.
+ *
+ */
+
+
+goog.provide('goog.ds.JsDataSource');
+goog.provide('goog.ds.JsPropertyDataSource');
+
+goog.require('goog.ds.BaseDataNode');
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNode');
+goog.require('goog.ds.EmptyNodeList');
+goog.require('goog.ds.LoadState');
+
+
+/**
+ * Data source whose backing is JavaScript data
+ *
+ * Names that are reserved for system use and shouldn't be used for data node
+ * names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
+ * undefined if these names are used.
+ *
+ * @param {Object} root The root JS node.
+ * @param {string} dataName The name of this node relative to the parent node.
+ * @param {Object=} opt_parent Optional parent of this JsDataSource.
+ *
+ * implements goog.ds.DataNode.
+ * @constructor
+ * @extends {goog.ds.DataNode}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.JsDataSource = function(root, dataName, opt_parent) {
+  this.parent_ = opt_parent;
+  this.dataName_ = dataName;
+  this.setRoot(root);
+};
+
+
+/**
+ * The root JS object. Can be null.
+ * @type {*}
+ * @protected
+ * @suppress {underscore|visibility}
+ */
+goog.ds.JsDataSource.prototype.root_;
+
+
+/**
+ * Sets the root JS object
+ * @param {Object} root The root JS object. Can be null.
+ *
+ * @protected
+ */
+goog.ds.JsDataSource.prototype.setRoot = function(root) {
+  this.root_ = root;
+  this.childNodeList_ = null;
+};
+
+
+/**
+ * Set this data source to use list semantics. List data sources:
+ * - Are assumed to have child nodes of all of the same type of data
+ * - Fire data changes on the root node of the list whenever children
+ *     are added or removed
+ * @param {?boolean} isList True to use list semantics.
+ * @private
+ */
+goog.ds.JsDataSource.prototype.setIsList_ = function(isList) {
+  this.isList_ = isList;
+};
+
+
+/** @override */
+goog.ds.JsDataSource.prototype.get = function() {
+  return !goog.isObject(this.root_) ? this.root_ : this.getChildNodes();
+};
+
+
+/**
+ * Set the value of the node
+ * @param {*} value The new value of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.set = function(value) {
+  if (value && goog.isObject(this.root_)) {
+    throw Error('Can\'t set group nodes to new values yet');
+  }
+
+  if (this.parent_) {
+    this.parent_.root_[this.dataName_] = value;
+  }
+  this.root_ = value;
+  this.childNodeList_ = null;
+
+  goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+};
+
+
+/**
+ * TODO(user) revisit lazy creation.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNodes = function(opt_selector) {
+  if (!this.root_) {
+    return new goog.ds.EmptyNodeList();
+  }
+
+  if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+    this.createChildNodes_(false);
+    return this.childNodeList_;
+  } else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
+    if (this.root_[opt_selector] != null) {
+      return new goog.ds.BasicNodeList([this.getChildNode(opt_selector)]);
+    } else {
+      return new goog.ds.EmptyNodeList();
+    }
+  } else {
+    throw Error('Selector not supported yet (' + opt_selector + ')');
+  }
+
+};
+
+
+/**
+ * Creates the DataNodeList with the child nodes for this element.
+ * Allows for only building list as needed.
+ *
+ * @param {boolean=} opt_force Whether to force recreating child nodes,
+ *     defaults to false.
+ * @private
+ */
+goog.ds.JsDataSource.prototype.createChildNodes_ = function(opt_force) {
+  if (this.childNodeList_ && !opt_force) {
+    return;
+  }
+
+  if (!goog.isObject(this.root_)) {
+    this.childNodeList_ = new goog.ds.EmptyNodeList();
+    return;
+  }
+
+  var childNodeList = new goog.ds.BasicNodeList();
+  var newNode;
+  if (goog.isArray(this.root_)) {
+    var len = this.root_.length;
+    for (var i = 0; i < len; i++) {
+      // "id" is reserved node name that will map to a named child node
+      // TODO(user) Configurable logic for choosing id node
+      var node = this.root_[i];
+      var id = node.id;
+      var name = id != null ? String(id) : '[' + i + ']';
+      newNode = new goog.ds.JsDataSource(node, name, this);
+      childNodeList.add(newNode);
+    }
+  } else {
+    for (var name in this.root_) {
+      var obj = this.root_[name];
+      // If the node is already a datasource, then add it.
+      if (obj.getDataName) {
+        childNodeList.add(obj);
+      } else if (!goog.isFunction(obj)) {
+        newNode = new goog.ds.JsDataSource(obj, name, this);
+        childNodeList.add(newNode);
+      }
+    }
+  }
+  this.childNodeList_ = childNodeList;
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @param {boolean=} opt_canCreate If true, can create child node.
+ * @return {goog.ds.DataNode} The child node, or null if no node of
+ *     this name exists.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNode = function(name, opt_canCreate) {
+  if (!this.root_) {
+    return null;
+  }
+  var node = /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
+  if (!node && opt_canCreate) {
+    var newObj = {};
+    if (goog.isArray(this.root_)) {
+      newObj['id'] = name;
+      this.root_.push(newObj);
+    } else {
+      this.root_[name] = newObj;
+    }
+    node = new goog.ds.JsDataSource(newObj, name, this);
+    if (this.childNodeList_) {
+      this.childNodeList_.add(node);
+    }
+  }
+  return node;
+};
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {Object} The value of the node, or null if no value or the child
+ *    node doesn't exist.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNodeValue = function(name) {
+  if (this.childNodeList_) {
+    var node = this.getChildNodes().get(name);
+    return node ? node.get() : null;
+  } else if (this.root_) {
+    return this.root_[name];
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * Sets a named child node of the current node.
+ * If value is null, removes the child node.
+ * @param {string} name The node name.
+ * @param {Object} value The value to set, can be DataNode, object,
+ *     property, or null.
+ * @return {Object} The child node, if set.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.setChildNode = function(name, value) {
+  var removedPath = null;
+  var node = null;
+  var addedNode = false;
+
+  // Set node to the DataNode to add - if the value isn't already a DataNode,
+  // creates a JsDataSource or JsPropertyDataSource wrapper
+  if (value != null) {
+    if (value.getDataName) {
+      // The value is a DataNode. We must update its parent.
+      node = value;
+      node.parent_ = this;
+    } else {
+      if (goog.isArray(value) || goog.isObject(value)) {
+        node = new goog.ds.JsDataSource(value, name, this);
+      } else {
+        node = new goog.ds.JsPropertyDataSource(
+            /** @type {goog.ds.DataNode} */ (this.root_), name, this);
+      }
+    }
+  }
+
+  // This logic will get cleaner once we can remove the backing array / object
+  // and just rely on the childNodeList_. This is needed until dependent code
+  // is cleaned up.
+  // TODO(user) Remove backing array / object and just use childNodeList_
+
+  if (goog.isArray(this.root_)) {
+    // To remove by name, need to create a map of the child nodes by ID
+    this.createChildNodes_();
+    var index = this.childNodeList_.indexOf(name);
+    if (value == null) {
+      // Remove the node
+      var nodeToRemove = this.childNodeList_.get(name);
+      if (nodeToRemove) {
+        removedPath = nodeToRemove.getDataPath();
+      }
+      this.root_.splice(index, 1);
+    } else {
+      // Add the node
+      if (index) {
+        this.root_[index] = value;
+      } else {
+        this.root_.push(value);
+      }
+    }
+    if (index == null) {
+      addedNode = true;
+    }
+    this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
+  } else if (goog.isObject(this.root_)) {
+    if (value == null) {
+      // Remove the node
+      this.createChildNodes_();
+      var nodeToRemove = this.childNodeList_.get(name);
+      if (nodeToRemove) {
+        removedPath = nodeToRemove.getDataPath();
+      }
+      delete this.root_[name];
+    } else {
+      // Add the node
+      if (!this.root_[name]) {
+        addedNode = true;
+      }
+      this.root_[name] = value;
+    }
+    // Only need to update childNodeList_ if has been created already
+    if (this.childNodeList_) {
+      this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
+    }
+  }
+
+  // Fire the event that the node changed
+  var dm = goog.ds.DataManager.getInstance();
+  if (node) {
+    dm.fireDataChange(node.getDataPath());
+    if (addedNode && this.isList()) {
+      dm.fireDataChange(this.getDataPath());
+      dm.fireDataChange(this.getDataPath() + '/count()');
+    }
+  } else if (removedPath) {
+    dm.fireDataChange(removedPath);
+    if (this.isList()) {
+      dm.fireDataChange(this.getDataPath());
+      dm.fireDataChange(this.getDataPath() + '/count()');
+    }
+  }
+  return node;
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getDataName = function() {
+  return this.dataName_;
+};
+
+
+/**
+ * Setthe name of the node relative to the parent node
+ * @param {string} dataName The name of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.setDataName = function(dataName) {
+  this.dataName_ = dataName;
+};
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getDataPath = function() {
+  var parentPath = '';
+  if (this.parent_) {
+    parentPath = this.parent_.getDataPath() + goog.ds.STR_PATH_SEPARATOR;
+  }
+
+  return parentPath + this.dataName_;
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ * @override
+ */
+goog.ds.JsDataSource.prototype.load = function() {
+  // Nothing to do
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * TODO(user) Discuss null value handling
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getLoadState = function() {
+  return (this.root_ == null) ? goog.ds.LoadState.NOT_LOADED :
+      goog.ds.LoadState.LOADED;
+};
+
+
+/**
+ * Whether the value of this node is a homogeneous list of data
+ * @return {boolean} True if a list.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.isList = function() {
+  return this.isList_ != null ? this.isList_ : goog.isArray(this.root_);
+};
+
+
+
+/**
+ * Data source for JavaScript properties that arent objects. Contains reference
+ * to parent object so that you can set the vaule
+ *
+ * @param {goog.ds.DataNode} parent Parent object.
+ * @param {string} dataName Name of this property.
+ * @param {goog.ds.DataNode=} opt_parentDataNode The parent data node. If
+ *     omitted, assumes that the parent object is the parent data node.
+ *
+ * @constructor
+ * @extends {goog.ds.BaseDataNode}
+ * @final
+ */
+goog.ds.JsPropertyDataSource = function(parent, dataName, opt_parentDataNode) {
+  goog.ds.BaseDataNode.call(this);
+  this.dataName_ = dataName;
+  this.parent_ = parent;
+  this.parentDataNode_ = opt_parentDataNode || this.parent_;
+};
+goog.inherits(goog.ds.JsPropertyDataSource, goog.ds.BaseDataNode);
+
+
+/**
+ * Get the value of the node
+ * @return {Object} The value of the node, or null if no value.
+ */
+goog.ds.JsPropertyDataSource.prototype.get = function() {
+  return this.parent_[this.dataName_];
+};
+
+
+/**
+ * Set the value of the node
+ * @param {Object} value The new value of the node.
+ * @override
+ */
+goog.ds.JsPropertyDataSource.prototype.set = function(value) {
+  var oldValue = this.parent_[this.dataName_];
+  this.parent_[this.dataName_] = value;
+
+  if (oldValue != value) {
+    goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+  }
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.JsPropertyDataSource.prototype.getDataName = function() {
+  return this.dataName_;
+};
+
+
+/** @override */
+goog.ds.JsPropertyDataSource.prototype.getParent = function() {
+  return this.parentDataNode_;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsondatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsondatasource.js b/externs/GCL/externs/goog/datasource/jsondatasource.js
new file mode 100644
index 0000000..1621002
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsondatasource.js
@@ -0,0 +1,153 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Implementation of DataNode for wrapping JSON data.
+ *
+ */
+
+
+goog.provide('goog.ds.JsonDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.JsDataSource');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.log');
+
+
+
+/**
+ * Data source whose backing is a JSON-like service, in which
+ * retreiving the resource specified by URL with the additional parameter
+ * callback. The resource retreived is executable JavaScript that
+ * makes a call to the named function with a JavaScript object literal
+ * as the only parameter.
+ *
+ * Example URI could be:
+ * http://www.google.com/data/search?q=monkey&callback=mycb
+ * which might return the JS:
+ * mycb({searchresults:
+ *   [{uri: 'http://www.monkey.com', title: 'Site About Monkeys'}]});
+ *
+ * TODO(user): Evaluate using goog.net.Jsonp here.
+ *
+ * A URI of an empty string will mean that no request is made
+ * and the data source will be a data source with no child nodes
+ *
+ * @param {string|goog.Uri} uri URI for the request.
+ * @param {string} name Name of the datasource.
+ * @param {string=} opt_callbackParamName The parameter name that is used to
+ *     specify the callback. Defaults to 'callback'.
+ *
+ * @extends {goog.ds.JsDataSource}
+ * @constructor
+ * @final
+ */
+goog.ds.JsonDataSource = function(uri, name, opt_callbackParamName) {
+  goog.ds.JsDataSource.call(this, null, name, null);
+  if (uri) {
+    this.uri_ = new goog.Uri(uri);
+  } else {
+    this.uri_ = null;
+  }
+
+  /**
+   * This is the callback parameter name that is added to the uri.
+   * @type {string}
+   * @private
+   */
+  this.callbackParamName_ = opt_callbackParamName || 'callback';
+
+};
+goog.inherits(goog.ds.JsonDataSource, goog.ds.JsDataSource);
+
+
+/**
+ * Default load state is NOT_LOADED
+ * @private
+ */
+goog.ds.JsonDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
+
+
+/**
+ * Map of all data sources, needed for callbacks
+ * Doesn't work unless dataSources is exported (not renamed)
+ */
+goog.ds.JsonDataSource['dataSources'] = {};
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the JsonDataSource
+ * @override
+ */
+goog.ds.JsonDataSource.prototype.load = function() {
+  if (this.uri_) {
+    // NOTE: "dataSources" is expose above by name so that it will not be
+    // renamed.  It should therefore be accessed via array notation here so
+    // that it also doesn't get renamed and stops the compiler from complaining
+    goog.ds.JsonDataSource['dataSources'][this.dataName_] = this;
+    goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
+        this.getDataName() + ' to ' + this.uri_);
+
+    this.loadState_ = goog.ds.LoadState.LOADING;
+
+    var uriToCall = new goog.Uri(this.uri_);
+    uriToCall.setParameterValue(this.callbackParamName_,
+        'JsonReceive.' + this.dataName_);
+
+    goog.global['JsonReceive'][this.dataName_] =
+        goog.bind(this.receiveData, this);
+
+    var scriptEl = goog.dom.createDom(goog.dom.TagName.SCRIPT,
+                                      {'src': uriToCall});
+    goog.dom.getElementsByTagNameAndClass(
+        goog.dom.TagName.HEAD)[0].appendChild(scriptEl);
+  } else {
+    this.root_ = {};
+    this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+  }
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsonDataSource.prototype.getLoadState = function() {
+  return this.loadState_;
+};
+
+
+/**
+ * Receives data from a Json request
+ * @param {Object} obj The JSON data.
+ */
+goog.ds.JsonDataSource.prototype.receiveData = function(obj) {
+  this.setRoot(obj);
+  this.loadState_ = goog.ds.LoadState.LOADED;
+  goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+};
+
+
+/**
+* Temp variable to hold callbacks
+* until BUILD supports multiple externs.js files
+*/
+goog.global['JsonReceive'] = {};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js b/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
new file mode 100644
index 0000000..bd2a024
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
@@ -0,0 +1,196 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview
+ * DataSource implementation that uses XMLHttpRequest as transport, with
+ * response as serialized JS object (not required to be JSON) that can
+ * be evaluated and set to a variable.
+ *
+ * Response can have unexecutable starting/ending text to prevent inclusion
+ * using <script src="...">
+ *
+ */
+
+
+goog.provide('goog.ds.JsXmlHttpDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.FastDataNode');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.events');
+goog.require('goog.log');
+goog.require('goog.net.EventType');
+goog.require('goog.net.XhrIo');
+
+
+
+/**
+ * Similar to JsonDataSource, with using XMLHttpRequest for transport
+ * Currently requires the result be a JS object that can be evaluated and
+ * set to a variable and doesn't require strict JSON notation.
+ *
+ * @param {(string|goog.Uri)} uri URI for the request.
+ * @param {string} name Name of the datasource.
+ * @param {string=} opt_startText Text to expect/strip before JS response.
+ * @param {string=} opt_endText Text to expect/strip after JS response.
+ * @param {boolean=} opt_usePost If true, use POST. Defaults to false (GET).
+ *
+ * @extends {goog.ds.FastDataNode}
+ * @constructor
+ * @final
+ */
+goog.ds.JsXmlHttpDataSource = function(uri, name, opt_startText, opt_endText,
+                                       opt_usePost) {
+  goog.ds.FastDataNode.call(this, {}, name, null);
+  if (uri) {
+    this.uri_ = new goog.Uri(uri);
+    this.xhr_ = new goog.net.XhrIo();
+    this.usePost_ = !!opt_usePost;
+
+    goog.events.listen(this.xhr_, goog.net.EventType.COMPLETE,
+        this.completed_, false, this);
+  } else {
+    this.uri_ = null;
+  }
+  this.startText_ = opt_startText;
+  this.endText_ = opt_endText;
+};
+goog.inherits(goog.ds.JsXmlHttpDataSource, goog.ds.FastDataNode);
+
+
+/**
+ * Delimiter for start of JSON data in response.
+ * null = starts at first character of response
+ * @type {string|undefined}
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.startText_;
+
+
+/**
+ * Delimiter for end of JSON data in response.
+ * null = ends at last character of response
+ * @type {string|undefined}
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.endText_;
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsXmlHttpDataSource.prototype.getLoadState = function() {
+  return this.loadState_;
+};
+
+
+/**
+ * Sets the request data. This can be used if it is required to
+ * send a specific body rather than build the body from the query
+ * parameters. Only used in POST requests.
+ * @param {string} data The data to send in the request body.
+ */
+goog.ds.JsXmlHttpDataSource.prototype.setQueryData = function(data) {
+  this.queryData_ = data;
+};
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the JsonDataSource
+ * @override
+ */
+goog.ds.JsXmlHttpDataSource.prototype.load = function() {
+  goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
+      this.getDataName() + ' to ' + this.uri_);
+
+  if (this.uri_) {
+    if (this.usePost_) {
+
+      var queryData;
+      if (!this.queryData_) {
+        queryData = this.uri_.getQueryData().toString();
+      } else {
+        queryData = this.queryData_;
+      }
+
+      var uriNoQuery = this.uri_.clone();
+      uriNoQuery.setQueryData(null);
+      this.xhr_.send(String(uriNoQuery), 'POST', queryData);
+    } else {
+      this.xhr_.send(String(this.uri_));
+    }
+  } else {
+    this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+  }
+};
+
+
+/**
+ * Called on successful request.
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.success_ = function()  {
+  goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+};
+
+
+/**
+ * Completed callback. Loads data if successful, otherwise sets
+ * state to FAILED
+ * @param {goog.events.Event} e Event object, Xhr is target.
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.completed_ = function(e) {
+  if (this.xhr_.isSuccess()) {
+    goog.log.info(goog.ds.logger,
+        'Got data for DataSource ' + this.getDataName());
+    var text = this.xhr_.getResponseText();
+
+    // Look for start and end token and trim text
+    if (this.startText_) {
+      var startpos = text.indexOf(this.startText_);
+      text = text.substring(startpos + this.startText_.length);
+    }
+    if (this.endText_) {
+      var endpos = text.lastIndexOf(this.endText_);
+      text = text.substring(0, endpos);
+    }
+
+    // Eval result
+    /** @preserveTry */
+    try {
+      var jsonObj = /** @type {Object} */ (eval('[' + text + '][0]'));
+      this.extendWith(jsonObj);
+      this.loadState_ = goog.ds.LoadState.LOADED;
+    }
+    catch (ex) {
+      // Invalid JS
+      this.loadState_ = goog.ds.LoadState.FAILED;
+      goog.log.error(goog.ds.logger, 'Failed to parse data: ' + ex.message);
+    }
+
+    // Call on a timer to avoid threading issues on IE.
+    goog.global.setTimeout(goog.bind(this.success_, this), 0);
+  } else {
+    goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
+        this.getDataName());
+    this.loadState_ = goog.ds.LoadState.FAILED;
+  }
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/xmldatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/xmldatasource.js b/externs/GCL/externs/goog/datasource/xmldatasource.js
new file mode 100644
index 0000000..5327269
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/xmldatasource.js
@@ -0,0 +1,417 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview
+ * Implementations of DataNode for wrapping XML data.
+ *
+ */
+
+goog.provide('goog.ds.XmlDataSource');
+goog.provide('goog.ds.XmlHttpDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.xml');
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNode');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.net.XhrIo');
+goog.require('goog.string');
+
+
+
+/**
+ * Data source whose backing is an xml node
+ *
+ * @param {Node} node The XML node. Can be null.
+ * @param {goog.ds.XmlDataSource} parent Parent of XML element. Can be null.
+ * @param {string=} opt_name The name of this node relative to the parent node.
+ *
+ * @extends {goog.ds.DataNode}
+ * @constructor
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.XmlDataSource = function(node, parent, opt_name) {
+  this.parent_ = parent;
+  this.dataName_ = opt_name || (node ? node.nodeName : '');
+  this.setNode_(node);
+};
+
+
+/**
+ * Constant to select XML attributes for getChildNodes
+ * @type {string}
+ * @private
+ */
+goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_ = '@*';
+
+
+/**
+ * Set the current root nodeof the data source.
+ * Can be an attribute node, text node, or element node
+ * @param {Node} node The node. Can be null.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.setNode_ = function(node) {
+  this.node_ = node;
+  if (node != null) {
+    switch (node.nodeType) {
+      case goog.dom.NodeType.ATTRIBUTE:
+      case goog.dom.NodeType.TEXT:
+        this.value_ = node.nodeValue;
+        break;
+      case goog.dom.NodeType.ELEMENT:
+        if (node.childNodes.length == 1 &&
+            node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
+          this.value_ = node.firstChild.nodeValue;
+        }
+    }
+  }
+};
+
+
+/**
+ * Creates the DataNodeList with the child nodes for this element.
+ * Allows for only building list as needed.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.createChildNodes_ = function() {
+  if (this.childNodeList_) {
+    return;
+  }
+  var childNodeList = new goog.ds.BasicNodeList();
+  if (this.node_ != null) {
+    var childNodes = this.node_.childNodes;
+    for (var i = 0, childNode; childNode = childNodes[i]; i++) {
+      if (childNode.nodeType != goog.dom.NodeType.TEXT ||
+          !goog.ds.XmlDataSource.isEmptyTextNodeValue_(childNode.nodeValue)) {
+        var newNode = new goog.ds.XmlDataSource(childNode,
+            this, childNode.nodeName);
+        childNodeList.add(newNode);
+      }
+    }
+  }
+  this.childNodeList_ = childNodeList;
+};
+
+
+/**
+ * Creates the DataNodeList with the attributes for the element
+ * Allows for only building list as needed.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.createAttributes_ = function() {
+  if (this.attributes_) {
+    return;
+  }
+  var attributes = new goog.ds.BasicNodeList();
+  if (this.node_ != null && this.node_.attributes != null) {
+    var atts = this.node_.attributes;
+    for (var i = 0, att; att = atts[i]; i++) {
+      var newNode = new goog.ds.XmlDataSource(att, this, att.nodeName);
+      attributes.add(newNode);
+    }
+  }
+  this.attributes_ = attributes;
+};
+
+
+/**
+ * Get the value of the node
+ * @return {Object} The value of the node, or null if no value.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.get = function() {
+  this.createChildNodes_();
+  return this.value_;
+};
+
+
+/**
+ * Set the value of the node
+ * @param {*} value The new value of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.set = function(value) {
+  throw Error('Can\'t set on XmlDataSource yet');
+};
+
+
+/** @override */
+goog.ds.XmlDataSource.prototype.getChildNodes = function(opt_selector) {
+  if (opt_selector && opt_selector ==
+      goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_) {
+    this.createAttributes_();
+    return this.attributes_;
+  } else if (opt_selector == null ||
+      opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+    this.createChildNodes_();
+    return this.childNodeList_;
+  } else {
+    throw Error('Unsupported selector');
+  }
+
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @return {goog.ds.DataNode} The child node, or null if
+ *   no node of this name exists.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getChildNode = function(name) {
+  if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
+    var att = this.node_.getAttributeNode(name.substring(1));
+    return att ? new goog.ds.XmlDataSource(att, this) : null;
+  } else {
+    return /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
+  }
+};
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {*} The value of the node, or null if no value or the child node
+ *    doesn't exist.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getChildNodeValue = function(name) {
+  if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
+    var node = this.node_.getAttributeNode(name.substring(1));
+    return node ? node.nodeValue : null;
+  } else {
+    var node = this.getChildNode(name);
+    return node ? node.get() : null;
+  }
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getDataName = function() {
+  return this.dataName_;
+};
+
+
+/**
+ * Setthe name of the node relative to the parent node
+ * @param {string} name The name of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.setDataName = function(name) {
+  this.dataName_ = name;
+};
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getDataPath = function() {
+  var parentPath = '';
+  if (this.parent_) {
+    parentPath = this.parent_.getDataPath() +
+        (this.dataName_.indexOf(goog.ds.STR_ARRAY_START) != -1 ? '' :
+        goog.ds.STR_PATH_SEPARATOR);
+  }
+
+  return parentPath + this.dataName_;
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.load = function() {
+  // Nothing to do
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getLoadState = function() {
+  return this.node_ ? goog.ds.LoadState.LOADED : goog.ds.LoadState.NOT_LOADED;
+};
+
+
+/**
+ * Check whether a node is an empty text node. Nodes consisting of only white
+ * space (#x20, #xD, #xA, #x9) can generally be collapsed to a zero length
+ * text string.
+ * @param {string} str String to match.
+ * @return {boolean} True if string equates to empty text node.
+ * @private
+ */
+goog.ds.XmlDataSource.isEmptyTextNodeValue_ = function(str) {
+  return /^[\r\n\t ]*$/.test(str);
+};
+
+
+/**
+ * Creates an XML document with one empty node.
+ * Useful for places where you need a node that
+ * can be queried against.
+ *
+ * @return {Document} Document with one empty node.
+ * @private
+ */
+goog.ds.XmlDataSource.createChildlessDocument_ = function() {
+  return goog.dom.xml.createDocument('nothing');
+};
+
+
+
+/**
+ * Data source whose backing is an XMLHttpRequest,
+ *
+ * A URI of an empty string will mean that no request is made
+ * and the data source will be a single, empty node.
+ *
+ * @param {(string|goog.Uri)} uri URL of the XMLHttpRequest.
+ * @param {string} name Name of the datasource.
+ *
+ * implements goog.ds.XmlHttpDataSource.
+ * @constructor
+ * @extends {goog.ds.XmlDataSource}
+ * @final
+ */
+goog.ds.XmlHttpDataSource = function(uri, name) {
+  goog.ds.XmlDataSource.call(this, null, null, name);
+  if (uri) {
+    this.uri_ = new goog.Uri(uri);
+  } else {
+    this.uri_ = null;
+  }
+};
+goog.inherits(goog.ds.XmlHttpDataSource, goog.ds.XmlDataSource);
+
+
+/**
+ * Default load state is NOT_LOADED
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the XMLHttpRequest
+ * @override
+ */
+goog.ds.XmlHttpDataSource.prototype.load = function() {
+  if (this.uri_) {
+    goog.log.info(goog.ds.logger, 'Sending XML request for DataSource ' +
+        this.getDataName() + ' to ' + this.uri_);
+    this.loadState_ = goog.ds.LoadState.LOADING;
+
+    goog.net.XhrIo.send(this.uri_, goog.bind(this.complete_, this));
+  } else {
+    this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+    this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+  }
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.XmlHttpDataSource.prototype.getLoadState = function() {
+  return this.loadState_;
+};
+
+
+/**
+ * Handles the completion of an XhrIo request. Dispatches to success or load
+ * based on the result.
+ * @param {!goog.events.Event} e The XhrIo event object.
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.complete_ = function(e) {
+  var xhr = /** @type {goog.net.XhrIo} */ (e.target);
+  if (xhr && xhr.isSuccess()) {
+    this.success_(xhr);
+  } else {
+    this.failure_();
+  }
+};
+
+
+/**
+ * Success result. Checks whether valid XML was returned
+ * and sets the XML and loadstate.
+ *
+ * @param {!goog.net.XhrIo} xhr The successful XhrIo object.
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.success_ = function(xhr) {
+  goog.log.info(goog.ds.logger,
+      'Got data for DataSource ' + this.getDataName());
+  var xml = xhr.getResponseXml();
+
+  // Fix for case where IE returns valid XML as text but
+  // doesn't parse by default
+  if (xml && !xml.hasChildNodes() &&
+      goog.isObject(xhr.getResponseText())) {
+    xml = goog.dom.xml.loadXml(xhr.getResponseText());
+  }
+  // Failure result
+  if (!xml || !xml.hasChildNodes()) {
+    this.loadState_ = goog.ds.LoadState.FAILED;
+    this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+  } else {
+    this.loadState_ = goog.ds.LoadState.LOADED;
+    this.node_ = xml.documentElement;
+  }
+
+  if (this.getDataName()) {
+    goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+  }
+};
+
+
+/**
+ * Failure result
+ *
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.failure_ = function() {
+  goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
+      this.getDataName());
+
+  this.loadState_ = goog.ds.LoadState.FAILED;
+  this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+
+  if (this.getDataName()) {
+    goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+  }
+};