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 import org.jboss.dna.common.text.TextEncoder; 029 030 /** 031 * Representation of a property consisting of a name and value(s). Note that this property is immutable, meaning that the property 032 * values may not be changed through this interface. 033 * <p> 034 * This class is designed to be used with the {@link ValueFactories} interface and the particular {@link ValueFactory} that 035 * corresponds to the type of value you'd like to use. The <code>ValueFactory</code> will then return the values (if no type 036 * conversion is required) or will convert the values using the appropriate conversion algorithm. 037 * </p> 038 * <p> 039 * The following example shows how to obtain the {@link String} representations of the {@link #getValues() property values}: 040 * 041 * <pre> 042 * ValueFactories valueFactories = ... 043 * Property property = ... 044 * Iterator<String> iter = valueFactories.getStringFactory().create(property.getValues()); 045 * while ( iter.hasNext() ) { 046 * System.out.println(iter.next()); 047 * } 048 * </pre> 049 * 050 * Meanwhile, the {@link ValueFactories#getLongFactory() long value factory} converts the values to <code>long</code>, the 051 * {@link ValueFactories#getDateFactory() date value factory} converts the values to {@link DateTime} instances, and so on. 052 * </p> 053 * <p> 054 * This technique is much better and far safer than casting the values. It is possible that some Property instances contain 055 * heterogeneous values, so casting may not always work. Also, this technique guarantees that the values are properly converted if 056 * the type is not what you expected. 057 * </p> 058 * 059 * @author Randall Hauch 060 */ 061 @Immutable 062 public interface Property extends Iterable<Object>, Comparable<Property> { 063 064 /** 065 * Get the name of the property. 066 * 067 * @return the property name; never null 068 */ 069 Name getName(); 070 071 /** 072 * Get the number of actual values in this property. If the property allows {@link #isMultiple() multiple values}, then this 073 * method may return a value greater than 1. If the property only allows a {@link #isSingle() single value}, then this method 074 * will return either 0 or 1. This method may return 0 regardless of whether the property allows a {@link #isSingle() single 075 * value}, or {@link #isMultiple() multiple values}. 076 * 077 * @return the number of actual values in this property; always non-negative 078 */ 079 int size(); 080 081 /** 082 * Determine whether the property currently has multiple values. 083 * 084 * @return true if the property has multiple values, or false otherwise. 085 * @see #isSingle() 086 * @see #isEmpty() 087 */ 088 boolean isMultiple(); 089 090 /** 091 * Determine whether the property currently has a single value. 092 * 093 * @return true if the property has a single value, or false otherwise. 094 * @see #isMultiple() 095 * @see #isEmpty() 096 */ 097 boolean isSingle(); 098 099 /** 100 * Determine whether this property has no actual values. This method may return <code>true</code> regardless of whether the 101 * property allows a {@link #isSingle() single value}, or {@link #isMultiple() multiple values}. 102 * <p> 103 * This method is a convenience method that is equivalent to <code>size() == 0</code>. 104 * </p> 105 * 106 * @return true if this property has no values, or false otherwise 107 * @see #isMultiple() 108 * @see #isSingle() 109 */ 110 boolean isEmpty(); 111 112 /** 113 * Obtain the property's first value in its natural form. This is equivalent to calling 114 * <code>isEmpty() ? null : iterator().next()</code> 115 * 116 * @return the first value, or null if the property is {@link #isEmpty() empty} 117 * @see Iterable#iterator() 118 * @see #getValues() 119 * @see #getValuesAsArray() 120 * @see #isEmpty() 121 */ 122 Object getFirstValue(); 123 124 /** 125 * Obtain the property's values in their natural form. This is equivalent to calling {@link Iterable#iterator() iterator()}. 126 * <p> 127 * A valid iterator is returned if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}. 128 * </p> 129 * <p> 130 * The resulting iterator is immutable, and all property values are immutable. 131 * </p> 132 * 133 * @return an iterator over the values; never null 134 * @see #getFirstValue() 135 * @see Iterable#iterator() 136 * @see #getValuesAsArray() 137 * @see ValueFactory#create(Iterator) 138 */ 139 Iterator<?> getValues(); 140 141 /** 142 * Obtain the property's values as an array of objects in their natural form. 143 * <p> 144 * A valid array is return if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}, or a 145 * null value is returned if the property is {@link #isEmpty() empty}. 146 * </p> 147 * <p> 148 * The resulting array is a copy, guaranteeing immutability for the property. 149 * </p> 150 * 151 * @return the array of values 152 * @see #getFirstValue() 153 * @see Iterable#iterator() 154 * @see #getValues() 155 * @see ValueFactory#create(Object[]) 156 */ 157 Object[] getValuesAsArray(); 158 159 /** 160 * Get the string form of the property, using the default encoder. 161 * 162 * @return the encoded string 163 * @see #getString(TextEncoder) 164 */ 165 public String getString(); 166 167 /** 168 * Get the encoded string form of the property, using the supplied encoder to encode characters in the property's name and 169 * values. 170 * 171 * @param encoder the encoder to use, or null if the default encoder should be used 172 * @return the encoded string 173 * @see #getString() 174 */ 175 public String getString( TextEncoder encoder ); 176 177 /** 178 * Get the string form of the property, using the supplied namespace registry to convert the property's name and values. 179 * 180 * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the 181 * {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name} 182 * @return the string 183 * @throws IllegalArgumentException if the namespace registry is null 184 * @see #getString(NamespaceRegistry,TextEncoder) 185 * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder) 186 */ 187 public String getString( NamespaceRegistry namespaceRegistry ); 188 189 /** 190 * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs 191 * to prefixes and the supplied encoder to encode characters in the property's name and values. 192 * 193 * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the 194 * {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace 195 * registry should not be used 196 * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used 197 * @return the encoded string 198 * @see #getString(NamespaceRegistry) 199 * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder) 200 */ 201 public String getString( NamespaceRegistry namespaceRegistry, 202 TextEncoder encoder ); 203 204 /** 205 * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs 206 * to prefixes and the supplied encoder to encode characters in the property's name and values. 207 * 208 * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the 209 * {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace 210 * registry should not be used 211 * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used 212 * @param delimiterEncoder the encoder to use for encoding delimiters used in paths and names, or null if the standard 213 * delimiters should be used 214 * @return the encoded string 215 * @see #getString(NamespaceRegistry) 216 * @see #getString(NamespaceRegistry, TextEncoder) 217 */ 218 public String getString( NamespaceRegistry namespaceRegistry, 219 TextEncoder encoder, 220 TextEncoder delimiterEncoder ); 221 }