001 /*
002 * file StpProperty.java
003 *
004 * Licensed Materials - StpProperty of IBM
005 * Restricted Materials of IBM
006 *
007 * com.ibm.rational.wvcm.stp.StpProperty
008 *
009 * (C) Copyright IBM Corporation 2004, 2008. All Rights Reserved.
010 * Note to U.S. Government Users Restricted Rights: Use, duplication or
011 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
012 */
013
014 package com.ibm.rational.wvcm.stp;
015
016 import static com.ibm.rational.wvcm.stpex.StpExBase.METADATA_NAMESPACE;
017
018 import java.util.ArrayList;
019 import java.util.List;
020
021 import javax.wvcm.PropertyNameList;
022 import javax.wvcm.Resource;
023 import javax.wvcm.WvcmException;
024 import javax.wvcm.PropertyNameList.PropertyName;
025
026 import com.ibm.rational.wvcm.stp.cq.CqFieldValue.ValueType;
027 import com.ibm.rational.wvcm.stpex.StpExBase;
028 import com.ibm.rational.wvcm.stpex.StpExEnumeration;
029 import com.ibm.rational.wvcm.stpex.StpExEnumerationBase;
030
031 /**
032 * A property is a named collection of metadata associated with a resource. The
033 * collection is named by its PropertyName.
034 *
035 * <h2>Meta-Properties</h2>
036 *
037 * <p>
038 * Each metadata component is called a meta-property and is a (name, value)
039 * pair. That is, a property is a named collection of meta-properties. The name
040 * of a meta-property is denoted by a {@link MetaPropertyName MetaPropertyName}
041 * object. The value is an arbitrary Object.
042 * </p>
043 *
044 * <p>
045 * The term "meta-property" is used here rather loosely. Meta-properties specify
046 * more than just static attributes of a property (such as its type or name),
047 * but often define very dynamic aspects of the property (e.g., what resource it
048 * came from) or its value (e.g. whether or not the value is null). There is
049 * even a VALUE meta-property, whose value is the value of the property.
050 * </p>
051 *
052 * <p>
053 * Just like a PropertyName, a MetaPropertyName is composed from a namespace and
054 * a simple name. (In fact, to simplify this API, MetaPropertyName is a subclass
055 * of javax.wvcm.PropertyNameList.PropertyName.) The PropertyName and
056 * MetaPropertyName namespaces cannot overlap.
057 * </p>
058 *
059 * <p>
060 * Every property has the meta-properties defined in this class; namely
061 * {@link #NAME NAME}, {@link #NAMESPACE NAMESPACE}, {@link #PROPERTY_NAME
062 * PROPERTY_NAME}, {@link #RESOURCE RESOURCE} and {@link #VALUE VALUE}. Each
063 * property may have additional meta-properties of its own as well.
064 * </p>
065 *
066 * <p>
067 * When we speak of the "<i>value of a property</i>", we are actually
068 * referring to the value of the VALUE meta-property of the property.
069 * </p>
070 *
071 * <h2>Requesting Meta-properties</h2>
072 *
073 * <p>
074 * An StpProperty object is a client-side proxy for a property; just as a
075 * Resource object is a client-side proxy for a resource. Like a resource proxy,
076 * each StpProperty instance defines only those meta-properties that have been
077 * explicitly requested from the server. (The NAME, NAMESPACE, and PROPERTY_NAME
078 * meta-properties are an exception since they are required to construct a
079 * StpProperty instance and are always present.)
080 * </p>
081 *
082 * <p>
083 * An StpProperty instance does not provide an interface for changing the value
084 * of a meta-property. Clients can change only property values, which may have
085 * the side-effect of changing other meta-properties for that property or
086 * meta-properties for other properties.
087 * </p>
088 *
089 * <p>
090 * Property meta-properties are available only in the context of a specific
091 * resource and the request for property meta-properties is tied directly to
092 * that resource using the same mechanism used to request properties from that
093 * resource.
094 * </p>
095 *
096 * <h3>MetaPropertyName Objects in a NestedPropertyName</h3>
097 *
098 * <p>
099 * To request a meta-property of a property, a MetaPropertyName object for the
100 * meta-property is included in the PropertyRequest argument to
101 * PropertyName.nest(). MetaPropertyName objects and PropertyName objects can
102 * coexist in the same nested PropertyRequest; the nested MetaPropertyName
103 * objects request meta-properties of the property, while the nested ProperyName
104 * objects request properties of the resource named by the value of the
105 * property.
106 * </p>
107 *
108 * <p>
109 * To request the meta-properties of a property-valued property, the
110 * MetaPropertyNames must be nested within a NestedPropertyName. The root
111 * meta-property of this request will be StpProperty.VALUE and the desired
112 * meta-properties of the value will be nested in the PropertyRequest of the
113 * NestedPropertyName.
114 * </p>
115 *
116 * <p>
117 * Examples
118 * </p>
119 *
120 * <pre>
121 * PropertyRequest wanted=new PropertyRequest(
122 * // The value of the DISPLAY_NAME property
123 * Resource.DISPLAY_NAME,
124 * Resource.WORKSPACE_FOLDER_LIST.nest(
125 * // The type of the WORKSPACE_FOLDER_LIST property
126 * StpProperty.TYPE,
127 * // The value of the CHILD_LIST property for each folder
128 * // named by the WORKSPACE_FOLDER_LIST
129 * Folder.CHILD_LIST),
130 * Resource.INVALID_PROPERTIES.nest(
131 * // The type of the INVALID_PROPERTIES property
132 * StpProperty.TYPE,
133 * StpProperty.VALUE.nest(
134 * // The type of each property named by the value of the
135 * // INVALID_PROPERTIES property.
136 * StpProperty.TYPE,
137 * // The value of each property named by the value of the
138 * // INVALID_PROPERTIES property.
139 * StpProperty.VALUE),
140 * );
141 * </pre>
142 *
143 * <h3>The VALUE Meta-Property</h3>
144 *
145 * <p>
146 * Every property has a VALUE meta-property. The use of a PropertyName by itself
147 * implicitly requests this meta-property. A NestedPropertyName containing
148 * nested ProperyNames also implicitly requests the VALUE meta-property (since
149 * it would be impossible to request properties of the value without also
150 * requesting the value itself).
151 * </p>
152 *
153 * <p>
154 * On the other hand, a NestedPropertyName that contains only nested
155 * MetaPropertyNames must include StpProperty.VALUE if the value of the property
156 * is desired. This makes it possible for a client to request information about
157 * a property (such as is size) without actually retrieving the value itself.
158 * </p>
159 *
160 * <h2>Accessing Meta-Properties</h2>
161 *
162 * <p>
163 * Like property values, meta-properties retrieved from the server are stored in
164 * the resource proxy and accessed via methods defined in the StpResource class.
165 * The principal method is {@link
166 * com.ibm.rational.wvcm.stp.StpResource#getMetaProperties(PropertyNameList.PropertyName)
167 * Resource.getMetaProperties(PropertyName)}, which returns an StpProperty object
168 * containing all of the meta-properties for a given property retrieved from the
169 * server and diagnostic information for those meta-properties that couldn't be
170 * retrieved.
171 * </p>
172 *
173 * <p>
174 * As long as the PropertyName was mentioned in the request and that property is
175 * defined by the resource, getMetaProperties will return a StpProperty object
176 * for that PropertyName. An exception is thrown only if the property is not
177 * defined by the resource or no meta-property of the property was requested.
178 * </p>
179 *
180 * <p>
181 * {@link javax.wvcm.Resource#getProperty(PropertyNameList.PropertyName)
182 * Resource.getProperty(PropertyName)} returns the value of the VALUE
183 * meta-property of the property and will throw an exception if that
184 * meta-property was not requested or the server reported an error in attempting
185 * to retrieve the value. If the value of a property is, itself, a property,
186 * getProperty will return an StpProperty object.
187 * </p>
188 *
189 * <p>
190 * From the StpProperty object, the client can access the retrieved
191 * meta-properties, either generically using the {@link
192 * StpProperty#getMetaProperty(StpProperty.MetaPropertyName) getMetaProperty()}
193 * method and an explicit MetaPropertyName or using the specialized methods,
194 * such as {@link #getName getName} and {@link #getValue getValue}, where the
195 * MetaPropertyName is implicit. Subclasses of Resource may define subclasses of
196 * StpProperty and provide typed accessors for them. The subclasses of
197 * StpProperty may, in turn, define more typed accessors for meta-properties
198 * they know about. (See, for example
199 * {@link com.ibm.rational.wvcm.stp.cq.CqRecord Record} and
200 * {@link com.ibm.rational.wvcm.stp.cq.CqFieldValue CqFieldValue}.)
201 * </p>
202 * <p>
203 * The type parameter of an StpProperty instance specifies the type of the
204 * property's VALUE meta-property.
205 */
206 public interface StpProperty<T>
207 {
208 /**
209 * A List of Properties.
210 */
211 public static class List<S extends StpProperty>
212 extends ArrayList<S>
213 {
214 /**
215 *
216 */
217 private static final long serialVersionUID = 1181176128014802915L;
218
219 /**
220 * Returns the names of the properties in the list
221 *
222 * @return A PropertyNameList containing a PropertyName for each element
223 * of the list.
224 */
225 public PropertyNameList getPropertyNameList()
226 {
227 int n = size();
228 PropertyName[] names = new PropertyName[n];
229
230 for (int i = 0; i < n; ++i)
231 names[i] = get(i).getPropertyName();
232
233 return new PropertyNameList(names);
234 }
235
236 /* (non-Javadoc)
237 * @see java.util.ArrayList#add(java.lang.Object)
238 */
239 @Override
240 public boolean add(S arg0)
241 {
242 return super.add(arg0);
243 }
244 }
245
246 /**
247 * An object representing the name of a meta-property. This class extends
248 * PropertyName so that MetaPropertyName objects may be included in a
249 * PropertyRequest. Otherwise, MetaPropertyName and PropertyName are not
250 * interchangeable. The type parameter specifies the type of meta-property's
251 * value.
252 */
253 public static class MetaPropertyName<V>
254 extends PropertyName<V>
255 {
256 /**
257 * Creates a new MetaPropertyName from a simple name and a specified
258 * namespace.
259 *
260 * @param namespace the namespace for this MetaPropertyName. May not
261 * be <b>null</b>.
262 * @param name the name for this property. May not be <b>null</b>.
263 */
264 public MetaPropertyName(
265 String namespace,
266 String name)
267 {
268 super(namespace, name);
269 }
270
271 /**
272 * Parameterized method for constructing MetaPropertyName<?>
273 *
274 * @param <U> The value type for the MetaPropertyName
275 * @param namespace The namespace for this MetaPropertyName. May not be
276 * <b>null</b>.
277 * @param name the name for this property. May not be <b>null</b>.
278 * @return A new instanceof MetaPropertyName using the given namespace
279 * and name
280 */
281 public static final <U> MetaPropertyName<U> build(String namespace,
282 String name)
283 {
284 return new MetaPropertyName<U>(namespace, name);
285 }
286 }
287
288 /**
289 * Returns the value of the given meta-property defined by this StpProperty
290 * instance.
291 *
292 * @param name A MetaPropertyName object identifying the meta-property
293 * desired.
294 *
295 * @return An Object representing the value of the meta-property requested.
296 *
297 * @throws WvcmException if this StpProperty instance does not define a
298 * value for the named meta-property.
299 */
300 public <U> U getMetaProperty(MetaPropertyName<U> name)
301 throws WvcmException;
302
303 /**
304 * Returns the names of meta-properties available on this client StpProperty
305 * proxy. This is the analog of Resource.propertyNameList. A meta-property
306 * is available if it would not throw an exception if retrieved from this
307 * StpProperty. Failing to retrieve a meta-property would cause a
308 * meta-property name to not appear in the metaPropertyNames result and
309 * forgetting or removing a meta-property would remove that property from
310 * the metaPropertyNames result.
311 *
312 * @return the list of MetaPropertyName objects identifying the
313 * meta-properties available on this client StpProperty proxy.
314 *
315 * @see javax.wvcm.Resource#propertyNameList()
316 */
317 public MetaPropertyName<?>[] metaPropertyNames();
318
319 /**
320 * Returns an array of StpPropertyException objects, each of which
321 * represents a meta-property whose value was requested but could not be
322 * successfully retrieved.
323 *
324 * @return An array containing an StpPropertyException object for each
325 * meta-property that could not be retrieved. The PropertyName field
326 * of the PropertyException identifies the meta-property that could
327 * not be retrieved.
328 */
329 public StpPropertyException[] metaPropertyExceptions();
330
331 /**
332 * Returns the StpPropertyException that would be thrown if getMetaProperty
333 * were invoked on a specified meta-property.
334 *
335 * @param name The name of the meta-property whose retrieval status is being
336 * interrogated.
337 * @return an StpPropertyException is returned if the named meta-property
338 * could not be retrieved or if it's retrieval was not requested;
339 * otherwise <b>null</b>.
340 */
341 public StpPropertyException metaPropertyException(MetaPropertyName<?> name);
342
343 /**
344 * A list of all the meta-property names defined for this property. This is
345 * the analog of Resource.doGetPropertyNameList. Since properties may not be
346 * addressed directly, this analogous capability is expressed as a
347 * meta-property.
348 */
349 public static final MetaPropertyName<PropertyNameList> META_PROPERTY_NAMES =
350 new MetaPropertyName<PropertyNameList>(METADATA_NAMESPACE,
351 "meta-property-names");
352
353 /**
354 * Returns the value of the {@link #META_PROPERTY_NAMES META_PROPERTY_NAMES}
355 * meta-property as defined by this StpProperty instance.
356 *
357 * @return A PropertyRequest containing a MetaPropertyName for each meta-
358 * property defined by this StpProperty.
359 *
360 * @throws WvcmException if this StpProperty instance does not define a value
361 * for the {@link
362 * #META_PROPERTY_NAMES META_PROPERTY_NAMES}
363 * meta-property.
364 */
365 public PropertyNameList getMetaPropertyNames()
366 throws WvcmException;
367
368 /**
369 * The meta-property whose value is the value of the property. (The type of
370 * the value is specified by the TYPE meta-property.) This meta-property is
371 * defined for all properties.
372 */
373 public static final MetaPropertyName<?> VALUE =
374 new MetaPropertyName(StpExBase.METADATA_NAMESPACE, "value");
375
376 /**
377 * Returns the value of the {@link #VALUE VALUE} meta-property as defined by
378 * this StpProperty instance.
379 *
380 * @return An Object representing the value of the property represented by
381 * this StpProperty instance.
382 *
383 * @throws WvcmException if this StpProperty instance does not define a
384 * value for the {@link #VALUE VALUE} meta-property.
385 */
386 public T getValue()
387 throws WvcmException;
388
389 /**
390 * An enumeration of the possible property types. Subclasses may extend this
391 * list to include any new data types introduced by that subclass.
392 */
393 public enum Type
394 implements StpExEnumeration
395 {
396 /** An initial value for Type variables */
397 UNKNOWN,
398
399 /** An integer in the range -9999999999 to 9999999999 */
400 INTEGER,
401
402 /**
403 * A GMT date/time between 12:00:01 AM January 1, 1970 and 11:59:59 PM
404 * January 18, 2038.
405 */
406 DATE_TIME,
407
408 /** A proxy for a Resource of a specific ResourceType. */
409 RESOURCE,
410
411 /** A list of proxies for a Resource of a specific ResourceType */
412 RESOURCE_LIST,
413
414 /** A floating point value */
415 FLOAT,
416
417 /** A generic string value */
418 STRING,
419
420 /** An StpLocation property value. */
421 LOCATION,
422
423 /** A Locale property value. */
424 LOCALE,
425
426 /** A property value that is a list of Strings. */
427 STRING_LIST,
428
429 /** A long property value. */
430 LONG,
431
432 /** An double property value. */
433 DOUBLE,
434
435 /** A boolean property value. */
436 BOOL,
437
438 /** A ResourceType property value */
439 RESOURCE_TYPE,
440
441 /** A property value derived from StpExEnumerationBase */
442 ENUMERATED_TYPE,
443
444 /** A list of values derived from StpExEnumerationBase */
445 ENUMERATED_LIST,
446
447 /** A PropertyName property value */
448 PROPERTY_NAME,
449
450 /** A PropertyNameList property value */
451 PROPERTY_NAME_LIST,
452
453 /** An StpProperty property value */
454 PROPERTY,
455
456 /** An StpProperty.List property value */
457 PROPERTY_LIST,
458
459 /** A structure derived from Object */
460 OBJECT,
461
462 /** A list of structures derived from Object */
463 OBJECT_LIST,
464
465 /** An XML content property value. */
466 XML,
467
468 /** A pair of long values specifying a range. */
469 RANGE;
470 }
471
472 /**
473 * An enumerator denoting the type of this property's VALUE meta-property
474 * value.
475 */
476 public static final MetaPropertyName<Type> TYPE =
477 new MetaPropertyName<Type>(StpExBase.METADATA_NAMESPACE, "type");
478
479 /**
480 * Returns the value of the {@link #TYPE TYPE} meta-property as defined by
481 * this StpProperty instance.
482 *
483 * @return A Type enumeration representing the type of this property's
484 * VALUE meta-property.
485 *
486 * @throws WvcmException if this StpProperty instance does not define a value
487 * for the {@link #TYPE TYPE} meta-property.
488 */
489 public Type getType()
490 throws WvcmException;
491
492 /** A PropertyName object for this property. */
493 public static final MetaPropertyName<PropertyName<?>> PROPERTY_NAME =
494 new MetaPropertyName<PropertyName<?>>(StpExBase.METADATA_NAMESPACE, "property-name");
495
496 /**
497 * Returns the value of the {@link #PROPERTY_NAME PROPERTY_NAME}
498 * meta-property as defined by this StpProperty instance. Note that this
499 * meta-property is always defined by a property and does not need to be
500 * requested.
501 *
502 * @return This object as a PropertyName.
503 */
504 public PropertyName<T> getPropertyName();
505
506 /** The simple name for this property. */
507 public static final MetaPropertyName<String> NAME =
508 new MetaPropertyName<String>(StpExBase.METADATA_NAMESPACE, "name");
509
510 /**
511 * Returns the value of the {@link #NAME NAME} meta-property as defined by
512 * this StpProperty instance. Note that this meta-property is always defined
513 * by a property and does not need to be requested.
514 *
515 * @return A string representing the simple name of this property's
516 * PropertyName
517 */
518 public String getName();
519
520 /** The namespace for this property. */
521 public static final MetaPropertyName<String> NAMESPACE =
522 new MetaPropertyName<String>(StpExBase.METADATA_NAMESPACE, "namespace");
523
524 /**
525 * Returns the value of the {@link #NAMESPACE NAMESPACE} meta-property as
526 * defined by this StpProperty instance. Note that this meta-property is
527 * always defined by a property and does not need to be requested.
528 *
529 * @return A String representing the namespace in which this property is
530 * defined.
531 */
532 public String getNamespace();
533
534 /** The resource of which this is a property. */
535 public static final MetaPropertyName<Resource> RESOURCE =
536 new MetaPropertyName<Resource>(StpExBase.METADATA_NAMESPACE, "resource");
537
538 /**
539 * Returns the value of the {@link #RESOURCE RESOURCE} meta-property as
540 * defined by this StpProperty instance.
541 *
542 * @return A Resource proxy for the resource this property belongs to.
543 *
544 * @throws WvcmException if this StpProperty instance does not define a
545 * value for the {@link #RESOURCE RESOURCE} meta-property
546 * component.
547 */
548 public Resource getResource()
549 throws WvcmException;
550
551 /**
552 * A metric relating to the size of the property value, such as the number
553 * of characters in a string, or the number of items in a list. Not all
554 * properties define this meta-property; see the property documentation.
555 */
556 public static final MetaPropertyName<Long> SIZE =
557 new MetaPropertyName<Long>(StpExBase.METADATA_NAMESPACE, "size");
558
559 /**
560 * Returns the value of the {@link #SIZE SIZE} meta-property as defined by
561 * this StpProperty instance.
562 *
563 * @return An non-negative integer.
564 *
565 * @throws WvcmException if this StpProperty instance does not define a
566 * value for the {@link #SIZE SIZE} meta-property component.
567 */
568 public long getSize()
569 throws WvcmException;
570
571 /**
572 * Whether or not the value of this property is empty/null. Not all
573 * properties define this meta-property; see the property documentation.
574 */
575 public static final MetaPropertyName<Boolean> IS_EMPTY =
576 new MetaPropertyName<Boolean>(StpExBase.METADATA_NAMESPACE, "is-empty");
577
578 /**
579 * Returns the value of the {@link #IS_EMPTY IS_EMPTY} meta-property as
580 * defined by this StpProperty instance.
581 *
582 * @return <b>true</b> if the value of this StpProperty is empty or null;
583 * <b> false</b> otherwise.
584 *
585 * @throws WvcmException if this StpProperty instance does not define a
586 * value for the {@link #IS_EMPTY IS_EMPTY} meta-property
587 * component.
588 */
589 public boolean getIsEmpty()
590 throws WvcmException;
591 }