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    }