001    /*
002     * file CqRecord.java
003     *
004     * Licensed Materials - Property of IBM
005     * Restricted Materials of IBM 
006     *
007     * com.ibm.rational.wvcm.stp.cq.CqRecord
008     *
009     * (C) Copyright IBM Corporation 2004, 2010.  All Rights Reserved.
010     * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
011     * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp.
012     */
013    
014    package com.ibm.rational.wvcm.stp.cq;
015    import static com.ibm.rational.wvcm.stpex.StpExBase.PROPERTY_NAMESPACE;
016    
017    import java.util.Date;
018    import java.util.List;
019    
020    import javax.wvcm.Feedback;
021    import javax.wvcm.PropertyNameList;
022    import javax.wvcm.ResourceList;
023    import javax.wvcm.WvcmException;
024    import javax.wvcm.PropertyNameList.PropertyName;
025    
026    import com.ibm.rational.wvcm.stp.StpActivity;
027    import com.ibm.rational.wvcm.stp.StpErrorMessageException;
028    import com.ibm.rational.wvcm.stp.StpProperty;
029    import com.ibm.rational.wvcm.stp.StpResource;
030    import com.ibm.rational.wvcm.stpex.StpExBase;
031    import com.ibm.rational.wvcm.stpex.StpExEnumeration;
032    import com.ibm.rational.wvcm.stpex.StpExEnumerationBase;
033    
034    /**
035     * A CqRecord resource proxy provides access to a record in a database, possibly
036     * through its change context.
037     * 
038     * <p>
039     * To ensure the integrity of record field data, the modification of a record is
040     * a multi-step process.
041     * 
042     * <ul>
043     * <li>First, a writable copy of the record is added to the database's change
044     * context using the current field values from the database. This writable copy
045     * of the record is visible only in the provider where it was created. While it
046     * exists in the change context, it hides the record in the database as seen
047     * through the provider.
048     * <li>Field values are modified in the CqRecord proxy by the client.
049     * <li>As needed, modified field values are written to the writable copy of the
050     * record on the server. (see
051     * {@link CqContextResource#doWriteProperties(Feedback, List) doWriteProperties}.)
052     * <li>The client modifies a record or a set of records in this fashion until
053     * all have been modified and made consistent to the client's satisfaction. Then
054     * they are written back to the database is a single atomic operation. (See
055     * {@link com.ibm.rational.wvcm.stp.cq.CqUserDb#doDeliver(Feedback, List)} or
056     * {@link com.ibm.rational.wvcm.stp.cq.CqContextResource#doDeliver(Feedback)} or
057     * {@link CqContextResource#doWriteProperties(Feedback, List) doWriteProperties}.)
058     * </ul>
059     * 
060     * If these steps succeed, the client can be assured that the data written back
061     * to the record is faithfully derived from the data read from the record.
062     * 
063     * <p>
064     * If doWriteProperties is applied to a record that is not yet writable, an
065     * action must be started under which the record will be modified. If an action
066     * is not specified as the value of the ACTION property of this proxy, the
067     * default MODIFY-type action for the record is used.
068     * 
069     * <p>
070     * The fields of a record manifest themselves as properties of the record
071     * resource and thus record field values are made available to the client via
072     * the normal property request mechanism. The names, types, and other
073     * characteristics of the fields of a record are available as properties of the
074     * {@link CqFieldDefinition CqFieldDefinition} resources enumerated by the
075     * CqRecordType resource associated with the record.
076     * 
077     * <p>
078     * In addition to their value, record fields also have meta-properties such as
079     * their requiredness, their original value, and a list of their legal values.
080     * Each of these can be requested using a MetaPropertyName object in a
081     * nested PropertyRequest of the field PropertyName.
082     * <p>
083     * The user-friendly specification for the location of a record has the form
084     * 
085     * <pre>
086     *  <b>cq.record:</b><i>&lt;record-type&gt;</i>/<i>&lt;record-id&gt;</i>@<i>&lt;db-set&gt;</i>/<i>&lt;user-db&gt;</i>
087     * </pre>
088     * 
089     * @see CqRecordType
090     * @see CqFieldDefinition
091     * @see CqFieldValue
092     */
093    public interface CqRecord extends StpActivity, CqContextResource
094    {
095        /**
096         * Defines the value of the specified property for this proxy. The
097         * PropertyName may specify a record field name, in which case the Object
098         * may be a {@link CqFieldValue CqFieldValue} structure or the actual value
099         * of the field.
100         * 
101         * @see StpResource#setProperty(PropertyNameList.PropertyName, Object)
102         */
103        <T> void setProperty(PropertyName<T> name,
104                             T value);
105    
106        /**
107         * Returns the value defined by this proxy for the property specified by the
108         * given PropertyName. The PropertyName may specify a record field, in which
109         * case the Object returned is <i>not</i> a
110         * {@link CqFieldValue CqFieldValue} structure, but the actual value of the
111         * field. (Clients may use {@link #getField getField} or
112         * {@link StpResource#getMetaProperties(PropertyName)} to obtain a
113         * CqFieldValue structure if the additional information provided by the
114         * CqFieldValue structure is needed.).
115         * 
116         * @see javax.wvcm.Resource#getProperty(javax.wvcm.PropertyNameList.PropertyName)
117         */
118        <T> T getProperty(PropertyName<T> name) throws WvcmException;
119    
120        /**
121         * A CqRecordType proxy for the record-type resource that defines what kind
122         * of record this is.
123         */
124        PropertyName<CqRecordType> RECORD_TYPE =
125            new PropertyName<CqRecordType>(StpExBase.PROPERTY_NAMESPACE,
126                                           "record-type");
127    
128        /**
129         * A CqRecordType proxy for the record-type resource that defines what kind
130         * of record this is.
131         * 
132         * @return A proxy for the record-type of this record is returned.
133         * 
134         * @throws WvcmException if this proxy does not define a value for the
135         *             {@link #RECORD_TYPE RECORD_TYPE} property.
136         */
137        CqRecordType getRecordType() throws WvcmException;
138    
139        /**
140         * A subclass of PropertyName used for naming the record resource properties
141         * that are schema-defined fields of a ClearQuest record. Note that, as with
142         * PropertyName, the type parameter specifies the field's value type.
143         */
144        public static class FieldName<T> extends PropertyName<T>
145        {
146            /**
147             * Constructs a PropertyName designating the resource property that
148             * corresponds to a field of a ClearQuest record.
149             * 
150             * @param fieldName The schema-defined name of the record field. Must
151             *            not be null.
152             */
153            public FieldName(String fieldName)
154            {
155                super(StpExBase.FIELD_NAMESPACE, fieldName);
156            }
157        }
158    
159        /**
160         * Returns the meta-property bundle of a record field defined by this proxy.
161         * Since CqFieldValue is an extension of StpProperty, this method is merely
162         * a type-specialized version of
163         * {@link StpResource#getMetaProperties(javax.wvcm.PropertyNameList.PropertyName)}.
164         * 
165         * @param fieldName The name of the desired field expressed as a FieldName
166         *            object. Cannot be <code>null</code>.
167         * 
168         * @return A CqFieldValue structure is returned containing the field
169         *         value(s) and/or attributes defined by this proxy.
170         * 
171         * @throws WvcmException If the field value denoted by the given field name
172         *             is not defined by this proxy--that is, if no field values or
173         *             attributes were requested or could not be retrieved when
174         *             requested.
175         */
176        <T> CqFieldValue<T> getFieldInfo(FieldName<T> fieldName)
177            throws WvcmException;
178    
179        /**
180         * Defines a new meta-property bundle for a record field in this proxy. Only
181         * the VALUE meta-property of the CqFieldValue is written to the resource,
182         * but the TYPE meta-property is often useful to the library for
183         * interpreting the VALUE when expressed as a String image.
184         * 
185         * @param fieldName The name of the field to be updated expressed as a
186         *            FieldName object. Cannot be <code>null</code>.
187         * 
188         * @param value A CqFieldValue object containing the new field value. Must
189         *            not be <b>null</b>
190         */
191        <T> void setFieldInfo(FieldName<T> fieldName,
192                              CqFieldValue<T> value);
193    
194        /**
195         * Defines in this proxy, a new value for a field of this record. The field
196         * will not be updated until this proxy is used to invoke a "do" method.
197         * 
198         * @param fieldName The name of the field whose value is to be set
199         * @param value The new value for the field expressed as a native Java
200         *            object. The String image of the value may be used.
201         */
202        void setField(String fieldName,
203                      Object value);
204    
205        /**
206         * Retrieves the value of a field previously requested by an instance of
207         * FieldName having the same fieldName parameter as this method. To retrieve
208         * other meta-properties requested for the field, use
209         * {@link #getFieldInfo(com.ibm.rational.wvcm.stp.cq.CqRecord.FieldName)}.
210         * 
211         * @param fieldName The name of the field for which a value was requested.
212         * @return The value of the requested field returned by the server expressed
213         *         as a native Java object (not just its String image).
214         * @throws WvcmException If the field value was not requested or could not
215         *             be retrieved.
216         */
217        Object getField(String fieldName) throws WvcmException;
218    
219        /**
220         * Creates a new record at the location specified by this proxy, initialized
221         * with the dirty properties of this proxy. The type of record created is
222         * determined by the parent location of this proxy (which must name an
223         * existing record type resource).
224         * <p>
225         * An action must be started under which the record will be created. If an
226         * action is not specified as the value of the ACTION property of this
227         * proxy, the default SUBMIT-type action for the record is used.
228         * <p>
229         * The server is permitted to modify the location as it deems fit. The proxy
230         * returned by this method is a proxy that addresses the location actually
231         * chosen by the server.
232         * 
233         * @param feedback A Feedback object requesting the properties desired from
234         *            the record created by this operation. May be <b>null</b> if
235         *            no properties are desired.
236         * 
237         * @return An CqRecord proxy for the created record. This proxy will define
238         *         the properties specified in the feedback argument.
239         * 
240         * @throws WvcmException If the record cannot be created with the given
241         *             properties.
242         */
243        CqRecord doCreateRecord(Feedback feedback) throws WvcmException;
244    
245        /**
246         * Creates a new record at the location specified by this proxy, initialized
247         * with the dirty properties of this proxy. The type of record created is
248         * determined by the parent location of this proxy (which must name an
249         * existing record type resource).
250         * <p>
251         * An action must be started under which the record will be created. If an
252         * action is not specified as the value of the ACTION property of this
253         * proxy, the default SUBMIT-type action for the record is used.
254         * <p>
255         * The server is permitted to modify the location as it deems fit. The proxy
256         * returned by this method is a proxy that addresses the location actually
257         * chosen by the server.
258         * 
259         * @param feedback A Feedback object requesting the properties desired from
260         *            the record created by this operation. May be <b>null</b> if
261         *            no properties are desired.
262         * 
263         * @param deliveryOrder If {@link CqProvider#HOLD} the created record is
264         *            left in a writable state in the change context--the new record
265         *            in the change context must be delivered before the it becomes
266         *            visible to other providers. If not {@link CqProvider#HOLD},
267         *            the modified and moribund resources specified by this
268         *            parameter will be delivered to or deleted from the database in
269         *            the order indicated. To deliver all modified and moribund
270         *            resources in an arbitrary order, use
271         *            {@link CqProvider#DELIVER_ALL}. To deliver just this new
272         *            record, use {@link CqProvider#DELIVER}. Must not be <b>null</b>.
273         * @return A CqRecord proxy for the created record. This proxy will define
274         *         the properties specified in the feedback argument.
275         * 
276         * @throws WvcmException If the record cannot be created with the given
277         *             properties.
278         */
279        CqRecord doCreateRecord(Feedback feedback,
280                                List<CqContextResource> deliveryOrder)
281            throws WvcmException;
282    
283        /**
284         * Executes a hook (record script) named in the NAMED_HOOK_LIST property of
285         * this record's RECORD_TYPE resource. Additionally a global hook can be
286         * executed if the global hook's name is known in advance. The impact on 
287         * the change context in which the hook is executed is essentially
288         * the same as executing 
289         * {@link com.ibm.rational.wvcm.stp.cq.CqContextResource#doWriteProperties(Feedback, List)}
290         * in that context (where the hook is in control of which properties are
291         * written).
292         * <p>
293         * As with doWriteProperties, the record need not be editable prior to
294         * invoking this method, but, unlike doWriteProperties, if it isn't editable
295         * and the hook wants to modify it, then the hook must be prepared to start
296         * an action itself to do so. An implicit Modify-type action is not
297         * automatically started for the hook (except in the case noted below).
298         * <p>
299         * If this proxy contains updated property values when this method is
300         * invoked, an attempt will be made to write those new property values to
301         * the server <i>before</i> the hook is executed. If such an update is
302         * required and this record isn't editable, it will be made editable using
303         * the default Modify-type action and the hook will be applied to that
304         * editable version of the record before delivering the changes to the
305         * database. If the property update fails, this operation fails immediately
306         * and subsequent execution of the hook will not be attempted.
307         * 
308         * @param hook A CqHook proxy for the named hook to be fired. If the client
309         *            knows the name of the hook to be fired, it should construct a
310         *            CqHook proxy at the computed location <i>record</i><code>.stpLocation().recomposeWithNamespace(Namespace.HOOK).parent().child(</code><i>hook-name</i><code>)</code>
311         *            If the client does not know the name of the hook to be fired,
312         *            a list of available hooks to choose from can be obtained from
313         *            the NAMED_HOOK_LIST property of the parent record type of this
314         *            record.
315         *            Additionally, the client can specify a global hook. If using
316         *            a global hook, the client must know the name in advance and
317         *            should construct a CqHook proxy at the computed location 
318         *            <i>record</i><code>.stpLocation().recomposeWithMods(Namespace.HOOK,</code><i>hook-name</i><code>,</code><i>null</i><code>,</code><i>null</i><code>)</code>
319         * @param parameters A String containing any parameters required by the
320         *            hook. The format and content of this parameter string is
321         *            prescribed solely by the hook, which is also responsible for
322         *            parsing it into a usable value or values.
323         * @param feedback Properties to be retrieved from the target record and/or
324         *            those records changed by the execution of the hook (and after
325         *            delivery if delivery has been requested).
326         * @param deliveryOrder Delivery of the changes made to the record will be
327         *            considered only if the hook succeeds. If this argument is
328         *            {@link CqProvider#HOLD} the modified record is left in a
329         *            writable state in the change context--the modified record must
330         *            be delivered before the changes made by the hook become
331         *            visible outside the change context. If not
332         *            {@link CqProvider#HOLD}, the modified and moribund resources
333         *            specified by this parameter will be delivered to or deleted
334         *            from the database in the order indicated. To deliver all
335         *            modified and moribund resources in an arbitrary order, use
336         *            {@link CqProvider#DELIVER_ALL}. To deliver just this modified
337         *            record, use {@link CqProvider#DELIVER}. Must not be <b>null</b>.
338         * @return A CqRecord proxy for the modified record, populated with the
339         *         resources requested by the feedback argument.
340         * @throws WvcmException if there are problems finding or executing the
341         *             named hook, writing updated properties, or starting the
342         *             implied action.
343         * @throws StpErrorMessageException if the hook returns a non-empty result
344         */
345        CqRecord doFireNamedHook(CqHook hook,
346                                 String parameters,
347                                 Feedback feedback,
348                                 List<CqContextResource> deliveryOrder)
349            throws WvcmException, StpErrorMessageException;
350    
351        /**
352         * Causes the execution of an action of type
353         * CqAction.Type.RECORD_SCRIPT_ALIAS. Such actions are defined solely by a
354         * hook script, which is executed when the action is applied to a record.
355         * When this method is called, the action is started on this record and the
356         * action's hook script is executed as the sole content of that action and
357         * then the action is committed. The impact of this operation on the change
358         * context is essentially equivalent to executing in the same context
359         * {@link com.ibm.rational.wvcm.stp.cq.CqContextResource#doWriteProperties(Feedback, List)}
360         * where the deliveryOrder argument forces an immediate delivery of the
361         * change context.
362         * <p>
363         * Because of this prescribed processing
364         * <ul>
365         * <li>This record must not be editable when this method is called so that
366         * the specified RECORD_SCRIPT_ALIAS action can be started on it.
367         * <li> This record must not contain updated property values because only
368         * the record script of the action is allowed to make modifications to the
369         * record once the action has started.
370         * <li>If the action script succeeds, delivery of the targeted record is
371         * immediate and cannot be deferred--i.e., CqProvider.HOLD <i>may not</i>
372         * be used for the delivery order list. Furthermore, the targeted record is
373         * delivered first, regardless of the content of the delivery order list.
374         * <li>If the action script fails, no delivery will be attempted and the
375         * change context will remain as it was before invoking this method.
376         * </ul>
377         * <p>
378         * Typically, schema designers have associated arbitrary executable code
379         * with a record type, represented in a GUI as a button with the display
380         * name of the record type action.
381         * 
382         * @param action A CqAction for an action of type RECORD_SCRIPT_ALIAS. This
383         *            action must be defined by the record type of this record
384         *            instance.
385         * @param feedback A Feedback object requesting the properties desired from
386         *            resources involved in this operation. May be <b>null</b> if
387         *            no properties are desired.
388         * @param deliveryOrder Upon successful execution of the action script, the
389         *            target record will be delivered to its database. Then, any
390         *            other resources specified by this argument will be delivered.
391         *            Must not be <b>null</b> and must not be CqProvider.HOLD.
392         * @return A String containing the return value computed by the hook script.
393         * @throws WvcmException if there are problems
394         *             <ul>
395         *             <li>finding the record,
396         *             <li>finding a RECORD_SCRIPT_ALIAS as specified
397         *             <li>starting the action
398         *             <li>executing the script
399         *             <li>delivering the changes to the database
400         *             </ul>
401         */
402        String doFireRecordScriptAlias(CqAction action,
403                                       Feedback feedback,
404                                       List<CqContextResource> deliveryOrder)
405            throws WvcmException;
406    
407        /**
408         * Returns the date of the submit action in the record history field.
409         * 
410         * @see javax.wvcm.Resource#getCreationDate()
411         */
412        Date getCreationDate() throws WvcmException;
413    
414        /**
415         * Returns the date of the last action applied to the record from its
416         * history
417         * 
418         * @see javax.wvcm.Resource#getLastModified()
419         */
420        Date getLastModified() throws WvcmException;
421    
422        /**
423         * Returns the login name of the user who submitted the record
424         * 
425         * @see com.ibm.rational.wvcm.stp.StpResource#getCreatorLoginName()
426         */
427        String getCreatorLoginName() throws WvcmException;
428    
429        /**
430         * The error message generated when the record, in its current state, was
431         * validated against the repository schema for compliance with its rules.
432         * This property will be empty if the record is fully compliant (which is
433         * always the case if the record is not open for edit).
434         * <p>
435         * When this property is requested for a record open for editing, the record
436         * is validated before any other properties are retrieved. Thus, all
437         * properties returned with this property reflect the state of the record
438         * after validation was attempted.
439         * <p>
440         * Before a record being edited can be delivered, it must be validated (even
441         * if no fields have been changed). Normally, validation is performed as the
442         * first phase of a delivery and any validation errors cause the delivery to
443         * be aborted. Requesting this property will force validation of the record
444         * without attempting to deliver it. The time and resources needed to 
445         * perform a record validation vary with the schema. Unless you have 
446         * specific knowledge of the target database's schema, it is best to assume
447         * that the validation process is an expensive operation and design your
448         * application to request this property only when validation is really 
449         * required.
450         * <p>
451         * If you are changing the contents of a record programmatically, you should
452         * make sure that your code provides valid data.
453         * <p>
454         * You should not attempt to parse and interpret the returned String
455         * programmatically, because the error text may change in future releases.
456         * If you want to try to correct the value in an field with incorrect
457         * values, you can use the INVALID_FIELDS property to discover which fields
458         * are invalid. The MESSAGE_TEXT meta-property of those fields will identify
459         * problems specific to the field.
460         */
461        PropertyName<String> VALIDATION_ERROR =
462            new PropertyName<String>(StpExBase.PROPERTY_NAMESPACE,
463                                     "validation-error");
464    
465        /**
466         * Returns the value of the {@link #VALIDATION_ERROR VALIDATION_ERROR}
467         * property as defined by this proxy.
468         * 
469         * @return Returns a String containing the error message generated when this
470         *         record was validated against the repository schema. Will never be
471         *         <b>null</b>, but may be empty is the record field values are
472         *         fully compliant with the rules of the schema.
473         * 
474         * @throws WvcmException if this proxy does not define a value for the
475         *             {@link #VALIDATION_ERROR VALIDATION_ERROR } property.
476         */
477        String getValidationError() throws WvcmException;
478    
479        /**
480         * The action under which this record is being modified; null if the record
481         * is not being modified.
482         */
483        PropertyName<CqAction> ACTION =
484            new PropertyName<CqAction>(StpExBase.PROPERTY_NAMESPACE, "action");
485    
486        /**
487         * Returns the value of the {@link #ACTION ACTION} property as defined by
488         * this proxy.
489         * 
490         * @return Returns an Action proxy representing the action associated with
491         *         this record.
492         * 
493         * @throws WvcmException if this proxy does not define a value for the
494         *             {@link #ACTION ACTION} property.
495         */
496        CqAction getAction() throws WvcmException;
497    
498        /**
499         * Defines a new value for the {@link #ACTION ACTION} property of this
500         * proxy. Set this value prior to invoking doWriteProperties,
501         * doCreateRecord, or doUnbindAll to specify an action other than the
502         * default action specified for those operations. If this property is not
503         * set prior to invocation of these methods, an action of the required type
504         * will be used if one is unique defined.
505         * 
506         * @param action A CqAction proxy identifying the action under which this
507         *            record is to be created, modified, or deleted. Must not be
508         *            <b>null</b>. For the update to succeed, the given action must
509         *            be on the LEGAL_ACTIONs list for this record.
510         */
511        CqRecord setAction(CqAction action);
512    
513        /**
514         * The type of the action under which this record is being modified,
515         * Type.NIL if the record is not being modified
516         */
517        PropertyName<CqAction.Type> ACTION_TYPE =
518            new PropertyName<CqAction.Type>(StpExBase.PROPERTY_NAMESPACE,
519                                            "action-type");
520    
521        /**
522         * Returns the value of the {@link #ACTION ACTION} property as defined by
523         * this proxy.
524         * 
525         * @return An Action.Type enumerator indicating the type of action
526         *         associated with this record.
527         * 
528         * @throws WvcmException if this proxy does not define a value for the
529         *             {@link #ACTION_TYPE ACTION_TYPE} property.
530         */
531        CqAction.Type getActionType() throws WvcmException;
532    
533        /**
534         * A list of {@link CqFieldValue CqFieldValue} objects corresponding to all
535         * of the fields of this record. By default, no meta-property of any field
536         * is included in the CqFieldValue's on this list. So, essentially, the
537         * result is just a list of field property names. Using a NestedPropertyName
538         * in the PropertyRequest of this property would allow the client to request
539         * any or all meta-properties of the fields in the list.
540         * <code>
541         * new PropertyRequest(ALL_FIELD_VALUES.nest(VALUE.nest(VALUE))), 
542         * </code>
543         * for example, would request the value of each field of the record.
544         */
545        PropertyName<StpProperty.List<CqFieldValue<?>>> ALL_FIELD_VALUES =
546            new PropertyName<StpProperty.List<CqFieldValue<?>>>(PROPERTY_NAMESPACE,
547                                                                "all-field-values");
548    
549        /**
550         * Returns the value of the {@link #ALL_FIELD_VALUES ALL_FIELD_VALUES}
551         * property as defined by this proxy.
552         * 
553         * @return An StpProperty.List containing a CqFieldValue instance for each
554         *         field of this record. Each CqFieldValue instance defines all of
555         *         the metadata requested from the server for the field.
556         * 
557         * @throws WvcmException if this proxy does not define a value for the
558         *             {@link #ALL_FIELD_VALUES ALL_FIELD_VALUES} property.
559         */
560        StpProperty.List<CqFieldValue<?>> getAllFieldValues() throws WvcmException;
561    
562        /** The default action associated with the current state of this record. */
563        PropertyName<CqAction> DEFAULT_ACTION =
564            new PropertyName<CqAction>(StpExBase.PROPERTY_NAMESPACE,
565                                       "default-action");
566    
567        /**
568         * Returns the value of the {@link #DEFAULT_ACTION DEFAULT_ACTION} property
569         * as defined by this proxy.
570         * 
571         * @return A CqAction proxy representing the default action associated with
572         *         this record in its current state. Will be null if a default
573         *         action is not defined for this record.
574         * 
575         * @throws WvcmException if this proxy does not define a value for the
576         *             {@link #DEFAULT_ACTION DEFAULT_ACTION} property.
577         */
578        CqAction getDefaultAction() throws WvcmException;
579    
580        /** Whether this record has been marked as a duplicate of another record. */
581        PropertyName<Boolean> IS_DUPLICATE =
582            new PropertyName<Boolean>(StpExBase.PROPERTY_NAMESPACE, "is-duplicate");
583    
584        /**
585         * Returns the value of the {@link #IS_DUPLICATE IS_DUPLICATE} property as
586         * defined by this proxy.
587         * 
588         * @return <b>true</b> if this record has been recorded as a duplicate of
589         *         another record.
590         * 
591         * @throws WvcmException if this proxy does not define a value for the
592         *             {@link #IS_DUPLICATE IS_DUPLICATE} property.
593         * 
594         * @see #getAllDuplicates()
595         * @see #getDuplicates()
596         * @see #getHasDuplicates()
597         */
598        boolean getIsDuplicate() throws WvcmException;
599    
600        /**
601         * The CqRecord that is marked as the original of this duplicate record.
602         */
603        PropertyName<CqRecord> ORIGINAL =
604            new PropertyName<CqRecord>(StpExBase.PROPERTY_NAMESPACE, "original");
605    
606        /**
607         * Returns the value of the {@link #ORIGINAL ORIGINAL} property as defined
608         * by this proxy.
609         * 
610         * @return A CqRecord proxy representing the record of which this is a
611         *         duplicate. Will be <b>null</b> if this record is not a
612         *         duplicate.
613         * 
614         * @throws WvcmException if this proxy does not define a value for the
615         *             {@link #ORIGINAL ORIGINAL} property.
616         */
617        CqRecord getOriginal() throws WvcmException;
618    
619        /** The visible ID of this object's original record. */
620        PropertyName<String> ORIGINAL_ID =
621            new PropertyName<String>(StpExBase.PROPERTY_NAMESPACE, "original-id");
622    
623        /**
624         * Returns the value of the {@link #ORIGINAL_ID ORIGINAL_ID} property as
625         * defined by this proxy.
626         * 
627         * @return A String containing the record id for the record that this record
628         *         is a duplicate of. Will be <b>null</b> if this record is not a
629         *         duplicate.
630         * 
631         * @throws WvcmException if this proxy does not define a value for the
632         *             {@link #ORIGINAL_ID ORIGINAL_ID} property.
633         */
634        String getOriginalId() throws WvcmException;
635    
636        /**
637         * Whether other records have been marked as being duplicates of this record
638         */
639        PropertyName<Boolean> HAS_DUPLICATES =
640            new PropertyName<Boolean>(StpExBase.PROPERTY_NAMESPACE,
641                                      "has-duplicates");
642    
643        /**
644         * Returns the value of the {@link #HAS_DUPLICATES HAS_DUPLICATES} property
645         * as defined by this proxy.
646         * 
647         * @return <b>true</b> if records have been marked as duplicates of this
648         *         record.
649         * 
650         * @throws WvcmException if this proxy does not define a value for the
651         *             {@link #HAS_DUPLICATES HAS_DUPLICATES} property.
652         * 
653         * @see #getDuplicates()
654         * @see #getAllDuplicates()
655         * @see #getIsOriginal()
656         */
657        boolean getHasDuplicates() throws WvcmException;
658    
659        /**
660         * True if this record has duplicates but is not itself a duplicate (i.e.
661         * !IS_DUPLICATE & HAS_DUPLICATES)
662         */
663        PropertyName<Boolean> IS_ORIGINAL =
664            new PropertyName<Boolean>(StpExBase.PROPERTY_NAMESPACE, "is-original");
665    
666        /**
667         * Returns the value of the {@link #IS_ORIGINAL IS_ORIGINAL} property as
668         * defined by this proxy.
669         * 
670         * @return <b>true</b> if this record has duplicates but is not, itself, a
671         *         duplicate of another record.
672         * 
673         * @throws WvcmException if this proxy does not define a value for the
674         *             {@link #IS_ORIGINAL IS_ORIGINAL} property.
675         */
676        boolean getIsOriginal() throws WvcmException;
677    
678        /** The immediate duplicates of this record. */
679        PropertyName<ResourceList<CqRecord>> DUPLICATES =
680            new PropertyName<ResourceList<CqRecord>>(StpExBase.PROPERTY_NAMESPACE,
681                                                     "duplicates");
682    
683        /**
684         * Returns the value of the {@link #DUPLICATES DUPLICATES} property as
685         * defined by this proxy.
686         * 
687         * @return A ResourceList of CqRecord proxies representing all of the
688         *         records that have been explicitly marked as a duplicate of this
689         *         record.
690         * 
691         * @throws WvcmException if this proxy does not define a value for the
692         *             {@link #DUPLICATES DUPLICATES} property.
693         * 
694         * @see #getAllDuplicates()
695         */
696        ResourceList<CqRecord> getDuplicates() throws WvcmException;
697    
698        /**
699         * All of the duplicates of this record, including duplicates of duplicates,
700         * etc.
701         */
702        PropertyName<ResourceList<CqRecord>> ALL_DUPLICATES =
703            new PropertyName<ResourceList<CqRecord>>(StpExBase.PROPERTY_NAMESPACE,
704                                                     "all-duplicates");
705    
706        /**
707         * Returns the value of the {@link #ALL_DUPLICATES ALL_DUPLICATES} property
708         * as defined by this proxy.
709         * 
710         * @return A ResourceList of CqRecord proxies representing all of the
711         *         records marked as duplicates of this record or (recursively) one
712         *         of its duplicates.
713         * 
714         * @throws WvcmException if this proxy does not define a value for the
715         *             {@link #ALL_DUPLICATES ALL_DUPLICATES} property.
716         */
717        ResourceList<CqRecord> getAllDuplicates() throws WvcmException;
718    
719        /**
720         * A list of the fields that were modified by the on-going action applied to
721         * this record.
722         */
723        PropertyName<StpProperty.List<CqFieldValue<?>>> FIELDS_UPDATED_THIS_ACTION =
724            new PropertyName<StpProperty.List<CqFieldValue<?>>>(StpExBase.PROPERTY_NAMESPACE,
725                                                                "fields-updated-this-action");
726    
727        /**
728         * Returns the value of the {@link #FIELDS_UPDATED_THIS_ACTION
729         * FIELDS_UPDATED_THIS_ACTION} property as defined by this proxy.
730         * 
731         * @return An StpProperty.List containing a CqFieldValue for each field
732         *         updated since the beginning of the current action on this record.
733         *         Each CqFieldValue defines the metadata requested when this
734         *         property was retrieved from the server.
735         * 
736         * @throws WvcmException if this proxy does not define a value for the
737         *             {@link #FIELDS_UPDATED_THIS_ACTION
738         *             FIELDS_UPDATED_THIS_ACTION} property.
739         */
740        StpProperty.List<CqFieldValue<?>> getFieldsUpdatedThisAction()
741            throws WvcmException;
742    
743        /**
744         * A list of the fields that were modified under the current action since
745         * the last time this property was set.
746         * 
747         * @see #setFieldsUpdatedThisGroup()
748         */
749        PropertyName<StpProperty.List<CqFieldValue<?>>> FIELDS_UPDATED_THIS_GROUP =
750            new PropertyName<StpProperty.List<CqFieldValue<?>>>(StpExBase.PROPERTY_NAMESPACE,
751                                                                "fields-updated-this-group");
752    
753        /**
754         * Returns the value of the {@link #FIELDS_UPDATED_THIS_GROUP
755         * FIELDS_UPDATED_THIS_GROUP} property as defined by this proxy.
756         * 
757         * @return An StpProperty.List containing a CqFieldValue instance for each
758         *         field updated since the last time the
759         *         {@link #FIELDS_UPDATED_THIS_GROUP} property was set.
760         * 
761         * @throws WvcmException if this proxy does not define a value for the
762         *             {@link #FIELDS_UPDATED_THIS_GROUP FIELDS_UPDATED_THIS_GROUP}
763         *             property.
764         */
765        StpProperty.List<CqFieldValue<?>> getFieldsUpdatedThisGroup()
766            throws WvcmException;
767    
768        /**
769         * Clears the FIELDS_UPDATED_THIS_GROUP property. Only fields updated after
770         * this value is set will be returned by subsequent requests for the
771         * FIELDS_UPDATED_THIS_GROUP property.
772         */
773        void setFieldsUpdatedThisGroup();
774    
775        /**
776         * The fields that were modified by the last field update.
777         */
778        PropertyName<StpProperty.List<CqFieldValue<?>>> FIELDS_UPDATED_THIS_SET_VALUE =
779            new PropertyName<StpProperty.List<CqFieldValue<?>>>(StpExBase.PROPERTY_NAMESPACE,
780                                                                "fields-updated-this-set-value");
781    
782        /**
783         * Returns the value of the {@link #FIELDS_UPDATED_THIS_SET_VALUE
784         * FIELDS_UPDATED_THIS_SET_VALUE} property as defined by this proxy.
785         * 
786         * @return An StpProperty.List containing a CqFieldValue instance for each
787         *         field modified by the most recent client-initiated field update.
788         * 
789         * @throws WvcmException if this proxy does not define a value for the
790         *             {@link #FIELDS_UPDATED_THIS_SET_VALUE
791         *             FIELDS_UPDATED_THIS_SET_VALUE} property.
792         */
793        StpProperty.List<CqFieldValue<?>> getFieldsUpdatedThisSetValue()
794            throws WvcmException;
795    
796        /**
797         * A list of the record's invalid fields.
798         */
799        PropertyName<StpProperty.List<CqFieldValue<?>>> INVALID_FIELDS =
800            new PropertyName<StpProperty.List<CqFieldValue<?>>>(StpExBase.PROPERTY_NAMESPACE,
801                                                                "invalid-fields");
802    
803        /**
804         * Returns the value of the {@link #INVALID_FIELDS INVALID_FIELDS} property
805         * as defined by this proxy.
806         * 
807         * @return An StpProperty.list of CqFieldValue instances identifying the
808         *         fields of this record that are currently invalid.
809         * 
810         * @throws WvcmException if this proxy does not define a value for the
811         *             {@link #INVALID_FIELDS INVALID_FIELDS} property.
812         */
813        StpProperty.List<CqFieldValue<?>> getInvalidFields() throws WvcmException;
814    
815        /**
816         * The actions that can be legally applied to this record in its current
817         * state.
818         */
819        PropertyName<ResourceList<CqAction>> LEGAL_ACTIONS =
820            new PropertyName<ResourceList<CqAction>>(StpExBase.PROPERTY_NAMESPACE,
821                                                     "legal-actions");
822    
823        /**
824         * Returns the value of the {@link #LEGAL_ACTIONS LEGAL_ACTIONS} property as
825         * defined by this proxy.
826         * 
827         * @return A list of CqAction proxies representing the actions that are
828         *         currently legal for this record.
829         * 
830         * @throws WvcmException if this proxy does not define a value for the
831         *             {@link #LEGAL_ACTIONS LEGAL_ACTIONS} property.
832         */
833        ResourceList<CqAction> getLegalActions() throws WvcmException;
834    
835        /** The type (state-based or stateless) of the record. */
836        PropertyName<CqRecord.Class> RECORD_CLASS =
837            new PropertyName<CqRecord.Class>(StpExBase.PROPERTY_NAMESPACE,
838                                             "record-class");
839    
840        /**
841         * Returns the value of the {@link #RECORD_CLASS RECORD_CLASS} property as
842         * defined by this proxy.
843         * 
844         * @return A CqRecord.Class enumeration identifying the class of this record.
845         * 
846         * @throws WvcmException if this proxy does not define a value for the
847         *             {@link #RECORD_CLASS RECORD_CLASS} property.
848         */
849        Class getRecordClass() throws WvcmException;
850    
851        /**
852         * The CqAttachmentFolder resources that correspond to the fields of this
853         * record that have or may have attachments. The display name of the 
854         * attachment folder is the same as the name of the attachment field.
855         */
856        PropertyName<ResourceList<CqAttachmentFolder>> ATTACHMENT_FOLDERS =
857            new PropertyName<ResourceList<CqAttachmentFolder>>(StpExBase.PROPERTY_NAMESPACE,
858                                                               "attachment-folders");
859    
860        /**
861         * Returns the value of the {@link #ATTACHMENT_FOLDERS ATTACHMENT_FOLDERS}
862         * property as defined by this proxy.
863         * 
864         * @return A ResourceList contain CqAttachmentFolder proxies identifying the
865         *         attachment folders of this record.
866         * 
867         * @throws WvcmException if this proxy does not define a value for the
868         *             {@link #ATTACHMENT_FOLDERS ATTACHMENT_FOLDERS} property.
869         */
870        ResourceList<CqAttachmentFolder> getAttachmentFolders()
871            throws WvcmException;
872    
873        /**
874         * An enumeration of the possible types of records; state-based or
875         * stateless.
876         */
877        public static enum Class implements StpExEnumeration
878        {
879            /** A record type having no state table. */
880            STATELESS,
881    
882            /**
883             * A record type whose records progress from state to state along
884             * prescribed paths based on the actions applied to them.
885             */
886            STATE_BASED;
887        }
888    
889        /** The name of the record's current state. */
890        PropertyName<String> STATE_NAME =
891            new PropertyName<String>(StpExBase.PROPERTY_NAMESPACE, "state-name");
892    
893        /**
894         * Returns the value of the {@link #STATE_NAME STATE} property as defined by
895         * this proxy.
896         * 
897         * @return A String containing the name of the state the record is currently
898         *         in.
899         * 
900         * @throws WvcmException if this proxy does not define a value for the
901         *             {@link #STATE_NAME STATE} property.
902         */
903        String getStateName() throws WvcmException;
904    
905        /**
906         * The replica that has mastership of this record.
907         */
908        PropertyName<CqReplica> CQ_MASTER_REPLICA =
909            new PropertyName<CqReplica>(StpExBase.PROPERTY_NAMESPACE,
910                                        "cq-master-replica");
911    
912        /**
913         * Returns the value of the {@link #CQ_MASTER_REPLICA CQ_MASTER_REPLICA}
914         * property as defined by this proxy.
915         * 
916         * @return A CqReplica proxy for the replica that has mastership of this
917         *         record
918         * 
919         * @throws WvcmException if this proxy does not define a value for the
920         *             {@link #CQ_MASTER_REPLICA CQ_MASTER_REPLICA} property.
921         */
922        CqReplica getCqMasterReplica() throws WvcmException;
923    
924        /**
925         * Defines a new value for the {@link #CQ_MASTER_REPLICA CQ_MASTER_REPLICA}
926         * property of this proxy.
927         * 
928         * @param master A CqReplica proxy identifying the replica that should
929         *            assume mastership of this resource.
930         */
931        void setCqMasterReplica(CqReplica master);
932    
933        /**
934         * A list of all the fields that were modified by the on-going action
935         * applied to this record. Unlike the {@link #FIELDS_UPDATED_THIS_ACTION}
936         * property, this list includes fields modified by the hooks that ran during
937         * start up of the action.
938         */
939        PropertyName<StpProperty.List<CqFieldValue<?>>> FIELDS_UPDATED_THIS_ENTIRE_ACTION =
940            new PropertyName<StpProperty.List<CqFieldValue<?>>>(StpExBase.PROPERTY_NAMESPACE,
941                                                                "fields-updated-this-entire-action");
942    
943        /**
944         * Returns the value of the
945         * {@link #FIELDS_UPDATED_THIS_ENTIRE_ACTION FIELDS_UPDATED_THIS_ENTIRE_ACTION}
946         * property as defined by this proxy.
947         * 
948         * @return An StpProperty.List containing a CqFieldValue for each field
949         *         modified during the initialization and execution of the current
950         *         action. Will never be <b>null</b>, but may be empty.
951         * 
952         * @throws WvcmException if this proxy does not define a value for the
953         *             {@link #FIELDS_UPDATED_THIS_ENTIRE_ACTION FIELDS_UPDATED_THIS_ENTIRE_ACTION}
954         *             property.
955         */
956        StpProperty.List<CqFieldValue<?>> getFieldsUpdatedThisEntireAction()
957            throws WvcmException;
958    
959        /**
960         * A list of the fields of this record of
961         * {@link CqFieldValue.ValueType#JOURNAL}
962         */
963        PropertyName<StpProperty.List<CqHistoryFieldValue>> HISTORY_FIELDS =
964            new PropertyName<StpProperty.List<CqHistoryFieldValue>>(StpExBase.PROPERTY_NAMESPACE,
965                                                                    "history-fields");
966    
967        /**
968         * Returns the value of the {@link #HISTORY_FIELDS HISTORY_FIELDS} property
969         * as defined by this proxy.
970         * 
971         * @return An StpProperty.List containing a CqFieldValue instance for each
972         *         field of the record whose field value type is JOURNAL. Will never
973         *         be <b>null</b>, but may be empty.
974         * 
975         * @throws WvcmException if this proxy does not define a value for the
976         *             {@link #HISTORY_FIELDS HISTORY_FIELDS} property.
977         */
978        StpProperty.List<CqHistoryFieldValue> getHistoryFields()
979            throws WvcmException;
980    
981        /**
982         * A list of the actions that the current user may apply to this record.
983         */
984        PropertyName<ResourceList<CqAction>> LEGAL_ACCESSIBLE_ACTIONS =
985            new PropertyName<ResourceList<CqAction>>(StpExBase.PROPERTY_NAMESPACE,
986                                                     "legal-accessible-actions");
987    
988        /**
989         * Returns the value of the
990         * {@link #LEGAL_ACCESSIBLE_ACTIONS LEGAL_ACCESSIBLE_ACTIONS} property as
991         * defined by this proxy.
992         * 
993         * @return A ResourceList of CqAction proxies enumerating the actions that
994         *         the current user may apply to this record in its current state.
995         *         Will never be <b>null</b>, but may be empty.
996         * 
997         * @throws WvcmException if this proxy does not define a value for the
998         *             {@link #LEGAL_ACCESSIBLE_ACTIONS LEGAL_ACCESSIBLE_ACTIONS}
999         *             property.
1000         */
1001        ResourceList<CqAction> getLegalAccessibleActions() throws WvcmException;
1002    
1003        /**
1004         * The site-extension field for this record.
1005         */
1006        PropertyName<String> SITE_EXTENSION =
1007            new PropertyName<String>(StpExBase.PROPERTY_NAMESPACE, "site-extension");
1008    
1009        /**
1010         * Returns the value of the {@link #SITE_EXTENSION SITE_EXTENSION} property
1011         * as defined by this proxy.
1012         * 
1013         * @return A String containing the site-extension field used for this record
1014         *         when forming its site-extended name. Will never be <b>null</b>.
1015         * 
1016         * @throws WvcmException if this proxy does not define a value for the
1017         *             {@link #SITE_EXTENSION SITE_EXTENSION} property.
1018         */
1019        String getSiteExtension() throws WvcmException;
1020    
1021        /**
1022         * A list of all the records of this record type whose names differ from the
1023         * name of this record only in their site extensions.
1024         */
1025        PropertyName<ResourceList<CqRecord>> SITE_EXTENDED_NAMES =
1026            new PropertyName<ResourceList<CqRecord>>(StpExBase.PROPERTY_NAMESPACE,
1027                                                     "site-extended-names");
1028    
1029        /**
1030         * Returns the value of the {@link #SITE_EXTENDED_NAMES SITE_EXTENDED_NAMES}
1031         * property as defined by this proxy.
1032         * 
1033         * @return A ResourceList containing a proxy for each CqRecord resource
1034         *         whose name differs from the name of this record only in the
1035         *         site extensions used.
1036         * 
1037         * @throws WvcmException if this proxy does not define a value for the
1038         *             {@link #SITE_EXTENDED_NAMES SITE_EXTENDED_NAMES} property.
1039         */
1040        public ResourceList<CqRecord> getSiteExtendedNames() throws WvcmException;
1041    
1042        /**
1043         * The login name of the user currently holding a lock on this record ("*"
1044         * if the current user is not permitted to see user names). A zero-length
1045         * string indicates that the record is not locked. Setting this property to
1046         * the user's login-name or to a zero-length string locks or unlocks the
1047         * record, respectively.
1048         */
1049        PropertyName<String> LOCK_OWNER =
1050            new PropertyName<String>(PROPERTY_NAMESPACE, "lock-owner");
1051    
1052        /**
1053         * Returns the value of the {@link #LOCK_OWNER LOCK_OWNER} property as
1054         * defined by this proxy.
1055         * 
1056         * @return A String containing the login name of the user that has a lock on
1057         *         this record ("*" if the current user is not permitted to see
1058         *         other's login names). If no user has a lock on this record, a
1059         *         zero-length String is returned.
1060         * 
1061         * @throws WvcmException if this proxy does not define a value for the
1062         *             {@link #LOCK_OWNER LOCK_OWNER} property.
1063         */
1064        String getLockOwner() throws WvcmException;
1065    
1066        /**
1067         * Defines a new value for the {@link #LOCK_OWNER LOCK_OWNER} property of
1068         * this proxy.
1069         * <p>
1070         * Unlike the other writable properties of a record, updating the LOCK_OWNER
1071         * property <i>does not</i> require that an action be started or be in
1072         * progress. And if an action is started or is in progress, the record is
1073         * locked immediately and will remain locked only until the action is
1074         * delivered or reverted.
1075         * 
1076         * @param owner Either a zero-length String or a String containing the login
1077         *            name of the current user. Setting the value to a zero-length
1078         *            String will unlock the record. Setting a non-zero length value
1079         *            will lock the record.
1080         * 
1081         * @return This proxy.
1082         */
1083        CqRecord setLockOwner(String owner);
1084    }