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
014package com.ibm.rational.wvcm.stp.cq;
015import static com.ibm.rational.wvcm.stpex.StpExBase.PROPERTY_NAMESPACE;
016
017import java.util.Date;
018import java.util.List;
019
020import javax.wvcm.Feedback;
021import javax.wvcm.PropertyNameList;
022import javax.wvcm.PropertyNameList.PropertyName;
023import javax.wvcm.ResourceList;
024import javax.wvcm.WvcmException;
025
026import com.ibm.rational.wvcm.stp.StpActivity;
027import com.ibm.rational.wvcm.stp.StpErrorMessageException;
028import com.ibm.rational.wvcm.stp.StpProperty;
029import com.ibm.rational.wvcm.stp.StpResource;
030import com.ibm.rational.wvcm.stpex.StpExBase;
031import 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 */
092public 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}