~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/mono-addins/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// ExtensionNodeSet.cs
 
3
//
 
4
// Author:
 
5
//   Lluis Sanchez Gual
 
6
//
 
7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
 
8
//
 
9
// Permission is hereby granted, free of charge, to any person obtaining
 
10
// a copy of this software and associated documentation files (the
 
11
// "Software"), to deal in the Software without restriction, including
 
12
// without limitation the rights to use, copy, modify, merge, publish,
 
13
// distribute, sublicense, and/or sell copies of the Software, and to
 
14
// permit persons to whom the Software is furnished to do so, subject to
 
15
// the following conditions:
 
16
// 
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
// 
 
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
//
 
28
 
 
29
 
 
30
using System;
 
31
using System.Collections;
 
32
using System.Xml;
 
33
using Mono.Addins.Serialization;
 
34
using System.Collections.Specialized;
 
35
 
 
36
namespace Mono.Addins.Description
 
37
{
 
38
        /// <summary>
 
39
        /// An extension node set definition.
 
40
        /// </summary>
 
41
        /// <remarks>
 
42
        /// Node sets allow grouping a set of extension node declarations and give an identifier to that group
 
43
        /// (the node set). Once a node set is declared, it can be referenced from several extension points
 
44
        /// which use the same extension node structure. Extension node sets also allow declaring recursive
 
45
        /// extension nodes, that is, extension nodes with a tree structure.
 
46
        /// </remarks>
 
47
        public class ExtensionNodeSet: ObjectDescription
 
48
        {
 
49
                string id;
 
50
                ExtensionNodeTypeCollection nodeTypes;
 
51
                NodeSetIdCollection nodeSets;
 
52
                bool missingNodeSetId;
 
53
                ExtensionNodeTypeCollection cachedAllowedTypes;
 
54
                
 
55
                internal string SourceAddinId { get; set; }
 
56
                
 
57
                internal ExtensionNodeSet (XmlElement element)
 
58
                {
 
59
                        Element = element;
 
60
                        id = element.GetAttribute (IdAttribute);
 
61
                }
 
62
                
 
63
                /// <summary>
 
64
                /// Copies data from another node set
 
65
                /// </summary>
 
66
                /// <param name='nset'>
 
67
                /// Node set from which to copy
 
68
                /// </param>
 
69
                public void CopyFrom (ExtensionNodeSet nset)
 
70
                {
 
71
                        id = nset.id;
 
72
                        NodeTypes.Clear ();
 
73
                        foreach (ExtensionNodeType nt in nset.NodeTypes) {
 
74
                                ExtensionNodeType cnt = new ExtensionNodeType ();
 
75
                                cnt.CopyFrom (nt);
 
76
                                NodeTypes.Add (cnt);
 
77
                        }
 
78
                        NodeSets.Clear ();
 
79
                        foreach (string ns in nset.NodeSets)
 
80
                                NodeSets.Add (ns);
 
81
                        missingNodeSetId = nset.missingNodeSetId;
 
82
                }
 
83
                
 
84
                internal override void Verify (string location, StringCollection errors)
 
85
                {
 
86
                        if (missingNodeSetId)
 
87
                                errors.Add (location + "Missing id attribute in extension set reference");
 
88
                        
 
89
                        NodeTypes.Verify (location + "ExtensionNodeSet (" + Id + ")/", errors);
 
90
                }
 
91
                
 
92
                internal override void SaveXml (XmlElement parent)
 
93
                {
 
94
                        SaveXml (parent, "ExtensionNodeSet");
 
95
                }
 
96
                
 
97
                internal virtual void SaveXml (XmlElement parent, string nodeName)
 
98
                {
 
99
                        if (Element == null) {
 
100
                                Element = parent.OwnerDocument.CreateElement (nodeName);
 
101
                                parent.AppendChild (Element);
 
102
                        }
 
103
                        if (Id.Length > 0)
 
104
                                Element.SetAttribute (IdAttribute, Id);
 
105
                        if (nodeTypes != null)
 
106
                                nodeTypes.SaveXml (Element);
 
107
                        if (nodeSets != null) {
 
108
                                foreach (string s in nodeSets) {
 
109
                                        if (Element.SelectSingleNode ("ExtensionNodeSet[@id='" + s + "']") == null) {
 
110
                                                XmlElement e = Element.OwnerDocument.CreateElement ("ExtensionNodeSet");
 
111
                                                e.SetAttribute ("id", s);
 
112
                                                Element.AppendChild (e);
 
113
                                        }
 
114
                                }
 
115
                                ArrayList list = new ArrayList ();
 
116
                                foreach (XmlElement e in Element.SelectNodes ("ExtensionNodeSet")) {
 
117
                                        if (!nodeSets.Contains (e.GetAttribute ("id")))
 
118
                                                list.Add (e);
 
119
                                }
 
120
                                foreach (XmlElement e in list)
 
121
                                        Element.RemoveChild (e);
 
122
                        }
 
123
                }
 
124
                
 
125
                /// <summary>
 
126
                /// Initializes a new instance of the <see cref="Mono.Addins.Description.ExtensionNodeSet"/> class.
 
127
                /// </summary>
 
128
                public ExtensionNodeSet ()
 
129
                {
 
130
                }
 
131
                
 
132
                /// <summary>
 
133
                /// Gets or sets the identifier of the node set.
 
134
                /// </summary>
 
135
                /// <value>
 
136
                /// The identifier.
 
137
                /// </value>
 
138
                public string Id {
 
139
                        get { return id != null ? id : string.Empty; }
 
140
                        set { id = value; }
 
141
                }
 
142
                        
 
143
                internal virtual string IdAttribute {
 
144
                        get { return "id"; }
 
145
                }
 
146
                
 
147
                /// <summary>
 
148
                /// Gets the node types allowed in this node set.
 
149
                /// </summary>
 
150
                /// <value>
 
151
                /// The node types.
 
152
                /// </value>
 
153
                public ExtensionNodeTypeCollection NodeTypes {
 
154
                        get {
 
155
                                if (nodeTypes == null) {
 
156
                                        if (Element != null)
 
157
                                                InitCollections ();
 
158
                                        else
 
159
                                                nodeTypes = new ExtensionNodeTypeCollection (this);
 
160
                                }
 
161
                                return nodeTypes;
 
162
                        }
 
163
                }
 
164
                
 
165
                /// <summary>
 
166
                /// Gets a list of other node sets included in this node set.
 
167
                /// </summary>
 
168
                /// <value>
 
169
                /// The node sets.
 
170
                /// </value>
 
171
                public NodeSetIdCollection NodeSets {
 
172
                        get {
 
173
                                if (nodeSets == null) {
 
174
                                        if (Element != null)
 
175
                                                InitCollections ();
 
176
                                        else
 
177
                                                nodeSets = new NodeSetIdCollection ();
 
178
                                }
 
179
                                return nodeSets;
 
180
                        }
 
181
                }
 
182
                
 
183
                /// <summary>
 
184
                /// Gets all the allowed node types.
 
185
                /// </summary>
 
186
                /// <returns>
 
187
                /// The allowed node types.
 
188
                /// </returns>
 
189
                /// <remarks>
 
190
                /// Gets all allowed node types, including those defined in included node sets.
 
191
                /// This method only works for descriptions loaded from a registry.
 
192
                /// </remarks>
 
193
                public ExtensionNodeTypeCollection GetAllowedNodeTypes ()
 
194
                {
 
195
                        if (cachedAllowedTypes == null) {
 
196
                                cachedAllowedTypes = new ExtensionNodeTypeCollection ();
 
197
                                GetAllowedNodeTypes (new Hashtable (), cachedAllowedTypes);
 
198
                        }
 
199
                    return cachedAllowedTypes;
 
200
                }
 
201
                
 
202
                void GetAllowedNodeTypes (Hashtable visitedSets, ExtensionNodeTypeCollection col)
 
203
                {
 
204
                        if (Id.Length > 0) {
 
205
                                if (visitedSets.Contains (Id))
 
206
                                        return;
 
207
                                visitedSets [Id] = Id;
 
208
                        }
 
209
                        
 
210
                        // Gets all allowed node types, including those defined in node sets
 
211
                        // It only works for descriptions generated from a registry
 
212
                        
 
213
                        foreach (ExtensionNodeType nt in NodeTypes)
 
214
                                col.Add (nt);
 
215
                        
 
216
                        AddinDescription desc = ParentAddinDescription;
 
217
                        if (desc == null || desc.OwnerDatabase == null)
 
218
                            return;
 
219
                        
 
220
                        foreach (string[] ns in NodeSets.InternalList) {
 
221
                                string startAddin = ns [1];
 
222
                                if (startAddin == null || startAddin.Length == 0)
 
223
                                        startAddin = desc.AddinId;
 
224
                                ExtensionNodeSet nset = desc.OwnerDatabase.FindNodeSet (ParentAddinDescription.Domain, startAddin, ns[0]);
 
225
                                if (nset != null)
 
226
                                        nset.GetAllowedNodeTypes (visitedSets, col);
 
227
                        }
 
228
                }
 
229
                
 
230
                internal void Clear ()
 
231
                {
 
232
                        Element = null;
 
233
                        nodeSets = null;
 
234
                        nodeTypes = null;
 
235
                }
 
236
                
 
237
                internal void SetExtensionsAddinId (string addinId)
 
238
                {
 
239
                        foreach (ExtensionNodeType nt in NodeTypes) {
 
240
                                nt.AddinId = addinId;
 
241
                                nt.SetExtensionsAddinId (addinId);
 
242
                        }
 
243
                        NodeSets.SetExtensionsAddinId (addinId);
 
244
                }
 
245
                
 
246
                internal void MergeWith (string thisAddinId, ExtensionNodeSet other)
 
247
                {
 
248
                        foreach (ExtensionNodeType nt in other.NodeTypes) {
 
249
                                if (nt.AddinId != thisAddinId && !NodeTypes.Contains (nt))
 
250
                                        NodeTypes.Add (nt);
 
251
                        }
 
252
                        NodeSets.MergeWith (thisAddinId, other.NodeSets);
 
253
                }
 
254
                
 
255
                internal void UnmergeExternalData (string thisAddinId, Hashtable addinsToUnmerge)
 
256
                {
 
257
                        // Removes extension types and extension sets coming from other add-ins.
 
258
                        
 
259
                        ArrayList todelete = new ArrayList ();
 
260
                        foreach (ExtensionNodeType nt in NodeTypes) {
 
261
                                if (nt.AddinId != thisAddinId && (addinsToUnmerge == null || addinsToUnmerge.Contains (nt.AddinId)))
 
262
                                        todelete.Add (nt);
 
263
                        }
 
264
                        foreach (ExtensionNodeType nt in todelete)
 
265
                                NodeTypes.Remove (nt);
 
266
                        
 
267
                        NodeSets.UnmergeExternalData (thisAddinId, addinsToUnmerge);
 
268
                }
 
269
                
 
270
                void InitCollections ()
 
271
                {
 
272
                        nodeTypes = new ExtensionNodeTypeCollection (this);
 
273
                        nodeSets = new NodeSetIdCollection ();
 
274
                        
 
275
                        foreach (XmlNode n in Element.ChildNodes) {
 
276
                                XmlElement nt = n as XmlElement;
 
277
                                if (nt == null)
 
278
                                        continue;
 
279
                                if (nt.LocalName == "ExtensionNode") {
 
280
                                        ExtensionNodeType etype = new ExtensionNodeType (nt);
 
281
                                        nodeTypes.Add (etype);
 
282
                                }
 
283
                                else if (nt.LocalName == "ExtensionNodeSet") {
 
284
                                        string id = nt.GetAttribute ("id");
 
285
                                        if (id.Length > 0)
 
286
                                                nodeSets.Add (id);
 
287
                                        else
 
288
                                                missingNodeSetId = true;
 
289
                                }
 
290
                        }
 
291
                }
 
292
                
 
293
                internal override void Write (BinaryXmlWriter writer)
 
294
                {
 
295
                        writer.WriteValue ("Id", id);
 
296
                        writer.WriteValue ("NodeTypes", NodeTypes);
 
297
                        writer.WriteValue ("NodeSets", NodeSets.InternalList);
 
298
                }
 
299
                
 
300
                internal override void Read (BinaryXmlReader reader)
 
301
                {
 
302
                        id = reader.ReadStringValue ("Id");
 
303
                        nodeTypes = (ExtensionNodeTypeCollection) reader.ReadValue ("NodeTypes", new ExtensionNodeTypeCollection (this));
 
304
                        reader.ReadValue ("NodeSets", NodeSets.InternalList);
 
305
                }
 
306
        }
 
307
        
 
308
        /// <summary>
 
309
        /// A collection of node set identifiers
 
310
        /// </summary>
 
311
        public class NodeSetIdCollection: IEnumerable
 
312
        {
 
313
                // A list of string[2]. Item 0 is the node set id, item 1 is the addin that defines it.
 
314
                
 
315
                ArrayList list = new ArrayList ();
 
316
                
 
317
                /// <summary>
 
318
                /// Gets the node set identifier at the specified index.
 
319
                /// </summary>
 
320
                /// <param name='n'>
 
321
                /// An index.
 
322
                /// </param>
 
323
                public string this [int n] {
 
324
                        get { return ((string[])list [n])[0]; }
 
325
                }
 
326
                
 
327
                /// <summary>
 
328
                /// Gets the item count.
 
329
                /// </summary>
 
330
                /// <value>
 
331
                /// The count.
 
332
                /// </value>
 
333
                public int Count {
 
334
                        get { return list.Count; }
 
335
                }
 
336
                
 
337
                /// <summary>
 
338
                /// Gets the collection enumerator.
 
339
                /// </summary>
 
340
                /// <returns>
 
341
                /// The enumerator.
 
342
                /// </returns>
 
343
                public IEnumerator GetEnumerator ()
 
344
                {
 
345
                        ArrayList ll = new ArrayList (list.Count);
 
346
                        foreach (string[] ns in list)
 
347
                                ll.Add (ns [0]);
 
348
                        return ll.GetEnumerator ();
 
349
                }
 
350
                
 
351
                /// <summary>
 
352
                /// Add the specified node set identifier.
 
353
                /// </summary>
 
354
                /// <param name='nodeSetId'>
 
355
                /// Node set identifier.
 
356
                /// </param>
 
357
                public void Add (string nodeSetId)
 
358
                {
 
359
                        if (!Contains (nodeSetId))
 
360
                                list.Add (new string [] { nodeSetId, null });
 
361
                }
 
362
                
 
363
                /// <summary>
 
364
                /// Remove a node set identifier
 
365
                /// </summary>
 
366
                /// <param name='nodeSetId'>
 
367
                /// Node set identifier.
 
368
                /// </param>
 
369
                public void Remove (string nodeSetId)
 
370
                {
 
371
                        int i = IndexOf (nodeSetId);
 
372
                        if (i != -1)
 
373
                                list.RemoveAt (i);
 
374
                }
 
375
                
 
376
                /// <summary>
 
377
                /// Clears the collection
 
378
                /// </summary>
 
379
                public void Clear ()
 
380
                {
 
381
                        list.Clear ();
 
382
                }
 
383
                
 
384
                /// <summary>
 
385
                /// Checks if the specified identifier is present in the collection
 
386
                /// </summary>
 
387
                /// <param name='nodeSetId'>
 
388
                /// <c>true</c> if the node set identifier is present.
 
389
                /// </param>
 
390
                public bool Contains (string nodeSetId)
 
391
                {
 
392
                        return IndexOf (nodeSetId) != -1;
 
393
                }
 
394
 
 
395
                /// <summary>
 
396
                /// Returns the index of the specified node set identifier
 
397
                /// </summary>
 
398
                /// <returns>
 
399
                /// The index.
 
400
                /// </returns>
 
401
                /// <param name='nodeSetId'>
 
402
                /// A node set identifier.
 
403
                /// </param>
 
404
                public int IndexOf (string nodeSetId)
 
405
                {
 
406
                        for (int n=0; n<list.Count; n++)
 
407
                                if (((string[])list [n])[0] == nodeSetId)
 
408
                                        return n;
 
409
                        return -1;
 
410
                }
 
411
                
 
412
                internal void SetExtensionsAddinId (string id)
 
413
                {
 
414
                        foreach (string[] ns in list)
 
415
                                ns [1] = id;
 
416
                }
 
417
                
 
418
                internal ArrayList InternalList {
 
419
                        get { return list; }
 
420
                        set { list = value; }
 
421
                }
 
422
                
 
423
                internal void MergeWith (string thisAddinId, NodeSetIdCollection other)
 
424
                {
 
425
                        foreach (string[] ns in other.list) {
 
426
                                if (ns [1] != thisAddinId && !list.Contains (ns))
 
427
                                        list.Add (ns);
 
428
                        }
 
429
                }
 
430
                
 
431
                internal void UnmergeExternalData (string thisAddinId, Hashtable addinsToUnmerge)
 
432
                {
 
433
                        ArrayList newList = new ArrayList ();
 
434
                        foreach (string[] ns in list) {
 
435
                                if (ns[1] == thisAddinId || (addinsToUnmerge != null && !addinsToUnmerge.Contains (ns[1])))
 
436
                                        newList.Add (ns);
 
437
                        }
 
438
                        list = newList;
 
439
                }
 
440
        }
 
441
}