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