001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *  http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.directory.api.ldap.model.entry;
020
021
022import java.io.Externalizable;
023
024import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
025import org.apache.directory.api.ldap.model.schema.AttributeType;
026
027
028/**
029 * A generic interface used to store the LDAP Attributes.
030 *
031 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
032 */
033public interface Attribute extends Iterable<Value<?>>, Externalizable
034{
035    /**
036     * Adds some values to this attribute. If the new values are already present in
037     * the attribute values, the method has no effect.
038     * <p>
039     * The new values are added at the end of list of values.
040     * </p>
041     * <p>
042     * This method returns the number of values that were added.
043     * </p>
044     * <p>
045     * If the value's type is different from the attribute's type,
046     * a conversion is done. For instance, if we try to set some String
047     * into a Binary attribute, we just store the UTF-8 byte array 
048     * encoding for this String.
049     * </p>
050     * <p>
051     * If we try to store some byte[] in a HR attribute, we try to 
052     * convert those byte[] assuming they represent an UTF-8 encoded
053     * String. Of course, if it's not the case, the stored value will
054     * be incorrect.
055     * </p>
056     * <p>
057     * It's the responsibility of the caller to check if the stored
058     * values are consistent with the attribute's type.
059     * </p>
060     * <p>
061     * The caller can set the HR flag in order to enforce a type for 
062     * the current attribute, otherwise this type will be set while
063     * adding the first value, using the value's type to set the flag.
064     * </p>
065     *
066     * @param vals some new values to be added which may be null
067     * @return the number of added values, or 0 if none has been added
068     * @throws LdapInvalidAttributeValueException if some of the added values are not valid
069     */
070    int add( String... vals ) throws LdapInvalidAttributeValueException;
071
072
073    /**
074     * Adds some values to this attribute. If the new values are already present in
075     * the attribute values, the method has no effect.
076     * <p>
077     * The new values are added at the end of list of values.
078     * </p>
079     * <p>
080     * This method returns the number of values that were added.
081     * </p>
082     * If the value's type is different from the attribute's type,
083     * a conversion is done. For instance, if we try to set some String
084     * into a Binary attribute, we just store the UTF-8 byte array 
085     * encoding for this String.
086     * If we try to store some byte[] in a HR attribute, we try to 
087     * convert those byte[] assuming they represent an UTF-8 encoded
088     * String. Of course, if it's not the case, the stored value will
089     * be incorrect.
090     * <br>
091     * It's the responsibility of the caller to check if the stored
092     * values are consistent with the attribute's type.
093     * <br>
094     * The caller can set the HR flag in order to enforce a type for 
095     * the current attribute, otherwise this type will be set while
096     * adding the first value, using the value's type to set the flag.
097     *
098     * @param vals some new values to be added which may be null
099     * @return the number of added values, or 0 if none has been added
100     * @throws LdapInvalidAttributeValueException if some of the added values are not valid
101     */
102    int add( byte[]... vals ) throws LdapInvalidAttributeValueException;
103
104
105    /**
106     * Adds some values to this attribute. If the new values are already present in
107     * the attribute values, the method has no effect.
108     * <p>
109     * The new values are added at the end of list of values.
110     * </p>
111     * <p>
112     * This method returns the number of values that were added.
113     * </p>
114     * <p>
115     * If the value's type is different from the attribute's type,
116     * a conversion is done. For instance, if we try to set some 
117     * StringValue into a Binary attribute, we just store the UTF-8 
118     * byte array encoding for this StringValue.
119     * </p>
120     * <p>
121     * If we try to store some BinaryValue in a HR attribute, we try to 
122     * convert those BinaryValue assuming they represent an UTF-8 encoded
123     * String. Of course, if it's not the case, the stored value will
124     * be incorrect.
125     * </p>
126     * <p>
127     * It's the responsibility of the caller to check if the stored
128     * values are consistent with the attribute's type.
129     * </p>
130     * <p>
131     * The caller can set the HR flag in order to enforce a type for 
132     * the current attribute, otherwise this type will be set while
133     * adding the first value, using the value's type to set the flag.
134     * </p>
135     * <p>
136     * <b>Note : </b>If the entry contains no value, and the unique added value
137     * is a null length value, then this value will be considered as
138     * a binary value.
139     * </p>
140     * @param val some new values to be added which may be null
141     * @return the number of added values, or 0 if none has been added
142     * @throws LdapInvalidAttributeValueException if some of the added values are not valid
143     */
144    int add( Value<?>... val ) throws LdapInvalidAttributeValueException;
145
146
147    /**
148     * Remove all the values from this attribute.
149     */
150    void clear();
151
152
153    /**
154     * @return A clone of the current object
155     */
156    Attribute clone();
157
158
159    /**
160     * <p>
161     * Indicates whether the specified values are some of the attribute's values.
162     * </p>
163     * <p>
164     * If the Attribute is not HR, the values will be converted to byte[]
165     * </p>
166     *
167     * @param vals the values
168     * @return true if this attribute contains all the given values, otherwise false
169     */
170    boolean contains( String... vals );
171
172
173    /**
174     * <p>
175     * Indicates whether the specified values are some of the attribute's values.
176     * </p>
177     * <p>
178     * If the Attribute is HR, the values will be converted to String
179     * </p>
180     *
181     * @param vals the values
182     * @return true if this attribute contains all the given values, otherwise false
183     */
184    boolean contains( byte[]... vals );
185
186
187    /**
188     * <p>
189     * Indicates whether the specified values are some of the attribute's values.
190     * </p>
191     * <p>
192     * If the Attribute is HR, the binary values will be converted to String before
193     * being checked.
194     * </p>
195     *
196     * @param vals the values
197     * @return true if this attribute contains all the given values, otherwise false
198     */
199    boolean contains( Value<?>... vals );
200
201
202    /**
203     * Get the attribute type associated with this EntryAttribute.
204     *
205     * @return the attributeType associated with this entry attribute
206     */
207    AttributeType getAttributeType();
208
209
210    /**
211     * <p>
212     * Set the attribute type associated with this EntryAttribute.
213     * </p>
214     * <p>
215     * The current attributeType will be replaced. It is the responsibility of
216     * the caller to insure that the existing values are compatible with the new
217     * AttributeType
218     * </p>
219     *
220     * @param attributeType the attributeType associated with this entry attribute
221     * @throws LdapInvalidAttributeValueException if the contained values are not valid accordingly
222     * to the added AttributeType
223     */
224    void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException;
225
226
227    /**
228     * <p>
229     * Check if the current attribute type has the same type (or is a descendant of)
230     * than the given attributeType
231     *
232     * @param attributeType The AttributeType to check
233     * @return true if the current attribute is of the expected attributeType or a descendant of it
234     * @throws LdapInvalidAttributeValueException If there is no AttributeType
235     */
236    boolean isInstanceOf( AttributeType attributeType ) throws LdapInvalidAttributeValueException;
237
238
239    /**
240     * <p>
241     * Get the first value of this attribute. If there is none, 
242     * null is returned.
243     * </p>
244     * <p> 
245     * This method is meant to be used if the attribute hold only one value.
246     * </p>
247     * 
248     *  @return The first value for this attribute.
249     */
250    Value<?> get();
251
252
253    /**
254     * <p>
255     * Get the byte[] value, if and only if the value is known to be Binary,
256     * otherwise a InvalidAttributeValueException will be thrown
257     * </p>
258     * <p>
259     * Note that this method returns the first value only.
260     * </p>
261     *
262     * @return The value as a byte[]
263     * @throws LdapInvalidAttributeValueException If the value is a String
264     */
265    byte[] getBytes() throws LdapInvalidAttributeValueException;
266
267
268    /**
269     * Get's the attribute identifier for this entry. This is the value
270     * that will be used as the identifier for the attribute within the
271     * entry.
272     *
273     * @return the identifier for this attribute
274     */
275    String getId();
276
277
278    /**
279     * Get's the user provided identifier for this entry.  This is the value
280     * that will be used as the identifier for the attribute within the
281     * entry.  If this is a commonName attribute for example and the user
282     * provides "COMMONname" instead when adding the entry then this is
283     * the format the user will have that entry returned by the directory
284     * server.  To do so we store this value as it was given and track it
285     * in the attribute using this property.
286     *
287     * @return the user provided identifier for this attribute
288     */
289    String getUpId();
290
291
292    /**
293     * <p>
294     * Tells if the attribute is human readable. 
295     * </p>
296     * <p>This flag is set by the caller, or implicitly when adding String 
297     * values into an attribute which is not yet declared as Binary.
298     * </p> 
299     * @return true if the attribute is human readable
300     */
301    boolean isHumanReadable();
302
303
304    /**
305     * <p>
306     * Get the String value, if and only if the value is known to be a String,
307     * otherwise a InvalidAttributeValueException will be thrown
308     * </p>
309     * <p>
310     * Note that this method returns the first value only.
311     * </p>
312     *
313     * @return The value as a String
314     * @throws LdapInvalidAttributeValueException If the value is a byte[]
315     */
316    String getString() throws LdapInvalidAttributeValueException;
317
318
319    /**
320     * <p>
321     * Removes all the  values that are equal to the given values.
322     * </p>
323     * <p>
324     * Returns true if all the values are removed.
325     * </p>
326     * <p>
327     * If the attribute type is not HR, then the values will be first converted
328     * to byte[]
329     * </p>
330     *
331     * @param vals the values to be removed
332     * @return true if all the values are removed, otherwise false
333     */
334    boolean remove( String... vals );
335
336
337    /**
338     * <p>
339     * Removes all the  values that are equal to the given values.
340     * </p>
341     * <p>
342     * Returns true if all the values are removed. 
343     * </p>
344     * <p>
345     * If the attribute type is HR, then the values will be first converted
346     * to String
347     * </p>
348     *
349     * @param val the values to be removed
350     * @return true if all the values are removed, otherwise false
351     */
352    boolean remove( byte[]... val );
353
354
355    /**
356     * <p>
357     * Removes all the  values that are equal to the given values.
358     * </p>
359     * <p>
360     * Returns true if all the values are removed.
361     * </p>
362     * <p>
363     * If the attribute type is HR and some value which are not String, we
364     * will convert the values first (same thing for a non-HR attribute).
365     * </p>
366     *
367     * @param vals the values to be removed
368     * @return true if all the values are removed, otherwise false
369     */
370    boolean remove( Value<?>... vals );
371
372
373    /**
374     * Set the user provided ID. It will also set the ID, normalizing
375     * the upId (removing spaces before and after, and lower casing it)
376     *
377     * @param upId The attribute ID
378     * @throws IllegalArgumentException If the ID is empty or null or
379     * resolve to an empty value after being trimmed
380     */
381    void setUpId( String upId );
382
383
384    /**
385     * <p>
386     * Set the user provided ID. If we have none, the upId is assigned
387     * the attributetype's name. If it does not have any name, we will
388     * use the OID.
389     * </p>
390     * <p>
391     * If we have an upId and an AttributeType, they must be compatible. :
392     *  - if the upId is an OID, it must be the AttributeType's OID
393     *  - otherwise, its normalized form must be equals to ones of
394     *  the attributeType's names.
395     * </p>
396     * <p>
397     * In any case, the ATtributeType will be changed. The caller is responsible for
398     * the present values to be compatible with the new AttributeType.
399     * </p>
400     * 
401     * @param upId The attribute ID
402     * @param attributeType The associated attributeType
403     */
404    void setUpId( String upId, AttributeType attributeType );
405
406
407    /**
408      * Retrieves the number of values in this attribute.
409      *
410      * @return the number of values in this attribute, including any values
411      * wrapping a null value if there is one
412      */
413    int size();
414
415
416    /**
417     * Checks to see if this attribute is valid along with the values it contains.
418     *
419     * @param attributeType The AttributeType
420     * @return true if the attribute and it's values are valid, false otherwise
421     * @throws LdapInvalidAttributeValueException if there is a failure to check syntaxes of values
422     */
423    boolean isValid( AttributeType attributeType ) throws LdapInvalidAttributeValueException;
424    
425    
426    /**
427     * A pretty-pinter for Attribute
428     * 
429     * @param tabs The tabs to add before any output
430     * @return The pretty-printed entry
431     */
432    String toString( String tabs );
433}