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