Web Inspector: replace TypeVerifier with subclasses of WI.Collection
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Models / ResourceCollection.js
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2016 Devin Rousso <webkit@devinrousso.com>. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 WI.ResourceCollection = class ResourceCollection extends WI.Collection
28 {
29     constructor(resourceType)
30     {
31         super();
32
33         this._resourceType = resourceType || null;
34         this._resourceURLMap = new Map;
35         this._resourcesTypeMap = new Map;
36     }
37
38     // Public
39
40     get resourceType() { return this._resourceType; }
41
42     get displayName()
43     {
44         const plural = true;
45         return this._resourceType ? WI.Resource.displayNameForType(this._resourceType, plural) : WI.UIString("Resources");
46     }
47
48     objectIsRequiredType(object)
49     {
50         if (!(object instanceof WI.Resource))
51             return false;
52
53         if (!this._resourceType)
54             return true;
55
56         if (this._resourceType === WI.Resource.Type.Stylesheet && object instanceof WI.CSSStyleSheet)
57             return true;
58
59         return object.type === this._resourceType;
60     }
61
62     resourceForURL(url)
63     {
64         return this._resourceURLMap.get(url) || null;
65     }
66
67     resourceCollectionForType(type)
68     {
69         if (this._resourceType) {
70             console.assert(type === this._resourceType);
71             return this;
72         }
73
74         let resourcesCollectionForType = this._resourcesTypeMap.get(type);
75         if (!resourcesCollectionForType) {
76             resourcesCollectionForType = new WI.ResourceCollection(type);
77             this._resourcesTypeMap.set(type, resourcesCollectionForType);
78         }
79
80         return resourcesCollectionForType;
81     }
82
83     clear()
84     {
85         super.clear();
86
87         this._resourceURLMap.clear();
88
89         if (!this._resourceType)
90             this._resourcesTypeMap.clear();
91     }
92
93     // Protected
94
95     itemAdded(item)
96     {
97         this._associateWithResource(item);
98     }
99
100     itemRemoved(item)
101     {
102         this._disassociateWithResource(item);
103     }
104
105     itemsCleared(items)
106     {
107         const skipRemoval = true;
108
109         for (let item of items)
110             this._disassociateWithResource(item, skipRemoval);
111     }
112
113     // Private
114
115     _associateWithResource(resource)
116     {
117         this._resourceURLMap.set(resource.url, resource);
118
119         if (!this._resourceType) {
120             let resourcesCollectionForType = this.resourceCollectionForType(resource.type);
121             resourcesCollectionForType.add(resource);
122         }
123
124         resource.addEventListener(WI.Resource.Event.URLDidChange, this._resourceURLDidChange, this);
125         resource.addEventListener(WI.Resource.Event.TypeDidChange, this._resourceTypeDidChange, this);
126     }
127
128     _disassociateWithResource(resource, skipRemoval)
129     {
130         resource.removeEventListener(WI.Resource.Event.URLDidChange, this._resourceURLDidChange, this);
131         resource.removeEventListener(WI.Resource.Event.TypeDidChange, this._resourceTypeDidChange, this);
132
133         if (skipRemoval)
134             return;
135
136         if (!this._resourceType) {
137             let resourcesCollectionForType = this.resourceCollectionForType(resource.type);
138             resourcesCollectionForType.remove(resource);
139         }
140
141         this._resourceURLMap.delete(resource.url);
142     }
143
144     _resourceURLDidChange(event)
145     {
146         let resource = event.target;
147         console.assert(resource instanceof WI.Resource);
148         if (!(resource instanceof WI.Resource))
149             return;
150
151         let oldURL = event.data.oldURL;
152         console.assert(oldURL);
153         if (!oldURL)
154             return;
155
156         this._resourceURLMap.set(resource.url, resource);
157         this._resourceURLMap.delete(oldURL);
158     }
159
160     _resourceTypeDidChange(event)
161     {
162         let resource = event.target;
163         console.assert(resource instanceof WI.Resource);
164         if (!(resource instanceof WI.Resource))
165             return;
166
167         if (this._resourceType) {
168             console.assert(resource.type !== this._resourceType);
169             this.remove(resource);
170             return;
171         }
172
173         console.assert(event.data.oldType);
174
175         let resourcesWithNewType = this.resourceCollectionForType(resource.type);
176         resourcesWithNewType.add(resource);
177
178         // It is not necessary to remove the resource from the sub-collection for the old type since
179         // this is handled by that sub-collection's own _resourceTypeDidChange handler (via the
180         // above if statement).
181     }
182 };