blob: e23db935fe3c7793cb6b1d55e53b9346dd54d389 [file] [log] [blame]
Chris Craikb2cbf152015-07-28 16:26:29 -07001<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/model/event_container.html">
9<link rel="import" href="/model/object_instance.html">
10<link rel="import" href="/model/time_to_object_instance_map.html">
11<link rel="import" href="/base/utils.html">
12<link rel="import" href="/base/range.html">
13<link rel="import" href="/base/sorted_array_utils.html">
14
15<script>
16'use strict';
17
18/**
19 * @fileoverview Provides the ObjectCollection class.
20 */
21tr.exportTo('tr.model', function() {
22 var ObjectInstance = tr.model.ObjectInstance;
23 var ObjectSnapshot = tr.model.ObjectSnapshot;
24
25 /**
26 * A collection of object instances and their snapshots, accessible by id and
27 * time, or by object name.
28 *
29 * @constructor
30 */
31 function ObjectCollection(parent) {
32 tr.model.EventContainer.call(this);
33 this.parent = parent;
34 this.instanceMapsById_ = {}; // id -> TimeToObjectInstanceMap
35 this.instancesByTypeName_ = {};
36 this.createObjectInstance_ = this.createObjectInstance_.bind(this);
37 }
38
39 ObjectCollection.prototype = {
40 __proto__: tr.model.EventContainer.prototype,
41
42 iterateAllChildEventContainers: function(callback, opt_this) {
43 },
44
45 iterateAllEventsInThisContainer: function(eventTypePredicate,
46 callback, opt_this) {
47 var bI = !!eventTypePredicate.call(opt_this, ObjectInstance);
48 var bS = !!eventTypePredicate.call(opt_this, ObjectSnapshot);
49 if (bI === false && bS === false)
50 return;
51 this.iterObjectInstances(function(instance) {
52 if (bI)
53 callback.call(opt_this, instance);
54 if (bS)
55 instance.snapshots.forEach(callback, opt_this);
56 }, opt_this);
57 },
58
59 createObjectInstance_: function(
60 parent, id, category, name, creationTs, opt_baseTypeName) {
61 var constructor = tr.model.ObjectInstance.getConstructor(
62 category, name);
63 var instance = new constructor(
64 parent, id, category, name, creationTs, opt_baseTypeName);
65 var typeName = instance.typeName;
66 var instancesOfTypeName = this.instancesByTypeName_[typeName];
67 if (!instancesOfTypeName) {
68 instancesOfTypeName = [];
69 this.instancesByTypeName_[typeName] = instancesOfTypeName;
70 }
71 instancesOfTypeName.push(instance);
72 return instance;
73 },
74
75 getOrCreateInstanceMap_: function(id) {
76 var instanceMap = this.instanceMapsById_[id];
77 if (instanceMap)
78 return instanceMap;
79 instanceMap = new tr.model.TimeToObjectInstanceMap(
80 this.createObjectInstance_, this.parent, id);
81 this.instanceMapsById_[id] = instanceMap;
82 return instanceMap;
83 },
84
85 idWasCreated: function(id, category, name, ts) {
86 var instanceMap = this.getOrCreateInstanceMap_(id);
87 return instanceMap.idWasCreated(category, name, ts);
88 },
89
90 addSnapshot: function(id, category, name, ts, args, opt_baseTypeName) {
91 var instanceMap = this.getOrCreateInstanceMap_(id);
92 var snapshot = instanceMap.addSnapshot(
93 category, name, ts, args, opt_baseTypeName);
94 if (snapshot.objectInstance.category != category) {
95 var msg = 'Added snapshot name=' + name + ' with cat=' + category +
96 ' impossible. It instance was created/snapshotted with cat=' +
97 snapshot.objectInstance.category + ' name=' +
98 snapshot.objectInstance.name;
99 throw new Error(msg);
100 }
101 if (opt_baseTypeName &&
102 snapshot.objectInstance.baseTypeName != opt_baseTypeName) {
103 throw new Error('Could not add snapshot with baseTypeName=' +
104 opt_baseTypeName + '. It ' +
105 'was previously created with name=' +
106 snapshot.objectInstance.baseTypeName);
107 }
108 if (snapshot.objectInstance.name != name) {
109 throw new Error('Could not add snapshot with name=' + name + '. It ' +
110 'was previously created with name=' +
111 snapshot.objectInstance.name);
112 }
113 return snapshot;
114 },
115
116 idWasDeleted: function(id, category, name, ts) {
117 var instanceMap = this.getOrCreateInstanceMap_(id);
118 var deletedInstance = instanceMap.idWasDeleted(category, name, ts);
119 if (!deletedInstance)
120 return;
121 if (deletedInstance.category != category) {
122 var msg = 'Deleting object ' + deletedInstance.name +
123 ' with a different category ' +
124 'than when it was created. It previous had cat=' +
125 deletedInstance.category + ' but the delete command ' +
126 'had cat=' + category;
127 throw new Error(msg);
128 }
129 if (deletedInstance.baseTypeName != name) {
130 throw new Error('Deletion requested for name=' +
131 name + ' could not proceed: ' +
132 'An existing object with baseTypeName=' +
133 deletedInstance.baseTypeName + ' existed.');
134 }
135 },
136
137 autoDeleteObjects: function(maxTimestamp) {
138 tr.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
139 var lastInstance = i2imap.lastInstance;
140 if (lastInstance.deletionTs != Number.MAX_VALUE)
141 return;
142 i2imap.idWasDeleted(
143 lastInstance.category, lastInstance.name, maxTimestamp);
144 // idWasDeleted will cause lastInstance.deletionTsWasExplicit to be set
145 // to true. Unset it here.
146 lastInstance.deletionTsWasExplicit = false;
147 });
148 },
149
150 getObjectInstanceAt: function(id, ts) {
151 var instanceMap = this.instanceMapsById_[id];
152 if (!instanceMap)
153 return undefined;
154 return instanceMap.getInstanceAt(ts);
155 },
156
157 getSnapshotAt: function(id, ts) {
158 var instance = this.getObjectInstanceAt(id, ts);
159 if (!instance)
160 return undefined;
161 return instance.getSnapshotAt(ts);
162 },
163
164 iterObjectInstances: function(iter, opt_this) {
165 opt_this = opt_this || this;
166 tr.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
167 i2imap.instances.forEach(iter, opt_this);
168 });
169 },
170
171 getAllObjectInstances: function() {
172 var instances = [];
173 this.iterObjectInstances(function(i) { instances.push(i); });
174 return instances;
175 },
176
177 getAllInstancesNamed: function(name) {
178 return this.instancesByTypeName_[name];
179 },
180
181 getAllInstancesByTypeName: function() {
182 return this.instancesByTypeName_;
183 },
184
185 preInitializeAllObjects: function() {
186 this.iterObjectInstances(function(instance) {
187 instance.preInitialize();
188 });
189 },
190
191 initializeAllObjects: function() {
192 this.iterObjectInstances(function(instance) {
193 instance.initialize();
194 });
195 },
196
197 initializeInstances: function() {
198 this.iterObjectInstances(function(instance) {
199 instance.initialize();
200 });
201 },
202
203 updateBounds: function() {
204 this.bounds.reset();
205 this.iterObjectInstances(function(instance) {
206 instance.updateBounds();
207 this.bounds.addRange(instance.bounds);
208 }, this);
209 },
210
211 shiftTimestampsForward: function(amount) {
212 this.iterObjectInstances(function(instance) {
213 instance.shiftTimestampsForward(amount);
214 });
215 },
216
217 addCategoriesToDict: function(categoriesDict) {
218 this.iterObjectInstances(function(instance) {
219 categoriesDict[instance.category] = true;
220 });
221 }
222 };
223
224 return {
225 ObjectCollection: ObjectCollection
226 };
227});
228</script>