--- /dev/null
+/**\r
+ * Constructs a new Namespace.\r
+ * @exports ProtoBuf.Reflect.Namespace\r
+ * @param {!ProtoBuf.Builder} builder Builder reference\r
+ * @param {?ProtoBuf.Reflect.Namespace} parent Namespace parent\r
+ * @param {string} name Namespace name\r
+ * @param {Object.<string,*>=} options Namespace options\r
+ * @param {string?} syntax The syntax level of this definition (e.g., proto3)\r
+ * @constructor\r
+ * @extends ProtoBuf.Reflect.T\r
+ */\r
+var Namespace = function(builder, parent, name, options, syntax) {\r
+ T.call(this, builder, parent, name);\r
+\r
+ /**\r
+ * @override\r
+ */\r
+ this.className = "Namespace";\r
+\r
+ /**\r
+ * Children inside the namespace.\r
+ * @type {!Array.<ProtoBuf.Reflect.T>}\r
+ */\r
+ this.children = [];\r
+\r
+ /**\r
+ * Options.\r
+ * @type {!Object.<string, *>}\r
+ */\r
+ this.options = options || {};\r
+\r
+ /**\r
+ * Syntax level (e.g., proto2 or proto3).\r
+ * @type {!string}\r
+ */\r
+ this.syntax = syntax || "proto2";\r
+};\r
+\r
+/**\r
+ * @alias ProtoBuf.Reflect.Namespace.prototype\r
+ * @inner\r
+ */\r
+var NamespacePrototype = Namespace.prototype = Object.create(T.prototype);\r
+\r
+/**\r
+ * Returns an array of the namespace's children.\r
+ * @param {ProtoBuf.Reflect.T=} type Filter type (returns instances of this type only). Defaults to null (all children).\r
+ * @return {Array.<ProtoBuf.Reflect.T>}\r
+ * @expose\r
+ */\r
+NamespacePrototype.getChildren = function(type) {\r
+ type = type || null;\r
+ if (type == null)\r
+ return this.children.slice();\r
+ var children = [];\r
+ for (var i=0, k=this.children.length; i<k; ++i)\r
+ if (this.children[i] instanceof type)\r
+ children.push(this.children[i]);\r
+ return children;\r
+};\r
+\r
+/**\r
+ * Adds a child to the namespace.\r
+ * @param {ProtoBuf.Reflect.T} child Child\r
+ * @throws {Error} If the child cannot be added (duplicate)\r
+ * @expose\r
+ */\r
+NamespacePrototype.addChild = function(child) {\r
+ var other;\r
+ if (other = this.getChild(child.name)) {\r
+ // Try to revert camelcase transformation on collision\r
+ if (other instanceof Message.Field && other.name !== other.originalName && this.getChild(other.originalName) === null)\r
+ other.name = other.originalName; // Revert previous first (effectively keeps both originals)\r
+ else if (child instanceof Message.Field && child.name !== child.originalName && this.getChild(child.originalName) === null)\r
+ child.name = child.originalName;\r
+ else\r
+ throw Error("Duplicate name in namespace "+this.toString(true)+": "+child.name);\r
+ }\r
+ this.children.push(child);\r
+};\r
+\r
+/**\r
+ * Gets a child by its name or id.\r
+ * @param {string|number} nameOrId Child name or id\r
+ * @return {?ProtoBuf.Reflect.T} The child or null if not found\r
+ * @expose\r
+ */\r
+NamespacePrototype.getChild = function(nameOrId) {\r
+ var key = typeof nameOrId === 'number' ? 'id' : 'name';\r
+ for (var i=0, k=this.children.length; i<k; ++i)\r
+ if (this.children[i][key] === nameOrId)\r
+ return this.children[i];\r
+ return null;\r
+};\r
+\r
+/**\r
+ * Resolves a reflect object inside of this namespace.\r
+ * @param {string|!Array.<string>} qn Qualified name to resolve\r
+ * @param {boolean=} excludeNonNamespace Excludes non-namespace types, defaults to `false`\r
+ * @return {?ProtoBuf.Reflect.Namespace} The resolved type or null if not found\r
+ * @expose\r
+ */\r
+NamespacePrototype.resolve = function(qn, excludeNonNamespace) {\r
+ var part = typeof qn === 'string' ? qn.split(".") : qn,\r
+ ptr = this,\r
+ i = 0;\r
+ if (part[i] === "") { // Fully qualified name, e.g. ".My.Message'\r
+ while (ptr.parent !== null)\r
+ ptr = ptr.parent;\r
+ i++;\r
+ }\r
+ var child;\r
+ do {\r
+ do {\r
+ if (!(ptr instanceof Reflect.Namespace)) {\r
+ ptr = null;\r
+ break;\r
+ }\r
+ child = ptr.getChild(part[i]);\r
+ if (!child || !(child instanceof Reflect.T) || (excludeNonNamespace && !(child instanceof Reflect.Namespace))) {\r
+ ptr = null;\r
+ break;\r
+ }\r
+ ptr = child; i++;\r
+ } while (i < part.length);\r
+ if (ptr != null)\r
+ break; // Found\r
+ // Else search the parent\r
+ if (this.parent !== null)\r
+ return this.parent.resolve(qn, excludeNonNamespace);\r
+ } while (ptr != null);\r
+ return ptr;\r
+};\r
+\r
+/**\r
+ * Determines the shortest qualified name of the specified type, if any, relative to this namespace.\r
+ * @param {!ProtoBuf.Reflect.T} t Reflection type\r
+ * @returns {string} The shortest qualified name or, if there is none, the fqn\r
+ * @expose\r
+ */\r
+NamespacePrototype.qn = function(t) {\r
+ var part = [], ptr = t;\r
+ do {\r
+ part.unshift(ptr.name);\r
+ ptr = ptr.parent;\r
+ } while (ptr !== null);\r
+ for (var len=1; len <= part.length; len++) {\r
+ var qn = part.slice(part.length-len);\r
+ if (t === this.resolve(qn, t instanceof Reflect.Namespace))\r
+ return qn.join(".");\r
+ }\r
+ return t.fqn();\r
+};\r
+\r
+/**\r
+ * Builds the namespace and returns the runtime counterpart.\r
+ * @return {Object.<string,Function|Object>} Runtime namespace\r
+ * @expose\r
+ */\r
+NamespacePrototype.build = function() {\r
+ /** @dict */\r
+ var ns = {};\r
+ var children = this.children;\r
+ for (var i=0, k=children.length, child; i<k; ++i) {\r
+ child = children[i];\r
+ if (child instanceof Namespace)\r
+ ns[child.name] = child.build();\r
+ }\r
+ if (Object.defineProperty)\r
+ Object.defineProperty(ns, "$options", { "value": this.buildOpt() });\r
+ return ns;\r
+};\r
+\r
+/**\r
+ * Builds the namespace's '$options' property.\r
+ * @return {Object.<string,*>}\r
+ */\r
+NamespacePrototype.buildOpt = function() {\r
+ var opt = {},\r
+ keys = Object.keys(this.options);\r
+ for (var i=0, k=keys.length; i<k; ++i) {\r
+ var key = keys[i],\r
+ val = this.options[keys[i]];\r
+ // TODO: Options are not resolved, yet.\r
+ // if (val instanceof Namespace) {\r
+ // opt[key] = val.build();\r
+ // } else {\r
+ opt[key] = val;\r
+ // }\r
+ }\r
+ return opt;\r
+};\r
+\r
+/**\r
+ * Gets the value assigned to the option with the specified name.\r
+ * @param {string=} name Returns the option value if specified, otherwise all options are returned.\r
+ * @return {*|Object.<string,*>}null} Option value or NULL if there is no such option\r
+ */\r
+NamespacePrototype.getOption = function(name) {\r
+ if (typeof name === 'undefined')\r
+ return this.options;\r
+ return typeof this.options[name] !== 'undefined' ? this.options[name] : null;\r
+};\r