001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: AttrSet.java,v 1.4 2009/01/28 05:34:49 ww203982 Exp $
026 *
027 */
028
029/**
030 * Portions Copyrighted [2011] [ForgeRock AS]
031 */
032package com.iplanet.services.ldap;
033
034import java.util.ArrayList;
035import java.util.Enumeration;
036import java.util.Iterator;
037
038import com.sun.identity.shared.ldap.LDAPAttributeSet;
039
040/**
041 * Represents a set of attributes
042 * @supported.api
043 */
044public class AttrSet implements java.io.Serializable, java.lang.Cloneable {
045
046    private ArrayList _attrs = new ArrayList();
047
048    /**
049     * Empty Attribute Set.
050     * @supported.api
051     */
052    public static final AttrSet EMPTY_ATTR_SET = new AttrSet();
053
054    /**
055     * No argument constructor
056     * @supported.api
057     */
058    public AttrSet() {
059    }
060
061    /**
062     * Construct attribute set given an array of attributes.
063     * 
064     * @param attrs
065     *            array of attributes to be defined in the attribute set
066     * @supported.api
067     */
068    public AttrSet(Attr[] attrs) {
069        int size = attrs.length;
070        _attrs = new ArrayList(size);
071        for (int i = 0; i < size; i++) {
072            _attrs.add(attrs[i]);
073        }
074    }
075
076    /**
077     * Construct attribute set given an attribute
078     * 
079     * @param attr
080     *            attribute to be defined in the attribute set
081     * @supported.api
082     */
083    public AttrSet(Attr attr) {
084        add(attr);
085    }
086
087    /**
088     * Construct AttrSet from LDAPAttributeSet
089     * 
090     * @param ldapAttrSet
091     *            LDAP attribute set
092     * 
093     */
094    public AttrSet(LDAPAttributeSet ldapAttrSet) {
095        int size = ldapAttrSet.size();
096        _attrs = new ArrayList(size);
097        for (int i = 0; i < size; i++) {
098            _attrs.add(new Attr(ldapAttrSet.elementAt(i)));
099        }
100    }
101
102    /**
103     * Add one attribute to the AttrSet The attribute
104     * should have only string values
105     * 
106     * @param attr
107     *            attribute to be added to the set
108     * @supported.api
109     */
110    public void add(Attr attr) {
111        if (attr == null)
112            return;
113        Attr attr1 = findAttribute(attr.getName());
114        if (attr1 == null) {
115            _attrs.add(attr);
116        } else {
117            // attribute already exists,
118            // add new values to existing attribute
119            attr1.addValues(attr.getStringValues());
120        }
121    }
122
123    /**
124     * Add one attribute to the AttrSet The attribute
125     * should have only byte values
126     * 
127     * @param attr
128     *            attribute to be added to the set
129     * @supported.api
130     */
131    public void addBinaryAttr(Attr attr) {
132        Attr attr1 = findAttribute(attr.getName());
133        if (attr1 == null) {
134            _attrs.add(attr);
135        } else {
136            // attribute already exists,
137            // add new values to existing attribute
138            attr1.addValues(attr.getByteValues());
139        }
140    }
141
142    /**
143     * Removes an exisiting attribute
144     * 
145     * @param name
146     *            attribute to be removed
147     * @supported.api
148     */
149    public void remove(String name) {
150        int index = indexOf(name);
151        if (index != -1) {
152            _attrs.remove(index);
153        }
154    }
155
156    /**
157     * Remove a specified value for an attribute in the
158     * set
159     * 
160     * @param attrName
161     *            attribute name to be looked up
162     * @param delValue
163     *            value to be deleted for the specified attribute
164     * @supported.api
165     */
166    public void remove(String attrName, String delValue) {
167        int index = indexOf(attrName);
168        if (index != -1) {
169            Attr attr = (Attr) _attrs.get(index);
170            attr.removeValue(delValue);
171            if (attr.size() == 0) {
172                _attrs.remove(index);
173            }
174        }
175    }
176
177    /**
178     * Replace an existing attribute.
179     * 
180     * @param attr
181     *            attribute to be replaced
182     * @supported.api
183     */
184    public void replace(Attr attr) {
185        int index = indexOf(attr.getName());
186        if (index != -1) {
187            _attrs.set(index, attr);
188        } else {
189            _attrs.add(attr);
190        }
191    }
192
193    /**
194     * Get names of attributes.
195     * 
196     * @return Names of attributes in the set
197     * @supported.api
198     */
199    public String[] getAttributeNames() {
200        int size = size();
201        String[] names = new String[size];
202        for (int i = 0; i < size; i++) {
203            names[i] = ((Attr) _attrs.get(i)).getName();
204        }
205        return names;
206    }
207
208    /**
209     * Gets the attribute contained in the set. If not
210     * found returns null object
211     * 
212     * @param name
213     *            name of the attribute to get
214     * @return attribute found
215     * @supported.api
216     */
217    public Attr getAttribute(String name) {
218        // We may probably want to clone. Not cloning now.
219        return findAttribute(name);
220    }
221
222    /**
223     * Enumerate the attributes contained in the attribute
224     * set
225     * 
226     * @return enmeration of attributes in the set
227     * @supported.api
228     */
229    public Enumeration getAttributes() {
230        // iterator would be preferred; returning Enumeration for backward
231        // compatibility
232        return new IterEnumeration(_attrs.iterator());
233    }
234
235    /**
236     * Gets the first string value right from a specified
237     * attribute
238     * 
239     * @param attrName
240     *            name of the attribute to be queried in the set
241     * @return the first string value found
242     * @supported.api
243     */
244    public String getValue(String attrName) {
245        String value = null;
246        Attr attr = findAttribute(attrName);
247        if (attr != null) {
248            value = attr.getValue();
249        }
250        return value;
251    }
252
253    /**
254     * Check if attrSet has this attribute
255     * 
256     * @param attrName
257     *            name of the attribute to be checked against the set
258     * @return true if found and false otherwise
259     * @supported.api
260     */
261    public boolean contains(String attrName) {
262        boolean containsTheValue = false;
263        int index = indexOf(attrName);
264        if (index != -1) {
265            containsTheValue = true;
266        }
267        return containsTheValue;
268    }
269
270    /**
271     * Check if this attrSet has the attribute with the
272     * given value
273     * 
274     * @param attrName
275     *            name of the attribute to be checked against the set
276     * @param value
277     *            value of the attribute the attribute should contain
278     * @return true if found and false otherwise
279     * @supported.api
280     */
281    public boolean contains(String attrName, String value) {
282        boolean containsTheValue = false;
283        Attr attr = findAttribute(attrName);
284        if (attr != null) {
285            containsTheValue = attr.contains(value);
286        }
287        return containsTheValue;
288    }
289
290    /**
291     * Get the number of attributes in the Attribute Set
292     * 
293     * @return number of attributes in the set
294     * @supported.api
295     */
296    public int size() {
297        return _attrs.size();
298    }
299
300    /**
301     * Get the attribute at an index that starts from 0
302     * 
303     * @return the attribute at the given index
304     */
305    public Attr elementAt(int index) {
306        return (Attr) _attrs.get(index);
307    }
308
309    /**
310     * Gets the index for an attribute contained in the set
311     * 
312     * @return index that is zero based. If attrName is not found in the set,
313     *         this method returns -1.
314     */
315    public int indexOf(String attrName) {
316        attrName = attrName.toLowerCase();
317        int index = -1;
318        int size = _attrs.size();
319        for (int i = 0; i < size; i++) {
320            if (attrName.equals(((Attr) _attrs.get(i)).getName())) {
321                index = i;
322                break;
323            }
324        }
325        return index;
326    }
327
328    /**
329     * Find the attribute gvien the attribute name
330     * 
331     * @return attribute found, returns null if no such attribute exists
332     */
333    private Attr findAttribute(String name) {
334        name = name.toLowerCase();
335        Attr attr = null;
336        if (_attrs != null) {
337            int size = _attrs.size();
338            for (int i = 0; i < size; i++) {
339                Attr attr1 = (Attr) _attrs.get(i);
340                if (attr1.getName().equals(name)) {
341                    attr = attr1;
342                    break;
343                }
344            }
345        }
346        return attr;
347    }
348
349    /**
350     * Return a copy of the object
351     * 
352     * @return A copy of the object
353     * @supported.api
354     */
355    public Object clone() {
356        AttrSet attrSet = new AttrSet();
357        int size = _attrs.size();
358        for (int i = 0; i < size; i++) {
359            attrSet.add((Attr) ((Attr) _attrs.get(i)).clone());
360        }
361        return attrSet;
362    }
363
364    /**
365     * Maps to an LDAPAttributeSet
366     * 
367     * @return the equivalent LDAPAttributeSet
368     */
369    public LDAPAttributeSet toLDAPAttributeSet() {
370        LDAPAttributeSet ldapAttrSet = new LDAPAttributeSet();
371        int size = size();
372        for (int i = 0; i < size; i++) {
373            Attr attr = (Attr) _attrs.get(i);
374            if (attr.size() > 0) {
375                ldapAttrSet.add(attr.toLDAPAttribute());
376            }
377        }
378        return ldapAttrSet;
379    }
380
381    /**
382     * Retrieves the string representation of an AttrSet
383     * 
384     * @return string representation of the AttrSet.
385     * @supported.api
386     */
387    public String toString() {
388        StringBuilder sb = new StringBuilder("AttrSet: ");
389        int size = _attrs.size();
390        for (int i = 0; i < size; i++) {
391            sb.append(_attrs.get(i).toString()).append("\n");
392        }
393        return sb.toString();
394    }
395
396}
397
398class IterEnumeration implements Enumeration {
399
400    private Iterator _iter;
401
402    IterEnumeration(Iterator iterator) {
403        _iter = iterator;
404    }
405
406    public boolean hasMoreElements() {
407        return _iter.hasNext();
408    }
409
410    public Object nextElement() {
411        return _iter.next();
412    }
413
414}