/******************************************************************************
* 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:
///
/// getAttribute("cn")
returns only the "cn" attribute
/// getAttribute("cn;lang-en")
returns only the "cn;lang-en"
/// attribute.
///
/// 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:
///
///
/// - cn;lang-en
/// - cn;lang-ja-JP-kanji
/// - sn
///
///
/// Examples:
///
/// getAttribute( "cn" )
returns null
.
/// getAttribute( "sn" )
returns the "sn" attribute.
/// getAttribute( "cn", "lang-en-us" )
/// returns the "cn;lang-en" attribute.
/// getAttribute( "cn", "lang-en" )
/// returns the "cn;lang-en" attribute.
/// getAttribute( "cn", "lang-ja" )
/// returns null
.
/// getAttribute( "sn", "lang-en" )
/// returns the "sn" attribute.
///
///
/// 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:
///
///
/// - cn
/// - cn;lang-ja
/// - sn;phonetic;lang-ja
/// - sn;lang-us
///
///
/// Calling the getSubset
method and passing lang-ja as the
/// argument, the method returns an attribute set containing the following
/// attributes:
///
///
/// - cn;lang-ja
/// - sn;phonetic;lang-ja
///
///
///
/// Semi-colon delimited list of subtypes to include. For
/// example:
///
/// - "lang-ja" specifies only Japanese language subtypes
/// - "binary" specifies only binary subtypes
/// - "binary;lang-ja" specifies only Japanese language subtypes
/// which also are binary
///
///
/// 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();
}
}
}