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 2009-2010 Sun Microsystems, Inc.
025 *      Portions copyright 2012 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.ldap;
029
030import java.util.Collection;
031
032import org.forgerock.i18n.LocalizedIllegalArgumentException;
033
034/**
035 * An entry, comprising of a distinguished name and zero or more attributes.
036 * <p>
037 * Some methods require a schema in order to decode their parameters (e.g.
038 * {@link #addAttribute(String, Object...)} and {@link #setName(String)}). In
039 * these cases the default schema is used unless an alternative schema is
040 * specified in the {@code Entry} constructor. The default schema is not used
041 * for any other purpose. In particular, an {@code Entry} may contain attributes
042 * which have been decoded using different schemas.
043 * <p>
044 * When determining whether or not an entry already contains a particular
045 * attribute, attribute descriptions will be compared using
046 * {@link AttributeDescription#matches}.
047 * <p>
048 * Full LDAP modify semantics are provided via the {@link #addAttribute},
049 * {@link #removeAttribute}, and {@link #replaceAttribute} methods.
050 * <p>
051 * Implementations should specify any constraints or special behavior.
052 * Specifically:
053 * <ul>
054 * <li>Which methods are supported.
055 * <li>The order in which attributes are returned using the
056 * {@link #getAllAttributes()} method.
057 * <li>How existing attributes are modified during calls to
058 * {@link #addAttribute}, {@link #removeAttribute}, and
059 * {@link #replaceAttribute} and the conditions, if any, where a reference to
060 * the passed in attribute is maintained.
061 * </ul>
062 *
063 * @see Entries
064 */
065public interface Entry {
066
067    /**
068     * Ensures that this entry contains the provided attribute and values
069     * (optional operation). This method has the following semantics:
070     * <ul>
071     * <li>If this entry does not already contain an attribute with a
072     * {@link AttributeDescription#matches matching} attribute description, then
073     * this entry will be modified such that it contains {@code attribute}, even
074     * if it is empty.
075     * <li>If this entry already contains an attribute with a
076     * {@link AttributeDescription#matches matching} attribute description, then
077     * the attribute values contained in {@code attribute} will be merged with
078     * the existing attribute values.
079     * </ul>
080     * <p>
081     * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
082     * LDAP Modify add semantics.
083     *
084     * @param attribute
085     *            The attribute values to be added to this entry, merging with
086     *            any existing attribute values.
087     * @return {@code true} if this entry changed as a result of this call.
088     * @throws UnsupportedOperationException
089     *             If this entry does not permit attributes or their values to
090     *             be added.
091     * @throws NullPointerException
092     *             If {@code attribute} was {@code null}.
093     */
094    boolean addAttribute(Attribute attribute);
095
096    /**
097     * Ensures that this entry contains the provided attribute and values
098     * (optional operation). This method has the following semantics:
099     * <ul>
100     * <li>If this entry does not already contain an attribute with a
101     * {@link AttributeDescription#matches matching} attribute description, then
102     * this entry will be modified such that it contains {@code attribute}, even
103     * if it is empty.
104     * <li>If this entry already contains an attribute with a
105     * {@link AttributeDescription#matches matching} attribute description, then
106     * the attribute values contained in {@code attribute} will be merged with
107     * the existing attribute values.
108     * </ul>
109     * <p>
110     * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
111     * LDAP Modify add semantics.
112     *
113     * @param attribute
114     *            The attribute values to be added to this entry, merging with
115     *            any existing attribute values.
116     * @param duplicateValues
117     *            A collection into which duplicate values will be added, or
118     *            {@code null} if duplicate values should not be saved.
119     * @return {@code true} if this entry changed as a result of this call.
120     * @throws UnsupportedOperationException
121     *             If this entry does not permit attributes or their values to
122     *             be added.
123     * @throws NullPointerException
124     *             If {@code attribute} was {@code null}.
125     */
126    boolean addAttribute(Attribute attribute, Collection<? super ByteString> duplicateValues);
127
128    /**
129     * Ensures that this entry contains the provided attribute and values
130     * (optional operation). This method has the following semantics:
131     * <ul>
132     * <li>If this entry does not already contain an attribute with a
133     * {@link AttributeDescription#matches matching} attribute description, then
134     * this entry will be modified such that it contains {@code attribute}, even
135     * if it is empty.
136     * <li>If this entry already contains an attribute with a
137     * {@link AttributeDescription#matches matching} attribute description, then
138     * the attribute values contained in {@code attribute} will be merged with
139     * the existing attribute values.
140     * </ul>
141     * <p>
142     * The attribute description will be decoded using the schema associated
143     * with this entry (usually the default schema).
144     * <p>
145     * Any attribute values which are not instances of {@code ByteString} will
146     * be converted using the {@link ByteString#valueOf(Object)} method.
147     * <p>
148     * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
149     * LDAP Modify add semantics.
150     *
151     * @param attributeDescription
152     *            The name of the attribute whose values are to be added.
153     * @param values
154     *            The attribute values to be added to this entry, merging any
155     *            existing attribute values.
156     * @return This entry.
157     * @throws LocalizedIllegalArgumentException
158     *             If {@code attributeDescription} could not be decoded using
159     *             the schema associated with this entry.
160     * @throws UnsupportedOperationException
161     *             If this entry does not permit attributes or their values to
162     *             be added.
163     * @throws NullPointerException
164     *             If {@code attributeDescription} was {@code null}.
165     */
166    Entry addAttribute(String attributeDescription, Object... values);
167
168    /**
169     * Removes all the attributes from this entry (optional operation).
170     *
171     * @return This entry.
172     * @throws UnsupportedOperationException
173     *             If this entry does not permit attributes to be removed.
174     */
175    Entry clearAttributes();
176
177    /**
178     * Returns {@code true} if this entry contains all of the attribute values
179     * contained in {@code attribute}. If {@code attribute} is empty then this
180     * method will return {@code true} if the attribute is present in this
181     * entry, regardless of how many values it contains.
182     *
183     * @param attribute
184     *            The attribute values whose presence in this entry is to be
185     *            tested.
186     * @param missingValues
187     *            A collection into which missing values will be added, or
188     *            {@code null} if missing values should not be saved.
189     * @return {@code true} if this entry contains all of the attribute values
190     *         contained in {@code attribute}.
191     * @throws NullPointerException
192     *             If {@code attribute} was {@code null}.
193     */
194    boolean containsAttribute(Attribute attribute, Collection<? super ByteString> missingValues);
195
196    /**
197     * Returns {@code true} if this entry contains all of the attribute values
198     * contained in {@code values}. If {@code values} is {@code null} or empty
199     * then this method will return {@code true} if the attribute is present in
200     * this entry, regardless of how many values it contains.
201     * <p>
202     * The attribute description will be decoded using the schema associated
203     * with this entry (usually the default schema).
204     * <p>
205     * Any attribute values which are not instances of {@code ByteString} will
206     * be converted using the {@link ByteString#valueOf(Object)} method.
207     *
208     * @param attributeDescription
209     *            The name of the attribute whose presence in this entry is to
210     *            be tested.
211     * @param values
212     *            The attribute values whose presence in this entry is to be
213     *            tested, which may be {@code null}.
214     * @return {@code true} if this entry contains all of the attribute values
215     *         contained in {@code values}.
216     * @throws LocalizedIllegalArgumentException
217     *             If {@code attributeDescription} could not be decoded using
218     *             the schema associated with this entry.
219     * @throws NullPointerException
220     *             If {@code attributeDescription} was {@code null}.
221     */
222    boolean containsAttribute(String attributeDescription, Object... values);
223
224    /**
225     * Returns {@code true} if {@code object} is an entry which is equal to this
226     * entry. Two entries are considered equal if their distinguished names are
227     * equal, they both have the same number of attributes, and every attribute
228     * contained in the first entry is also contained in the second entry.
229     *
230     * @param object
231     *            The object to be tested for equality with this entry.
232     * @return {@code true} if {@code object} is an entry which is equal to this
233     *         entry, or {@code false} if not.
234     */
235    boolean equals(Object object);
236
237    /**
238     * Returns an {@code Iterable} containing all of the attributes in this
239     * entry. The returned {@code Iterable} may be used to remove attributes if
240     * permitted by this entry.
241     *
242     * @return An {@code Iterable} containing all of the attributes.
243     */
244    Iterable<Attribute> getAllAttributes();
245
246    /**
247     * Returns an {@code Iterable} containing all the attributes in this entry
248     * having an attribute description which is a sub-type of the provided
249     * attribute description. The returned {@code Iterable} may be used to
250     * remove attributes if permitted by this entry.
251     *
252     * @param attributeDescription
253     *            The name of the attributes to be returned.
254     * @return An {@code Iterable} containing the matching attributes.
255     * @throws NullPointerException
256     *             If {@code attributeDescription} was {@code null}.
257     */
258    Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription);
259
260    /**
261     * Returns an {@code Iterable} containing all the attributes in this entry
262     * having an attribute description which is a sub-type of the provided
263     * attribute description. The returned {@code Iterable} may be used to
264     * remove attributes if permitted by this entry.
265     * <p>
266     * The attribute description will be decoded using the schema associated
267     * with this entry (usually the default schema).
268     *
269     * @param attributeDescription
270     *            The name of the attributes to be returned.
271     * @return An {@code Iterable} containing the matching attributes.
272     * @throws LocalizedIllegalArgumentException
273     *             If {@code attributeDescription} could not be decoded using
274     *             the schema associated with this entry.
275     * @throws NullPointerException
276     *             If {@code attributeDescription} was {@code null}.
277     */
278    Iterable<Attribute> getAllAttributes(String attributeDescription);
279
280    /**
281     * Returns the named attribute contained in this entry, or {@code null} if
282     * it is not included with this entry.
283     *
284     * @param attributeDescription
285     *            The name of the attribute to be returned.
286     * @return The named attribute, or {@code null} if it is not included with
287     *         this entry.
288     * @throws NullPointerException
289     *             If {@code attributeDescription} was {@code null}.
290     */
291    Attribute getAttribute(AttributeDescription attributeDescription);
292
293    /**
294     * Returns the named attribute contained in this entry, or {@code null} if
295     * it is not included with this entry.
296     * <p>
297     * The attribute description will be decoded using the schema associated
298     * with this entry (usually the default schema).
299     *
300     * @param attributeDescription
301     *            The name of the attribute to be returned.
302     * @return The named attribute, or {@code null} if it is not included with
303     *         this entry.
304     * @throws LocalizedIllegalArgumentException
305     *             If {@code attributeDescription} could not be decoded using
306     *             the schema associated with this entry.
307     * @throws NullPointerException
308     *             If {@code attributeDescription} was {@code null}.
309     */
310    Attribute getAttribute(String attributeDescription);
311
312    /**
313     * Returns the number of attributes in this entry.
314     *
315     * @return The number of attributes.
316     */
317    int getAttributeCount();
318
319    /**
320     * Returns the string representation of the distinguished name of this
321     * entry.
322     *
323     * @return The string representation of the distinguished name.
324     */
325    DN getName();
326
327    /**
328     * Returns the hash code for this entry. It will be calculated as the sum of
329     * the hash codes of the distinguished name and all of the attributes.
330     *
331     * @return The hash code for this entry.
332     */
333    int hashCode();
334
335    /**
336     * Returns a parser for the named attribute contained in this entry.
337     *
338     * @param attributeDescription
339     *            The name of the attribute to be parsed.
340     * @return A parser for the named attribute.
341     * @throws NullPointerException
342     *             If {@code attributeDescription} was {@code null}.
343     */
344    AttributeParser parseAttribute(AttributeDescription attributeDescription);
345
346    /**
347     * Returns a parser for the named attribute contained in this entry.
348     * <p>
349     * The attribute description will be decoded using the schema associated
350     * with this entry (usually the default schema).
351     *
352     * @param attributeDescription
353     *            The name of the attribute to be parsed.
354     * @return A parser for the named attribute.
355     * @throws LocalizedIllegalArgumentException
356     *             If {@code attributeDescription} could not be decoded using
357     *             the schema associated with this entry.
358     * @throws NullPointerException
359     *             If {@code attributeDescription} was {@code null}.
360     */
361    AttributeParser parseAttribute(String attributeDescription);
362
363    /**
364     * Removes all of the attribute values contained in {@code attribute} from
365     * this entry if it is present (optional operation). If {@code attribute} is
366     * empty then the entire attribute will be removed if it is present.
367     * <p>
368     * <b>NOTE:</b> This method implements LDAP Modify delete semantics.
369     *
370     * @param attribute
371     *            The attribute values to be removed from this entry, which may
372     *            be empty if the entire attribute is to be removed.
373     * @param missingValues
374     *            A collection into which missing values will be added, or
375     *            {@code null} if missing values should not be saved.
376     * @return {@code true} if this entry changed as a result of this call.
377     * @throws UnsupportedOperationException
378     *             If this entry does not permit attributes or their values to
379     *             be removed.
380     * @throws NullPointerException
381     *             If {@code attribute} was {@code null}.
382     */
383    boolean removeAttribute(Attribute attribute, Collection<? super ByteString> missingValues);
384
385    /**
386     * Removes the named attribute from this entry if it is present (optional
387     * operation). If this attribute does not contain the attribute, the call
388     * leaves this entry unchanged and returns {@code false}.
389     *
390     * @param attributeDescription
391     *            The name of the attribute to be removed.
392     * @return {@code true} if this entry changed as a result of this call.
393     * @throws UnsupportedOperationException
394     *             If this entry does not permit attributes to be removed.
395     * @throws NullPointerException
396     *             If {@code attributeDescription} was {@code null}.
397     */
398    boolean removeAttribute(AttributeDescription attributeDescription);
399
400    /**
401     * Removes all of the attribute values contained in {@code values} from the
402     * named attribute in this entry if it is present (optional operation). If
403     * {@code values} is {@code null} or empty then the entire attribute will be
404     * removed if it is present.
405     * <p>
406     * The attribute description will be decoded using the schema associated
407     * with this entry (usually the default schema).
408     * <p>
409     * Any attribute values which are not instances of {@code ByteString} will
410     * be converted using the {@link ByteString#valueOf(Object)} method.
411     * <p>
412     * <b>NOTE:</b> This method implements LDAP Modify delete semantics.
413     *
414     * @param attributeDescription
415     *            The name of the attribute whose values are to be removed.
416     * @param values
417     *            The attribute values to be removed from this entry, which may
418     *            be {@code null} or empty if the entire attribute is to be
419     *            removed.
420     * @return This entry.
421     * @throws LocalizedIllegalArgumentException
422     *             If {@code attributeDescription} could not be decoded using
423     *             the schema associated with this entry.
424     * @throws UnsupportedOperationException
425     *             If this entry does not permit attributes or their values to
426     *             be removed.
427     * @throws NullPointerException
428     *             If {@code attributeDescription} was {@code null}.
429     */
430    Entry removeAttribute(String attributeDescription, Object... values);
431
432    /**
433     * Adds all of the attribute values contained in {@code attribute} to this
434     * entry, replacing any existing attribute values (optional operation). If
435     * {@code attribute} is empty then the entire attribute will be removed if
436     * it is present.
437     * <p>
438     * <b>NOTE:</b> This method implements LDAP Modify replace semantics as
439     * described in <a href="http://tools.ietf.org/html/rfc4511#section-4.6"
440     * >RFC 4511 - Section 4.6. Modify Operation</a>.
441     *
442     * @param attribute
443     *            The attribute values to be added to this entry, replacing any
444     *            existing attribute values, and which may be empty if the
445     *            entire attribute is to be removed.
446     * @return {@code true} if this entry changed as a result of this call.
447     * @throws UnsupportedOperationException
448     *             If this entry does not permit attributes or their values to
449     *             be replaced.
450     * @throws NullPointerException
451     *             If {@code attribute} was {@code null}.
452     */
453    boolean replaceAttribute(Attribute attribute);
454
455    /**
456     * Adds all of the attribute values contained in {@code values} to this
457     * entry, replacing any existing attribute values (optional operation). If
458     * {@code values} is {@code null} or empty then the entire attribute will be
459     * removed if it is present.
460     * <p>
461     * The attribute description will be decoded using the schema associated
462     * with this entry (usually the default schema).
463     * <p>
464     * Any attribute values which are not instances of {@code ByteString} will
465     * be converted using the {@link ByteString#valueOf(Object)} method.
466     * <p>
467     * <b>NOTE:</b> This method implements LDAP Modify replace semantics as
468     * described in <a href="http://tools.ietf.org/html/rfc4511#section-4.6"
469     * >RFC 4511 - Section 4.6. Modify Operation</a>.
470     *
471     * @param attributeDescription
472     *            The name of the attribute whose values are to be replaced.
473     * @param values
474     *            The attribute values to be added to this entry, replacing any
475     *            existing attribute values, and which may be {@code null} or
476     *            empty if the entire attribute is to be removed.
477     * @return This entry.
478     * @throws LocalizedIllegalArgumentException
479     *             If {@code attributeDescription} could not be decoded using
480     *             the schema associated with this entry.
481     * @throws UnsupportedOperationException
482     *             If this entry does not permit attributes or their values to
483     *             be replaced.
484     * @throws NullPointerException
485     *             If {@code attribute} was {@code null}.
486     */
487    Entry replaceAttribute(String attributeDescription, Object... values);
488
489    /**
490     * Sets the distinguished name of this entry (optional operation).
491     *
492     * @param dn
493     *            The distinguished name.
494     * @return This entry.
495     * @throws UnsupportedOperationException
496     *             If this entry does not permit the distinguished name to be
497     *             set.
498     * @throws NullPointerException
499     *             If {@code dn} was {@code null}.
500     */
501    Entry setName(DN dn);
502
503    /**
504     * Sets the distinguished name of this entry (optional operation).
505     * <p>
506     * The distinguished name will be decoded using the schema associated with
507     * this entry (usually the default schema).
508     *
509     * @param dn
510     *            The string representation of the distinguished name.
511     * @return This entry.
512     * @throws LocalizedIllegalArgumentException
513     *             If {@code dn} could not be decoded using the schema
514     *             associated with this entry.
515     * @throws UnsupportedOperationException
516     *             If this entry does not permit the distinguished name to be
517     *             set.
518     * @throws NullPointerException
519     *             If {@code dn} was {@code null}.
520     */
521    Entry setName(String dn);
522
523    /**
524     * Returns a string representation of this entry.
525     *
526     * @return The string representation of this entry.
527     */
528    String toString();
529}