UNPKG

jaydata-reso

Version:

Jaydata fork for RESO Web API

462 lines (434 loc) 19.1 kB
///EntitySet is responsible for /// -creating and holding entityType through schema /// - provide Add method /// - provide Delete method /// - provide Update method /// - provide queryProvider for queryable $data.EntitySchemaConfig = function EntitySchemaConfig() { this.Name = ""; }; $data.entitySetState = { created: 0, defined: 1, active: 2 }; $data.Class.defineEx('$data.EntitySet', [ { type: $data.Queryable, params: [new ConstructorParameter(1)] } ], null, { constructor: function (elementType, context, collectionName, eventHandlers, roles) { /// <signature> /// <summary>Represents a typed entity set that is used to perform create, read, update, and delete operations</summary> /// <param name="elementType" type="Function" subClassOf="$data.Entity">Type of entity set elements, elementType must be subclass of $data.Entity</param> /// <param name="context" type="$data.EntityContext">Context of the EntitySet</param> /// <param name="collectionName" type="String">Name of the EntitySet</param> /// </signature> this.createNew = this[elementType.name] = this.elementType = this.defaultType = elementType; var self = this; context['createAdd' + elementType.name] = function (initData) { var entity = new elementType(initData); return self.add(entity); } this.stateManager = new $data.EntityStateManager(this); this.collectionName = collectionName; this.roles = roles; for (var i in eventHandlers){ this[i] = eventHandlers[i]; } }, addNew: function(item, cb) { var callback = $data.typeSystem.createCallbackSetting(cb); var _item = new this.createNew(item); this.entityContext.saveChanges(cb); return _item; }, executeQuery: function (expression, on_ready) { //var compiledQuery = this.entityContext var callBack = $data.typeSystem.createCallbackSetting(on_ready); this.entityContext.executeQuery(expression, callBack); }, getTraceString: function (expression) { return this.entityContext.getTraceString(expression); }, setContext: function (entityContext) { this.entitySetState = $data.entitySetState.active; this.entityContext = entityContext; this.entityContext[this.schema.name] = this[this.schema.name]; }, _trackEntity: function (entity) { var trackedEntities = this.entityContext.stateManager.trackedEntities; for (var i = 0; i < trackedEntities.length; i++) { if (trackedEntities[i].data === entity) return; } trackedEntities.push({ entitySet: this, data: entity }); }, add: function (entity, req) { /// <signature> /// <summary>Creates a typed entity and adds to the context.</summary> /// <param name="entity" type="Object">The init parameters whish is based on Entity</param> /// <example> /// /// Persons.add({ Name: 'John', Email: 'john@example.com', Age: 30, Gender: 'Male' }); /// /// </example> /// </signature> /// <signature> /// <summary>Adds the given entity to the context.</summary> /// <param name="entity" type="$data.Entity">The entity to add</param> /// <example> /// /// Persons.add(new $news.Types.Person({ Name: 'John', Email: 'john@example.com', Age: 30, Gender: 'Male' })); /// /// </example> /// <example> /// /// var person = new $news.Types.Person({ Name: 'John', Email: 'john@example.com', Age: 30, Gender: 'Male' }); /// Persons.add(person); /// /// </example> /// </signature> var data = entity; if (entity instanceof $data.EntityWrapper) { data = entity.getEntity(); } else if (!(entity instanceof this.createNew)) { data = new this.createNew(entity); } data.entityState = $data.EntityState.Added; data.changedProperties = undefined; data.context = this.entityContext; var keyName =this.elementType.memberDefinitions.getKeyProperties()[0].name; var keyValue = data[keyName]; if (req.reso.externalIndex) { if (INDEX.indexOf(keyValue) == -1) { INDEX[INDEX.length] = keyValue; req.reso.resultSize = 1; req.reso.keyValue = keyValue; this._trackEntity(data); //console.dir(data); // } else { //console.log("Item with a " + keyName + " of " + keyValue + " already exists. Not added"); } } else { req.reso.resultSize = 1; req.reso.keyValue = keyValue; this._trackEntity(data); } return data; }, addMany: function(entities) { var result = []; var self = this; entities.forEach(function (entity) { result.push(self.add(entity)); }); return result; }, remove: function (entity, req) { /// <signature> /// <summary>Creates a typed entity and marks it as Deleted.</summary> /// <param name="entity" type="Object">The init parameters whish is based on Entity</param> /// <example> /// Person will be marked as Deleted where an id is 5. Id is a key of entity. /// Persons.remove({ Id: 5 }); /// /// </example> /// </signature> /// <signature> /// <summary>Marks the given entity as Deleted.</summary> /// <param name="entity" type="$data.Entity">The entity to remove</param> /// <example> /// /// Persons.remove(person); /// /// </example> /// <example> /// Person will be marked as Deleted where an Id is 5. Id is a key of entity. /// Persons.add(new $news.Types.Person({ Id: 5 })); /// /// </example> /// </signature> var data = entity; if (entity instanceof $data.EntityWrapper) { data = entity.getEntity(); } else if (!(entity instanceof this.createNew)) { data = new this.createNew(entity); } data.entityState = $data.EntityState.Deleted; var keyName =this.elementType.memberDefinitions.getKeyProperties()[0].name; if (req.reso.externalIndex) { if (entity[keyName]) { var keyValue = entity[keyName]; req.reso.resultSize = 1; req.reso.keyValue = entity[keyName]; var position = INDEX.indexOf(keyValue); if (position != -1) { INDEX.splice(position,1); } } } else { req.reso.resultSize = 1; req.reso.keyValue = entity[keyName]; } data.changedProperties = undefined; this._trackEntity(data); }, attach: function (entity, mode, req) { /// <signature> /// <summary>Creates a typed entity and adds to the Context with Unchanged state.</summary> /// <param name="entity" type="Object">The init parameters whish is based on Entity</param> /// <example> /// /// Persons.attach({ Id: 5, Email: 'newEmail@example.com' }); /// /// </example> /// </signature> /// <signature> /// <summary>Adds to the context and sets state Unchanged.</summary> /// <param name="entity" type="$data.Entity">The entity to attach</param> /// <example> /// /// Persons.attach(person); /// /// </example> /// <example> /// Set an entity's related entities without loading /// /// var categoryPromo = new $news.Types.Category({ Id: 5 }); /// Category.attach(categoryPromo); /// var article = new $news.Types.Article({ Title: 'New Article title', Body: 'Article body', Category: [ categoryPromo ] }); /// Article.attach(article); /// /// </example> /// </signature> var data = entity; if (entity instanceof $data.EntityWrapper) { data = entity.getEntity(); } else if (!(entity instanceof this.createNew)) { data = new this.createNew(entity); } for (var i = 0; i < this.entityContext.stateManager.trackedEntities.length; i++) { var current = this.entityContext.stateManager.trackedEntities[i]; if (current.data === data) break; if (current.data.equals(data)) { Guard.raise(new Exception("Context already contains this entity!!!")); } } if (mode === true) { if (data.changedProperties && data.changedProperties.length > 0) { data.entityState = $data.EntityState.Modified; } else { data.entityState = $data.EntityState.Unchanged; } } else { if (typeof mode === "string") mode = $data.EntityAttachMode[mode]; var attachMode = mode || $data.EntityAttachMode[$data.EntityAttachMode.defaultMode]; if (typeof attachMode === "function") { attachMode.call($data.EntityAttachMode, data); } else { data.entityState = $data.EntityState.Unchanged; data.changedProperties = undefined; } } /*if (!keepChanges) { data.entityState = $data.EntityState.Unchanged; data.changedProperties = undefined; }*/ data.context = this.entityContext; if (req) { var keyName =this.elementType.memberDefinitions.getKeyProperties()[0].name; req.reso.resultSize = 1; req.reso.keyValue = entity[keyName]; } this._trackEntity(data); }, detach: function (entity) { /// <signature> /// <summary>Creates a typed entity and detach from the Context with Detached state.</summary> /// <param name="entity" type="Object">The init parameters whish is based on Entity</param> /// <example> /// Person will be Detached where an id is 5. Id is a key of entity. /// Persons.detach({ Id: 5 }); /// /// </example> /// </signature> /// <signature> /// <summary>Detach from the context and sets state Detached.</summary> /// <param name="entity" type="$data.Entity">The entity to detach</param> /// <example> /// /// Persons.detach(person); /// /// </example> /// <example> /// Person will be Detached where an Id is 5. Id is a key of entity. /// Persons.add(new $news.Types.Person({ Id: 5 })); /// /// </example> /// </signature> var data = entity; if (entity instanceof $data.EntityWrapper) { data = entity.getEntity(); } else if (!(entity instanceof this.createNew)) { data = new this.createNew(entity); } var existsItem; var trackedEnt = this.entityContext.stateManager.trackedEntities; for (var i = 0; i < trackedEnt.length; i++) { if (trackedEnt[i].data.equals(data)) existsItem = trackedEnt[i]; } //var existsItem = this.entityContext.stateManager.trackedEntities.filter(function (i) { return i.data.equals(data); }).pop(); if (existsItem) { var idx = this.entityContext.stateManager.trackedEntities.indexOf(existsItem); entity.entityState = $data.EntityState.Detached; this.entityContext.stateManager.trackedEntities.splice(idx, 1); return; } }, attachOrGet: function (entity, mode) { /// <signature> /// <summary>Creates a typed entity and adds to the Context with Unchanged state.</summary> /// <param name="entity" type="Object">The init parameters whish is based on Entity</param> /// <returns type="$data.Entity" /> /// <example> /// Id is a key of entity. /// var person = Persons.attachOrGet({ Id: 5 }); /// /// </example> /// </signature> /// <signature> /// <summary>If not in context then adds to it and sets state Unchanged.</summary> /// <param name="entity" type="$data.Entity">The entity to detach</param> /// <returns type="$data.Entity" /> /// <example> /// /// var attachedPerson = Persons.attachOrGet(person); /// /// </example> /// <example> /// Id is a key of entity. /// var p = new $news.Types.Person({ Id: 5 }); /// var attachedPerson = Persons.attachOrGet(p); /// /// </example> /// </signature> var data = entity; if (entity instanceof $data.EntityWrapper) { data = entity.getEntity(); } else if (!(entity instanceof this.createNew)) { data = new this.createNew(entity); } var existsItem; var trackedEnt = this.entityContext.stateManager.trackedEntities; for (var i = 0; i < trackedEnt.length; i++) { if (trackedEnt[i].data.equals(data)) existsItem = trackedEnt[i]; } //var existsItem = this.entityContext.stateManager.trackedEntities.filter(function (i) { return i.data.equals(data); }).pop(); if (existsItem) { return existsItem.data; } if (typeof mode === "string") mode = $data.EntityAttachMode[mode]; var attachMode = mode || $data.EntityAttachMode[$data.EntityAttachMode.defaultMode]; if (typeof attachMode === "function") { attachMode.call($data.EntityAttachMode, data); } else { data.entityState = $data.EntityState.Unchanged; data.changedProperties = undefined; } //data.entityState = $data.EntityState.Unchanged; //data.changedProperties = undefined; data.context = this.entityContext; this._trackEntity(data); return data; }, //find: function (keys) { // //todo global scope // if (!this.entityKeys) { // this.entityKeys = this.createNew.memberDefinition.filter(function (prop) { return prop.key; }, this); // } // this.entityContext.stateManager.trackedEntities.forEach(function (item) { // if (item.entitySet == this) { // var isOk = true; // this.entityKeys.forEach(function (item, index) { isOK = isOk && (item.data[item.name] == keys[index]); }, this); // if (isOk) { // return item.data; // } // } // }, this); // //TODO: db call // return null; //}, loadItemProperty: function (entity, memberDefinition, callback) { /// <signature> /// <summary>Loads a property of the entity through the storage provider.</summary> /// <param name="entity" type="$data.Entity">Entity object</param> /// <param name="property" type="String">Property name</param> /// <param name="callback" type="Function"> /// <summary>Callback function</summary> /// <param name="propertyValue" /> /// </param> /// <returns type="$.Deferred" /> /// </signature> /// <signature> /// <summary>Loads a property of the entity through the storage provider.</summary> /// <param name="entity" type="$data.Entity">Entity object</param> /// <param name="property" type="String">Property name</param> /// <param name="callbacks" type="Object"> /// Success and error callbacks definition. /// Example: [code]{ success: function(db) { .. }, error: function() { .. } }[/code] /// </param> /// <returns type="$.Deferred" /> /// </signature> /// <signature> /// <summary>Loads a property of the entity through the storage provider.</summary> /// <param name="entity" type="$data.Entity">Entity object</param> /// <param name="property" type="$data.MemberDefinition">Property definition</param> /// <param name="callback" type="Function"> /// <summary>Callback function</summary> /// <param name="propertyValue" /> /// </param> /// <returns type="$.Deferred" /> /// </signature> /// <signature> /// <summary>Loads a property of the entity through the storage provider.</summary> /// <param name="entity" type="$data.Entity">Entity object</param> /// <param name="property" type="$data.MemberDefinition">Property definition</param> /// <param name="callbacks" type="Object"> /// Success and error callbacks definition. /// Example: [code]{ success: function(db) { .. }, error: function() { .. } }[/code] /// </param> /// <returns type="$.Deferred" /> /// </signature> return this.entityContext.loadItemProperty(entity, memberDefinition, callback); }, saveChanges: function () { return this.entityContext.saveChanges.apply(this.entityContext, arguments); }, addProperty: function (name, getter, setter) { return this.elementType.addProperty.apply(this.elementType, arguments); }, expression: { get: function () { if (!this._expression) { var ec = Container.createEntityContextExpression(this.entityContext); //var name = entitySet.collectionName; //var entitySet = this.entityContext[entitySetName]; var memberdef = this.entityContext.getType().getMemberDefinition(this.collectionName); var es = Container.createEntitySetExpression(ec, Container.createMemberInfoExpression(memberdef), null, this); this._expression = es; } return this._expression; }, set: function (value) { this._expression = value; } }, getFieldUrl: function (keys, field) { return this.entityContext.getFieldUrl(keys, field, this); }, bulkInsert: function (fields, datas, callback) { return this.entityContext.bulkInsert(this, fields, datas, callback); } }, null);