001    /*
002     * file StpResource.java
003     *
004     * Licensed Materials - Property of IBM
005     * Restricted Materials of IBM 
006     *
007     * com.ibm.rational.wvcm.stp.StpResource
008     *
009     * (C) Copyright IBM Corporation 2004, 2011.  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    package com.ibm.rational.wvcm.stp;
014    
015    
016    import static com.ibm.rational.wvcm.stpex.StpExBase.PROPERTY_NAMESPACE;
017    
018    import java.lang.annotation.ElementType;
019    import java.lang.annotation.Retention;
020    import java.lang.annotation.RetentionPolicy;
021    import java.lang.annotation.Target;
022    
023    import javax.wvcm.Feedback;
024    import javax.wvcm.PropertyNameList.PropertyName;
025    import javax.wvcm.PropertyRequestItem;
026    import javax.wvcm.Resource;
027    import javax.wvcm.WvcmException;
028    
029    import com.ibm.rational.wvcm.stp.StpProperty.MetaPropertyName;
030    import com.ibm.rational.wvcm.stpex.StpExBase;
031    
032    /**
033     * A proxy for a resource persisted in a repository or in a file area.
034     */
035    public interface StpResource extends javax.wvcm.Resource
036    {
037        /**
038         * Returns true iff it can be determined that this proxy references the same
039         * resource as the given proxy. Proxy equality is based either on the value
040         * of the proxy's Location or on the value of the proxy's
041         * RESOURCE_IDENTIFIER property.
042         * <p>
043         * This proxy equates to another proxy iff one of the following conditions
044         * is true...
045         * <ul>
046         * <li>The location() of this proxy equals the location() of the other
047         * proxy, OR
048         * <li>The other proxy defines the RESOURCE_IDENTIFIER property and the
049         * location().string() of this proxy equals the RESOURCE_IDENTIFIER of the
050         * other proxy, OR
051         * <li>This proxy defines the RESOURCE_IDENTIFIER property and it equals
052         * the location().string() of the other proxy, OR
053         * <li>Both proxies define the RESOURCE_IDENTIFIER property and they are
054         * equal
055         * </ul>
056         * 
057         * @param rhs The Object against which to compare this proxy. If the Object
058         *            is not a Resource, equals returns <b>false</b>.
059         * @return <b>true</b> if the proxies compare equal as defined above;
060         *         <b>false</b> otherwise.
061         * @see Object#equals(java.lang.Object)
062         */
063        boolean equals(Object rhs);
064    
065        /**
066         * Returns the hashCode() for the value of this proxy's RESOURCE_IDENTIFIER
067         * property if the proxy has a value for it; otherwise returns the
068         * hashCode() for the proxy's Location object.
069         * 
070         * @see Object#hashCode()
071         */
072        int hashCode();
073    
074        /**
075         * Returns the collection of metadata components defined in this proxy for a
076         * given PropertyName.
077         * 
078         * @param name A PropertyName identifying the property whose metadata is
079         *            desired
080         * @return An StpProperty instance that contains the metadata for the given
081         *         property requested from the server through this proxy.
082         * @throws WvcmException if no metadata for the given property has been
083         *             requested from the server through this proxy.
084         */
085        <T> StpProperty<T> getMetaProperties(PropertyName<T> name)
086            throws WvcmException;
087    
088        /**
089         * Request the properties specified in <code>feedback</code> from the
090         * server resource represented by this proxy. A new proxy will be
091         * constructed whose property map contains just the requested properties.
092         * <p>
093         * Properties are computed relative to the given context. For example, the
094         * {@link com.ibm.rational.wvcm.stp.cc.CcVersion#VIEW_RELATIVE_PATH VIEW_RELATIVE_PATH}
095         * property of a CcVersion or CcElement resource can only be provided in the
096         * context of a CcView. Hence, you would use this form of doReadProperties
097         * to specify the CcView context that should be used.
098         * 
099         * @param context An optional proxy (often CcView) providing context for the
100         *            generation of certain properties in the returned report. 
101         *            May be <b>null</b>.
102         * @param feedback Provides optional feedback to the caller for long-running
103         *            requests and/or a list of properties desired from the server.
104         *            If the parameter is null or empty, a request is still made,
105         *            and the returned proxy will have only the properties always
106         *            requested from the server.
107         * @return A proxy containing the properties retrieved from the server (and
108         *         error messages for those that could not be retrieved). The class
109         *         of the returned proxy is the one most suited to the type of
110         *         resource addressed.
111         * 
112         * @throws WvcmException if failures occur
113         * 
114         * @see StpResource#doReadProperties(Feedback)
115         */
116        Resource doReadProperties(Resource context,
117                                  Feedback feedback) throws WvcmException;
118    
119        /**
120         * Returns whether or not from this proxy uncorrupted property values can be
121         * obtained for all the properties and meta-properties specified by a given
122         * PropertyRequestItem, which may specify multiple and nested properties.
123         * <p>
124         * If <code>wantedProp</code> is a nested property request then the test
125         * is applied recursively to the non-null value(s) of the property named by
126         * <code>wantedProp.getRoot()</code> testing in each value for valid
127         * instances of the properties named by <code>wantedProp.getNested()</code>.
128         * If any of the values identified by the property name are invalid, then
129         * this method returns <code>false</code>. Note that if the value for the
130         * root property of a PropertyName is <code>null</code>, the test for
131         * that PropertyName is deemed valid even if the PropertyName had nested
132         * properties.
133         * 
134         * @param wantedProp A PropertyRequestItem, possibly with multiple nested
135         *            properties, to check the value for. Cannot be
136         *            <code>null</code>.
137         * 
138         * @return <code>true</code> if there is an entry in this proxy for all
139         *         properties named at the top level of the PropertyRequestItem, and
140         *         those entries contain a valid value (not in error) and for those
141         *         property values that are resources any nested property request is
142         *         also similarly satisfied; <code>false</code> otherwise.
143         */
144        boolean hasProperties(PropertyRequestItem wantedProp);
145    
146        /**
147         * Sets the value of the specified property in this resource proxy.
148         * This method differs from setProperty() in that this method does not mark
149         * the property "dirty", so subsequent calls to doWriteProperties() or other
150         * "do()" methods will not commit this new value to the underlying resource.
151         * @param name the name of the property.
152         * @param value the new value of the specified property.
153         * @see #setProperty
154         * @see #getProperty
155         */
156        public <T> void setPropertyClean(PropertyName<T> name, T value);
157    
158        /**
159         * Returns the StpPropertyException that would be thrown by getProperty if
160         * it were called with the given PropertyName.
161         * 
162         * <p>
163         * If there was an error retrieving the property when requested, or the
164         * property was never defined in the proxy, an {@link StpPropertyException}
165         * is returned; otherwise <b>null</b> is returned.
166         * 
167         * @param propertyName The property for which an exception is desired.
168         *            Cannot be <b>null</b>.
169         * 
170         * @return The exception that would be thrown by getProperty() if it were
171         *         used to access the given <code>propertyName</code>; Will be
172         *         <b> null</b> if no exception would be thrown.
173         */
174        StpException getPropertyException(PropertyName<?> propertyName);
175    
176        /**
177         * The most human-readable location for a resource. This is the form of
178         * location that clients should show to users when a precise location must
179         * be displayed--e.g. one which the user must remember and re-enter in a
180         * subsequent session. When such precision is not needed, the
181         * {@link javax.wvcm.Resource#DISPLAY_NAME} property would be a better
182         * choice for the presentation.
183         * <p>
184         * The USER_FRIENDLY_LOCATION is <i>usually</i> expressed by a
185         * user-friendly-selector scheme location, but other location schemes may
186         * also be used depending on the type of resource.
187         * <p>
188         * The value of this property is <i>not</i> always defined for every
189         * resource. If a resource does not have a USER_FRIENDLY_LOCATION, that is a
190         * strong indication that that resource should not be part of the normal
191         * object model presented to the user. If not defined, the value will be an
192         * empty string.
193         * <p>
194         * Note that the location used by a proxy returned by the server is
195         * formatted to provide the most efficient access to the resource in
196         * subsequent interactions with the server in the current session. That
197         * location is not necessarily the same as the resource's
198         * USER_FRIENDLY_LOCATION or its STABLE_LOCATION.
199         * 
200         * @see #STABLE_LOCATION
201         * @see #EFFICIENT_LOCATION
202         */
203        PropertyName<StpLocation> USER_FRIENDLY_LOCATION =
204            new PropertyName<StpLocation>(PROPERTY_NAMESPACE,
205                                          "user-friendly-location");
206    
207        /**
208         * Returns the value of the
209         * {@link #USER_FRIENDLY_LOCATION USER_FRIENDLY_LOCATION} property as
210         * defined by this proxy.
211         * 
212         * @return The StpLocation value. Will never be <b>null</b>.
213         * 
214         * @throws WvcmException if this proxy does not define a value for the
215         *             {@link #USER_FRIENDLY_LOCATION USER_FRIENDLY_LOCATION}
216         *             property.
217         */
218        StpLocation getUserFriendlyLocation() throws WvcmException;
219    
220        /**
221         * The most stable (over space and time) location available for this
222         * resource. Clients should use this form of location when archiving
223         * resource references for use between sessions.
224         * <p>
225         * The stable location is <i>usually</i> expressed by a repo-selector
226         * scheme location, but other location schemes may also be used depending on
227         * the type of resource.
228         * <p>
229         * The value of this property is always defined for every resource, but, in
230         * fact, <i>it may not be stable</i>. But, if the resource has a stable
231         * location, that location will be returned by this property.
232         * <p>
233         * The value returned always represents the identifier associated with the
234         * server state of the resource, even if the Resource on which it is
235         * requested has client-side state.
236         * <p>
237         * Note that the location used by a proxy returned by the server is
238         * formatted to provide the <i>most efficient</i> access to the resource in
239         * subsequent interactions with the server in the current session. That
240         * location is not necessarily the same as the resource's
241         * USER_FRIENDLY_LOCATION or its STABLE_LOCATION.
242         * 
243         * @see #USER_FRIENDLY_LOCATION
244         * @see #EFFICIENT_LOCATION
245         */
246        PropertyName<StpLocation> STABLE_LOCATION =
247            new PropertyName<StpLocation>(PROPERTY_NAMESPACE, "stable-location");
248    
249        /**
250         * Returns the value of the {@link #STABLE_LOCATION STABLE_LOCATION}
251         * property as defined by this proxy.
252         * 
253         * @return The StpLocation value. Will never be <b>null</b>.
254         * 
255         * @throws WvcmException if this proxy does not define a value for the
256         *             {@link #STABLE_LOCATION STABLE_LOCATION} property.
257         */
258        StpLocation getStableLocation() throws WvcmException;
259    
260        /**
261         * The most efficient location available for this resource. Clients should
262         * use this form of location when it is not necessary to either show this
263         * location to users, nor to archive resource references for use between
264         * sessions.
265         * <p>
266         * The efficient location is <i>usually</i> expressed by a repo-selector
267         * scheme location, but other location schemes may also be used depending on
268         * the type of resource.
269         * <p>
270         * The value of this property is always defined for every resource, but, in
271         * fact, <i>it may not be more efficient than the other forms</i>. But, if
272         * the resource has an efficient location, that location will be returned by
273         * this property.
274         * <p>
275         * The value returned always represents the identifier associated with the
276         * server state of the resource, even if the Resource on which it is
277         * requested has client-side state.
278         * <p>
279         * This is the location format usually used in the proxies returned from the
280         * server.
281         * 
282         * @see #USER_FRIENDLY_LOCATION
283         * @see #STABLE_LOCATION
284         */
285        PropertyName<StpLocation> EFFICIENT_LOCATION =
286            new PropertyName<StpLocation>(PROPERTY_NAMESPACE, "efficient-location");
287    
288        /**
289         * Returns the value of the {@link #EFFICIENT_LOCATION EFFICIENT_LOCATION}
290         * property as defined by this proxy.
291         * 
292         * @return The StpLocation value for the resources most efficient location.
293         *         Will never be <b>null</b>.
294         * 
295         * @throws WvcmException if this proxy does not define a value for the
296         *             {@link #EFFICIENT_LOCATION EFFICIENT_LOCATION} property.
297         */
298        StpLocation getEfficientLocation() throws WvcmException;
299    
300        /**
301         * Note: the {@link #RESOURCE_IDENTIFIER} property is defined only for
302         * server resources (it's undefined for uncontrolled controllable resources)
303         * and it's value is not available locally via
304         * ControllableResource.readProperties().
305         * 
306         * @see javax.wvcm.Resource#getResourceIdentifier()
307         * @see javax.wvcm.Resource#RESOURCE_IDENTIFIER
308         */
309        public String getResourceIdentifier() throws WvcmException;
310    
311        /**
312         * The authentication realm in which this resource resides. When credentials
313         * are needed to access this resource this is string that should be
314         * presented to the user to identify what the user is to provide credentials
315         * for.
316         */
317        PropertyName<String> AUTHENTICATION_REALM =
318            new PropertyName<String>(PROPERTY_NAMESPACE, "authentication-realm");
319    
320        /**
321         * Returns the value of the {@link #AUTHENTICATION_REALM
322         * AUTHENTICATION_REALM} property as defined by this proxy.
323         * 
324         * @return A String containing the realm identifier passed to the
325         *         authentication callback when accessing this resource.
326         * 
327         * @throws WvcmException if this proxy does not define a value for the
328         *             {@link #AUTHENTICATION_REALM AUTHENTICATION_REALM} property.
329         */
330        String getAuthenticationRealm() throws WvcmException;
331    
332        /** A list of the properties that are currently invalid for this resource */
333        PropertyName<StpProperty.List<StpProperty<?>>> INVALID_PROPERTIES =
334            new PropertyName<StpProperty.List<StpProperty<?>>>(PROPERTY_NAMESPACE,
335                                                               "invalid-properties");
336    
337        /**
338         * Returns the value of the {@link #INVALID_PROPERTIES INVALID_PROPERTIES}
339         * property as defined by this proxy.
340         * 
341         * @return A Property.List of Property objects, each identifying one invalid
342         *         property of this Resource
343         * 
344         * @throws WvcmException if this proxy does not define a value for the
345         *             {@link #INVALID_PROPERTIES INVALID_PROPERTIES} property.
346         */
347        StpProperty.List<StpProperty<?>> getInvalidProperties()
348            throws WvcmException;
349    
350        /**
351         * A list of all the properties that are defined on this resource. The
352         * returned properties can be retrieved as a list using getAllProperties()
353         * or individually, using
354         * {@link javax.wvcm.Resource#getProperty(javax.wvcm.PropertyNameList.PropertyName) getProperty} or an
355         * appropriate getter method.
356         */
357        PropertyName<StpProperty.List<StpProperty<?>>> ALL_PROPERTIES =
358            new PropertyName<StpProperty.List<StpProperty<?>>>(StpExBase.PROPERTY_NAMESPACE,
359                                                               "all-properties");
360    
361        /**
362         * Returns the properties defined in this proxy. Note, this "getter" will
363         * work even if ALL_PROPERTIES was not explicitly requested when building
364         * the proxy.
365         * 
366         * @return An StpProperty.List containing a Property object for each
367         *         property defined by this proxy. If there were errors in
368         *         retrieving any meta-properties (including the VALUE
369         *         meta-property), these errors can be discovered through the
370         *         StpProperty interface.
371         */
372        StpProperty.List<StpProperty<?>> getAllProperties();
373    
374        /**
375         * Returns the custom properties recorded in this proxy. Note, this "getter"
376         * will work even if ALL_CUSTOM_PROPERTIES was not explicitly requested when
377         * building the proxy.
378         * 
379         * @return A Property.List containing a Property object for each custom
380         *         (i.e. not defined by WVCM) property defined by this proxy. If
381         *         there were errors in retrieving any meta-properties (including
382         *         the VALUE meta-property), these errors can be discovered through
383         *         the Property interface.
384         */
385        StpProperty.List<StpProperty<?>> getCustomProperties();
386    
387        /** The StpRepository that contains this resource. */
388        PropertyName<StpRepository> REPOSITORY =
389            new PropertyName<StpRepository>(PROPERTY_NAMESPACE, "repository");
390    
391        /**
392         * Returns the value of the {@link #REPOSITORY} property as defined by this
393         * proxy.
394         * 
395         * @return The StpRepository that this resource is in. Will never be <b>null</b>.
396         * 
397         * @throws WvcmException if this proxy does not define a value for the
398         *             {@link #REPOSITORY} property.
399         */
400        StpRepository getRepository() throws WvcmException;
401    
402        /**
403         * The login name of the user that created this object. A request for this
404         * value can only be satisfied by a request to a server; it is not available
405         * locally.
406         */
407        PropertyName<String> CREATOR_LOGIN_NAME =
408            new PropertyName<String>(PROPERTY_NAMESPACE, "creator-login-name");
409    
410        /**
411         * Returns the value of the {@link #CREATOR_LOGIN_NAME} property as defined
412         * by this proxy.
413         * 
414         * @throws WvcmException Thrown if the property was never requested, or
415         *             otherwise unavailable (e.g. requested in a client-context
416         *             only).
417         */
418        String getCreatorLoginName() throws WvcmException;
419    
420        /**
421         * The group name of the user that created an object. This value can only be
422         * satisfied by a request to the server; it is not available locally.
423         */
424        PropertyName<String> CREATOR_GROUP_NAME =
425            new PropertyName<String>(PROPERTY_NAMESPACE, "creator-group-name");
426    
427        /**
428         * Returns the value of the {@link #CREATOR_GROUP_NAME} property as defined
429         * by this proxy.
430         * 
431         * @throws WvcmException Thrown if the property was never requested, or is
432         *             otherwise unavailable (e.g. requested in a client-context
433         *             only).
434         */
435        String getCreatorGroupName() throws WvcmException;
436    
437        /**
438         * Returns the Location of this proxy's Location cast as an StpLocation.
439         * 
440         * @return The StpLocation for this Resource proxy. Will never be <b>null</b>.
441         */
442        StpLocation stpLocation();
443    
444        /**
445         * Returns the value of the <i>resource error attribute</i> associated with
446         * this proxy.
447         * 
448         * <p>
449         * If this attribute is not null it indicates that an error occurred when
450         * trying to access the resource addressed by this proxy (even though that
451         * address was actually generated by the server). In this case, none of the
452         * properties requested for this proxy will be defined. The value of the
453         * resource error attribute is an StpException that records the nature of
454         * the problem encountered by the server.
455         * 
456         * <p>
457         * This attribute is set only when this proxy is returned as an indirect
458         * result of a server interaction. If this defective address was used by a
459         * client as the target of a server contact method or if it was the expected
460         * direct result of some server contact method, that contact method would
461         * have thrown an exception rather than setting this attribute.
462         * 
463         * <p>
464         * Whenever the server returns a list of resources (either as a direct
465         * response to a request or as the value of a property) it is possible that
466         * the server can enumerate all of the members of the list but cannot
467         * actually access one or more of the enumerated members to access its
468         * properties. When this happens, the operation is not aborted and does not
469         * itself throw an exception. Instead, a proxy is generated and marked with
470         * this resource error attribute so that the problem is record and then the
471         * rest of the list is processed.
472         * 
473         * @return <b>null</b> if no error is associated with the resource,
474         *         otherwise a StpException describing the error.
475         */
476        StpException getResourceError();
477    
478        /**
479         * @return Returns the StpProvider from which this proxy was obtained.
480         */
481        StpProvider stpProvider();
482    
483        /**
484         * Sets the value of a meta-property of a property into this proxy without
485         * causing that property to be written to the resource on the next
486         * repository interaction. Like the setProperty() method, this method does
487         * not verify that the given object is a value suitable for the specified
488         * meta-property. This method also does not verify that the given
489         * PropertyName is appropriate for the type of resource represented by this
490         * proxy nor that the given MetaPropertyName is appropriate for the given
491         * PropertyName.
492         * <p>
493         * This method may be used in conjunction with
494         * {@link StpProvider#buildProxy(StpLocation, String, String) StpProvider.buildProxy()}
495         * to reconstruct proxies previously saved to persistent storage. Use
496         * buildProxy() to construct a proxy object of the appropriate type and then
497         * use this method to copy each saved meta-property value into that proxy
498         * object.
499         * <p>
500         * This method may also be used in conjunction with forgetProperty to merge
501         * meta-property values from one proxy into another and thereby facilitate
502         * the use of a proxy object as a long-lived cache for resource data. This
503         * approach is not recommended unless the client fully understands the
504         * pitfalls inherent in maintaining a cache of shared server data in a
505         * client for any length of time.
506         * <p style="padding-left:47;text-indent:-47">
507         * Note 1: Since the primary intent of this method is to provide the client
508         * with a means to restore a proxy from archive, this method will throw an
509         * exception if an attempt is made to define a meta-property value already
510         * being defined by this proxy.
511         * <p style="padding-left:47">
512         * If a client wants to use this method to update an existing meta-property
513         * entry within a proxy, that existing meta-property value must first be
514         * removed. Since the meta-properties of a property are usually tightly
515         * coupled, they cannot be removed independently. They can only be removed
516         * as a group using the javax.wvcm.forgetProperty() method. If the client
517         * wants to retain some of the existing meta-property values while updating
518         * others, it must first fetch all the existing meta-property values from
519         * the proxy (using getMetaProperties()), then remove their definitions from
520         * the proxy using forgetProperty(), and then redefine the individual
521         * meta-property entries via multiple invocations of this method, reusing
522         * the old values or computing new values in a manner appropriate to the
523         * client's needs.
524         * <p style="padding-left:47;text-indent:-47">
525         * Note 2: Because of its role in the definition of Resource.equals() and
526         * Resource.hashCode(), the Resource.RESOURCE_IDENTIFIER property may only
527         * be initialized at the time of proxy construction; e.g., via
528         * Provider.buildProxy().
529         * <p style="padding-left:47;text-indent:-47">
530         * Note 3: A property value set by any of the setXXX methods defined by this
531         * interface (or any of its extensions) will activate the writing of that
532         * value to the repository by the next doXYZ method. Use of initProperty to
533         * set any of the meta-properties of such a property will fail until the
534         * property is successfully written to the repository.
535         * <p style="padding-left:47;text-indent:-47">
536         * Note 4: If the entry in this proxy for the given PropertyName indicates
537         * that an error occurred on the last attempt to read the property from the
538         * repository, initMetaProperty will fail as if the meta-property being set
539         * were already defined; i.e. it will throw an exception. In this case, the
540         * client must execute forgetProperty() on the invalid entry before
541         * attempting to initialize any of its meta-properties.
542         * 
543         * @param propertyName The PropertyName for the property whose meta-property
544         *            is to be defined by the proxy. Must not be <b>null</b>, must
545         *            not be equal to Resource.RESOURCE_IDENTIFIER, and must not be
546         *            a PropertyName currently on the
547         *            {@link javax.wvcm.Resource#updatedPropertyNameList()}.
548         * @param metaPropertyName The MetaPropertyName for the meta-property whose
549         *            value is to be defined by the proxy. Must not be <b>null</b>
550         *            and must not name a meta-property whose value is already
551         *            defined by this proxy.
552         * @param value The initial value for the meta-property identified by the
553         *            other two arguments of this method. May be <b>null</b>.
554         * @throws WvcmException If the meta-property is already defined by this
555         *             proxy.
556         * 
557         * @see StpProvider#buildProxy(StpLocation, String, String)
558         * @see javax.wvcm.Resource#forgetProperty(javax.wvcm.PropertyNameList.PropertyName)
559         */
560        <T> void initMetaProperty(PropertyName<?> propertyName,
561                                  MetaPropertyName<T> metaPropertyName,
562                                  T value) throws WvcmException;
563    
564        /**
565         * Returns an identifier that may be passed to StpProvider.buildProxy() to
566         * construct a proxy that supports the same interfaces as this proxy.
567         * 
568         * @return A String object containing the proxy class information; will
569         *         never be <b>null</b>.
570         */
571        String proxyType();
572    
573        /**
574         * An annotation used on property getters or setters of a proxy interface to
575         * indicate that a property defined in a super interface is not supported by
576         * that proxy.
577         */
578        @Retention(RetentionPolicy.RUNTIME)
579        @Target(ElementType.METHOD)
580        public @interface UnsupportedProperty {
581            /**
582             * @return The StpReasonCode of the StpException that will be thrown if
583             *         the annotated method is used.
584             */
585            StpException.StpReasonCode value();
586        }
587    }