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