001 /*
002 * file PropertyNameList.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM
006 *
007 * (c) Copyright IBM Corporation 2004, 2008. All Rights Reserved.
008 * Note to U.S. Government Users Restricted Rights: Use, duplication or
009 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
010 */
011 package javax.wvcm;
012
013 import java.util.Arrays;
014 import java.util.Collections;
015 import java.util.HashSet;
016 import java.util.Set;
017
018 /**
019 * A list of resource property names.
020 *
021 * @since 1.0
022 */
023 public final class PropertyNameList implements PropertyRequestItem {
024
025 /**
026 * The name of a property of a persistent resource. The PropertyName
027 * type parameter specifies the type of the value of the PropertyName
028 */
029 public static class PropertyName<T> implements PropertyRequestItem {
030
031 private final String _namespace;
032 private final String _name;
033
034 /**
035 * Create a PropertyName with a null namespace and the given name.
036 *
037 * @param name the name for this property. May not be null.
038 */
039 PropertyName(String name) {
040 this(null, name);
041 }
042
043 /**
044 * Create a PropertyName with the given namespace and name.
045 *
046 * @param namespace the namespace for this PropertyName.
047 * May be null to indicate a system property, or non-null
048 * to indicate a property in the specified name space.
049 * @param name the name for this property. May not be null.
050 */
051 public PropertyName(String namespace, String name) {
052 _namespace = namespace;
053 _name = name;
054 }
055
056 /**
057 * Get the namespace of the property name.
058 *
059 * @return the namespace. May be null to indicate a system property,
060 * or non-null to indicate a property in the specified name space.
061 */
062 public String getNamespace() {
063 return _namespace;
064 }
065
066 /**
067 * Get the property name.
068 *
069 * @return the name part of the property name */
070 public String getName() {
071 return _name;
072 }
073
074 /**
075 * Calculate a hash code value for the object.
076 *
077 * @return the hash code for the object.
078 */
079 @Override
080 public int hashCode() {
081 int result = 17;
082 result = 37*result + ((_namespace == null) ? 0 : _namespace.hashCode());
083 result = 37*result + _name.hashCode();
084 return result;
085 }
086
087 /**
088 * Indicates whether some other object is "equal to" this one.
089 *
090 * @param o the object to compare with.
091 * @return true if and only if the specified object is a PropertyName whose
092 * type, namespace value, and name value equals those of this object.
093 */
094 @Override
095 public boolean equals(Object o) {
096 if (o == null || this.getClass() != o.getClass()) {
097 return false;
098 }
099 PropertyName<?> pn = (PropertyName<?>) o;
100 if (_namespace == null) {
101 return pn._namespace == null && _name.equals(pn._name);
102 }
103 return _namespace.equals(pn._namespace) && _name.equals(pn._name);
104 }
105
106 /**
107 * Returns a string representation of the PropertyName for diagnostic
108 * purposes.
109 * @see java.lang.Object#toString
110 *
111 * @return The string representation of this PropertyName in the format
112 * [namespace:]name.
113 */
114 @Override
115 public String toString() {
116 if (_namespace != null)
117 return _namespace + ":" + _name; //$NON-NLS-1$
118 else
119 return _name;
120 }
121
122 /**
123 * Constructs a NestedPropertyName whose root property is this
124 * PropertyName with the property request items supplied as arguments as
125 * its nested property request. This method allows a more succinct
126 * syntax for the declaration of PropertyRequest objects at compile
127 * time. For example,
128 *
129 * <pre>
130 * final static PropertyRequest WORKSPACE_PROPERTIES =
131 * new PropertyRequest(
132 * Workspace.DISPLAY_NAME,
133 * Workspace.COMMENT,
134 * Workspace.ACTIVITY_LIST.nest(
135 * Activity.DISPLAY_NAME,
136 * Activity.ACTIVITY_VERSION_LIST.nest(
137 * Version.DISPLAY_NAME,
138 * Version.COMMENT,
139 * Version.CREATION_DATE)));
140 * </pre>
141 *
142 * @param pnl An array of PropertyRequestItem objects that specify the
143 * properties to be requested from the value of the property
144 * identified by this PropertyName.
145 * @return A NestedPropertyName whose root is this PropertyName and
146 * whose nested properties are the property request items given
147 * as arguments.
148 */
149 public NestedPropertyName<T> nest(PropertyRequestItem... pnl)
150 {
151 return new NestedPropertyName<T>(this, pnl);
152 }
153
154 /**
155 * A convenience method for constructing nested property names from a
156 * NestedPropertyName[] without requiring an explicit cast to
157 * PropertyRequestItem[]
158 *
159 * @param pnl A NestedPropertyName[] that specifies the nested
160 * properties of the NestedPropertyName to be constructed
161 * @return A NestedPropertyName whose root is this PropertyName and
162 * whose nested properties are the elements of the
163 * NestedPropertyNames[] argument.
164 */
165 public NestedPropertyName<T> nest(NestedPropertyName<?>[] pnl)
166 {
167 return new NestedPropertyName<T>(this, (PropertyRequestItem[])pnl);
168 }
169
170 /**
171 * A convenience method for constructing nested property names from a
172 * PropertyName[] without requiring an explicit cast to
173 * PropertyRequestItem[]
174 *
175 * @param pnl A PropertyName[] that specifies the nested properties of
176 * the NestedPropertyName to be constructed
177 * @return A NestedPropertyName whose root is this PropertyName and
178 * whose nested properties are the elements of the
179 * PropertyNames[] argument.
180 */
181 public NestedPropertyName<T> nest(PropertyName<?>[] pnl)
182 {
183 return new NestedPropertyName<T>(this, (PropertyRequestItem[])pnl);
184 }
185 }
186
187 // An empty immutable PropertyName[]
188 private static final PropertyName<?>[] EMPTY_PNA = new PropertyName[0];
189
190 // The immutable array of property names for this PropertyNameList.
191 private final PropertyName<?>[] _propertyNames;
192
193 // The lazy initialized Set for this immutable object.
194 private volatile Set<PropertyName<?>> _asSet = null;
195
196 /**
197 * Construct a PropertyNameList from an array of property names.
198 *
199 * @param propertyNames an array of property names, or null.
200 * Passing null is equivalent to passing an empty array.
201 */
202 public PropertyNameList(PropertyName<?>... propertyNames) {
203 _propertyNames = (propertyNames == null || propertyNames.length == 0)
204 ? EMPTY_PNA : propertyNames;
205 }
206
207 /**
208 * Get an array of property names from a property name list.
209 *
210 * @return the array of property names maintained by this
211 * PropertyNameList. Will never be <code>null</code>.
212 */
213 public PropertyName<?>[] getPropertyNames() {
214 return _propertyNames;
215 }
216
217 /**
218 * Indicates whether some other object is "equal to" this one.
219 *
220 * @param o the object to compare with.
221 * @return true if and only if the specified object is a PropertyNameList
222 * whose property names array is equal to the property names array
223 * of this ignoring order.
224 */
225 @Override
226 public boolean equals(Object o) {
227 if (o == null || this.getClass() != o.getClass()) {
228 return false;
229 }
230 PropertyNameList pnl = (PropertyNameList) o;
231 return getPropertyNamesAsSet().equals(pnl.getPropertyNamesAsSet());
232 }
233
234
235 /**
236 * Calculate a hash code for a PropertyNameList.
237 *
238 * @return a hash code for the list.
239 */
240 @Override
241 public int hashCode() {
242 return getPropertyNamesAsSet().hashCode();
243 }
244
245 /**
246 * Returns a string representation of this PropertyNameList suitable for
247 * diagnostics.
248 *
249 * @return The string representation of this PropertyNameList formatted as
250 * "[<first property name>, <second property name>]"
251 */
252 @Override
253 public String toString() {
254
255 StringBuffer builder = new StringBuffer();
256 builder.append('[');
257
258 for(PropertyName<?> name: getPropertyNames()) {
259 if (builder.length() > 1)
260 builder.append(", "); //$NON-NLS-1$
261
262 builder.append(name.toString());
263 }
264
265 builder.append(']');
266
267 return builder.toString();
268 }
269
270 // the property names maintained by this PropertyNameList as a Set.
271 private Set<PropertyName<?>> getPropertyNamesAsSet() {
272 if (_asSet == null) {
273 if (_propertyNames == EMPTY_PNA)
274 _asSet = Collections.emptySet();
275 else
276 _asSet = new HashSet<PropertyName<?>>(Arrays.asList(_propertyNames));
277 }
278 return _asSet;
279 }
280 }