001/*
002 * Copyright 2009-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2009-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.migrate.ldapjdk;
022
023
024
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.Enumeration;
029import java.util.Iterator;
030
031import com.unboundid.util.Mutable;
032import com.unboundid.util.NotExtensible;
033import com.unboundid.util.StaticUtils;
034import com.unboundid.util.ThreadSafety;
035import com.unboundid.util.ThreadSafetyLevel;
036
037
038
039/**
040 * This class provides a data structure that contains a set of LDAP attribute
041 * objects.
042 * <BR><BR>
043 * This class is primarily intended to be used in the process of updating
044 * applications which use the Netscape Directory SDK for Java to switch to or
045 * coexist with the UnboundID LDAP SDK for Java.  For applications not written
046 * using the Netscape Directory SDK for Java, arrays or collections of
047 * {@link com.unboundid.ldap.sdk.Attribute} objects should be used instead.
048 */
049@NotExtensible()
050@Mutable()
051@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
052public class LDAPAttributeSet
053       implements Serializable
054{
055  /**
056   * The serial version UID for this serializable class.
057   */
058  private static final long serialVersionUID = -4872457565092606186L;
059
060
061
062  // The list of LDAPAttribute objects.
063  private final ArrayList<LDAPAttribute> attributes;
064
065
066
067  /**
068   * Creates a new LDAP attribute set with no attributes.
069   */
070  public LDAPAttributeSet()
071  {
072    attributes = new ArrayList<>(20);
073  }
074
075
076
077  /**
078   * Creates a new LDAP attribute set with the provided attributes.
079   *
080   * @param  attrs  The set of attributes to include in the set.
081   */
082  public LDAPAttributeSet(final LDAPAttribute[] attrs)
083  {
084    attributes = new ArrayList<>(Arrays.asList(attrs));
085  }
086
087
088
089  /**
090   * Creates a new LDAP attribute set with the provided attributes.
091   *
092   * @param  attrs  The set of attributes to include in the set.
093   */
094  private LDAPAttributeSet(final ArrayList<LDAPAttribute> attrs)
095  {
096    attributes = new ArrayList<>(attrs);
097  }
098
099
100
101  /**
102   * Retrieves an enumeration of the attributes in this set.
103   *
104   * @return  An enumeration of the attributes in this set.
105   */
106  public Enumeration<LDAPAttribute> getAttributes()
107  {
108    return new IterableEnumeration<>(attributes);
109  }
110
111
112
113  /**
114   * Retrieves a subset of the attributes in this attribute set which contain
115   * the specified subtype.
116   *
117   * @param  subtype  The subtype for which to retrieve all of the attributes.
118   *
119   * @return  A new attribute set with all attributes from this set containing
120   *          the specified subtype.
121   */
122  public LDAPAttributeSet getSubset(final String subtype)
123  {
124    final ArrayList<LDAPAttribute> subset = new ArrayList<>(attributes.size());
125
126    for (final LDAPAttribute a : attributes)
127    {
128      if (a.hasSubtype(subtype))
129      {
130        subset.add(a);
131      }
132    }
133
134    return new LDAPAttributeSet(subset);
135  }
136
137
138
139  /**
140   * Retrieves the attribute from this set whose name exactly matches the
141   * provided name.
142   *
143   * @param  attrName  The name of the attribute to retrieve.
144   *
145   * @return  The requested attribute, or {@code null} if there is no such
146   *          attribute in this set.
147   */
148  public LDAPAttribute getAttribute(final String attrName)
149  {
150    for (final LDAPAttribute a : attributes)
151    {
152      if (a.getName().equalsIgnoreCase(attrName))
153      {
154        return a;
155      }
156    }
157
158    return null;
159  }
160
161
162
163  /**
164   * Retrieves the attribute with the specified base name and the specified
165   * language subtype.
166   *
167   * @param  attrName  The base name for the attribute to retrieve.
168   * @param  lang      The language subtype to retrieve, or {@code null} if
169   *                   there should not be a language subtype.
170   *
171   * @return  The attribute with the specified base name and language subtype,
172   *          or {@code null} if there is no such attribute.
173   */
174  public LDAPAttribute getAttribute(final String attrName, final String lang)
175  {
176    if (lang == null)
177    {
178      return getAttribute(attrName);
179    }
180
181    final String lowerLang = StaticUtils.toLowerCase(lang);
182
183    for (final LDAPAttribute a : attributes)
184    {
185      if (a.getBaseName().equalsIgnoreCase(attrName))
186      {
187        final String[] subtypes = a.getSubtypes();
188        if (subtypes != null)
189        {
190          for (final String s : subtypes)
191          {
192            final String lowerOption = StaticUtils.toLowerCase(s);
193            if (lowerOption.equals(lowerLang) ||
194                lowerOption.startsWith(lang + '-'))
195            {
196              return a;
197            }
198          }
199        }
200      }
201    }
202
203    return null;
204  }
205
206
207
208  /**
209   * Retrieves the attribute at the specified position in this attribute set.
210   *
211   * @param  index  The position of the attribute to retrieve.
212   *
213   * @return  The attribute at the specified position.
214   *
215   * @throws  IndexOutOfBoundsException  If the provided index invalid.
216   */
217  public LDAPAttribute elementAt(final int index)
218         throws IndexOutOfBoundsException
219  {
220    return attributes.get(index);
221  }
222
223
224
225  /**
226   * Adds the provided attribute to this attribute set.
227   *
228   * @param  attr  The attribute to be added to this set.
229   */
230  public void add(final LDAPAttribute attr)
231  {
232    for (final LDAPAttribute a : attributes)
233    {
234      if (attr.getName().equalsIgnoreCase(a.getName()))
235      {
236        for (final byte[] value : attr.getByteValueArray())
237        {
238          a.addValue(value);
239        }
240        return;
241      }
242    }
243
244    attributes.add(attr);
245  }
246
247
248
249  /**
250   * Removes the attribute with the specified name.
251   *
252   * @param  name  The name of the attribute to remove.
253   */
254  public void remove(final String name)
255  {
256    final Iterator<LDAPAttribute> iterator = attributes.iterator();
257    while (iterator.hasNext())
258    {
259      final LDAPAttribute a = iterator.next();
260      if (name.equalsIgnoreCase(a.getName()))
261      {
262        iterator.remove();
263        return;
264      }
265    }
266  }
267
268
269
270  /**
271   * Removes the attribute at the specified position in this attribute set.
272   *
273   * @param  index  The position of the attribute to remove.
274   *
275   * @throws  IndexOutOfBoundsException  If the provided index is invalid.
276   */
277  public void removeElementAt(final int index)
278         throws IndexOutOfBoundsException
279  {
280    attributes.remove(index);
281  }
282
283
284
285  /**
286   * Retrieves the number of attributes contained in this attribute set.
287   *
288   * @return  The number of attributes contained in this attribute set.
289   */
290  public int size()
291  {
292    return attributes.size();
293  }
294
295
296
297  /**
298   * Creates a duplicate of this attribute set.
299   *
300   * @return  A duplicate of this attribute set.
301   */
302  public LDAPAttributeSet duplicate()
303  {
304    return new LDAPAttributeSet(attributes);
305  }
306
307
308
309  /**
310   * Retrieves a string representation of this attribute set.
311   *
312   * @return  A string representation of this attribute set.
313   */
314  @Override()
315  public String toString()
316  {
317    return attributes.toString();
318  }
319}