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     */
011    package javax.wvcm;
012    
013    import java.io.InputStream;
014    import java.io.OutputStream;
015    import java.util.Collection;
016    import java.util.Date;
017    import java.util.List;
018    import java.util.Locale;
019    
020    import javax.wvcm.PropertyNameList.PropertyName;
021    import javax.wvcm.ResourceList.ResponseIterator;
022    import 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     */
053    public 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    }