001/*
002 * file Resource.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM
006 *
007 * (c) Copyright IBM Corporation 2004, 2008.  All Rights Reserved. 
008 * Note to U.S. Government Users Restricted Rights:  Use, duplication or  
009 * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp. 
010 */
011package javax.wvcm;
012
013import java.io.InputStream;
014import java.io.OutputStream;
015import java.util.Collection;
016import java.util.Date;
017import java.util.List;
018import java.util.Locale;
019
020import javax.wvcm.PropertyNameList.PropertyName;
021import javax.wvcm.ResourceList.ResponseIterator;
022import javax.wvcm.WvcmException.ReasonCode;
023
024
025/**
026 * A proxy for a persistent resource.
027 * 
028 * A proxy for a persistent resource is used to retrieve information from
029 * the resource and to perform operations on the resource.
030 * A resource has both standard properties, which are named values whose
031 * semantics are specified by the API, as well as custom properties
032 * whose names are arbitrary strings selected by the client.
033 * A custom property has a namespace which allows different clients
034 * to use simple property names without conflicting with each other.
035 * <p>
036 * A proxy for a persistent resource contains the location of
037 * that persistent resource on the server that maintains that resource.
038 * A proxy can be created as the return value of a request to the
039 * server, in which case the proxy is initialized with a set of
040 * properties reflecting the state of the persistent resource at
041 * the time of the request (the list of wanted
042 * properties is specified as an argument to the request).
043 * Alternatively, a proxy can be created locally by a client
044 * (using the Provider interface), in which case it is initialized
045 * with an empty set of properties.
046 * <p>
047 * Two proxies are equal if they are known to identify the same resource,
048 * where the identity of a proxy is determined by its {@link Resource#RESOURCE_IDENTIFIER}
049 * property if it has one loaded, and if not, by its {@link Resource#location}.
050 * 
051 * @since 1.0
052 */
053public interface Resource {
054
055    /**
056     * Get the location of this resource.<p>
057     * The format of the location string is specific to the repository that stores
058     * the persistent resource. A URL, a UNC filename, and an NFS filename
059     * are examples of possible formats for a location string.
060     *
061     * @return the location of the persistent resource for which this
062     * Resource is a proxy.
063     */
064    public Location location();
065
066    /**
067     * Modify the location of this resource.
068     * This does not affect the value of any property of this proxy.
069     */
070    public void modifyLocation(Location location);
071
072    /**
073     * Get the provider of this resource.
074     * 
075     * @return the {@link Provider} for this Resource.
076     */
077    public Provider provider();
078
079    // Resource properties
080
081    /**
082     * Get the names of standard properties available on the server resource
083     * identified by this Resource.
084     * 
085     * @param feedback Provides optional feedback to the caller for long-running requests.
086     * @return the list of names of standard properties available on the server
087     * resource identified by this Resource.
088     * @throws WvcmException if problems encountered communicating with server
089     */
090    public PropertyNameList doGetPropertyNameList(Feedback feedback)
091    throws WvcmException;
092
093    /**
094     * Get the names of properties in a given namespace available
095     * on the server resource identified by this Resource.
096     * 
097     * @param namespace the namespace for the requested property names.
098     * @param feedback Provides optional feedback to the caller for long-running requests.
099     * @return the list of names of properties in the specified namespace
100     * available on the server resource identified by this Resource.
101     * If the namespace is null, the system property names are listed.
102     * If the namespace is not null, the user-defined properties
103     * in that namespace are listed.
104     * @throws WvcmException if problems encountered communicating with server
105     */
106    public PropertyNameList doGetPropertyNameList(String namespace, Feedback feedback)
107    throws WvcmException;
108
109    /**
110     * Get a set of properties of this Resource from the server.
111     * Like all doXyz methods, any modified properties in this Resource
112     * are first written to the resource before the properties are read
113     * from the resource.  Note that this makes doReadProperties semantically
114     * identical to {@link #doWriteProperties}.
115     * 
116     * @param feedback the properties to be available in the returned proxy,
117     *  and any other feedback desired, such as progress indications.
118     * @return a Resource proxy for this resource containing the wanted properties.
119     * A requested property named XYZ can be retrieved from
120     * the resource with the <code>getXyz</code> method, when a
121     * <code>getXyz</code> method is defined in the interface.
122     * @throws WvcmException if problems encountered communicating with server or
123     * if modified properties cannot be written (see {@link #doWriteProperties}. 
124     */
125    public Resource doReadProperties(Feedback feedback) throws WvcmException;
126
127    /**
128     * Get the names of properties available on this client proxy.
129     * A property is available if it would not throw an exception if
130     * retrieved from this proxy.
131     * One difference between this and wantedPropertyRequestList
132     * is that {@link #ALL_CUSTOM_PROPERTIES} would appear in wantedPropertyRequestList,
133     * but the actual property names would appear in propertyNameList.
134     * In addition, failing to retrieve a property would cause a property
135     * to not appear in propertyNameList, 
136     * setting a property would add that property to propertyNameList,
137     * and forgetting or removing a property would remove that property
138     * from propertyNameList.
139     * @return the list of names of properties available on this client proxy.
140     */
141    public PropertyNameList propertyNameList();
142
143    /**
144     * Get a list of modified properties that have been updated in the proxy
145     * by setXyz operations, but not been successfully written to the
146     * corresponding persistent resource by a doXyz operation.
147     * @return the names of properties that have been updated in
148     * the proxy, but the updates have not yet been successfully
149     * applied to the resource. 
150     */
151    public PropertyNameList updatedPropertyNameList();
152
153    /**
154     * Persists property changes to this Resource.
155     * An exception is thrown if any of properties cannot be written.
156     * If an exception is thrown, the properties that were not be written
157     * can be determined from {@link #updatedPropertyNameList}
158     * on this Resource.
159     * Note that since doWriteProperties returns a new proxy whose properties are
160     * specified in the feedback argument, doWriteProperties is semantically identical
161     * to {@link #doReadProperties}.
162     * <p>
163     * Postconditions:
164     * <li>(auto-checkout-controlled-property): If the property is controlled,
165     *  and if this resource was a checked-in controlled,
166     *  resource, this resource MUST have been checked out by this request.
167     * 
168     * @param feedback Specifies optional feedback to the caller.
169     * @return a new proxy for this resource, whose properties are specified by feedback.
170     * @throws WvcmException ReasonCode:
171     * <li>{@link ReasonCode#PROPERTY_OVERWRITE_FORBIDDEN}:
172     * This property has been updated by another client after this proxy was created.
173     * <li>{@link ReasonCode#CANNOT_MODIFY_PROTECTED_PROPERTY}:
174     * Some properties cannot be directly updated.
175     * <li>{@link ReasonCode#CANNOT_MODIFY_VERSION}:
176     *  If this proxy identifies a version, the request MUST fail
177     *  unless the property is explicitly defined to be modifiable on a 
178     *  version.
179     * <li>Since this method may cause a checkout to be attempted on this resource,
180     *  see {@link ControllableResource#doCheckin} for additional reason codes.
181     */
182    public Resource doWriteProperties(Feedback feedback) throws WvcmException;
183
184    /**
185     * Get both the content and selected properties of this resource.
186     * 
187     * @param content the resource content is written to this
188     * byte stream.  The stream is then closed.
189     * @param feedback Specifies optional feedback to the caller.
190     * @return a new proxy for this resource, whose properties are specified by feedback.
191     * @throws WvcmException ReasonCode:
192     * <li>{@link ReasonCode#METHOD_NOT_SUPPORTED}:
193     * This resource has no content.
194     */
195    public Resource doReadContent(
196            OutputStream content, 
197            Feedback feedback)
198    throws WvcmException;
199
200    /**
201     * Persists content changes to a resource.
202     * <p>
203     * Postconditions:
204     * <li>(auto-checkout-controlled-content): If this resource was a checked-in controlled,
205     *  resource, this resource MUST have been checked out by this request.
206     * 
207     * @param content if <code>contentIdentifier</code> matches the current
208     * content identifier of the persistent resource,
209     * the content of the resource is replaced with the
210     * bytes read from <code>content</code>, and <code>content</code>
211     * is then closed.</p>
212     * @param contentIdentifier if this {@link #getContentIdentifier content identifier}
213     *  does not match
214     * the content identifier of the persistent resource, the persistent
215     * resource is left unaltered, and a WvcmException is thrown.
216     * <p>
217     * If reading from the stream throws a <code>java.io.IOException</code>,
218     * then no further data will be read from the stream,
219     * and after attempting to close the stream, a <code>WvcmException</code>
220     * wrapping the <code>IOException</code> is thrown,
221     * possibly leading to incomplete data being stored on the resource.</p>
222     * @param feedback Specifies optional feedback to the caller.
223     * @return a new proxy for this resource, whose properties are specified by feedback.
224     * @throws WvcmException ReasonCode:
225     * <li>{@link ReasonCode#CANNOT_MODIFY_VERSION}:
226     *  If this proxy identifies a version, the request MUST fail.
227     * <li>Since this method may cause a checkout to be attempted on this resource,
228     *  see {@link ControllableResource#doCheckin} for additional reason codes.
229     */
230    public Resource doWriteContent(InputStream content, String contentIdentifier, Feedback feedback)
231    throws WvcmException;
232
233    /** Boolean flags for the doCopy method */
234    public static enum CopyFlag 
235    {
236        /** 
237         * Indicates whether to overwrite an existing binding in the destination folder
238         */
239        OVERWRITE("overwrite"); //$NON-NLS-1$
240
241        private CopyFlag(String flagName) { _flagName = flagName; }
242
243        /**
244         * Returns a string representation of this flag suitable for diagnostics.
245         */
246        @Override
247        public String toString() { return _flagName; }
248
249        /**
250         * The string form of this flag.
251         */
252        private final String _flagName;
253
254    }
255
256    /**
257     * Create a copy of the resource identified by this Resource
258     * at the location identified by the <code>destination</code>.
259     * The content of the copy is the same as the content of the
260     * resource identified by this Resource, but the properties of the
261     * copy are the default properties for a new resource.
262     * <p>
263     * Postconditions:
264     * <li>(must-not-copy-resource-identifier): The copy must be a different resource.
265     *  In particular, it must have a different resource identifier.
266     * <li>(copy-creates-new-resource): If the source of a doCopy is a controlled resource
267     *  or a version,
268     *  and if there is no resource at the destination of the doCopy,
269     *  then the doCopy creates a new uncontrolled resource at the destination of the doCopy.
270     * 
271     * @param destination the location of the new resource created by doCopy.
272     * @param flags Array of boolean flags (may be null):
273     * <li>{@link CopyFlag#OVERWRITE}:
274     *  Indicates whether an existing destination resource
275     *  will be overwritten rather than the request failing.
276     * @param feedback Specifies optional feedback to the caller.
277     * @return a new proxy for this resource, whose properties are specified by feedback.
278     * @throws WvcmException ReasonCode:
279     * <li>{@link ReasonCode#CANNOT_OVERWRITE}:
280     *  If there already is a resource at the destination,
281     *  and the <code>overwrite</code> is <code>false</code>, the request MUST fail.
282     * <li>{@link ReasonCode#METHOD_NOT_SUPPORTED}:
283     *  This proxy MUST NOT identify a folder version or a version history.
284     *  In order to create another version history whose versions have the same content,
285     *  the appropriate sequence of doVersionControl, doCheckout, doWriteContent, and doCheckin requests must be made.
286     */
287    public Resource doCopy(Location destination, CopyFlag[] flags, Feedback feedback)
288    throws WvcmException;
289
290    /**
291     * Unbinds the resource identified by this Resource
292     * from all folders in its {@link #PARENT_LIST}.
293     * 
294     * See {@link Folder#doUnbindChild}.
295     */
296    public void doUnbindAll(Feedback feedback) throws WvcmException;
297
298    /**
299     * Find a persistent resource that "matches" this proxy.
300     * For example, 
301     * <pre>
302     *   Activity activityExample = WorkspaceProvider.activity(WorkspaceProvider.location("/my-act-repo")):
303     *   activityExample.setCreatorDisplayName("Geoff Clemm");
304     *   Activity activity = (Activity)activityExample.doFind(null);
305     * </pre> 
306     * would return an activity in "/my-act-repo" created by "Geoff Clemm".
307     * Unlike most doXyz methods, this method does not save changes to the proxy 
308     * before executing the query. In particular, it is valid to execute 
309     * this method on a proxy that could not be saved by {@link #doWriteProperties}.
310     * <p>The precise rules for matching are as follows:
311     * <li>A proxy Q matches a resource R if the type of Q "matches" the type of R,
312     *  if the location of Q "matches" the location of R,
313     *  and if for each loaded property P of the proxy Q,
314     *  Q.P.value (the value of the property P of the proxy Q) "matches" R.P.value
315     *  (the value of the property P of the resource R).
316     *  Note that a property is loaded into a proxy as the result of reading properties values
317     *  from the repository when creating the proxy (e.g., {@link #doReadProperties})
318     *  or by explicitly setting property values (e.g., {@link #setComment}
319     *  or more generally, {@link #setProperty}).
320     * <li>The type of a proxy matches the type of a resource if the resource implements the
321     *  result type of the method used to create the proxy.  So for example, if the proxy was
322     *  created by {@link WorkspaceProvider#workspace}, to match that proxy a resource
323     *  must implement the {@link Workspace} interface.
324     * <li>The location of a proxy Q matches the location of a resource R
325     *  if the resource identified by the location of Q would be in the same "repository" as R.
326     *  Note that whether or not a resource would be in the same repository as another
327     *  resource is decided by the implementation of the {@link #doFind} method. 
328     * <li>If Q.P.value is not a list and R.P.value is a list, then Q.P.value matches
329     *  R.P.value if Q.P.value matches at least one object in R.P.value.
330     * <li>If Q.P.value is a list of proxies, and R.P.value is not a list, then Q.P.value matches
331     *  R.P.value if at least one proxy in Q.P.value matches R.P.value.
332     * <li>If Q.P.value is a list of proxies, and R.P.value is a list, then Q.P.value matches
333     *  R.P.value if at least one proxy in Q.P.value matches at least one object in R.P.value.
334     * <li>If Q.P is Resource.PATHNAME_LOCATION, then Q matches R if R is the resource
335     *  identified by Q.P.value.
336     * <li>Otherwise, Q.P.value matches R.P.value if Q.P.value {@link Object#equals} R.P.value.
337     * 
338     * @param feedback the properties to be available in the returned resources.
339     * @return a proxy for a persistent resource that matches this Resource.
340     * If none found, <code>null</code> is returned.
341     * @throws WvcmException if problems encountered communicating with server
342     * or if the request could not be executed.
343     */
344    public Resource doFind(Feedback feedback)
345    throws WvcmException;    
346
347
348    /**
349     * Find all persistent resources that "match" this proxy.
350     * For example, 
351     * <pre>
352     *   Activity activityExample = WorkspaceProvider.activity(WorkspaceProvider.location("/my-act-repo")):
353     *   activityExample.setCreatorDisplayName("Geoff Clemm");
354     *   ResponseIterator myActivities = activityExample.doFindAll(null);
355     * </pre> 
356     * would return all activities in "/my-act-repo" created by "Geoff Clemm".
357     * See {@link #doFind}.
358     * 
359     * @param feedback the properties to be available in the returned resources.
360     * @return proxies for persistent resources that that match this Resource.
361     * @throws WvcmException if problems encountered communicating with server
362     * or if the request could not be executed.
363     */
364    public <T extends Resource> ResponseIterator<T> doFindAll(Feedback feedback)
365    throws WvcmException;    
366
367
368//  Resource Properties
369
370    /**
371     * A list of folders that contain workspaces that are being managed
372     * by the same server that is managing this resource.
373     */
374    public static final PropertyName<ResourceList<Folder>> WORKSPACE_FOLDER_LIST =
375        new PropertyName<ResourceList<Folder>>("workspace-folder-list"); //$NON-NLS-1$
376
377    /**
378     * Get the {@link #WORKSPACE_FOLDER_LIST} property.
379     * 
380     * @return the {@link #WORKSPACE_FOLDER_LIST} property.
381     * @throws WvcmException if this Resource was not created with
382     * {@link #WORKSPACE_FOLDER_LIST} as a wanted property.
383     */
384    public ResourceList<Folder> getWorkspaceFolderList() throws WvcmException;
385
386    /**
387     * A list of names of alternative providers for the
388     * persistent resource identified by this resource.
389     * Provider names are class names, and {@link Provider} objects
390     * can be generated from provider names using {@link ProviderFactory#createProvider(String,ProviderFactory.Callback)}.
391     * The preferred providers are specified earlier in the list.
392     */
393    public static final PropertyName<List<String>> PROVIDER_LIST =
394        new PropertyName<List<String>>("provider-list"); //$NON-NLS-1$
395
396    /**
397     * Get the {@link #PROVIDER_LIST} property.
398     * 
399     * @return the {@link #PROVIDER_LIST} property.
400     * @throws WvcmException if this Resource was not created with
401     * {@link #PROVIDER_LIST} as a wanted property.
402     */
403    public List<String> getProviderList()
404    throws WvcmException;
405
406    /**
407     * A resource identifier is an optional unique and immutable identifier for a resource.
408     * The resource identifier may be used to test whether two proxies
409     * identify the same persistent resource.
410     * The resource identifier is the string form of a stable location for the resource,
411     * where a stable location is a location that is not affected by moves/renames
412     * by {@link Folder#doRebindChild} or by the addition/removal of additional locations for the
413     * resource by {@link Folder#doBindChild} and {@link Folder#doUnbindChild}.
414     * <p>
415     * If {@link Provider#location} can be applied to the resource identifier of a resource
416     * to produces a valid location, then that location MUST identify that resource.
417     */
418    public static final PropertyName<String> RESOURCE_IDENTIFIER =
419        new PropertyName<String>("resource-id"); //$NON-NLS-1$
420
421    /**
422     * Get the {@link #RESOURCE_IDENTIFIER} property.
423     * 
424     * @return the {@link #RESOURCE_IDENTIFIER} property.
425     * @throws WvcmException if this Resource was not created with
426     * {@link #RESOURCE_IDENTIFIER} as a wanted property.
427     */
428    public String getResourceIdentifier()
429    throws WvcmException;
430
431    /**
432     * A location for this resource to which {@link Location#parent} can be applied
433     * zero or more times to produce a location for a folder in either
434     * the {@link Resource#WORKSPACE_FOLDER_LIST} of this resource, or for a folder in
435     * the {@link Workspace#ACTIVITY_FOLDER_LIST} or {@link Workspace#VERSION_HISTORY_FOLDER_LIST}
436     * of some workspace that is a member of a folder in {@link Resource#WORKSPACE_FOLDER_LIST}.
437     */
438    public static final PropertyName<Location> PATHNAME_LOCATION =
439        new PropertyName<Location>("pathname-location"); //$NON-NLS-1$
440
441    /**
442     * Get the {@link #PATHNAME_LOCATION} property.
443     * 
444     * @return the {@link #PATHNAME_LOCATION} property.
445     * @throws WvcmException if this Resource was not created with
446     * {@link #PATHNAME_LOCATION} as a wanted property.
447     */
448    public Location getPathnameLocation() throws WvcmException;
449
450    /**
451     * The PARENT_LIST property enables
452     * clients to discover what folders contain a binding to this resource
453     * (that is, which folders have this resource as a bound member).
454     * The value of the PARENT_LIST property is a list of 
455     * {@link Folder} objects.
456     */
457    public static final PropertyName<ResourceList<Folder>> PARENT_LIST =
458        new PropertyName<ResourceList<Folder>>("parent-list"); //$NON-NLS-1$
459
460    /**
461     * Get the {@link #PARENT_LIST} property.
462     * 
463     * @return the {@link #PARENT_LIST} property.
464     * @throws WvcmException if this Resource was not created with
465     * {@link #PARENT_LIST} as a wanted property.
466     */
467    public ResourceList<Folder> getParentList()
468    throws WvcmException;
469
470    /**
471     * Contains a description of the resource that is suitable
472     * for presentation to a user in a tree display.
473     * <p>
474     * Note that the {@link #DISPLAY_NAME} of a resource is in general
475     * not the binding name of that resource in its parent folder,
476     * because at a given time, a resource can be bound into
477     * multiple parent folders, and have a different binding name in
478     * each parent folder. </p>
479     */
480    public static final PropertyName<String> DISPLAY_NAME =
481        new PropertyName<String>("display-name"); //$NON-NLS-1$
482
483    /**
484     * Get the {@link #DISPLAY_NAME} property.
485     * 
486     * @return the {@link #DISPLAY_NAME} property.
487     * @throws WvcmException if this property was not set and
488     * this Resource was not created with
489     * {@link #DISPLAY_NAME} as a wanted property.
490     * @see #setDisplayName
491     */
492    public String getDisplayName() throws WvcmException;
493
494    /**
495     * Set the {@link #DISPLAY_NAME} property.
496     * 
497     * @param val the new display name to apply to the resource.
498     * @see #getDisplayName
499     */
500    public void setDisplayName(String val);
501
502    /**
503     * A brief comment about a resource that
504     * is suitable for presentation to a user.  The comment of a version
505     * can be used to indicate why that version was created.
506     */
507    public static final PropertyName<String> COMMENT =
508        new PropertyName<String>("comment"); //$NON-NLS-1$
509
510    /**
511     * Get the {@link #COMMENT} property.
512     * @return the {@link #COMMENT} property.
513     * @throws WvcmException if this property was not set and
514     * this Resource was not created with
515     * {@link #COMMENT} as a wanted property.
516     * @see #setComment
517     */
518    public String getComment() throws WvcmException;
519
520    /**
521     * Set the {@link #COMMENT} property.
522     * 
523     * @param comment the new comment to apply to this Resource.
524     * @see #getComment
525     */
526    public void setComment(String comment);
527
528    /**
529     * This property contains a description of the creator of the resource
530     * that is suitable for presentation to a user.  The {@link #CREATOR_DISPLAY_NAME}
531     * of a version can be used to indicate who created that version.
532     * A server may automatically set the {@link #CREATOR_DISPLAY_NAME} property
533     * and not allow it to be changed by a client.
534     */
535    public static final PropertyName<String> CREATOR_DISPLAY_NAME =
536        new PropertyName<String>("creator-display-name"); //$NON-NLS-1$
537
538    /**
539     * Get the {@link #CREATOR_DISPLAY_NAME} property.
540     * 
541     * @return the {@link #CREATOR_DISPLAY_NAME} property.
542     * @throws WvcmException if this property was not set and
543     * this Resource was not created with
544     * {@link #CREATOR_DISPLAY_NAME} as a wanted property.
545     * @see #setCreatorDisplayName
546     */
547    public String getCreatorDisplayName() throws WvcmException;
548
549    /**
550     * Set the {@link #CREATOR_DISPLAY_NAME} property.
551     * 
552     * @param val the new creator display name to apply to the resource.
553     * @see #getCreatorDisplayName
554     */
555    public void setCreatorDisplayName(String val);
556
557    /** The date and time the resource was created. */
558    public static final PropertyName<Date> CREATION_DATE =
559        new PropertyName<Date>("creation-date"); //$NON-NLS-1$
560
561    /**
562     * Get the {@link #CREATION_DATE} property.
563     * 
564     * @return the {@link #CREATION_DATE} property.
565     * @throws WvcmException if this Resource was not created with
566     * {@link #CREATION_DATE} as a wanted property
567     */
568    public Date getCreationDate() throws WvcmException;
569
570    /**
571     * The date and time the content of the resource was last modified.
572     */
573    public static final PropertyName<Date> LAST_MODIFIED =
574        new PropertyName<Date>("last-modified"); //$NON-NLS-1$
575
576    /**
577     * Get the {@link #LAST_MODIFIED} property.
578     * 
579     * @return the {@link #LAST_MODIFIED} property.
580     * @throws WvcmException if this Resource was not created with
581     * {@link #LAST_MODIFIED} as a wanted property.
582     */
583    public Date getLastModified() throws WvcmException;
584
585    /**
586     * The name of the character set of the resource content.
587     * Character sets names must be registered; see RFC 2278 and 1700
588     */
589    public static final PropertyName<String> CONTENT_CHARACTER_SET =
590        new PropertyName<String>("content-character-set"); //$NON-NLS-1$
591
592    /**
593     * Get the {@link #CONTENT_CHARACTER_SET} property.
594     * @return the {@link #CONTENT_CHARACTER_SET} property.
595     * @throws WvcmException if this property was not set and
596     * this Resource was not created with
597     * {@link #CONTENT_CHARACTER_SET} as a wanted property.
598     * @see #setContentCharacterSet
599     */
600    public String getContentCharacterSet() throws WvcmException;
601
602    /**
603     * Set the {@link #CONTENT_CHARACTER_SET} property.
604     * 
605     * @param contentCharacterSet the content character set for the resource.
606     * @see #getContentCharacterSet
607     */
608    public void setContentCharacterSet(String contentCharacterSet);
609
610    /**
611     * An implementation-defined String identifying the value of the content of a resource.
612     * The semantics of a Content Identifier are the same as that of an HTTP ETag (see RFC 2616).
613     */
614    public static final PropertyName<String> CONTENT_IDENTIFIER =
615        new PropertyName<String>("content-identifier"); //$NON-NLS-1$
616
617    /**
618     * Get the {@link #CONTENT_IDENTIFIER} property.
619     * @return the {@link #CONTENT_IDENTIFIER} property.
620     * @throws WvcmException if this Resource was not created with
621     * {@link #CONTENT_IDENTIFIER} as a wanted property.
622     */
623    public String getContentIdentifier() throws WvcmException;
624
625    /**
626     * The name of the natural language used in a resource content,
627     * represented by a {@link java.util.Locale Locale} object,
628     * with country, language, and variant if appropriate.
629     */
630    public static final PropertyName<Locale> CONTENT_LANGUAGE =
631        new PropertyName<Locale>("content-language"); //$NON-NLS-1$
632
633    /**
634     * Get the {@link #CONTENT_LANGUAGE} property.
635     * @return the {@link #CONTENT_LANGUAGE} property.
636     * @throws WvcmException if this property was not set and
637     * this Resource was not created with
638     * {@link #CONTENT_LANGUAGE} as a wanted property.
639     * @see #setContentLanguage
640     */
641    public Locale getContentLanguage() throws WvcmException;
642
643    /**
644     * Set the {@link #CONTENT_LANGUAGE} property.
645     * 
646     * @param contentLanguage the content language for the resource.
647     * @see #getContentLanguage
648     */
649    public void setContentLanguage(Locale contentLanguage);
650
651    /** The size in bytes of the content of a resource. */
652    public static final PropertyName<Long> CONTENT_LENGTH =
653        new PropertyName<Long>("content-length"); //$NON-NLS-1$
654
655    /**
656     * Get the {@link #CONTENT_LENGTH} property.
657     * 
658     * @return the {@link #CONTENT_LENGTH} property.
659     * @throws WvcmException if this Resource was not created with
660     * {@link #CONTENT_LENGTH} as a wanted property.
661     */
662    public long getContentLength() throws WvcmException;
663
664    /**
665     * A MIME type string (see RFC 1590) indicating the media type of the
666     * resource content.
667     */
668    public static final PropertyName<String> CONTENT_TYPE =
669        new PropertyName<String>("content-type"); //$NON-NLS-1$
670
671    /**
672     * Get the {@link #CONTENT_TYPE} property.
673     * A server may refuse to allow the {@link #CONTENT_TYPE} of a resource to be changed
674     * after the resource has been created.
675     * 
676     * @return the {@link #CONTENT_TYPE} property.
677     * @throws WvcmException if this property was not set and
678     * this Resource was not created with
679     * {@link #CONTENT_TYPE} as a wanted property.
680     * @see #setContentType
681     */
682    public String getContentType() throws WvcmException;
683
684    /**
685     * Set the {@link #CONTENT_TYPE} property.
686     * 
687     * @param contentType the content type for the resource.
688     * @see #getContentType
689     */
690    public void setContentType(String contentType);
691
692    /**
693     * Whether the content is executable (i.e, can be run as a program).
694     */
695    public static final PropertyName<Boolean> IS_EXECUTABLE =
696        new PropertyName<Boolean>("is-executable"); //$NON-NLS-1$
697
698    /**
699     * Get the {@link #IS_EXECUTABLE} property.
700     * 
701     * @return the {@link #IS_EXECUTABLE} property.
702     * @throws WvcmException if this property was not set and
703     * this Resource was not created with
704     * {@link #IS_EXECUTABLE} as a wanted property.
705     * @see #setIsExecutable
706     */
707    public Boolean getIsExecutable() throws WvcmException;
708
709    /**
710     * Set the {@link #IS_EXECUTABLE} property.
711     * 
712     * @param isExecutable whether the resource is executable.
713     * @see #getIsExecutable
714     */
715    public void setIsExecutable(Boolean isExecutable);
716
717    /** 
718     * A generic PropertyName that selects all custom properties
719     * (i.e., properties with a non-null namespace)
720     * that are defined on the resource.
721     */
722    public static final PropertyName<Object> ALL_CUSTOM_PROPERTIES =
723        new PropertyName<Object>("all-custom-properties"); //$NON-NLS-1$
724
725    /**
726     * Get the value of the specified property of this Resource.
727     * 
728     * @param name the name of the property.
729     * @return the value of the specified property of this Resource.
730     * @throws WvcmException if this property was not set and
731     * this Resource was not created with
732     * the specified property as a wanted property.
733     * @see #setProperty
734     */
735    public <T> T getProperty(PropertyName<T> name)
736    throws WvcmException;
737
738    /**
739     * Lookup the value of the specified property of this Resource.
740     * 
741     * @param name the name of the property.
742     * @return the value of the specified property of this Resource,
743     *  or a WvcmException if there was an error computing the property value
744     *  or if this property was not set and this resource was not created
745     *  with the specified property as a wanted property.
746     * @see #getProperty
747     */
748    public Object lookupProperty(PropertyName<?> name);
749
750    /**
751     * Adds or replaces the value of the specified property of this Resource.
752     * 
753     * @param name the name of the property.
754     * @param value the new value of the specified property.
755     * @see #getProperty
756     */
757    public <T> void setProperty(PropertyName<T> name, T value);
758
759    /**
760     * Initializes the value of the specified property of this Resource.
761     * If that property of the Resource is non-null when it is written
762     * (e.g., by a {@link #doWriteProperties} request),
763     * {@link WvcmException} with {@link ReasonCode#CANNOT_OVERWRITE}
764     * is thrown and the property of the Resource is not changed.
765     *  
766     * @param name the name of the property.
767     * @param value the value of the specified property.
768     * @see #getProperty
769     */
770    public <T> void initProperty(PropertyName<T> name, T value);
771
772    /**
773     * Adds and removes the specified values from the current value
774     * of the specified list-valued property.
775     * 
776     * @param name the name of the property.
777     * @param additions the values to be added to the value of the specified property value.
778     * @param removals the values to be removed from the value of the specified property.
779     * @see #setProperty
780     */
781    public <V, U extends Collection<V>> void setProperty(PropertyName<U> name, U additions, U removals);
782
783    /**
784     * Removes the specified property of this Resource.
785     * This is just a local change to this proxy, and is not
786     * persisted back to the resource identified by this Resource.
787     * This is commonly used to clear an updated property that
788     * caused {@link #doWriteProperties} to fail.
789     * 
790     * @param name the name of the property.
791     */
792    public void forgetProperty(PropertyName<?> name);
793
794    /**
795     * Removes the specified property of this Resource.
796     * The next doXyz() request will cause the server to remove this property
797     * from the resource on the server identified by this Resource.
798     * 
799     * @param name the name of the property.
800     */
801    public void removeProperty(PropertyName<?> name);
802
803}