Bladeren bron

event instance changeset

Adam Shaw 8 jaren geleden
bovenliggende
commit
c52721e0a7
5 gewijzigde bestanden met toevoegingen van 175 en 111 verwijderingen
  1. 2 0
      src.json
  2. 15 0
      src/models/EventInstanceChangeset.js
  3. 93 0
      src/models/EventInstanceRepo.js
  4. 32 20
      src/models/EventManager.js
  5. 33 91
      src/models/EventPeriod.js

+ 2 - 0
src.json

@@ -59,6 +59,8 @@
     "models/ComponentFootprint.js",
     "models/EventManager.js",
     "models/EventPeriod.js",
+    "models/EventInstanceRepo.js",
+    "models/EventInstanceChangeset.js",
     "models/BusinessHourGenerator.js",
     "models/event/EventDefParser.js",
     "models/event/EventDef.js",

+ 15 - 0
src/models/EventInstanceChangeset.js

@@ -0,0 +1,15 @@
+
+var EventInstanceChangeset = EventInstanceRepo.extend({
+
+	removals: null,
+
+
+	constructor: function(removals, adds) {
+		EventInstanceRepo.call(this);
+
+		this.removals = removals || [];
+
+		(adds || []).forEach(this.addEventInstance.bind(this));
+	}
+
+});

+ 93 - 0
src/models/EventInstanceRepo.js

@@ -0,0 +1,93 @@
+
+var EventInstanceRepo = Class.extend({
+
+	byDefId: null,
+
+
+	constructor: function() {
+		this.byDefId = {};
+	},
+
+
+	getEventInstancesForDef: function(eventDef) {
+		return (this.byDefId[eventDef.id] || []).filter(function(eventInstance) {
+			return eventInstance.def === eventDef;
+		});
+	},
+
+
+	getEventInstances: function() { // TODO: use iterator?
+		var byDefId = this.byDefId;
+		var a = [];
+		var id;
+
+		for (id in byDefId) {
+			a.push.apply(a, byDefId[id]);
+		}
+
+		return a;
+	},
+
+
+	getEventInstancesWithId: function(eventDefId) {
+		return (this.byDefId[eventDefId] || []).slice(); // returns a copy
+	},
+
+
+	getEventInstancesWithoutId: function(eventDefId) {
+		var byDefId = this.byDefId;
+		var a = [];
+		var id;
+
+		for (id in byDefId) {
+			if (id !== eventDefId) {
+				a.push.apply(a, byDefId[id]);
+			}
+		}
+
+		return a;
+	},
+
+
+	addEventInstance: function(eventInstance) {
+		var id = eventInstance.def.id;
+
+		(this.byDefId[id] || (this.byDefId[id] = []))
+			.push(eventInstance);
+	},
+
+
+	removeEventInstance: function(eventInstance) {
+		var id = eventInstance.def.id;
+		var bucket = this.byDefId[id];
+
+		if (bucket) {
+			removeExact(bucket, eventInstance);
+		}
+
+		if (!bucket.length) {
+			delete this.byDefId[id];
+		}
+	},
+
+
+	clear: function() {
+		this.byDefId = {};
+	},
+
+
+	applyChangeset: function(changeset) {
+		var ourHash = this.byDefId;
+		var theirHash = changeset.byDefId;
+		var id;
+		var ourBucket;
+
+		changeset.removals.forEach(this.removeEventInstance.bind(this));
+
+		for (id in theirHash) {
+			ourBucket = (ourHash[id] || (ourHash[id] = []));
+			ourBucket.push.apply(ourBucket, theirHash[id]);
+		}
+	}
+
+});

+ 32 - 20
src/models/EventManager.js

@@ -206,6 +206,38 @@ var EventManager = Class.extend(EmitterMixin, ListenerMixin, {
 	},
 
 
+	getEventDefsById: function(eventDefId) {
+		if (this.currentPeriod) {
+			return this.currentPeriod.getEventDefsById(eventDefId);
+		}
+		return [];
+	},
+
+
+	getEventInstances: function() {
+		if (this.currentPeriod) {
+			return this.currentPeriod.instanceRepo.getEventInstances();
+		}
+		return [];
+	},
+
+
+	getEventInstancesWithId: function(eventDefId) {
+		if (this.currentPeriod) {
+			return this.currentPeriod.instanceRepo.getEventInstancesWithId(eventDefId);
+		}
+		return [];
+	},
+
+
+	getEventInstancesWithoutId: function(eventDefId) {
+		if (this.currentPeriod) {
+			return this.currentPeriod.instanceRepo.getEventInstancesWithoutId(eventDefId);
+		}
+		return [];
+	},
+
+
 	addEventDef: function(eventDef, isSticky) {
 		if (isSticky) {
 			this.stickySource.addEventDef(eventDef);
@@ -327,26 +359,6 @@ var EventManager = Class.extend(EmitterMixin, ListenerMixin, {
 });
 
 
-// Methods that straight-up query the current EventPeriod for an array of results.
-[
-	'getEventDefsById',
-	'getEventInstances',
-	'getEventInstancesWithId',
-	'getEventInstancesWithoutId'
-].forEach(function(methodName) {
-
-	EventManager.prototype[methodName] = function() {
-		var currentPeriod = this.currentPeriod;
-
-		if (currentPeriod) {
-			return currentPeriod[methodName].apply(currentPeriod, arguments);
-		}
-
-		return [];
-	};
-});
-
-
 function isSourcesEquivalent(source0, source1) {
 	return source0.getPrimitive() == source1.getPrimitive();
 }

+ 33 - 91
src/models/EventPeriod.js

@@ -16,7 +16,7 @@ var EventPeriod = Class.extend(EmitterMixin, {
 
 	eventDefsByUid: null,
 	eventDefsById: null,
-	eventInstanceGroupsById: null,
+	instanceRepo: null,
 
 
 	constructor: function(start, end, timezone) {
@@ -32,7 +32,7 @@ var EventPeriod = Class.extend(EmitterMixin, {
 		this.requestsByUid = {};
 		this.eventDefsByUid = {};
 		this.eventDefsById = {};
-		this.eventInstanceGroupsById = {};
+		this.instanceRepo = new EventInstanceRepo();
 	},
 
 
@@ -157,17 +157,16 @@ var EventPeriod = Class.extend(EmitterMixin, {
 	addEventDef: function(eventDef) {
 		var eventDefsById = this.eventDefsById;
 		var eventDefId = eventDef.id;
-		var eventDefs = eventDefsById[eventDefId] || (eventDefsById[eventDefId] = []);
+		var bucket = eventDefsById[eventDefId] || (eventDefsById[eventDefId] = []);
 		var eventInstances = eventDef.buildInstances(this.unzonedRange);
-		var i;
 
-		eventDefs.push(eventDef);
+		bucket.push(eventDef);
 
 		this.eventDefsByUid[eventDef.uid] = eventDef;
 
-		for (i = 0; i < eventInstances.length; i++) {
-			this.addEventInstance(eventInstances[i], eventDefId);
-		}
+		this.applyChangeset(
+			new EventInstanceChangeset(null, eventInstances)
+		);
 	},
 
 
@@ -185,7 +184,7 @@ var EventPeriod = Class.extend(EmitterMixin, {
 
 		this.eventDefsByUid = {};
 		this.eventDefsById = {};
-		this.eventInstanceGroupsById = {};
+		this.instanceRepo.clear();
 
 		if (!isEmpty) {
 			this.tryRelease();
@@ -195,105 +194,35 @@ var EventPeriod = Class.extend(EmitterMixin, {
 
 	removeEventDef: function(eventDef) {
 		var eventDefsById = this.eventDefsById;
-		var eventDefs = eventDefsById[eventDef.id];
+		var bucket = eventDefsById[eventDef.id];
 
 		delete this.eventDefsByUid[eventDef.uid];
 
-		if (eventDefs) {
-			removeExact(eventDefs, eventDef);
+		if (bucket) {
+			removeExact(bucket, eventDef);
 
-			if (!eventDefs.length) {
+			if (!bucket.length) {
 				delete eventDefsById[eventDef.id];
 			}
 
-			this.removeEventInstancesForDef(eventDef);
+			this.applyChangeset(new EventInstanceChangeset(
+				this.instanceRepo.getEventInstancesForDef(eventDef) // removal
+			));
 		}
 	},
 
 
-	// Event Instances
+	// Releasing and Freezing
 	// -----------------------------------------------------------------------------------------------------------------
 
 
-	getEventInstances: function() { // TODO: consider iterator
-		var eventInstanceGroupsById = this.eventInstanceGroupsById;
-		var eventInstances = [];
-		var id;
-
-		for (id in eventInstanceGroupsById) {
-			eventInstances.push.apply(eventInstances, // append
-				eventInstanceGroupsById[id].eventInstances
-			);
-		}
-
-		return eventInstances;
-	},
-
-
-	getEventInstancesWithId: function(eventDefId) {
-		var eventInstanceGroup = this.eventInstanceGroupsById[eventDefId];
-
-		if (eventInstanceGroup) {
-			return eventInstanceGroup.eventInstances.slice(); // clone
-		}
-
-		return [];
-	},
-
-
-	getEventInstancesWithoutId: function(eventDefId) { // TODO: consider iterator
-		var eventInstanceGroupsById = this.eventInstanceGroupsById;
-		var matchingInstances = [];
-		var id;
-
-		for (id in eventInstanceGroupsById) {
-			if (id !== eventDefId) {
-				matchingInstances.push.apply(matchingInstances, // append
-					eventInstanceGroupsById[id].eventInstances
-				);
-			}
-		}
-
-		return matchingInstances;
-	},
-
-
-	addEventInstance: function(eventInstance, eventDefId) {
-		var eventInstanceGroupsById = this.eventInstanceGroupsById;
-		var eventInstanceGroup = eventInstanceGroupsById[eventDefId] ||
-			(eventInstanceGroupsById[eventDefId] = new EventInstanceGroup());
-
-		eventInstanceGroup.eventInstances.push(eventInstance);
+	applyChangeset: function(changeset) {
+		this.instanceRepo.applyChangeset(changeset);
 
 		this.tryRelease();
 	},
 
 
-	removeEventInstancesForDef: function(eventDef) {
-		var eventInstanceGroupsById = this.eventInstanceGroupsById;
-		var eventInstanceGroup = eventInstanceGroupsById[eventDef.id];
-		var removeCnt;
-
-		if (eventInstanceGroup) {
-			removeCnt = removeMatching(eventInstanceGroup.eventInstances, function(currentEventInstance) {
-				return currentEventInstance.def === eventDef;
-			});
-
-			if (!eventInstanceGroup.eventInstances.length) {
-				delete eventInstanceGroupsById[eventDef.id];
-			}
-
-			if (removeCnt) {
-				this.tryRelease();
-			}
-		}
-	},
-
-
-	// Releasing and Freezing
-	// -----------------------------------------------------------------------------------------------------------------
-
-
 	tryRelease: function() {
 		if (!this.pendingCnt) {
 			if (!this.freezeDepth) {
@@ -308,7 +237,7 @@ var EventPeriod = Class.extend(EmitterMixin, {
 
 	release: function() {
 		this.releaseCnt++;
-		this.trigger('release', this.eventInstanceGroupsById);
+		this.trigger('release', this.buildPayload());
 	},
 
 
@@ -316,7 +245,7 @@ var EventPeriod = Class.extend(EmitterMixin, {
 		var _this = this;
 
 		if (this.releaseCnt) {
-			return Promise.resolve(this.eventInstanceGroupsById);
+			return Promise.resolve(this.buildPayload());
 		}
 		else {
 			return Promise.construct(function(onResolve) {
@@ -326,6 +255,19 @@ var EventPeriod = Class.extend(EmitterMixin, {
 	},
 
 
+	buildPayload: function() { // temporary
+		var instancesById = this.instanceRepo.byDefId;
+		var instanceGroupsById = {};
+		var id;
+
+		for (id in instancesById) {
+			instanceGroupsById[id] = new EventInstanceGroup(instancesById[id]);
+		}
+
+		return instanceGroupsById;
+	},
+
+
 	freeze: function() {
 		if (!(this.freezeDepth++)) {
 			this.stuntedReleaseCnt = 0;