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
014package com.ibm.rational.wvcm.stp;
015
016import static com.ibm.rational.wvcm.stpex.StpExBase.METADATA_NAMESPACE;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import javax.wvcm.PropertyNameList;
022import javax.wvcm.Resource;
023import javax.wvcm.WvcmException;
024import javax.wvcm.PropertyNameList.PropertyName;
025
026import com.ibm.rational.wvcm.stp.cq.CqFieldValue.ValueType;
027import com.ibm.rational.wvcm.stpex.StpExBase;
028import com.ibm.rational.wvcm.stpex.StpExEnumeration;
029import 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 */
206public 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}