2003-10-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / TagAttributes.cs
1 //
2 // System.Web.Compilation.TagAttributes
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 using System;
11 using System.Collections;
12 using System.Text;
13
14 namespace System.Web.Compilation
15 {
16         class TagAttributes
17         {
18                 Hashtable atts_hash;
19                 Hashtable tmp_hash;
20                 ArrayList keys;
21                 ArrayList values;
22                 bool got_hashed;
23
24                 public TagAttributes ()
25                 {
26                         got_hashed = false;
27                         keys = new ArrayList ();
28                         values = new ArrayList ();
29                 }
30
31                 void MakeHash ()
32                 {
33                         atts_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
34                                                    CaseInsensitiveComparer.Default);
35                         for (int i = 0; i < keys.Count; i++)
36                                 atts_hash.Add (keys [i], values [i]);
37                         got_hashed = true;
38                         keys = null;
39                         values = null;
40                 }
41                 
42                 public bool IsRunAtServer ()
43                 {
44                         return got_hashed;
45                 }
46
47                 public void Add (object key, object value)
48                 {
49                         if (key != null && value != null &&
50                             0 == String.Compare ((string) key,  "runat", true)) {
51                                 if (0 != String.Compare ((string) value,  "server", true))
52                                         throw new HttpException ("runat attribute must have a 'server' value");
53
54                                 if (got_hashed)
55                                         return; // ignore duplicate runat="server"
56
57                                 MakeHash ();
58                         }
59
60                         if (got_hashed) {
61                                 if (atts_hash.ContainsKey (key))
62                                         throw new HttpException ("Tag contains duplicated '" + key +
63                                                                  "' attributes.");
64                                 atts_hash.Add (key, value);
65                         } else {
66                                 keys.Add (key);
67                                 values.Add (value);
68                         }
69                 }
70                 
71                 public ICollection Keys 
72                 {
73                         get { return (got_hashed ? atts_hash.Keys : keys); }
74                 }
75
76                 public ICollection Values 
77                 {
78                         get { return (got_hashed ? atts_hash.Values : values); }
79                 }
80
81                 private int CaseInsensitiveSearch (string key)
82                 {
83                         // Hope not to have many attributes when the tag is not a server tag...
84                         for (int i = 0; i < keys.Count; i++){
85                                 if (0 == String.Compare ((string) keys [i], key, true))
86                                         return i;
87                         }
88                         return -1;
89                 }
90                 
91                 public object this [object key]
92                 {
93                         get {
94                                 if (got_hashed)
95                                         return atts_hash [key];
96
97                                 int idx = CaseInsensitiveSearch ((string) key);
98                                 if (idx == -1)
99                                         return null;
100                                                 
101                                 return values [idx];
102                         }
103
104                         set {
105                                 if (got_hashed)
106                                         atts_hash [key] = value;
107                                 else {
108                                         int idx = CaseInsensitiveSearch ((string) key);
109                                         keys [idx] = value;
110                                 }
111                         }
112                 }
113                 
114                 public int Count 
115                 {
116                         get { return (got_hashed ? atts_hash.Count : keys.Count);}
117                 }
118
119                 public bool IsDataBound (string att)
120                 {
121                         if (att == null || !got_hashed)
122                                 return false;
123
124                         return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
125                 }
126                 
127                 public Hashtable GetDictionary (string key)
128                 {
129                         if (got_hashed)
130                                 return atts_hash;
131
132                         if (tmp_hash == null)
133                                 tmp_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
134                                                           CaseInsensitiveComparer.Default);
135                         
136                         tmp_hash.Clear ();
137                         for (int i = keys.Count - 1; i >= 0; i--)
138                                 if (key == null || String.Compare (key, (string) keys [i], true) == 0)
139                                         tmp_hash [keys [i]] = values [i];
140
141                         return tmp_hash;
142                 }
143                 
144                 public override string ToString ()
145                 {
146                         StringBuilder result = new StringBuilder ();
147                         string value;
148                         foreach (string key in Keys){
149                                 result.Append (key);
150                                 value = this [key] as string;
151                                 if (value != null)
152                                         result.AppendFormat ("=\"{0}\"", value);
153
154                                 result.Append (' ');
155                         }
156
157                         if (result.Length > 0 && result [result.Length - 1] == ' ')
158                                 result.Length--;
159                                 
160                         return result.ToString ();
161                 }
162         }
163 }
164