* TagAttribute.cs: attributes can be stored as encoded html so we
[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 (value != null)
61                                 value = HttpUtility.HtmlDecode (value.ToString ());
62
63                         if (got_hashed) {
64                                 if (atts_hash.ContainsKey (key))
65                                         throw new HttpException ("Tag contains duplicated '" + key +
66                                                                  "' attributes.");
67                                 atts_hash.Add (key, value);
68                         } else {
69                                 keys.Add (key);
70                                 values.Add (value);
71                         }
72                 }
73                 
74                 public ICollection Keys 
75                 {
76                         get { return (got_hashed ? atts_hash.Keys : keys); }
77                 }
78
79                 public ICollection Values 
80                 {
81                         get { return (got_hashed ? atts_hash.Values : values); }
82                 }
83
84                 private int CaseInsensitiveSearch (string key)
85                 {
86                         // Hope not to have many attributes when the tag is not a server tag...
87                         for (int i = 0; i < keys.Count; i++){
88                                 if (0 == String.Compare ((string) keys [i], key, true))
89                                         return i;
90                         }
91                         return -1;
92                 }
93                 
94                 public object this [object key]
95                 {
96                         get {
97                                 if (got_hashed)
98                                         return atts_hash [key];
99
100                                 int idx = CaseInsensitiveSearch ((string) key);
101                                 if (idx == -1)
102                                         return null;
103                                                 
104                                 return values [idx];
105                         }
106
107                         set {
108                                 if (got_hashed)
109                                         atts_hash [key] = value;
110                                 else {
111                                         int idx = CaseInsensitiveSearch ((string) key);
112                                         keys [idx] = value;
113                                 }
114                         }
115                 }
116                 
117                 public int Count 
118                 {
119                         get { return (got_hashed ? atts_hash.Count : keys.Count);}
120                 }
121
122                 public bool IsDataBound (string att)
123                 {
124                         if (att == null || !got_hashed)
125                                 return false;
126
127                         return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
128                 }
129                 
130                 public Hashtable GetDictionary (string key)
131                 {
132                         if (got_hashed)
133                                 return atts_hash;
134
135                         if (tmp_hash == null)
136                                 tmp_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
137                                                           CaseInsensitiveComparer.Default);
138                         
139                         tmp_hash.Clear ();
140                         for (int i = keys.Count - 1; i >= 0; i--)
141                                 if (key == null || String.Compare (key, (string) keys [i], true) == 0)
142                                         tmp_hash [keys [i]] = values [i];
143
144                         return tmp_hash;
145                 }
146                 
147                 public override string ToString ()
148                 {
149                         StringBuilder result = new StringBuilder ();
150                         string value;
151                         foreach (string key in Keys){
152                                 result.Append (key);
153                                 value = this [key] as string;
154                                 if (value != null)
155                                         result.AppendFormat ("=\"{0}\"", value);
156
157                                 result.Append (' ');
158                         }
159
160                         if (result.Length > 0 && result [result.Length - 1] == ' ')
161                                 result.Length--;
162                                 
163                         return result.ToString ();
164                 }
165         }
166 }
167