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 * Portions Copyrighted 2011-2015 ForgeRock AS.
028 */
029
030package com.iplanet.services.ldap;
031
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.Enumeration;
035import java.util.Iterator;
036
037import org.forgerock.opendj.ldap.Attribute;
038import org.forgerock.opendj.ldap.ByteString;
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(Collection<Attribute> ldapAttrSet) {
095        int size = ldapAttrSet.size();
096        _attrs = new ArrayList(size);
097        for (Attribute attribute : ldapAttrSet) {
098            Collection<byte[]> values = new ArrayList<>(attribute.size());
099            for (ByteString value : attribute) {
100                values.add(value.toByteArray());
101            }
102            _attrs.add(new Attr(attribute.getAttributeDescriptionAsString(), values.toArray(new byte[0][])));
103        }
104    }
105
106    /**
107     * Add one attribute to the AttrSet The attribute
108     * should have only string values
109     * 
110     * @param attr
111     *            attribute to be added to the set
112     * @supported.api
113     */
114    public void add(Attr attr) {
115        if (attr == null)
116            return;
117        Attr attr1 = findAttribute(attr.getName());
118        if (attr1 == null) {
119            _attrs.add(attr);
120        } else {
121            // attribute already exists,
122            // add new values to existing attribute
123            attr1.addValues(attr.getStringValues());
124        }
125    }
126
127    /**
128     * Add one attribute to the AttrSet The attribute
129     * should have only byte values
130     * 
131     * @param attr
132     *            attribute to be added to the set
133     * @supported.api
134     */
135    public void addBinaryAttr(Attr attr) {
136        Attr attr1 = findAttribute(attr.getName());
137        if (attr1 == null) {
138            _attrs.add(attr);
139        } else {
140            // attribute already exists,
141            // add new values to existing attribute
142            attr1.addValues(attr.getByteValues());
143        }
144    }
145
146    /**
147     * Removes an exisiting attribute
148     * 
149     * @param name
150     *            attribute to be removed
151     * @supported.api
152     */
153    public void remove(String name) {
154        int index = indexOf(name);
155        if (index != -1) {
156            _attrs.remove(index);
157        }
158    }
159
160    /**
161     * Remove a specified value for an attribute in the
162     * set
163     * 
164     * @param attrName
165     *            attribute name to be looked up
166     * @param delValue
167     *            value to be deleted for the specified attribute
168     * @supported.api
169     */
170    public void remove(String attrName, String delValue) {
171        int index = indexOf(attrName);
172        if (index != -1) {
173            Attr attr = (Attr) _attrs.get(index);
174            attr.removeValue(delValue);
175            if (attr.size() == 0) {
176                _attrs.remove(index);
177            }
178        }
179    }
180
181    /**
182     * Replace an existing attribute.
183     * 
184     * @param attr
185     *            attribute to be replaced
186     * @supported.api
187     */
188    public void replace(Attr attr) {
189        int index = indexOf(attr.getName());
190        if (index != -1) {
191            _attrs.set(index, attr);
192        } else {
193            _attrs.add(attr);
194        }
195    }
196
197    /**
198     * Get names of attributes.
199     * 
200     * @return Names of attributes in the set
201     * @supported.api
202     */
203    public String[] getAttributeNames() {
204        int size = size();
205        String[] names = new String[size];
206        for (int i = 0; i < size; i++) {
207            names[i] = ((Attr) _attrs.get(i)).getName();
208        }
209        return names;
210    }
211
212    /**
213     * Gets the attribute contained in the set. If not
214     * found returns null object
215     * 
216     * @param name
217     *            name of the attribute to get
218     * @return attribute found
219     * @supported.api
220     */
221    public Attr getAttribute(String name) {
222        // We may probably want to clone. Not cloning now.
223        return findAttribute(name);
224    }
225
226    /**
227     * Enumerate the attributes contained in the attribute
228     * set
229     * 
230     * @return enmeration of attributes in the set
231     * @supported.api
232     */
233    public Enumeration getAttributes() {
234        // iterator would be preferred; returning Enumeration for backward
235        // compatibility
236        return new IterEnumeration(_attrs.iterator());
237    }
238
239    /**
240     * Gets the first string value right from a specified
241     * attribute
242     * 
243     * @param attrName
244     *            name of the attribute to be queried in the set
245     * @return the first string value found
246     * @supported.api
247     */
248    public String getValue(String attrName) {
249        String value = null;
250        Attr attr = findAttribute(attrName);
251        if (attr != null) {
252            value = attr.getValue();
253        }
254        return value;
255    }
256
257    /**
258     * Check if attrSet has this attribute
259     * 
260     * @param attrName
261     *            name of the attribute to be checked against the set
262     * @return true if found and false otherwise
263     * @supported.api
264     */
265    public boolean contains(String attrName) {
266        boolean containsTheValue = false;
267        int index = indexOf(attrName);
268        if (index != -1) {
269            containsTheValue = true;
270        }
271        return containsTheValue;
272    }
273
274    /**
275     * Check if this attrSet has the attribute with the
276     * given value
277     * 
278     * @param attrName
279     *            name of the attribute to be checked against the set
280     * @param value
281     *            value of the attribute the attribute should contain
282     * @return true if found and false otherwise
283     * @supported.api
284     */
285    public boolean contains(String attrName, String value) {
286        boolean containsTheValue = false;
287        Attr attr = findAttribute(attrName);
288        if (attr != null) {
289            containsTheValue = attr.contains(value);
290        }
291        return containsTheValue;
292    }
293
294    /**
295     * Get the number of attributes in the Attribute Set
296     * 
297     * @return number of attributes in the set
298     * @supported.api
299     */
300    public int size() {
301        return _attrs.size();
302    }
303
304    /**
305     * Get the attribute at an index that starts from 0
306     * 
307     * @return the attribute at the given index
308     */
309    public Attr elementAt(int index) {
310        return (Attr) _attrs.get(index);
311    }
312
313    /**
314     * Gets the index for an attribute contained in the set
315     * 
316     * @return index that is zero based. If attrName is not found in the set,
317     *         this method returns -1.
318     */
319    public int indexOf(String attrName) {
320        attrName = attrName.toLowerCase();
321        int index = -1;
322        int size = _attrs.size();
323        for (int i = 0; i < size; i++) {
324            if (attrName.equals(((Attr) _attrs.get(i)).getName())) {
325                index = i;
326                break;
327            }
328        }
329        return index;
330    }
331
332    /**
333     * Find the attribute gvien the attribute name
334     * 
335     * @return attribute found, returns null if no such attribute exists
336     */
337    private Attr findAttribute(String name) {
338        name = name.toLowerCase();
339        Attr attr = null;
340        if (_attrs != null) {
341            int size = _attrs.size();
342            for (int i = 0; i < size; i++) {
343                Attr attr1 = (Attr) _attrs.get(i);
344                if (attr1.getName().equals(name)) {
345                    attr = attr1;
346                    break;
347                }
348            }
349        }
350        return attr;
351    }
352
353    /**
354     * Return a copy of the object
355     * 
356     * @return A copy of the object
357     * @supported.api
358     */
359    public Object clone() {
360        AttrSet attrSet = new AttrSet();
361        int size = _attrs.size();
362        for (int i = 0; i < size; i++) {
363            attrSet.add((Attr) ((Attr) _attrs.get(i)).clone());
364        }
365        return attrSet;
366    }
367
368    /**
369     * Maps to an LDAPAttributeSet
370     * 
371     * @return the equivalent LDAPAttributeSet
372     */
373    public Collection<Attribute> toLDAPAttributeSet() {
374        Collection<Attribute> ldapAttrSet = new ArrayList<>();
375        int size = size();
376        for (int i = 0; i < size; i++) {
377            Attr attr = (Attr) _attrs.get(i);
378            if (attr.size() > 0) {
379                ldapAttrSet.add(attr.toLDAPAttribute());
380            }
381        }
382        return ldapAttrSet;
383    }
384
385    /**
386     * Retrieves the string representation of an AttrSet
387     * 
388     * @return string representation of the AttrSet.
389     * @supported.api
390     */
391    public String toString() {
392        StringBuilder sb = new StringBuilder("AttrSet: ");
393        int size = _attrs.size();
394        for (int i = 0; i < size; i++) {
395            sb.append(_attrs.get(i).toString()).append("\n");
396        }
397        return sb.toString();
398    }
399
400}
401
402class IterEnumeration implements Enumeration {
403
404    private Iterator _iter;
405
406    IterEnumeration(Iterator iterator) {
407        _iter = iterator;
408    }
409
410    public boolean hasMoreElements() {
411        return _iter.hasNext();
412    }
413
414    public Object nextElement() {
415        return _iter.next();
416    }
417
418}