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