jaydata-reso
Version:
Jaydata fork for RESO Web API
462 lines (434 loc) • 19.1 kB
JavaScript
///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);