001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property;
025    
026    import java.util.Iterator;
027    import net.jcip.annotations.Immutable;
028    
029    /**
030     * Representation of a property consisting of a name and value(s). Note that this property is immutable, meaning that the property
031     * values may not be changed through this interface.
032     * <p>
033     * This class is designed to be used with the {@link ValueFactories} interface and the particular {@link ValueFactory} that
034     * corresponds to the type of value you'd like to use. The <code>ValueFactory</code> will then return the values (if no type
035     * conversion is required) or will convert the values using the appropriate conversion algorithm.
036     * </p>
037     * <p>
038     * The following example shows how to obtain the {@link String} representations of the {@link #getValues() property values}:
039     * 
040     * <pre>
041     *   ValueFactories valueFactories = ...
042     *   Property property = ...
043     *   Iterator&lt;String&gt; iter = valueFactories.getStringFactory().create(property.getValues());
044     *   while ( iter.hasNext() ) {
045     *       System.out.println(iter.next());
046     *   }
047     * </pre>
048     * 
049     * Meanwhile, the {@link ValueFactories#getLongFactory() long value factory} converts the values to <code>long</code>, the
050     * {@link ValueFactories#getDateFactory() date value factory} converts the values to {@link DateTime} instances, and so on.
051     * </p>
052     * <p>
053     * This technique is much better and far safer than casting the values. It is possible that some Property instances contain
054     * heterogeneous values, so casting may not always work. Also, this technique guarantees that the values are properly converted if
055     * the type is not what you expected.
056     * </p>
057     * 
058     * @author Randall Hauch
059     */
060    @Immutable
061    public interface Property extends Iterable<Object>, Comparable<Property>, Readable {
062    
063        /**
064         * Get the name of the property.
065         * 
066         * @return the property name; never null
067         */
068        Name getName();
069    
070        /**
071         * Get the number of actual values in this property. If the property allows {@link #isMultiple() multiple values}, then this
072         * method may return a value greater than 1. If the property only allows a {@link #isSingle() single value}, then this method
073         * will return either 0 or 1. This method may return 0 regardless of whether the property allows a {@link #isSingle() single
074         * value}, or {@link #isMultiple() multiple values}.
075         * 
076         * @return the number of actual values in this property; always non-negative
077         */
078        int size();
079    
080        /**
081         * Determine whether the property currently has multiple values.
082         * 
083         * @return true if the property has multiple values, or false otherwise.
084         * @see #isSingle()
085         * @see #isEmpty()
086         */
087        boolean isMultiple();
088    
089        /**
090         * Determine whether the property currently has a single value.
091         * 
092         * @return true if the property has a single value, or false otherwise.
093         * @see #isMultiple()
094         * @see #isEmpty()
095         */
096        boolean isSingle();
097    
098        /**
099         * Determine whether this property has no actual values. This method may return <code>true</code> regardless of whether the
100         * property allows a {@link #isSingle() single value}, or {@link #isMultiple() multiple values}.
101         * <p>
102         * This method is a convenience method that is equivalent to <code>size() == 0</code>.
103         * </p>
104         * 
105         * @return true if this property has no values, or false otherwise
106         * @see #isMultiple()
107         * @see #isSingle()
108         */
109        boolean isEmpty();
110    
111        /**
112         * Obtain the property's first value in its natural form. This is equivalent to calling
113         * <code>isEmpty() ? null : iterator().next()</code>
114         * 
115         * @return the first value, or null if the property is {@link #isEmpty() empty}
116         * @see Iterable#iterator()
117         * @see #getValues()
118         * @see #getValuesAsArray()
119         * @see #isEmpty()
120         */
121        Object getFirstValue();
122    
123        /**
124         * Obtain the property's values in their natural form. This is equivalent to calling {@link Iterable#iterator() iterator()}.
125         * <p>
126         * A valid iterator is returned if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}.
127         * </p>
128         * <p>
129         * The resulting iterator is immutable, and all property values are immutable.
130         * </p>
131         * 
132         * @return an iterator over the values; never null
133         * @see #getFirstValue()
134         * @see Iterable#iterator()
135         * @see #getValuesAsArray()
136         * @see ValueFactory#create(Iterator)
137         */
138        Iterator<?> getValues();
139    
140        /**
141         * Obtain the property's values as an array of objects in their natural form.
142         * <p>
143         * A valid array is return if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}, or a
144         * null value is returned if the property is {@link #isEmpty() empty}.
145         * </p>
146         * <p>
147         * The resulting array is a copy, guaranteeing immutability for the property.
148         * </p>
149         * 
150         * @return the array of values
151         * @see #getFirstValue()
152         * @see Iterable#iterator()
153         * @see #getValues()
154         * @see ValueFactory#create(Object[])
155         */
156        Object[] getValuesAsArray();
157    }