001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2015 ForgeRock AS
026 */
027package org.opends.server.protocols.ldap;
028
029import static org.opends.messages.ProtocolMessages.*;
030import static org.opends.server.util.CollectionUtils.*;
031import static org.opends.server.util.ServerConstants.*;
032
033import java.util.ArrayList;
034import java.util.Iterator;
035import java.util.List;
036
037import org.forgerock.i18n.LocalizableMessage;
038import org.forgerock.opendj.ldap.ByteString;
039import org.opends.server.types.Attribute;
040import org.opends.server.types.AttributeBuilder;
041import org.opends.server.types.LDAPException;
042import org.opends.server.types.RawAttribute;
043
044/**
045 * This class defines the data structures and methods to use when interacting
046 * with an LDAP attribute, which is the basic unit of information in an LDAP
047 * entry.
048 */
049public class LDAPAttribute
050       extends RawAttribute
051{
052  /** The set of values for this attribute. */
053  private List<ByteString> values;
054
055  /** The attribute type for this attribute. */
056  private String attributeType;
057
058
059
060  /**
061   * Creates a new LDAP attribute with the provided type and no values.
062   *
063   * @param  attributeType  The attribute type for this attribute.
064   */
065  public LDAPAttribute(String attributeType)
066  {
067    this.attributeType = attributeType;
068
069    values = new ArrayList<>(0);
070  }
071
072
073
074  /**
075   * Creates a new LDAP attribute with the provided type and no values.
076   *
077   * @param  attributeType  The attribute type for this attribute.
078   * @param  value          The value to use for this attribute.
079   */
080  public LDAPAttribute(String attributeType, String value)
081  {
082    this.attributeType = attributeType;
083
084    values = newArrayList(ByteString.valueOfUtf8(value));
085  }
086
087
088
089  /**
090   * Creates a new LDAP attribute with the provided type and no values.
091   *
092   * @param  attributeType  The attribute type for this attribute.
093   * @param  value          The value to use for this attribute.
094   */
095  public LDAPAttribute(String attributeType, ByteString value)
096  {
097    this.attributeType = attributeType;
098
099    values = newArrayList(value);
100  }
101
102
103
104  /**
105   * Creates a new LDAP attribute with the provided type and values.
106   *
107   * @param  attributeType  The attribute type for this attribute.
108   * @param  values         The set of values for this attribute.
109   */
110  public LDAPAttribute(String attributeType, List<String> values)
111  {
112    this.attributeType = attributeType;
113
114    if (values == null)
115    {
116      this.values = new ArrayList<>(0);
117    }
118    else
119    {
120      this.values = new ArrayList<>(values.size());
121      for (String value : values)
122      {
123        this.values.add(ByteString.valueOfUtf8(value));
124      }
125    }
126  }
127
128
129
130  /**
131   * Creates a new LDAP attribute with the provided type and values.
132   *
133   * @param  attributeType  The attribute type for this attribute.
134   * @param  values         The set of values for this attribute.
135   */
136  public LDAPAttribute(String attributeType, ArrayList<ByteString> values)
137  {
138    this.attributeType = attributeType;
139
140    if (values == null)
141    {
142      this.values = new ArrayList<>(0);
143    }
144    else
145    {
146      this.values = values;
147    }
148  }
149
150
151
152  /**
153   * Creates a new LDAP attribute from the provided attribute.
154   *
155   * @param  attribute  The attribute to use to create this LDAP attribute.
156   */
157  public LDAPAttribute(Attribute attribute)
158  {
159    this.attributeType = attribute.getNameWithOptions();
160
161    if (attribute.isVirtual())
162    {
163      values = new ArrayList<>();
164    }
165    else if (attribute.isEmpty())
166    {
167      values = new ArrayList<>(0);
168      return;
169    }
170    else
171    {
172      values = new ArrayList<>(attribute.size());
173    }
174
175    for (ByteString v : attribute)
176    {
177      values.add(v);
178    }
179  }
180
181
182
183  /**
184   * Retrieves the attribute type for this attribute.
185   *
186   * @return  The attribute type for this attribute.
187   */
188  @Override
189  public String getAttributeType()
190  {
191    return attributeType;
192  }
193
194
195
196  /**
197   * Specifies the attribute type for this attribute.
198   *
199   * @param  attributeType  The attribute type for this attribute.
200   */
201  @Override
202  public void setAttributeType(String attributeType)
203  {
204    this.attributeType = attributeType;
205  }
206
207
208
209  /**
210   * Retrieves the set of values for this attribute.  The returned list may be
211   * modified by the caller.
212   *
213   * @return  The set of values for this attribute.
214   */
215  @Override
216  public List<ByteString> getValues()
217  {
218    return values;
219  }
220
221
222
223  /**
224   * Retrieves a core attribute containing the information for this LDAP
225   * attribute.
226   *
227   * @return  A core attribute containing the information for this LDAP
228   *          attribute.
229   *
230   * @throws  LDAPException  If the provided value is invalid according to the
231   *                         attribute syntax.
232   */
233  @Override
234  public Attribute toAttribute()
235         throws LDAPException
236  {
237    AttributeBuilder builder;
238    int semicolonPos = attributeType.indexOf(';');
239    if (semicolonPos > 0)
240    {
241      builder = new AttributeBuilder(attributeType.substring(0, semicolonPos));
242      int nextPos = attributeType.indexOf(';', semicolonPos+1);
243      while (nextPos > 0)
244      {
245        String option = attributeType.substring(semicolonPos+1, nextPos);
246        if (option.length() > 0)
247        {
248          builder.setOption(option);
249        }
250
251        semicolonPos = nextPos;
252        nextPos = attributeType.indexOf(';', semicolonPos+1);
253      }
254
255      String option = attributeType.substring(semicolonPos+1);
256      if (option.length() > 0)
257      {
258        builder.setOption(option);
259      }
260    }
261    else
262    {
263      builder = new AttributeBuilder(attributeType);
264    }
265
266    for (ByteString value : values)
267    {
268      if (!builder.add(value))
269      {
270        LocalizableMessage message =
271            ERR_LDAP_ATTRIBUTE_DUPLICATE_VALUES.get(attributeType);
272        throw new LDAPException(
273                LDAPResultCode.ATTRIBUTE_OR_VALUE_EXISTS, message);
274      }
275    }
276
277    return builder.toAttribute();
278  }
279
280
281
282  /**
283   * Retrieves a string representation of this attribute.
284   *
285   * @return  A string representation of this attribute.
286   */
287  @Override
288  public String toString()
289  {
290    StringBuilder buffer = new StringBuilder();
291    toString(buffer);
292    return buffer.toString();
293  }
294
295
296
297  /**
298   * Appends a string representation of this attribute to the provided buffer.
299   *
300   * @param  buffer  The buffer to which the information should be appended.
301   */
302  @Override
303  public void toString(StringBuilder buffer)
304  {
305    buffer.append("LDAPAttribute(type=");
306    buffer.append(attributeType);
307    buffer.append(", values={");
308
309    if (! values.isEmpty())
310    {
311      Iterator<ByteString> iterator = values.iterator();
312      buffer.append(iterator.next());
313      while (iterator.hasNext())
314      {
315        buffer.append(", ");
316        buffer.append(iterator.next());
317      }
318    }
319
320    buffer.append("})");
321  }
322
323
324
325  /**
326   * Appends a multi-line string representation of this LDAP attribute to the
327   * provided buffer.
328   *
329   * @param  buffer  The buffer to which the information should be appended.
330   * @param  indent  The number of spaces from the margin that the lines should
331   *                 be indented.
332   */
333  @Override
334  public void toString(StringBuilder buffer, int indent)
335  {
336    StringBuilder indentBuf = new StringBuilder(indent);
337    for (int i=0 ; i < indent; i++)
338    {
339      indentBuf.append(' ');
340    }
341
342    buffer.append(indentBuf);
343    buffer.append("LDAP Attribute");
344    buffer.append(EOL);
345
346    buffer.append(indentBuf);
347    buffer.append("  Attribute Type:  ");
348    buffer.append(attributeType);
349    buffer.append(EOL);
350
351    buffer.append("  Attribute Values:");
352    buffer.append(EOL);
353
354    for (ByteString value : values)
355    {
356      buffer.append(value.toHexPlusAsciiString(indent+4));
357    }
358  }
359}
360