001/*
002 * file Folder.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM
006 *
007 * (c) Copyright IBM Corporation 2004, 2010.  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.util.Map;
014
015import javax.wvcm.PropertyNameList.PropertyName;
016import javax.wvcm.ResourceList.ResponseIterator;
017import javax.wvcm.WvcmException.ReasonCode;
018
019/**
020 * A proxy for a folder resource.
021 * 
022 * A folder resource is a resource that contains a set of named mappings
023 * to other resources, called the "bound members" of that folder.
024 * The "members" of a folder are the folder itself and all members
025 * of the bound members of the folder. 
026 * The semantics of a folder is similar to those of
027 * a Windows folder, a Unix directory, or a WebDAV collection.
028 * 
029 * @since 1.0
030 */
031public interface Folder extends Resource {
032
033    /**
034     * Get the contents of a folder.
035     * <p>
036     * Postconditions:
037     * <li>(read-bound-members): The result contains a proxy for each
038     *  bound member of the folder.  The Location of the bound member
039     *  whose binding name is "foo" must be
040     *  <code>Folder.location().child("foo")</code>.
041     * <li>(read-all-members): If deep is true, the result contains a proxy for
042     *  every member of the folder identified by this Folder.
043     * @param deep whether to retrieve properties for
044     * all members of this Folder. 
045     * @param feedback the properties to be retrieved.
046     *  
047     * @return an iterator of {@link Resource} objects that contain properties of
048     * the resources that are bound members of this Folder.
049     * If <code>deep</code> is <code>true</code>, then
050     * all members of the folder (including this Folder) are included.
051     * @throws WvcmException
052     */
053    public ResponseIterator<Resource> doReadMemberList(
054            boolean deep,
055            Feedback feedback) throws WvcmException;
056
057    /**
058     * Removes the binding named bindingName from the folder identified by this Folder.
059     * The removal of the binding only guarantees that the resource
060     * is no longer accessible via this binding; it does
061     * not affect its accessibility via other bindings.
062     * If a folder is unbound, no resource is accessible at any
063     * location that has the location of the unbound folder as its prefix.
064     * <p>
065     * Postconditions:
066     * <li>(resource-unbound): There is no resource at the location identified by this bindingName.
067     * <li>(unbind-activity-reference): If an activity is unbound and has no more bindings to it, 
068     *  any reference to that activity
069     *  in an {@link ControllableResource#ACTIVITY}, {@link Version#ACTIVITY}, or 
070     *  {@link Workspace#CURRENT_ACTIVITY} MUST be removed.
071     * <li>(update-predecessor-list): If a version was unbound and has no more bindings to it, the 
072     *  server MUST have replaced
073     *  any reference to that version in a {@link ControllableResource#PREDECESSOR_LIST} or 
074     *  {@link Version#PREDECESSOR_LIST} by a copy of the {@link Version#PREDECESSOR_LIST} of 
075     *  the unbound version.
076     * <li>(version-history-has-root): If the request unbound the root version of a version 
077     *  history and that version has no more bindings to it,
078     *  the request MUST have updated the {@link VersionHistory#ROOT_VERSION} of the version history to refer to
079     *  another version that is an ancestor of all other remaining versions in that version history.
080     *  A result of this postcondition is that every version history will have at least one version,
081     *  and the only way to delete all versions is to unbind the version history resource.
082     * <li>(delete-version-reference): If a version is unbound and has no more bindings to it, 
083     *  any reference to that version in a {@link ControllableResource#MERGE_LIST} or 
084     *  {@link ControllableResource#AUTO_MERGE_LIST} property MUST be removed.
085     * <li>(delete-version-set): If the request unbound a version history and has no more 
086     *  bindings to it, the request MUST have unbound all versions in the VersionList of 
087     *  that version history, and MUST have satisfied the postconditions for version deletion.
088     * <li>(unbind-workspace-reference): If a workspace is unbound and has no more bindings
089     *  to it, any reference to that workspace in an activity's {@link Activity#CURRENT_WORKSPACE_LIST}
090     *  MUST be removed.
091     * <li>(auto-checkout-parent): If the resource identified by <code>bindingName</code>
092     *  is version-controlled, and if this folder was a checked-in version-controlled folder
093     *  the request MAY have automatically checked out this folder.
094     * 
095     * @param feedback Specifies optional feedback to the caller.
096     * @return a new proxy for this resource, whose properties are specified by feedback.
097     * @throws WvcmException ReasonCode:
098     * <li>{@link ReasonCode#NOT_FOUND}:
099     * There must be a binding named <code>bindingName</code> in this Folder.
100     * <li>{@link ReasonCode#METHOD_NOT_SUPPORTED}:
101     *  A server MAY fail an attempt to unbind a version history or a version.
102     * <li>Since this method may cause a checkout to be attempted on this resource,
103     *  see {@link ControllableResource#doCheckin} for additional reason codes.
104     */
105    public Folder doUnbindChild(String bindingName, Feedback feedback) throws WvcmException;
106
107    /** Boolean flags for the doRebind method */
108    public static enum RebindFlag 
109    {
110        /** 
111         * Indicates whether to overwrite an existing binding in the destination folder
112         */
113        OVERWRITE("overwrite"); //$NON-NLS-1$
114
115        private RebindFlag(String flagName) { _flagName = flagName; }
116
117        /**
118         * Returns a string representation of this flag suitable for diagnostics.
119         */
120        @Override
121        public String toString() { return _flagName; }
122
123        /**
124         * The string form of this flag.
125         */
126        private final String _flagName;
127
128    }
129
130
131    /**
132     * Removes the binding named <code>sourceBindingName</code> from a resource in the folder
133     * identified by <code>sourceFolder</code> and adds the binding named <code>bindingName</code>
134     * to that resource in the folder identified by this Folder.
135     * The content and properties of the rebound resource are not modified
136     * by this request, except for the properties that are location dependent.
137     * <p>
138     * Postconditions:
139     * <li>(removed-from-source-parent): The binding named <code>sourceBindingName</code>
140     *  is removed from the folder identified by <code>sourceFolder</code>.
141     *  If this was the only binding to this resource in the source folder,
142     *  the {@link Resource#PARENT_LIST} of this resource
143     *  no longer contains a reference to the source folder.
144     * <li>(added-to-destination-parent): The folder identified by the this Folder
145     *  is modified to have a binding named <code>bindingName</code> to the rebound resource.
146     *  The {@link Resource#PARENT_LIST} of the rebound resource
147     *  contains a reference to the folder identified by this Folder.
148     * <li>(preserve-properties): The property values of the rebound resource
149     *  MUST NOT have been modified by the request unless this specification states otherwise.
150     * <li>(workspace-member-moved): If the rebound resource did not identify a workspace,
151     *  the {@link ControllableResource#WORKSPACE} property of the rebound resource
152     *  MUST have been updated to have the same value as 
153     *  the Workspace of this Folder.
154     * <li>(workspace-moved): If the rebound resource was a workspace,
155     *  any reference to that workspace in a {@link ControllableResource#WORKSPACE} property MUST have been updated
156     *  to refer to the new location of that workspace.
157     * <li>(update-checked-out-reference): If a checked-out resource is rebound, any reference
158     *  to that resource in an {@link Activity#ACTIVITY_CHECKOUT_LIST} property MUST be updated
159     *  to refer to the new location of that resource.
160     * <li>(update-workspace-reference): If the rebound resource was a workspace,
161     *  any reference to that workspace in a CurrentWorkspaceList property
162     *  MUST be updated to refer to the new location of that workspace.
163     * <li>(update-activity-reference): If the rebound resource was an activity, 
164     *  any reference to that activity in an {@link ControllableResource#ACTIVITY},
165     *  {@link Version#ACTIVITY}, or {@link Workspace#CURRENT_ACTIVITY} 
166     *  MUST be updated to refer to the new location of that activity.
167     *  <li>(auto-checkout-destination-parent): If the resource identified by 
168     *  <code>sourceBindingName</code> in <code>sourceFolder</code> is a version-controlled
169     *  resource, and if this folder was a checked-in folder
170     *  the request MUST have automatically checked out this folder.
171     *  <li>(auto-checkout-source-parent): If the resource identified by 
172     *  <code>sourceBindingName</code> in <code>sourceFolder</code> is a version-controlled
173     *  resource, and if the <code>sourceFolder</code> was a checked-in folder,
174     *  the request MUST have automatically checked out the source folder.
175     *  
176     * @param bindingName the new binding name of the resource being rebound.
177     * @param sourceFolder the previous parent folder of the rebound resource.
178     * @param sourceBindingName the original binding name of the rebound resource in the source folder.
179     * @param flags Array of boolean flags (may be null):
180     * <li>{@link RebindFlag#OVERWRITE}:
181     *  Indicates whether an existing binding in this folder
182     *  will be overwritten rather than the request failing.
183     * @param feedback Specifies optional feedback to the caller.
184     * @return a new proxy for this resource, whose properties are specified by feedback.
185     * @throws WvcmException ReasonCode:
186     * <li>{@link ReasonCode#BAD_ARGUMENT_TYPE}:
187     * The resource identified by the <code>sourceFolder</code> argument must be a folder.
188     * <li>{@link ReasonCode#CANNOT_OVERWRITE}:
189     *  If there already is a binding named <code>bindingName</code> in this Folder,
190     *  and <code>overwrite</code> is <code>false</code>, the request MUST fail.
191     * <li>{@link ReasonCode#METHOD_NOT_SUPPORTED}:
192     *  The folder does not support rebinding children.
193     * <li>Since this method may cause a checkout to be attempted on this resource,
194     *  see {@link ControllableResource#doCheckin} for additional reason codes.
195     */
196    public Folder doRebindChild(String bindingName,
197            Folder sourceFolder, String sourceBindingName,
198            RebindFlag[] flags, Feedback feedback)
199    throws WvcmException;
200
201    /**
202     * Removes all binding to the resource
203     * identified by <code>source</code> and adds the binding named <code>bindingName</code>
204     * to that resource in the folder identified by this Folder.
205     * The content and properties of the rebound resource are not modified
206     * by this request, except for the properties that are location dependent.
207     * @see #doRebindChild
208     */
209    public Folder doRebindAll(String bindingName,
210            Resource source,
211            RebindFlag[] flags, Feedback feedback)
212    throws WvcmException;
213
214    /** Boolean flags for the doBind method */
215    public static enum BindFlag 
216    {
217        /** 
218         * Indicates whether to overwrite an existing binding in the destination folder
219         */
220        OVERWRITE("overwrite"), //$NON-NLS-1$
221
222        /** 
223         * Indicates whether to automatically unbind the resource from its original
224         * folder if multiple bindings to the resource is not supported.
225         */
226        AUTO_UNBIND("auto-unbind"); //$NON-NLS-1$
227
228        private BindFlag(String flagName) { _flagName = flagName; }
229
230        /**
231         * Returns a string representation of this flag suitable for diagnostics.
232         */
233        @Override
234        public String toString() { return _flagName; }
235
236        /**
237         * The string form of this flag.
238         */
239        private final String _flagName;
240
241    }
242
243
244    /**
245     * Creates a binding named <code>bindingName</code> in the folder identified by this Folder
246     * to the resource identified by <code>resource</code>.
247     * The content and location-independent properties of the resource are not modified by this request.
248     * <p>
249     * Postconditions:
250     * <li>(preserve-properties): The property values of the resource identified by this Resource
251     *  MUST NOT have been modified by this request unless this specification states otherwise.
252     * <li>(new-binding): There MUST be a binding named <code>bindingName</code> in the folder
253     * identified by this Folder to the resource identified by <code>resource</code>.
254     * <li>(auto-checkout-parent): If <code>resource</code> identifies
255     *  a controlled resource, and if this Folder identifies a checked-in controlled folder,
256     *  this folder MAY have been checked-out by this request.
257     * 
258     * @param bindingName the name of the new binding in this Folder to the resource
259     * identified by <code>resource</code>.
260     * @param resource the resource being bound.
261     * @param flags Array of boolean flags (may be null):
262     * <li>{@link BindFlag#OVERWRITE}:
263     *  Indicates whether an existing binding in this folder
264     *  will be overwritten rather than the request failing.
265     * <li>{@link BindFlag#AUTO_UNBIND}:
266     *  Indicates whether the resource will be unbound from its original folder
267     *  rather than the request failing because multiple bindings to the same resource are not supported.
268     * @param feedback Specifies optional feedback to the caller.
269     * @return a new proxy for this resource, whose properties are specified by feedback.
270     * @throws WvcmException ReasonCode:
271     * <li>{@link ReasonCode#NOT_FOUND}:
272     * There must be a binding named <code>bindingName</code> in this Folder,
273     * and the folder identified by <code>sourceFolder</code> must exist.
274     * <li>{@link ReasonCode#METHOD_NOT_SUPPORTED}:
275     *  If the resource identified by <code>resource</code> does not
276     *  support multiple bindings to it, and {@link BindFlag#AUTO_UNBIND} is not
277     *  specified, the request MUST fail.
278     * <li>{@link ReasonCode#NO_CROSS_SERVER_BINDING}:
279     *  If the resource identified by <code>resource</code> is on another server from
280     *  the folder identified by this Folder, and the server for this Folder
281     *  does not support cross-server bindings, the request MUST fail.
282     * <li>{@link ReasonCode#CANNOT_OVERWRITE}:
283     *  If there already is a binding named <bindingName> in the folder identified
284     *  by this Folder, and <code>overwrite</code> is <code>false</code>, the request MUST fail.
285     * <li>{@link ReasonCode#CYCLE_NOT_ALLOWED}:
286     *  If the server does not support cycles in the location namespace,
287     *  and if <code>resource</code> identifies a folder,
288     *  and if the folder identified by this Folder is a member of that folder,
289     *  then the request MUST fail.
290     * <li>Since this method may cause a checkout to be attempted on this resource,
291     *  see {@link ControllableResource#doCheckin} for additional reason codes.
292     */
293    public Folder doBindChild(
294            String bindingName,
295            Resource resource,
296            BindFlag[] flags, 
297            Feedback feedback)
298    throws WvcmException;
299
300    /**
301     * The map of (name, resource) pairs identifying the resources bound to
302     * this folder as immediate children and the names by which they are known
303     * in this folder. A map entry's key is the binding name (String) and its value
304     * is the bound member (Resource).
305     * Unlike the locations returned by
306     * {@link #doReadMemberList}, the locations of the child resources in the
307     * {@link #CHILD_MAP} <i>do not</i> need to be simple extensions of the
308     * location of this folder. Thus, if <code>segment</code> is a
309     * binding name key from the {@link #CHILD_MAP} property of
310     * Folder <code>foo</code>, and <code>member</code> is a Resource value for
311     * that key:
312     * <ul>
313     * <li><code>segment</code> <i>does not</i> need to
314     * equal <code>member.location().lastSegment()</code>
315     * <li><code>member.location().getParent()</code>
316     * <i>does not</i> need to equal <code>foo.location()</code>
317     * <li>although <code>foo.location().child(binding)</code>
318     * <i>must be</i> a valid location for the bound resource, it <i>does not</i>
319     * need to equal <code>member.location()</code>
320     * </ul>
321     * Since the locations are less constrained, computation
322     * of {@link #CHILD_MAP} may be more efficient than {@link #doReadMemberList}.
323     */
324    final PropertyName<Map<String, Resource>> CHILD_MAP = 
325        new PropertyName<Map<String, Resource>>("child-map"); //$NON-NLS-1$
326
327    /**
328     * Get the {@link #CHILD_MAP} property.
329     * 
330     * @return {@link #CHILD_MAP} property.
331     * @throws WvcmException if this Folder was not created with
332     * {@link #CHILD_MAP} as a wanted property.
333     */
334    public Map<String, Resource> getChildMap() throws WvcmException;
335
336    /**
337     * The list of resources bound to this folder as immediate children.
338     * This list contains the same resources as the values of {@link #CHILD_MAP}.
339     * This may be a more efficient way of accessing the list
340     * of children when their binding names are not required.
341     */
342    final PropertyName<ResourceList<Resource>> CHILD_LIST = 
343        new PropertyName<ResourceList<Resource>>("child-list"); //$NON-NLS-1$
344
345    /**
346     * Get the {@link #CHILD_LIST} property.
347     * 
348     * @return {@link #CHILD_LIST} property.
349     * @throws WvcmException if this Folder was not created with
350     * {@link #CHILD_LIST} as a wanted property.
351     */
352    public ResourceList<Resource> getChildList() throws WvcmException;
353
354
355}