thingmodel
Version:
Synchronize data and models across multiple devices
229 lines (176 loc) • 6.79 kB
text/typescript
module ThingModel.Proto {
export class FromProtobuf {
private _warehouse: Warehouse;
public StringDeclarations: { [key: number]: string };
constructor(warehouse: Warehouse) {
this._warehouse = warehouse;
this.StringDeclarations = {};
}
private KeyToString(key: number): string {
if (key == 0) {
return "";
}
var value = this.StringDeclarations[key];
return typeof value === "undefined" ? "undefined" : value;
}
public Convert(data: ArrayBuffer, check: boolean = false): string {
var transaction = ProtoTools.Builder.Transaction.decode(data);
return this.ConvertTransaction(transaction, check);
}
public ConvertTransaction(transaction: Transaction, check: boolean): string {
// Convert the string declarations
_.each(transaction.string_declarations, (d: StringDeclaration) => {
this.StringDeclarations[d.key] = d.value;
});
var senderId = this.KeyToString(transaction.string_sender_id);
var thingsToDelete: { [id: string]: ThingModel.Thing } = {};
// Remove the things
_.each(transaction.things_remove_list, (key: number) => {
var id = this.KeyToString(key);
var thing = this._warehouse.GetThing(id);
if (thing) {
thingsToDelete[thing.ID] = thing;
}
});
this._warehouse.RemoveCollection(thingsToDelete, true, senderId);
// Declare the things type
_.each(transaction.thingtypes_declaration_list, (d: ThingType) => {
this.ConvertThingTypeDeclaration(d, senderId);
});
var thingsToConnect: { model: ThingModel.Thing;proto: Thing }[] = [];
// Create the things
_.each(transaction.things_publish_list, (t: Thing) => {
var modelThing = this.ConvertThingPublication(t, check, senderId);
if (t.connections_change) {
thingsToConnect.push({ proto: t, model: modelThing });
}
});
// Connect the things
_.each(thingsToConnect, (tuple) => {
tuple.model.DisconnectAll();
_.each(tuple.proto.connections, (connection) => {
var t = this._warehouse.GetThing(this.KeyToString(connection));
if (t) {
tuple.model.Connect(t);
}
});
this._warehouse.RegisterThing(tuple.model, false, false, senderId);
});
return senderId;
}
private ConvertThingTypeDeclaration(thingType: ThingType, senderId: string): void {
var modelType = new ThingModel.ThingType(this.KeyToString(thingType.string_name));
modelType.Description = this.KeyToString(thingType.string_description);
_.each(thingType.properties, (propertyType: PropertyType) => {
var type: ThingModel.Type = null;
switch (propertyType.type) {
case PropertyType.Type.LOCATION:
type = ThingModel.Type.Location;
break;
case PropertyType.Type.STRING:
type = ThingModel.Type.String;
break;
case PropertyType.Type.DOUBLE:
type = ThingModel.Type.Double;
break;
case PropertyType.Type.INT:
type = ThingModel.Type.Int;
break;
case PropertyType.Type.BOOLEAN:
type = ThingModel.Type.Boolean;
break;
case PropertyType.Type.DATETIME:
type = ThingModel.Type.DateTime;
break;
}
var modelProperty = new ThingModel.PropertyType(
this.KeyToString(propertyType.string_key),
type,
propertyType.required);
modelProperty.Description = this.KeyToString(propertyType.string_description);
modelProperty.Name = this.KeyToString(propertyType.string_name);
modelType.DefineProperty(modelProperty);
});
this._warehouse.RegisterType(modelType, true, senderId);
}
private ConvertThingPublication(thing: Thing, check: boolean, senderId: string): ThingModel.Thing {
var type: ThingModel.ThingType = null;
if (thing.string_type_name != 0) {
type = this._warehouse.GetThingType(this.KeyToString(thing.string_type_name));
}
var id = this.KeyToString(thing.string_id);
var modelThing = this._warehouse.GetThing(id);
if (modelThing == null || (
modelThing.Type == null && type != null ||
type == null && modelThing.Type != null ||
(modelThing.Type != null && type != null && modelThing.Type.Name != type.Name))) {
modelThing = new ThingModel.Thing(id, type);
}
_.each(thing.properties, (property) => {
this.ConvertThingProperty(property, modelThing);
});
if (check && type != null && !type.Check(modelThing)) {
console.log("Object «" + id + "» from «" + senderId + "»not valid, ignored");
} else if (!thing.connections_change) {
this._warehouse.RegisterThing(modelThing, false, false, senderId);
}
return modelThing;
}
private ConvertLocationProperty(location: Location, property: Property) {
if (property.location_value != null) {
location.X = property.location_value.x;
location.Y = property.location_value.y;
if (!property.location_value.z_null) {
location.Z = property.location_value.z;
}
}
}
private ConvertThingProperty(property: Property, modelThing: ThingModel.Thing): void {
var modelProperty: ThingModel.Property = null;
var key = this.KeyToString(property.string_key);
switch (property.type) {
case Property.Type.LOCATION_EQUATORIAL:
var locEquatorial = new ThingModel.Location.Equatorial();
this.ConvertLocationProperty(locEquatorial, property);
modelProperty = new ThingModel.Property.Location.Equatorial(key, locEquatorial);
break;
case Property.Type.LOCATION_POINT:
var locPoint = new ThingModel.Location.Point();
this.ConvertLocationProperty(locPoint, property);
modelProperty = new ThingModel.Property.Location.Point(key, locPoint);
break;
case Property.Type.LOCATION_LATLNG:
var locLatLng = new ThingModel.Location.LatLng();
this.ConvertLocationProperty(locLatLng, property);
modelProperty = new ThingModel.Property.Location.LatLng(key, locLatLng);
break;
case Property.Type.STRING:
var value: string;
if (property.string_value != null) {
value = property.string_value.value;
if (!value && property.string_value.string_value != 0) {
value = this.KeyToString(property.string_value.string_value);
}
} else {
value = "undefined";
}
modelProperty = new ThingModel.Property.String(key, value);
break;
case Property.Type.DOUBLE:
modelProperty = new ThingModel.Property.Double(key, property.double_value);
break;
case Property.Type.INT:
modelProperty = new ThingModel.Property.Int(key, property.int_value);
break;
case Property.Type.BOOLEAN:
modelProperty = new ThingModel.Property.Boolean(key, property.boolean_value);
break;
case Property.Type.DATETIME:
modelProperty = new ThingModel.Property.DateTime(key,
new Date((<any>property.datetime_value).toNumber()));
break;
}
modelThing.SetProperty(modelProperty);
}
}
}