[xbuild] Implements property functions using constructor syntax. Fixes #12999
[mono.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap / LdapAttributeSet.cs
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc.  www.novell.com
4
5 * Permission is hereby granted, free of charge, to any person obtaining  a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including  without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
9 * copies of the Software, and to  permit persons to whom the Software is 
10 * furnished to do so, subject to the following conditions:
11
12 * The above copyright notice and this permission notice shall be included in 
13 * all copies or substantial portions of the Software.
14
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
23 //
24 // Novell.Directory.Ldap.LdapAttributeSet.cs
25 //
26 // Author:
27 //   Sunil Kumar (Sunilk@novell.com)
28 //
29 // (C) 2003 Novell, Inc (http://www.novell.com)
30 //
31
32 using System;
33
34
35 namespace Novell.Directory.Ldap
36 {
37         
38         /// <summary> 
39         /// A set of {@link LdapAttribute} objects.
40         /// 
41         /// An <code>LdapAttributeSet</code> is a collection of <code>LdapAttribute</code>
42         /// classes as returned from an <code>LdapEntry</code> on a search or read
43         /// operation. <code>LdapAttributeSet</code> may be also used to contruct an entry
44         /// to be added to a directory.  If the <code>add()</code> or <code>addAll()</code>
45         /// methods are called and one or more of the objects to be added is not
46         /// an <code>LdapAttribute, ClassCastException</code> is thrown (as discussed in the
47         /// documentation for <code>java.util.Collection</code>).
48         /// 
49         /// 
50         /// </summary>
51         /// <seealso cref="LdapAttribute">
52         /// </seealso>
53         /// <seealso cref="LdapEntry">
54         /// </seealso>
55         public class LdapAttributeSet:SupportClass.AbstractSetSupport, System.ICloneable//, SupportClass.SetSupport
56         {
57                 /// <summary> Returns the number of attributes in this set.
58                 /// 
59                 /// </summary>
60                 /// <returns> number of attributes in this set.
61                 /// </returns>
62                 public override int Count
63                 {
64                         get
65                         {
66                                 return this.map.Count;
67                         }
68                         
69                 }
70                 
71                 /// <summary> This is the underlying data structure for this set.
72                 /// HashSet is similar to the functionality of this set.  The difference
73                 /// is we use the name of an attribute as keys in the Map and LdapAttributes
74                 /// as the values.  We also do not declare the map as transient, making the
75                 /// map serializable.
76                 /// </summary>
77                 private System.Collections.Hashtable map;
78                 
79                 /// <summary> Constructs an empty set of attributes.</summary>
80                 public LdapAttributeSet():base()
81                 {
82                         map = new System.Collections.Hashtable();
83                 }
84                 
85                 // ---  methods not defined in Set ---
86                 
87                 /// <summary> Returns a deep copy of this attribute set.
88                 /// 
89                 /// </summary>
90                 /// <returns> A deep copy of this attribute set.
91                 /// </returns>
92                 public override System.Object Clone()
93                 {
94                         try
95                         {
96                                 System.Object newObj = base.MemberwiseClone();
97                                 System.Collections.IEnumerator i = this.GetEnumerator();
98                                 while (i.MoveNext())
99                                 {
100                                         ((LdapAttributeSet) newObj).Add(((LdapAttribute) i.Current).Clone());
101                                 }
102                                 return newObj;
103                         }
104                         catch (System.Exception ce)
105                         {
106                                 throw new System.SystemException("Internal error, cannot create clone");
107                         }
108                 }
109                 
110                 /// <summary> Returns the attribute matching the specified attrName.
111                 /// 
112                 /// For example:
113                 /// <ul>
114                 /// <li><code>getAttribute("cn")</code>      returns only the "cn" attribute</li>
115                 /// <li><code>getAttribute("cn;lang-en")</code> returns only the "cn;lang-en"
116                 /// attribute.</li>
117                 /// </ul>
118                 /// In both cases, <code>null</code> is returned if there is no exact match to
119                 /// the specified attrName.
120                 /// 
121                 /// Note: Novell eDirectory does not currently support language subtypes.
122                 /// It does support the "binary" subtype.
123                 /// 
124                 /// </summary>
125                 /// <param name="attrName">  The name of an attribute to retrieve, with or without
126                 /// subtype specifications. For example, "cn", "cn;phonetic", and
127                 /// "cn;binary" are valid attribute names.
128                 /// 
129                 /// </param>
130                 /// <returns> The attribute matching the specified attrName, or <code>null</code>
131                 /// if there is no exact match.
132                 /// </returns>
133                 public virtual LdapAttribute getAttribute(System.String attrName)
134                 {
135                         return (LdapAttribute) map[attrName.ToUpper()];
136                 }
137                 
138                 /// <summary> Returns a single best-match attribute, or <code>null</code> if no match is
139                 /// available in the entry.
140                 /// 
141                 /// Ldap version 3 allows adding a subtype specification to an attribute
142                 /// name. For example, "cn;lang-ja" indicates a Japanese language
143                 /// subtype of the "cn" attribute and "cn;lang-ja-JP-kanji" may be a subtype
144                 /// of "cn;lang-ja". This feature may be used to provide multiple
145                 /// localizations in the same directory. For attributes which do not vary
146                 /// among localizations, only the base attribute may be stored, whereas
147                 /// for others there may be varying degrees of specialization.
148                 /// 
149                 /// For example, <code>getAttribute(attrName,lang)</code> returns the
150                 /// <code>LdapAttribute</code> that exactly matches attrName and that
151                 /// best matches lang.
152                 /// 
153                 /// If there are subtypes other than "lang" subtypes included
154                 /// in attrName, for example, "cn;binary", only attributes with all of
155                 /// those subtypes are returned. If lang is <code>null</code> or empty, the
156                 /// method behaves as getAttribute(attrName). If there are no matching
157                 /// attributes, <code>null</code> is returned. 
158                 /// 
159                 /// 
160                 /// Assume the entry contains only the following attributes:
161                 /// 
162                 /// <ul>
163                 /// <li>cn;lang-en</li>
164                 /// <li>cn;lang-ja-JP-kanji</li>
165                 /// <li>sn</li>
166                 /// </ul>
167                 /// 
168                 /// Examples:
169                 /// <ul>
170                 /// <li><code>getAttribute( "cn" )</code>       returns <code>null</code>.</li>
171                 /// <li><code>getAttribute( "sn" )</code>       returns the "sn" attribute.</li>
172                 /// <li><code>getAttribute( "cn", "lang-en-us" )</code>
173                 /// returns the "cn;lang-en" attribute.</li>
174                 /// <li><code>getAttribute( "cn", "lang-en" )</code>
175                 /// returns the "cn;lang-en" attribute.</li>
176                 /// <li><code>getAttribute( "cn", "lang-ja" )</code>
177                 /// returns <code>null</code>.</li>
178                 /// <li><code>getAttribute( "sn", "lang-en" )</code>
179                 /// returns the "sn" attribute.</li>
180                 /// </ul>
181                 /// 
182                 /// Note: Novell eDirectory does not currently support language subtypes.
183                 /// It does support the "binary" subtype.
184                 /// 
185                 /// </summary>
186                 /// <param name="attrName"> The name of an attribute to retrieve, with or without
187                 /// subtype specifications. For example, "cn", "cn;phonetic", and
188                 /// cn;binary" are valid attribute names.
189                 /// 
190                 /// </param>
191                 /// <param name="lang">  A language specification with optional subtypes
192                 /// appended using "-" as separator. For example, "lang-en", "lang-en-us",
193                 /// "lang-ja", and "lang-ja-JP-kanji" are valid language specification.
194                 /// 
195                 /// </param>
196                 /// <returns> A single best-match <code>LdapAttribute</code>, or <code>null</code>
197                 /// if no match is found in the entry.
198                 /// 
199                 /// </returns>
200                 public virtual LdapAttribute getAttribute(System.String attrName, System.String lang)
201                 {
202                         System.String key = attrName + ";" + lang;
203                         return (LdapAttribute) map[key.ToUpper()];
204                 }
205                 
206                 /// <summary> Creates a new attribute set containing only the attributes that have
207                 /// the specified subtypes.
208                 /// 
209                 /// For example, suppose an attribute set contains the following
210                 /// attributes:
211                 /// 
212                 /// <ul>
213                 /// <li>    cn</li>
214                 /// <li>    cn;lang-ja</li>
215                 /// <li>    sn;phonetic;lang-ja</li>
216                 /// <li>    sn;lang-us</li>
217                 /// </ul>
218                 /// 
219                 /// Calling the <code>getSubset</code> method and passing lang-ja as the
220                 /// argument, the method returns an attribute set containing the following
221                 /// attributes:
222                 /// 
223                 /// <ul>
224                 /// <li>cn;lang-ja</li>
225                 /// <li>sn;phonetic;lang-ja</li>
226                 /// </ul>
227                 /// 
228                 /// </summary>
229                 /// <param name="subtype">   Semi-colon delimited list of subtypes to include. For
230                 /// example:
231                 /// <ul>
232                 /// <li> "lang-ja" specifies only Japanese language subtypes</li>
233                 /// <li> "binary" specifies only binary subtypes</li>
234                 /// <li> "binary;lang-ja" specifies only Japanese language subtypes
235                 /// which also are binary</li>
236                 /// </ul>
237                 /// 
238                 /// Note: Novell eDirectory does not currently support language subtypes.
239                 /// It does support the "binary" subtype.
240                 /// 
241                 /// </param>
242                 /// <returns> An attribute set containing the attributes that match the
243                 /// specified subtype.
244                 /// </returns>
245                 public virtual LdapAttributeSet getSubset(System.String subtype)
246                 {
247                         
248                         // Create a new tempAttributeSet
249                         LdapAttributeSet tempAttributeSet = new LdapAttributeSet();
250                         System.Collections.IEnumerator i = this.GetEnumerator();
251                         
252                         // Cycle throught this.attributeSet
253                         while (i.MoveNext())
254                         {
255                                 LdapAttribute attr = (LdapAttribute) i.Current;
256                                 
257                                 // Does this attribute have the subtype we are looking for. If
258                                 // yes then add it to our AttributeSet, else next attribute
259                                 if (attr.hasSubtype(subtype))
260                                         tempAttributeSet.Add(attr.Clone());
261                         }
262                         return tempAttributeSet;
263                 }
264                 
265                 // --- methods defined in set ---
266                 
267                 /// <summary> Returns an iterator over the attributes in this set.  The attributes
268                 /// returned from this iterator are not in any particular order.
269                 /// 
270                 /// </summary>
271                 /// <returns> iterator over the attributes in this set
272                 /// </returns>
273                 public  override  System.Collections.IEnumerator GetEnumerator()
274                 {
275                         return this.map.Values.GetEnumerator();
276                 }
277                 
278                 /// <summary> Returns <code>true</code> if this set contains no elements
279                 /// 
280                 /// </summary>
281                 /// <returns> <code>true</code> if this set contains no elements
282                 /// </returns>
283                 public override bool IsEmpty()
284                 {
285                         return (this.map.Count == 0);
286                 }
287                 
288                 /// <summary> Returns <code>true</code> if this set contains an attribute of the same name
289                 /// as the specified attribute.
290                 /// 
291                 /// </summary>
292                 /// <param name="attr">  Object of type <code>LdapAttribute</code>
293                 /// 
294                 /// </param>
295                 /// <returns> true if this set contains the specified attribute
296                 /// 
297                 /// @throws ClassCastException occurs the specified Object
298                 /// is not of type LdapAttribute.
299                 /// </returns>
300                 public override bool Contains(object attr)
301                 {
302                         LdapAttribute attribute = (LdapAttribute) attr;
303                         return this.map.ContainsKey(attribute.Name.ToUpper());
304                 }
305                 
306                 /// <summary> Adds the specified attribute to this set if it is not already present.
307                 /// If an attribute with the same name already exists in the set then the
308                 /// specified attribute will not be added.
309                 /// 
310                 /// </summary>
311                 /// <param name="attr">  Object of type <code>LdapAttribute</code>
312                 /// 
313                 /// </param>
314                 /// <returns> true if the attribute was added.
315                 /// 
316                 /// @throws ClassCastException occurs the specified Object
317                 /// is not of type <code>LdapAttribute</code>.
318                 /// </returns>
319                 public override bool Add(object attr)
320                 {
321                         //We must enforce that attr is an LdapAttribute
322                         LdapAttribute attribute = (LdapAttribute) attr;
323                         System.String name = attribute.Name.ToUpper();
324                         if (this.map.ContainsKey(name))
325                                 return false;
326                         else
327                         {
328                                 SupportClass.PutElement(this.map, name, attribute);
329                                 return true;
330                         }
331                 }
332                 
333                 /// <summary> Removes the specified object from this set if it is present.
334                 /// 
335                 /// If the specified object is of type <code>LdapAttribute</code>, the
336                 /// specified attribute will be removed.  If the specified object is of type
337                 /// <code>String</code>, the attribute with a name that matches the string will
338                 /// be removed.
339                 /// 
340                 /// </summary>
341                 /// <param name="object">LdapAttribute to be removed or <code>String</code> naming
342                 /// the attribute to be removed.
343                 /// 
344                 /// </param>
345                 /// <returns> true if the object was removed.
346                 /// 
347                 /// @throws ClassCastException occurs the specified Object
348                 /// is not of type <code>LdapAttribute</code> or of type <code>String</code>.
349                 /// </returns>
350                 public override bool Remove(object object_Renamed)
351                 {
352                         System.String attributeName; //the name is the key to object in the HashMap
353                         if (object_Renamed is System.String)
354                         {
355                                 attributeName = ((System.String) object_Renamed);
356                         }
357                         else
358                         {
359                                 attributeName = ((LdapAttribute) object_Renamed).Name;
360                         }
361                         if ((System.Object) attributeName == null)
362                         {
363                                 return false;
364                         }
365                         return (SupportClass.HashtableRemove(this.map, attributeName.ToUpper()) != null);
366                 }
367                 
368                 /// <summary> Removes all of the elements from this set.</summary>
369                 public override void Clear()
370                 {
371                         this.map.Clear();
372                 }
373                 
374                 /// <summary> Adds all <code>LdapAttribute</code> objects in the specified collection to
375                 /// this collection.
376                 /// 
377                 /// </summary>
378                 /// <param name="c"> Collection of <code>LdapAttribute</code> objects.
379                 /// 
380                 /// @throws ClassCastException occurs when an element in the
381                 /// collection is not of type <code>LdapAttribute</code>.
382                 /// 
383                 /// </param>
384                 /// <returns> true if this set changed as a result of the call.
385                 /// </returns>
386                 public override bool AddAll(System.Collections.ICollection c)
387                 {
388                         bool setChanged = false;
389                         System.Collections.IEnumerator i = c.GetEnumerator();
390                         
391                         while (i.MoveNext())
392                         {
393                                 // we must enforce that everything in c is an LdapAttribute
394                                 // add will return true if the attribute was added
395                                 if (this.Add(i.Current))
396                                 {
397                                         setChanged = true;
398                                 }
399                         }
400                         return setChanged;
401                 }
402                 
403                 /// <summary> Returns a string representation of this LdapAttributeSet
404                 /// 
405                 /// </summary>
406                 /// <returns> a string representation of this LdapAttributeSet
407                 /// </returns>
408                 public override System.String ToString()
409                 {
410                         System.Text.StringBuilder retValue = new System.Text.StringBuilder("LdapAttributeSet: ");
411                         System.Collections.IEnumerator attrs = GetEnumerator();
412                         bool first = true;
413                         while (attrs.MoveNext())
414                         {
415                                 if (!first)
416                                 {
417                                         retValue.Append(" ");
418                                 }
419                                 first = false;
420                                 LdapAttribute attr = (LdapAttribute) attrs.Current;
421                                 retValue.Append(attr.ToString());
422                         }
423                         return retValue.ToString();
424                 }
425         }
426 }