2008-11-21 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / SiteMapNode.cs
1 //
2 // System.Web.SiteMapNode
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //
7 // (C) 2003 Ben Maurer
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 #if NET_2_0
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.Text;
35 using System.Web.UI;
36 using System.Web.UI.WebControls;
37 using System.ComponentModel;
38 using System.Resources;
39
40 namespace System.Web {
41         public class SiteMapNode : IHierarchyData, INavigateUIData, ICloneable {
42         
43                 SiteMapNode () {}
44                 
45                 public SiteMapNode (SiteMapProvider provider, string key)
46                         : this (provider, key, null, null, null, null, null, null, null) {}
47                 public SiteMapNode (SiteMapProvider provider, string key, string url)
48                         : this (provider, key, url, null, null, null, null, null, null) {}
49                 public SiteMapNode (SiteMapProvider provider, string key, string url, string title)
50                         : this (provider, key, url, title, null, null, null, null, null) {}
51                 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description)
52                         : this (provider, key, url, title, description, null, null, null, null) {}
53                 
54                 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description,
55                                     IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys,
56                                     string implicitResourceKey)
57                 {
58                         if (provider == null)
59                                 throw new ArgumentNullException ("provider");
60                         if (key == null)
61                                 throw new ArgumentNullException ("key");
62                         
63                         this.provider = provider;
64                         this.key = key;
65                         this.url = url;
66                         this.title = title;
67                         this.description = description;
68                         this.roles = roles;
69                         this.attributes = attributes;
70                         this.resourceKeys = explicitResourceKeys;
71                         this.resourceKey = implicitResourceKey;
72                 }
73
74                 public SiteMapDataSourceView GetDataSourceView (SiteMapDataSource owner, string viewName)
75                 {
76                         return new SiteMapDataSourceView (owner, viewName, this);
77                 }
78                 
79                 public SiteMapHierarchicalDataSourceView GetHierarchicalDataSourceView ()
80                 {
81                         return new SiteMapHierarchicalDataSourceView (this);
82                 }
83                 
84                 public virtual bool IsAccessibleToUser (System.Web.HttpContext ctx)
85                 {
86                         return provider.IsAccessibleToUser (ctx, this);
87                 }
88                 
89                 public override string ToString()
90                 {
91                         return Title;
92                 }
93
94                 public virtual bool HasChildNodes {
95                         get { return ChildNodes != null && ChildNodes.Count != 0; }
96                 }
97
98                 public SiteMapNodeCollection GetAllNodes ()
99                 {
100                         SiteMapNodeCollection ret;
101                 
102                         ret = new SiteMapNodeCollection ();
103                         GetAllNodesRecursive (ret);
104                         return SiteMapNodeCollection.ReadOnly (ret);
105                 }
106                 
107                 void GetAllNodesRecursive(SiteMapNodeCollection c)
108                 {
109                         SiteMapNodeCollection childNodes = this.ChildNodes;
110
111                         if (childNodes != null && childNodes.Count > 0) {
112                                 c.AddRange (childNodes);
113                                 foreach (SiteMapNode n in childNodes)
114                                         n.GetAllNodesRecursive (c);
115                         }
116                 }
117
118                 
119                 public virtual bool IsDescendantOf (SiteMapNode node)
120                 {
121                         for (SiteMapNode n = ParentNode; n != null; n = n.ParentNode)
122                                 if (n == node) return true; 
123
124                         return false; 
125                 }
126                 
127                 public virtual SiteMapNode NextSibling {
128                         get {
129                                 IList siblings = this.SiblingNodes;
130                                 if (siblings == null)
131                                         return null; 
132                                 
133                                 int pos = siblings.IndexOf (this);
134                                 if (pos >= 0 && pos < siblings.Count - 1)
135                                         return (SiteMapNode) siblings [pos + 1]; 
136                                 
137                                 return null; 
138                         }
139                 }
140                 
141                 public virtual SiteMapNode PreviousSibling {
142                         get {
143                                 IList siblings = this.SiblingNodes;
144                                 if (siblings == null)
145                                         return null; 
146                                 
147                                 int pos = siblings.IndexOf (this);
148                                 if (pos > 0 && pos < siblings.Count)
149                                         return (SiteMapNode) siblings [pos - 1]; 
150                                 
151                                 return null; 
152                         }
153                 }
154                 
155                 public virtual SiteMapNode ParentNode {
156                         get {
157                                 if (parent != null) return parent;
158                                 
159                                 SiteMapProvider provider = this.provider;
160                                 
161                                 do {
162                                         parent = provider.GetParentNode (this);
163                                         if (parent != null)
164                                                 return parent; 
165                                         
166                                         provider = provider.ParentProvider;
167                                 } while (provider != null);
168                                 return null;
169                         }
170                         set {
171                                 CheckWritable ();
172                                 parent = value;
173                         }
174                 }
175
176                 internal SiteMapNodeCollection ChildNodesInternal {
177                         get {
178                                 if (childNodes == null)
179                                         childNodes = new SiteMapNodeCollection ();
180                                 return childNodes;
181                         }
182                 }
183
184                 public virtual SiteMapNodeCollection ChildNodes {
185                         get {
186                                 if (childNodes != null) return childNodes;
187                                 return provider.GetChildNodes (this);
188                         } 
189                         set {
190                                 CheckWritable ();
191                                 childNodes = value;
192                         }
193                 }
194
195                 public virtual SiteMapNode RootNode { get { return provider.RootProvider.RootNode; }  }
196                 
197                 SiteMapNodeCollection SiblingNodes {
198                         get {
199                                 if (ParentNode != null)
200                                         return ParentNode.ChildNodes;
201                                 
202                                 return null;
203                         }
204                 }
205                 
206                 protected string GetExplicitResourceString (string attributeName, string defaultValue, bool throwIfNotFound)
207                 {
208                         if (attributeName == null)
209                                 throw new ArgumentNullException ("attributeName");
210                         
211                         if (resourceKeys != null){
212                                 string[] values = resourceKeys.GetValues (attributeName);
213                                 if (values != null && values.Length == 2) {
214                                         try {
215                                                 object o = HttpContext.GetGlobalResourceObject (values [0], values [1]);
216                                                 if (o is string)
217                                                         return (string) o;
218                                         }
219                                         catch (MissingManifestResourceException) {
220                                         }
221
222                                         if (throwIfNotFound && defaultValue == null)
223                                                 throw new InvalidOperationException (String.Format ("The resource object with classname '{0}' and key '{1}' was not found.", values [0], values [1]));
224                                 }
225                         }
226
227                         return defaultValue;
228                 }
229
230                 protected string GetImplicitResourceString (string attributeName)
231                 {
232                         if (attributeName == null)
233                                 throw new ArgumentNullException ("attributeName");
234
235                         string resourceKey = ResourceKey;
236                         if (String.IsNullOrEmpty (resourceKey))
237                                 return null;
238
239                         try {
240                                 object o = HttpContext.GetGlobalResourceObject (provider.ResourceKey, resourceKey + "." + attributeName);
241                                 if (o is string)
242                                         return (string) o;
243                         } catch (MissingManifestResourceException) {
244                         }
245                         
246                         return null;
247                 }
248                 
249                 public virtual string this [string key]
250                 {
251                         get {
252                                 if (provider.EnableLocalization) {
253                                         string val = GetImplicitResourceString (key);
254                                         if (val == null)
255                                                 val = GetExplicitResourceString (key, null, true);
256                                         if (val != null)
257                                                 return val;
258                                 }
259                                 if (attributes != null) return attributes [key];
260                                 return null;
261                         }
262                         set {
263                                 CheckWritable ();
264                                 if (attributes == null) attributes = new NameValueCollection ();
265                                 attributes [key] = value;
266                         }
267                 }
268                 
269                 object ICloneable.Clone ()
270                 {
271                         return Clone (false);
272                 }
273                 
274                 public virtual SiteMapNode Clone ()
275                 {
276                         return Clone (false);
277                 }
278                 
279                 public virtual SiteMapNode Clone (bool cloneParentNodes)
280                 {
281                         SiteMapNode node = new SiteMapNode ();
282                         node.provider = provider;
283                         node.key = key;
284                         node.url = url;
285                         node.title = title;
286                         node.description = description;
287                         if (roles != null)
288                                 node.roles = new ArrayList (roles);
289                         if (attributes != null)
290                                 node.attributes = new NameValueCollection (attributes);
291                         if (cloneParentNodes && ParentNode != null)
292                                 node.parent = (SiteMapNode) ParentNode.Clone (true);
293                         return node;
294                 }
295                                 
296                 public override bool Equals (object ob)
297                 {
298                         SiteMapNode node = ob as SiteMapNode;
299                         if (node == null) return false;
300                         
301                         if (node.key != key ||
302                                         node.url != url ||
303                                         node.title != title ||
304                                         node.description != description) {
305                                 return false;
306                         }
307
308                         if (roles == null || node.roles == null) {
309                                 if (roles != node.roles)
310                                         return false;
311                         }
312                         else {
313                                 if (roles.Count != node.roles.Count)
314                                         return false;
315
316                                 foreach (object role in roles)
317                                         if (!node.roles.Contains (role)) return false;
318                         }
319                         if (attributes == null || node.attributes == null) {
320                                 if (attributes != node.attributes)
321                                         return false;
322                         }
323                         else {
324                                 if (attributes.Count != node.attributes.Count)
325                                         return false;
326
327                                 foreach (string k in attributes)
328                                         if (attributes[k] != node.attributes[k])
329                                                 return false;
330                         }
331                         return true;
332                 }
333                 
334                 public override int GetHashCode ()
335                 {
336                         return (key + url + title + description).GetHashCode ();
337                 }
338                 
339                 void CheckWritable ()
340                 {
341                         if (readOnly)
342                                 throw new InvalidOperationException ("Can't modify read-only node");
343                 }
344                                 
345                 #region Field Accessors
346                 
347                 protected NameValueCollection Attributes {
348                         get { return attributes; } 
349                         set { CheckWritable (); attributes = value; }
350                 }
351                 
352                 [Localizable (true)]
353                 public virtual string Description {
354                         get {
355                                 string ret = null;
356                                 
357                                 if (provider.EnableLocalization) {
358                                         ret = GetImplicitResourceString ("description");
359                                         if (ret == null)
360                                                 ret = GetExplicitResourceString ("description", description, true);
361                                 } else
362                                         ret = description;
363                                 
364                                 return ret != null ? ret : String.Empty;
365                         }
366                         set { CheckWritable (); description = value; }
367                 }
368                 
369                 [LocalizableAttribute (true)]
370                 public virtual string Title {
371                         get {
372                                 string ret = null;
373
374                                 if (provider.EnableLocalization) {
375                                         ret = GetImplicitResourceString ("title");
376                                         if (ret == null)
377                                                 ret = GetExplicitResourceString ("title", title, true);
378                                 } else
379                                         ret = title;
380                                 
381                                 return ret != null ? ret : String.Empty;
382                         }
383                         set { CheckWritable (); title = value; }
384                 }
385                 
386                 public virtual string Url {
387                         get { return url != null ? url : ""; }
388                         set { CheckWritable (); url = value; }
389                 }
390                 
391                 public IList Roles {
392                         get { return roles; }
393                         set { CheckWritable (); roles = value; }
394                 }
395                 
396                 public bool ReadOnly {
397                         get { return readOnly; }
398                         set { readOnly = value; }
399                 }
400                 
401                 public string ResourceKey {
402                         get { return resourceKey; }
403                         set {
404                                 if (ReadOnly)
405                                         throw new InvalidOperationException ("The node is read-only.");
406                                 resourceKey = value;
407                         }
408                 }
409                 
410                 public string Key { get { return key; } }
411                 public SiteMapProvider Provider { get { return provider; } }
412                 
413                 #endregion
414                 
415                 #region INavigateUIData
416                 IHierarchicalEnumerable System.Web.UI.IHierarchyData.GetChildren () { return ChildNodes; }
417                 IHierarchyData System.Web.UI.IHierarchyData.GetParent ()
418                 {
419                         return ParentNode;
420                 }
421
422                 bool System.Web.UI.IHierarchyData.HasChildren { get { return HasChildNodes; } }
423                 object System.Web.UI.IHierarchyData.Item { get { return this; } }
424                 string System.Web.UI.IHierarchyData.Path { get { return Url; } }
425                 string System.Web.UI.IHierarchyData.Type { get { return "SiteMapNode"; } }
426                 #endregion
427                 
428                 #region INavigateUIData
429                 string INavigateUIData.Name { get { return Title; }  }
430                 string INavigateUIData.NavigateUrl { get { return Url; } }
431                 string INavigateUIData.Value { get { return Title; } }
432                 #endregion
433
434                 #region Fields
435                 SiteMapProvider provider;
436                 string key;
437                 string url;
438                 string title;
439                 string description;
440                 IList roles;
441                 NameValueCollection attributes;
442                 NameValueCollection resourceKeys;
443                 bool readOnly;
444                 string resourceKey;
445                 SiteMapNode parent;
446                 SiteMapNodeCollection childNodes;
447                 #endregion
448                 
449         }
450 }
451 #endif
452