basant307/AI_Governance_Project
048
1"use strict";2module.exports = OneOf;3 4// extends ReflectionObject5var ReflectionObject = require("./object");6((OneOf.prototype = Object.create(ReflectionObject.prototype)).constructor = OneOf).className = "OneOf";7 8var Field = require("./field"),9 util = require("./util");10 11/**12 * Constructs a new oneof instance.13 * @classdesc Reflected oneof.14 * @extends ReflectionObject15 * @constructor16 * @param {string} name Oneof name17 * @param {string[]|Object.<string,*>} [fieldNames] Field names18 * @param {Object.<string,*>} [options] Declared options19 * @param {string} [comment] Comment associated with this field20 */21function OneOf(name, fieldNames, options, comment) {22 if (!Array.isArray(fieldNames)) {23 options = fieldNames;24 fieldNames = undefined;25 }26 ReflectionObject.call(this, name, options);27 28 /* istanbul ignore if */29 if (!(fieldNames === undefined || Array.isArray(fieldNames)))30 throw TypeError("fieldNames must be an Array");31 32 /**33 * Field names that belong to this oneof.34 * @type {string[]}35 */36 this.oneof = fieldNames || []; // toJSON, marker37 38 /**39 * Fields that belong to this oneof as an array for iteration.40 * @type {Field[]}41 * @readonly42 */43 this.fieldsArray = []; // declared readonly for conformance, possibly not yet added to parent44 45 /**46 * Comment for this field.47 * @type {string|null}48 */49 this.comment = comment;50}51 52/**53 * Oneof descriptor.54 * @interface IOneOf55 * @property {Array.<string>} oneof Oneof field names56 * @property {Object.<string,*>} [options] Oneof options57 */58 59/**60 * Constructs a oneof from a oneof descriptor.61 * @param {string} name Oneof name62 * @param {IOneOf} json Oneof descriptor63 * @returns {OneOf} Created oneof64 * @throws {TypeError} If arguments are invalid65 */66OneOf.fromJSON = function fromJSON(name, json) {67 return new OneOf(name, json.oneof, json.options, json.comment);68};69 70/**71 * Converts this oneof to a oneof descriptor.72 * @param {IToJSONOptions} [toJSONOptions] JSON conversion options73 * @returns {IOneOf} Oneof descriptor74 */75OneOf.prototype.toJSON = function toJSON(toJSONOptions) {76 var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;77 return util.toObject([78 "options" , this.options,79 "oneof" , this.oneof,80 "comment" , keepComments ? this.comment : undefined81 ]);82};83 84/**85 * Adds the fields of the specified oneof to the parent if not already done so.86 * @param {OneOf} oneof The oneof87 * @returns {undefined}88 * @inner89 * @ignore90 */91function addFieldsToParent(oneof) {92 if (oneof.parent)93 for (var i = 0; i < oneof.fieldsArray.length; ++i)94 if (!oneof.fieldsArray[i].parent)95 oneof.parent.add(oneof.fieldsArray[i]);96}97 98/**99 * Adds a field to this oneof and removes it from its current parent, if any.100 * @param {Field} field Field to add101 * @returns {OneOf} `this`102 */103OneOf.prototype.add = function add(field) {104 105 /* istanbul ignore if */106 if (!(field instanceof Field))107 throw TypeError("field must be a Field");108 109 if (field.parent && field.parent !== this.parent)110 field.parent.remove(field);111 this.oneof.push(field.name);112 this.fieldsArray.push(field);113 field.partOf = this; // field.parent remains null114 addFieldsToParent(this);115 return this;116};117 118/**119 * Removes a field from this oneof and puts it back to the oneof's parent.120 * @param {Field} field Field to remove121 * @returns {OneOf} `this`122 */123OneOf.prototype.remove = function remove(field) {124 125 /* istanbul ignore if */126 if (!(field instanceof Field))127 throw TypeError("field must be a Field");128 129 var index = this.fieldsArray.indexOf(field);130 131 /* istanbul ignore if */132 if (index < 0)133 throw Error(field + " is not a member of " + this);134 135 this.fieldsArray.splice(index, 1);136 index = this.oneof.indexOf(field.name);137 138 /* istanbul ignore else */139 if (index > -1) // theoretical140 this.oneof.splice(index, 1);141 142 field.partOf = null;143 return this;144};145 146/**147 * @override148 */149OneOf.prototype.onAdd = function onAdd(parent) {150 ReflectionObject.prototype.onAdd.call(this, parent);151 var self = this;152 // Collect present fields153 for (var i = 0; i < this.oneof.length; ++i) {154 var field = parent.get(this.oneof[i]);155 if (field && !field.partOf) {156 field.partOf = self;157 self.fieldsArray.push(field);158 }159 }160 // Add not yet present fields161 addFieldsToParent(this);162};163 164/**165 * @override166 */167OneOf.prototype.onRemove = function onRemove(parent) {168 for (var i = 0, field; i < this.fieldsArray.length; ++i)169 if ((field = this.fieldsArray[i]).parent)170 field.parent.remove(field);171 ReflectionObject.prototype.onRemove.call(this, parent);172};173 174/**175 * Determines whether this field corresponds to a synthetic oneof created for176 * a proto3 optional field. No behavioral logic should depend on this, but it177 * can be relevant for reflection.178 * @name OneOf#isProto3Optional179 * @type {boolean}180 * @readonly181 */182Object.defineProperty(OneOf.prototype, "isProto3Optional", {183 get: function() {184 if (this.fieldsArray == null || this.fieldsArray.length !== 1) {185 return false;186 }187 188 var field = this.fieldsArray[0];189 return field.options != null && field.options["proto3_optional"] === true;190 }191});192 193/**194 * Decorator function as returned by {@link OneOf.d} (TypeScript).195 * @typedef OneOfDecorator196 * @type {function}197 * @param {Object} prototype Target prototype198 * @param {string} oneofName OneOf name199 * @returns {undefined}200 */201 202/**203 * OneOf decorator (TypeScript).204 * @function205 * @param {...string} fieldNames Field names206 * @returns {OneOfDecorator} Decorator function207 * @template T extends string208 */209OneOf.d = function decorateOneOf() {210 var fieldNames = new Array(arguments.length),211 index = 0;212 while (index < arguments.length)213 fieldNames[index] = arguments[index++];214 return function oneOfDecorator(prototype, oneofName) {215 util.decorateType(prototype.constructor)216 .add(new OneOf(oneofName, fieldNames));217 Object.defineProperty(prototype, oneofName, {218 get: util.oneOfGetter(fieldNames),219 set: util.oneOfSetter(fieldNames)220 });221 };222};223 