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<String> 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 }