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