/****************************************************************************** * The MIT License * Copyright (c) 2003 Novell Inc. www.novell.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the Software), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ // // Novell.Directory.Ldap.LdapAttributeSet.cs // // Author: // Sunil Kumar (Sunilk@novell.com) // // (C) 2003 Novell, Inc (http://www.novell.com) // using System; namespace Novell.Directory.Ldap { /// /// A set of {@link LdapAttribute} objects. /// /// An LdapAttributeSet is a collection of LdapAttribute /// classes as returned from an LdapEntry on a search or read /// operation. LdapAttributeSet may be also used to contruct an entry /// to be added to a directory. If the add() or addAll() /// methods are called and one or more of the objects to be added is not /// an LdapAttribute, ClassCastException is thrown (as discussed in the /// documentation for java.util.Collection). /// /// /// /// /// /// /// public class LdapAttributeSet:SupportClass.AbstractSetSupport, System.ICloneable//, SupportClass.SetSupport { /// Returns the number of attributes in this set. /// /// /// number of attributes in this set. /// public override int Count { get { return this.map.Count; } } /// This is the underlying data structure for this set. /// HashSet is similar to the functionality of this set. The difference /// is we use the name of an attribute as keys in the Map and LdapAttributes /// as the values. We also do not declare the map as transient, making the /// map serializable. /// private System.Collections.Hashtable map; /// Constructs an empty set of attributes. public LdapAttributeSet():base() { map = new System.Collections.Hashtable(); } // --- methods not defined in Set --- /// Returns a deep copy of this attribute set. /// /// /// A deep copy of this attribute set. /// public override System.Object Clone() { try { System.Object newObj = base.MemberwiseClone(); System.Collections.IEnumerator i = this.GetEnumerator(); while (i.MoveNext()) { ((LdapAttributeSet) newObj).Add(((LdapAttribute) i.Current).Clone()); } return newObj; } catch (System.Exception ce) { throw new System.SystemException("Internal error, cannot create clone"); } } /// Returns the attribute matching the specified attrName. /// /// For example: /// /// In both cases, null is returned if there is no exact match to /// the specified attrName. /// /// Note: Novell eDirectory does not currently support language subtypes. /// It does support the "binary" subtype. /// /// /// The name of an attribute to retrieve, with or without /// subtype specifications. For example, "cn", "cn;phonetic", and /// "cn;binary" are valid attribute names. /// /// /// The attribute matching the specified attrName, or null /// if there is no exact match. /// public virtual LdapAttribute getAttribute(System.String attrName) { return (LdapAttribute) map[attrName.ToUpper()]; } /// Returns a single best-match attribute, or null if no match is /// available in the entry. /// /// Ldap version 3 allows adding a subtype specification to an attribute /// name. For example, "cn;lang-ja" indicates a Japanese language /// subtype of the "cn" attribute and "cn;lang-ja-JP-kanji" may be a subtype /// of "cn;lang-ja". This feature may be used to provide multiple /// localizations in the same directory. For attributes which do not vary /// among localizations, only the base attribute may be stored, whereas /// for others there may be varying degrees of specialization. /// /// For example, getAttribute(attrName,lang) returns the /// LdapAttribute that exactly matches attrName and that /// best matches lang. /// /// If there are subtypes other than "lang" subtypes included /// in attrName, for example, "cn;binary", only attributes with all of /// those subtypes are returned. If lang is null or empty, the /// method behaves as getAttribute(attrName). If there are no matching /// attributes, null is returned. /// /// /// Assume the entry contains only the following attributes: /// /// /// /// Examples: /// /// /// Note: Novell eDirectory does not currently support language subtypes. /// It does support the "binary" subtype. /// /// /// The name of an attribute to retrieve, with or without /// subtype specifications. For example, "cn", "cn;phonetic", and /// cn;binary" are valid attribute names. /// /// /// A language specification with optional subtypes /// appended using "-" as separator. For example, "lang-en", "lang-en-us", /// "lang-ja", and "lang-ja-JP-kanji" are valid language specification. /// /// /// A single best-match LdapAttribute, or null /// if no match is found in the entry. /// /// public virtual LdapAttribute getAttribute(System.String attrName, System.String lang) { System.String key = attrName + ";" + lang; return (LdapAttribute) map[key.ToUpper()]; } /// Creates a new attribute set containing only the attributes that have /// the specified subtypes. /// /// For example, suppose an attribute set contains the following /// attributes: /// /// /// /// Calling the getSubset method and passing lang-ja as the /// argument, the method returns an attribute set containing the following /// attributes: /// /// /// /// /// Semi-colon delimited list of subtypes to include. For /// example: /// /// /// Note: Novell eDirectory does not currently support language subtypes. /// It does support the "binary" subtype. /// /// /// An attribute set containing the attributes that match the /// specified subtype. /// public virtual LdapAttributeSet getSubset(System.String subtype) { // Create a new tempAttributeSet LdapAttributeSet tempAttributeSet = new LdapAttributeSet(); System.Collections.IEnumerator i = this.GetEnumerator(); // Cycle throught this.attributeSet while (i.MoveNext()) { LdapAttribute attr = (LdapAttribute) i.Current; // Does this attribute have the subtype we are looking for. If // yes then add it to our AttributeSet, else next attribute if (attr.hasSubtype(subtype)) tempAttributeSet.Add(attr.Clone()); } return tempAttributeSet; } // --- methods defined in set --- /// Returns an iterator over the attributes in this set. The attributes /// returned from this iterator are not in any particular order. /// /// /// iterator over the attributes in this set /// public override System.Collections.IEnumerator GetEnumerator() { return this.map.Values.GetEnumerator(); } /// Returns true if this set contains no elements /// /// /// true if this set contains no elements /// public override bool IsEmpty() { return (this.map.Count == 0); } /// Returns true if this set contains an attribute of the same name /// as the specified attribute. /// /// /// Object of type LdapAttribute /// /// /// true if this set contains the specified attribute /// /// @throws ClassCastException occurs the specified Object /// is not of type LdapAttribute. /// public override bool Contains(object attr) { LdapAttribute attribute = (LdapAttribute) attr; return this.map.ContainsKey(attribute.Name.ToUpper()); } /// Adds the specified attribute to this set if it is not already present. /// If an attribute with the same name already exists in the set then the /// specified attribute will not be added. /// /// /// Object of type LdapAttribute /// /// /// true if the attribute was added. /// /// @throws ClassCastException occurs the specified Object /// is not of type LdapAttribute. /// public override bool Add(object attr) { //We must enforce that attr is an LdapAttribute LdapAttribute attribute = (LdapAttribute) attr; System.String name = attribute.Name.ToUpper(); if (this.map.ContainsKey(name)) return false; else { SupportClass.PutElement(this.map, name, attribute); return true; } } /// Removes the specified object from this set if it is present. /// /// If the specified object is of type LdapAttribute, the /// specified attribute will be removed. If the specified object is of type /// String, the attribute with a name that matches the string will /// be removed. /// /// /// LdapAttribute to be removed or String naming /// the attribute to be removed. /// /// /// true if the object was removed. /// /// @throws ClassCastException occurs the specified Object /// is not of type LdapAttribute or of type String. /// public override bool Remove(object object_Renamed) { System.String attributeName; //the name is the key to object in the HashMap if (object_Renamed is System.String) { attributeName = ((System.String) object_Renamed); } else { attributeName = ((LdapAttribute) object_Renamed).Name; } if ((System.Object) attributeName == null) { return false; } return (SupportClass.HashtableRemove(this.map, attributeName.ToUpper()) != null); } /// Removes all of the elements from this set. public override void Clear() { this.map.Clear(); } /// Adds all LdapAttribute objects in the specified collection to /// this collection. /// /// /// Collection of LdapAttribute objects. /// /// @throws ClassCastException occurs when an element in the /// collection is not of type LdapAttribute. /// /// /// true if this set changed as a result of the call. /// public override bool AddAll(System.Collections.ICollection c) { bool setChanged = false; System.Collections.IEnumerator i = c.GetEnumerator(); while (i.MoveNext()) { // we must enforce that everything in c is an LdapAttribute // add will return true if the attribute was added if (this.Add(i.Current)) { setChanged = true; } } return setChanged; } /// Returns a string representation of this LdapAttributeSet /// /// /// a string representation of this LdapAttributeSet /// public override System.String ToString() { System.Text.StringBuilder retValue = new System.Text.StringBuilder("LdapAttributeSet: "); System.Collections.IEnumerator attrs = GetEnumerator(); bool first = true; while (attrs.MoveNext()) { if (!first) { retValue.Append(" "); } first = false; LdapAttribute attr = (LdapAttribute) attrs.Current; retValue.Append(attr.ToString()); } return retValue.ToString(); } } }