1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc. www.novell.com
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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
22 *******************************************************************************/
24 // Novell.Directory.Ldap.LdapAttributeSet.cs
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
35 namespace Novell
.Directory
.Ldap
39 /// A set of {@link LdapAttribute} objects.
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>).
51 /// <seealso cref="LdapAttribute">
53 /// <seealso cref="LdapEntry">
55 public class LdapAttributeSet
:AbstractSetSupport
, System
.ICloneable
//, SupportClass.SetSupport
57 /// <summary> Returns the number of attributes in this set.
60 /// <returns> number of attributes in this set.
62 public override int Count
66 return this.map
.Count
;
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
77 private System
.Collections
.Hashtable map
;
79 /// <summary> Constructs an empty set of attributes.</summary>
80 public LdapAttributeSet():base()
82 map
= new System
.Collections
.Hashtable();
85 // --- methods not defined in Set ---
87 /// <summary> Returns a deep copy of this attribute set.
90 /// <returns> A deep copy of this attribute set.
92 public override System
.Object
Clone()
96 System
.Object newObj
= base.MemberwiseClone();
97 System
.Collections
.IEnumerator i
= this.GetEnumerator();
100 ((LdapAttributeSet
) newObj
).Add(((LdapAttribute
) i
.Current
).Clone());
104 catch (System
.Exception ce
)
106 throw new System
.SystemException("Internal error, cannot create clone");
110 /// <summary> Returns the attribute matching the specified attrName.
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"
118 /// In both cases, <code>null</code> is returned if there is no exact match to
119 /// the specified attrName.
121 /// Note: Novell eDirectory does not currently support language subtypes.
122 /// It does support the "binary" subtype.
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.
130 /// <returns> The attribute matching the specified attrName, or <code>null</code>
131 /// if there is no exact match.
133 public virtual LdapAttribute
getAttribute(System
.String attrName
)
135 return (LdapAttribute
) map
[attrName
.ToUpper()];
138 /// <summary> Returns a single best-match attribute, or <code>null</code> if no match is
139 /// available in the entry.
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.
149 /// For example, <code>getAttribute(attrName,lang)</code> returns the
150 /// <code>LdapAttribute</code> that exactly matches attrName and that
151 /// best matches lang.
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.
160 /// Assume the entry contains only the following attributes:
163 /// <li>cn;lang-en</li>
164 /// <li>cn;lang-ja-JP-kanji</li>
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>
182 /// Note: Novell eDirectory does not currently support language subtypes.
183 /// It does support the "binary" subtype.
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.
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.
196 /// <returns> A single best-match <code>LdapAttribute</code>, or <code>null</code>
197 /// if no match is found in the entry.
200 public virtual LdapAttribute
getAttribute(System
.String attrName
, System
.String lang
)
202 System
.String key
= attrName
+ ";" + lang
;
203 return (LdapAttribute
) map
[key
.ToUpper()];
206 /// <summary> Creates a new attribute set containing only the attributes that have
207 /// the specified subtypes.
209 /// For example, suppose an attribute set contains the following
214 /// <li> cn;lang-ja</li>
215 /// <li> sn;phonetic;lang-ja</li>
216 /// <li> sn;lang-us</li>
219 /// Calling the <code>getSubset</code> method and passing lang-ja as the
220 /// argument, the method returns an attribute set containing the following
224 /// <li>cn;lang-ja</li>
225 /// <li>sn;phonetic;lang-ja</li>
229 /// <param name="subtype"> Semi-colon delimited list of subtypes to include. For
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>
238 /// Note: Novell eDirectory does not currently support language subtypes.
239 /// It does support the "binary" subtype.
242 /// <returns> An attribute set containing the attributes that match the
243 /// specified subtype.
245 public virtual LdapAttributeSet
getSubset(System
.String subtype
)
248 // Create a new tempAttributeSet
249 LdapAttributeSet tempAttributeSet
= new LdapAttributeSet();
250 System
.Collections
.IEnumerator i
= this.GetEnumerator();
252 // Cycle throught this.attributeSet
255 LdapAttribute attr
= (LdapAttribute
) i
.Current
;
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());
262 return tempAttributeSet
;
265 // --- methods defined in set ---
267 /// <summary> Returns an iterator over the attributes in this set. The attributes
268 /// returned from this iterator are not in any particular order.
271 /// <returns> iterator over the attributes in this set
273 public override System
.Collections
.IEnumerator
GetEnumerator()
275 return this.map
.Values
.GetEnumerator();
278 /// <summary> Returns <code>true</code> if this set contains no elements
281 /// <returns> <code>true</code> if this set contains no elements
283 public override bool IsEmpty()
285 return (this.map
.Count
== 0);
288 /// <summary> Returns <code>true</code> if this set contains an attribute of the same name
289 /// as the specified attribute.
292 /// <param name="attr"> Object of type <code>LdapAttribute</code>
295 /// <returns> true if this set contains the specified attribute
297 /// @throws ClassCastException occurs the specified Object
298 /// is not of type LdapAttribute.
300 public override bool Contains(object attr
)
302 LdapAttribute attribute
= (LdapAttribute
) attr
;
303 return this.map
.ContainsKey(attribute
.Name
.ToUpper());
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.
311 /// <param name="attr"> Object of type <code>LdapAttribute</code>
314 /// <returns> true if the attribute was added.
316 /// @throws ClassCastException occurs the specified Object
317 /// is not of type <code>LdapAttribute</code>.
319 public override bool Add(object attr
)
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
))
328 SupportClass
.PutElement(this.map
, name
, attribute
);
333 /// <summary> Removes the specified object from this set if it is present.
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
341 /// <param name="object">LdapAttribute to be removed or <code>String</code> naming
342 /// the attribute to be removed.
345 /// <returns> true if the object was removed.
347 /// @throws ClassCastException occurs the specified Object
348 /// is not of type <code>LdapAttribute</code> or of type <code>String</code>.
350 public override bool Remove(object object_Renamed
)
352 System
.String attributeName
; //the name is the key to object in the HashMap
353 if (object_Renamed
is System
.String
)
355 attributeName
= ((System
.String
) object_Renamed
);
359 attributeName
= ((LdapAttribute
) object_Renamed
).Name
;
361 if ((System
.Object
) attributeName
== null)
365 return (SupportClass
.HashtableRemove(this.map
, attributeName
.ToUpper()) != null);
368 /// <summary> Removes all of the elements from this set.</summary>
369 public override void Clear()
374 /// <summary> Adds all <code>LdapAttribute</code> objects in the specified collection to
378 /// <param name="c"> Collection of <code>LdapAttribute</code> objects.
380 /// @throws ClassCastException occurs when an element in the
381 /// collection is not of type <code>LdapAttribute</code>.
384 /// <returns> true if this set changed as a result of the call.
386 public override bool AddAll(System
.Collections
.ICollection c
)
388 bool setChanged
= false;
389 System
.Collections
.IEnumerator i
= c
.GetEnumerator();
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
))
403 /// <summary> Returns a string representation of this LdapAttributeSet
406 /// <returns> a string representation of this LdapAttributeSet
408 public override System
.String
ToString()
410 System
.Text
.StringBuilder retValue
= new System
.Text
.StringBuilder("LdapAttributeSet: ");
411 System
.Collections
.IEnumerator attrs
= GetEnumerator();
413 while (attrs
.MoveNext())
417 retValue
.Append(" ");
420 LdapAttribute attr
= (LdapAttribute
) attrs
.Current
;
421 retValue
.Append(attr
.ToString());
423 return retValue
.ToString();