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 */
013package com.ibm.rational.wvcm.stp;
014
015
016import static com.ibm.rational.wvcm.stpex.StpExBase.PROPERTY_NAMESPACE;
017
018import java.lang.annotation.ElementType;
019import java.lang.annotation.Retention;
020import java.lang.annotation.RetentionPolicy;
021import java.lang.annotation.Target;
022
023import javax.wvcm.Feedback;
024import javax.wvcm.PropertyNameList.PropertyName;
025import javax.wvcm.PropertyRequestItem;
026import javax.wvcm.Resource;
027import javax.wvcm.WvcmException;
028
029import com.ibm.rational.wvcm.stp.StpProperty.MetaPropertyName;
030import com.ibm.rational.wvcm.stpex.StpExBase;
031
032/**
033 * A proxy for a resource persisted in a repository or in a file area.
034 */
035public 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}