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