001/*
002 * file CqFieldValue.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM 
006 *
007 * com.ibm.rational.wvcm.stp.cq.CqFieldValue
008 *
009 * (C) Copyright IBM Corporation 2004, 2008.  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;
015
016import static com.ibm.rational.wvcm.stpex.StpExBase.METADATA_NAMESPACE;
017
018import java.util.EnumMap;
019
020import javax.wvcm.WvcmException;
021
022import com.ibm.rational.wvcm.stp.StpProperty;
023import com.ibm.rational.wvcm.stp.cq.CqQuery.DisplayField;
024import com.ibm.rational.wvcm.stp.cq.CqQuery.DisplayField.FieldType;
025import com.ibm.rational.wvcm.stpex.StpExBase;
026import com.ibm.rational.wvcm.stpex.StpExEnumeration;
027import com.ibm.rational.wvcm.stpex.StpExEnumerationBase;
028
029
030/**
031 * The representation for the value of a record field as an extended StpProperty
032 * object.
033 */
034public interface CqFieldValue<T>
035    extends StpProperty<T>
036{
037    /**
038     * An enumeration of the possible types of values that can be stored in a
039     * record field. This enumeration is more precise than the StpProperty.Type
040     * enumeration in specifying the type of a field value.
041     */
042    public enum ValueType implements StpExEnumeration
043    {
044        /** An initial value for ValueType variables */
045        UNKNOWN(Type.UNKNOWN),
046
047        /**
048         * A single-line of text up to 254 characters. Leading and trailing
049         * whitespace is trimmed when stored in a record.
050         */
051        SHORT_STRING(Type.STRING),
052
053        /**
054         * An arbitrarily long string of characters, possibly containing one or
055         * more newline characters.
056         */
057        MULTILINE_STRING(Type.STRING),
058
059        /** An integer in the range -9999999999 to 9999999999 */
060        INTEGER(Type.INTEGER),
061
062        /**
063         * A GMT date/time between 12:00:01 AM January 1, 1970 and 11:59:59 PM
064         * January 18, 2038.
065         */
066        DATE_TIME(Type.DATE_TIME),
067
068        /** A proxy for a Resource of a specific ResourceValueType. */
069        RESOURCE(Type.RESOURCE),
070
071        /** A list of proxies for a Resource of a specific ResourceValueType */
072        RESOURCE_LIST(Type.RESOURCE_LIST),
073
074        /** A floating point value */
075        FLOAT(Type.FLOAT),
076
077        /** A field containing attachments */
078        ATTACHMENT_LIST(Type.RESOURCE_LIST),
079
080        /** A record id (alphanumeric) field */
081        ID(Type.STRING),
082
083        /** A field containing the name of the record's current state */
084        STATE(Type.STRING),
085
086        /** A field recording events in the history of the record */
087        JOURNAL(Type.OBJECT),
088
089        /** A database id (integer) field */
090        DBID(Type.LONG),
091
092        /** A field containing the type of the record's current state */
093        STATE_TYPE(Type.STRING),
094
095        /** A field containing the record's record type name */
096        RECORD_TYPE(Type.STRING);
097
098        /**
099         * The StpProperty.Type that corresponds to this field type.
100         * 
101         * @return An StpProperty.Type enumerator specifying as closely as
102         *         possible the Java representation of this type of value
103         *         corresponding
104         */
105        public Type toPropertyType()
106        {
107            return m_type;
108         }
109        
110        /**
111         * Returns the ValueType that exactly matches a given PropertyType;
112         * otherwise UNKNOWN.
113         * 
114         * @param type a Type enumerator
115         * @return the ValueType that exactly matches the given Type
116         *         PropertyType; otherwise UNKNOWN.
117         */
118        static public ValueType fromPropertyType(Type type)
119        {
120            for (ValueType vt: values())
121                if (vt.toPropertyType() == type)
122                    return vt;
123            
124            return UNKNOWN;
125        }
126        
127        /**
128         * The CqQuery.DisplayField.FieldType that corresponds to this field type.
129         * 
130         * @return An CqQuery.DisplayField.FieldType enumerator specifying as closely as
131         *         possible the Java representation of this type of value
132         *         corresponding
133         */
134        public FieldType toFieldType()
135        {
136            for(FieldType ft: FieldType.values())
137                if (ft.valueType() == this)
138                    return ft;
139            
140            switch (m_type) {
141            case RESOURCE:
142                return FieldType.REFERENCE;
143            case STRING:
144                return FieldType.MULTILINE_STRING;
145            case OBJECT:
146            case RESOURCE_LIST:
147                return FieldType.BINARY;
148            }
149            
150            return FieldType.UNKNOWN;
151        }
152        
153        private ValueType(Type type)
154        {
155            m_type = type;
156        }
157
158        private Type m_type;
159    }
160
161    /**
162     * An enumeration indicating the validity of a field value.
163     */
164    public enum ValidationStatus
165        implements StpExEnumeration
166    {
167        /** The field value has been validated and found to be valid. */
168        VALID,
169
170        /** The field value has been validated and found to be invalid. */
171        INVALID,
172
173        /**
174         * The field value has not yet been validated and so it is unknown
175         * whether it is valid or not.
176         */
177        NEEDS_VALIDATION;
178    }
179
180    /**
181     * An enumeration indicating whether or not a field has a value.
182     */
183    public enum ValueStatus
184        implements StpExEnumeration
185    {
186        /** The field has a value. */
187        HAS_A_VALUE,
188
189        /** The field has no value set. */
190        HAS_NO_VALUE,
191
192        /**
193         * The current state of the field prevents it from returning a value.
194         */
195        VALUE_NOT_AVAILABLE;
196    }
197
198    /**
199     * @return the PropertyName of this CqFieldValue property as a
200     *         CqRecord.FieldName
201     */
202    CqRecord.FieldName<T> getFieldName();
203    
204    /** The record instance of which this field is a part. */
205    MetaPropertyName<CqRecord> RECORD = 
206        new MetaPropertyName<CqRecord>(METADATA_NAMESPACE, "resource");
207
208
209    /**
210     * Returns the value of the {@link #RECORD RECORD} metadata component as
211     * defined by this Property instance.
212     *
213     * @return  A Record proxy for the record of which this field is a member.
214     *
215     * @throws  WvcmException  if this Property instance does not define a value
216     *                         for the {@link #RECORD RECORD} metadata
217     *                         component.
218     */
219    CqRecord getRecord()
220        throws WvcmException;
221
222    /**
223     * The field definition that defines all static properties of this field.
224     */
225    MetaPropertyName<CqFieldDefinition> FIELD_DEFINITION =
226        new MetaPropertyName<CqFieldDefinition>(METADATA_NAMESPACE,
227                                                "field-definition");
228
229    /**
230     * Returns the value of the {@link #FIELD_DEFINITION FIELD_DEFINITION}
231     * metadata component as defined by this Property instance.
232     *
233     * @return  A CqFieldDefinition proxy specifying the static properties of this
234     *          field.
235     *
236     * @throws  WvcmException  if this Property instance does not define a value
237     *                         for the {@link #FIELD_DEFINITION FIELD_DEFINITION
238     *                         } metadata component.
239     */
240    CqFieldDefinition getFieldDefinition()
241        throws WvcmException;
242
243    /** Identifies the requiredness of the specified field. */
244    MetaPropertyName<CqFieldDefinition.Requiredness> REQUIREDNESS =
245        new MetaPropertyName<CqFieldDefinition.Requiredness>(METADATA_NAMESPACE,
246                                                             "requiredness");
247
248    /**
249     * Returns the value of the {@link #REQUIREDNESS REQUIREDNESS} metadata
250     * component as defined by this Property instance.
251     *
252     * @return  A Requiredness enumerator specifying whether this field cannot,
253     *          may, or must have a value in the current state.
254     *
255     * @throws  WvcmException  if this Property instance does not define a value
256     *                         for the {@link #REQUIREDNESS REQUIREDNESS}
257     *                         metadata component.
258     */
259    public CqFieldDefinition.Requiredness getRequiredness()
260        throws WvcmException;
261
262    /**
263     * The current list of possible values for this field. If this list is empty
264     * and {@link CqFieldDefinition#HAS_OPEN_CHOICE_LIST} is true, it neither
265     * implies that all values are permitted nor that no values are permitted;
266     * it just means that the schema designer has not provided any hints about
267     * the values permitted in the field. On the other hand, if
268     * {@link CqFieldDefinition#HAS_OPEN_CHOICE_LIST} is false then the choice
269     * list contains only the values currently permitted for the field.
270     * <p>
271     * In general, the content of a field's choice list is quite volatile and
272     * can depend on the state of the record it is in, the value of other fields
273     * of that record or related records, the current user's permissions, and
274     * other dynamic aspects of the database environment known only to the
275     * schema. So, in general, the choice list must be obtained in the context
276     * in which it is to be used at the time it is to be used. In this
277     * interface, that very dynamic value is expressed as the value of this
278     * meta-property.
279     * <p>
280     * {@link CqFieldValue#CHOICE_LIST} always returns the choice list for the
281     * field whether that list is static or not. If the schema is designed such
282     * that the choice list for a field in all records in all contexts is fixed
283     * by the schema, then this meta-property will always return the same list
284     * for that field. In this static case, the list returned by this
285     * meta-property will be the same as the list returned by the
286     * {@link CqFieldDefinition#CHOICE_LIST} property.
287     * <p>
288     * Choice lists can be voluminous and, so, should be read from the server
289     * only when needed. Yet, as explained above, they can also be quite
290     * volatile and may easily change during the course of a session and not
291     * necessarily in direct response to anything the client is doing. To
292     * mitigate this problem, a choice-list-id is provided to help the client
293     * know when it should request a new copy of the list. Every choice list has
294     * a choice-list-id. The value of the choice-list-id changes when and only
295     * when the content of the associated choice list changes.
296     * <p>
297     * If a client does not know that a given field has a static choice list, it
298     * must assume that it is not and monitor the field's CHOICE_LIST_ID
299     * to know when to load/reload its content.
300     */
301    MetaPropertyName<java.util.List<String>> CHOICE_LIST =
302        new MetaPropertyName<java.util.List<String>>(METADATA_NAMESPACE,
303                                                     "choice-list");
304
305    /**
306     * Returns the value of the {@link #CHOICE_LIST CHOICE_LIST} metadata
307     * component as defined by this Property instance.
308     *
309     * @return  A List of Strings, each containing a possible value for this
310     *          field.
311     *
312     * @throws  WvcmException  if this Property instance does not define a value
313     *                         for the {@link #CHOICE_LIST CHOICE_LIST} metadata
314     *                         component.
315     */
316    java.util.List<String> getChoiceList()
317        throws WvcmException;
318
319    /** A String explaining why the value stored in the field is invalid. */
320    MetaPropertyName<String> MESSAGE_TEXT =
321        new MetaPropertyName<String>(METADATA_NAMESPACE, "message-text");
322
323    /**
324     * Returns the value of the {@link #MESSAGE_TEXT MESSAGE_TEXT} metadata
325     * component as defined by this Property instance.
326     *
327     * @return  A String containing any message currently associated with this
328     *          field.
329     *
330     * @throws  WvcmException  if this Property instance does not define a value
331     *                         for the {@link #MESSAGE_TEXT MESSAGE_TEXT}
332     *                         metadata component.
333     */
334    String getMessageText()
335        throws WvcmException;
336
337    /** Identifies whether the field's value is valid. */
338    MetaPropertyName<ValidationStatus> VALIDATION_STATUS =
339        new MetaPropertyName<ValidationStatus>(METADATA_NAMESPACE,
340                                               "validation-status");
341
342    /**
343     * Returns the value of the {@link #VALIDATION_STATUS VALIDATION_STATUS}
344     * metadata component as defined by this Property instance.
345     *
346     * @return  A ValidationStatus enumerator identifying the validation status
347     *          of this field.
348     *
349     * @throws  WvcmException  if this Property instance does not define a value
350     *                         for the {@link #VALIDATION_STATUS
351     *                         VALIDATION_STATUS} metadata component.
352     */
353    ValidationStatus getValidationStatus()
354        throws WvcmException;
355
356    /** Identifies whether the field currently has a value. */
357    MetaPropertyName<ValueStatus> VALUE_STATUS =
358        new MetaPropertyName<ValueStatus>(METADATA_NAMESPACE, "value-status");
359
360    /**
361     * Returns the value of the {@link #VALUE_STATUS VALUE_STATUS} metadata
362     * component as defined by this Property instance.
363     *
364     * @return  A ValueStatus enumeration indicating whether or not this field
365     *          has a value.
366     *
367     * @throws  WvcmException  if this Property instance does not define a value
368     *                         for the {@link #VALUE_STATUS VALUE_STATUS}
369     *                         metadata component.
370     */
371    ValueStatus getValueStatus()
372        throws WvcmException;
373
374    /** The type of this field's VALUE meta-property value. */
375    public static final MetaPropertyName<ValueType> FIELD_TYPE =
376        new MetaPropertyName<ValueType>(METADATA_NAMESPACE, "field-type");
377
378    /**
379     * Returns the value of the {@link #FIELD_TYPE FIELD_TYPE} meta-property as
380     * defined by this CqFieldValue instance.
381     * 
382     * @return A VAlueType enumeration representing the type of this property's
383     *         VALUE meta-property.
384     * 
385     * @throws WvcmException if this Property instance does not define a value
386     *             for the {@link #FIELD_TYPE FIELD_TYPE} meta-property.
387     */
388    public ValueType getFieldType()
389        throws WvcmException;
390
391    /** True if the field's validity was changed by the current action. */
392    MetaPropertyName<Boolean> VALIDITY_CHANGED_THIS_ACTION =
393        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
394                                      "validity-changed-this-action");
395
396    /**
397     * Returns the value of the {@link #VALIDITY_CHANGED_THIS_ACTION
398     * VALIDITY_CHANGED_THIS_ACTION} metadata component as defined by this
399     * Property instance.
400     *
401     * @return  <b>true</b> if the field validity changed during the current
402     *          action
403     *
404     * @throws  WvcmException  if this Property instance does not define a value
405     *                         for the {@link #VALIDITY_CHANGED_THIS_ACTION
406     *                         VALIDITY_CHANGED_THIS_ACTION} metadata component.
407     */
408    boolean getValidityChangedThisAction()
409        throws WvcmException;
410
411    /**
412     * True if the field's validity was changed by the most recent SetFieldValue
413     * call.
414     */
415    MetaPropertyName<Boolean> VALIDITY_CHANGED_THIS_SET_VALUE =
416        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
417                                      "validity-changed-this-set-value");
418
419    /**
420     * Returns the value of the {@link #VALIDITY_CHANGED_THIS_SET_VALUE
421     * VALIDITY_CHANGED_THIS_SET_VALUE} metadata component as defined by this
422     * Property instance.
423     *
424     * @return  <b>true</b> if the field validity was changed by the most recent
425     *          property update.
426     *
427     * @throws  WvcmException  if this Property instance does not define a value
428     *                         for the {@link #VALIDITY_CHANGED_THIS_SET_VALUE
429     *                         VALIDITY_CHANGED_THIS_SET_VALUE} metadata
430     *                         component.
431     */
432    boolean getValidityChangedThisSetValue()
433        throws WvcmException;
434
435    /**
436     * True if the field's validity was changed by the most recent group of
437     * SetFieldValue calls.
438     */
439    MetaPropertyName<Boolean> VALIDITY_CHANGED_THIS_GROUP =
440        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
441                                      "validity-changed-this-group");
442
443    /**
444     * Returns the value of the {@link #VALIDITY_CHANGED_THIS_GROUP
445     * VALIDITY_CHANGED_THIS_GROUP} metadata component as defined by this
446     * Property instance.
447     * 
448     * @return <b>true</b> if this field's validity has changed since the last
449     *         setting of {@link CqRecord#FIELDS_UPDATED_THIS_GROUP} in this
450     *         field's record.
451     * 
452     * @throws WvcmException if this Property instance does not define a value
453     *             for the {@link #VALIDITY_CHANGED_THIS_GROUP
454     *             VALIDITY_CHANGED_THIS_GROUP} metadata component.
455     */
456    boolean getValidityChangedThisGroup()
457        throws WvcmException;
458
459    /** True if this field's value was modified by the current action. */
460    MetaPropertyName<Boolean> VALUE_CHANGED_THIS_ACTION =
461        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
462                                      "value-changed-this-action");
463
464    /**
465     * Returns the value of the {@link #VALUE_CHANGED_THIS_ACTION
466     * VALUE_CHANGED_THIS_ACTION} metadata component as defined by this Property
467     * instance.
468     *
469     * @return  <b>true</b> if this field's value has changed during the current
470     *          action.
471     *
472     * @throws  WvcmException  if this Property instance does not define a value
473     *                         for the {@link #VALUE_CHANGED_THIS_ACTION
474     *                         VALUE_CHANGED_THIS_ACTION} metadata component.
475     */
476    boolean getValueChangedThisAction()
477        throws WvcmException;
478
479    /**
480     * True if this field's value was modified by the most recent property
481     * update interaction with the server.
482     */
483    MetaPropertyName<Boolean> VALUE_CHANGED_THIS_SET_VALUE =
484        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
485                                      "value-changed-this-set-value");
486
487    /**
488     * Returns the value of the {@link #VALUE_CHANGED_THIS_SET_VALUE
489     * VALUE_CHANGED_THIS_SET_VALUE} metadata component as defined by this
490     * Property instance.
491     *
492     * @return  <b>true</b> if this fields value changed during the latest
493     *          property-update interaction with the server
494     *
495     * @throws  WvcmException  if this Property instance does not define a value
496     *                         for the {@link #VALUE_CHANGED_THIS_SET_VALUE
497     *                         VALUE_CHANGED_THIS_SET_VALUE} metadata component.
498     */
499    boolean getValueChangedThisSetValue()
500        throws WvcmException;
501
502    /**
503     * True if the field's value was modified by the most recent group of
504     * SetFieldValue calls.
505     */
506    MetaPropertyName<Boolean> VALUE_CHANGED_THIS_GROUP =
507        new MetaPropertyName<Boolean>(METADATA_NAMESPACE,
508                                      "value-changed-this-group");
509
510    /**
511     * Returns the value of the {@link #VALUE_CHANGED_THIS_GROUP
512     * VALUE_CHANGED_THIS_GROUP} metadata component as defined by this Property
513     * instance.
514     * 
515     * @return <b>true</b> if this field's value has changed since the last
516     *         setting of {@link CqRecord#FIELDS_UPDATED_THIS_GROUP} in this
517     *         field's record.
518     * 
519     * @throws WvcmException if this Property instance does not define a value
520     *             for the {@link #VALUE_CHANGED_THIS_GROUP
521     *             VALUE_CHANGED_THIS_GROUP} metadata component.
522     */
523    boolean getValueChangedThisGroup()
524        throws WvcmException;
525
526    /**
527     * The field's value as it was retrieved from the database at the start of
528     * the action.
529     */
530    MetaPropertyName<?> ORIGINAL_VALUE =
531        MetaPropertyName.build(StpExBase.METADATA_NAMESPACE, "original-value");
532
533    /**
534     * Returns the value of the {@link #ORIGINAL_VALUE ORIGINAL_VALUE} metadata
535     * component as defined by this Property instance.
536     *
537     * @return  An Object representing the value of this field just prior to
538     *          being made editable in this workspace.
539     *
540     * @throws  WvcmException  if this Property instance does not define a value
541     *                         for the {@link #ORIGINAL_VALUE ORIGINAL_VALUE}
542     *                         metadata component.
543     */
544    T getOriginalValue()
545        throws WvcmException;
546
547    /**
548     * The field's value status as it was retrieved from the database at the
549     * start of the action.
550     */
551    MetaPropertyName<ValueStatus> ORIGINAL_VALUE_STATUS =
552        new MetaPropertyName<ValueStatus>(StpExBase.METADATA_NAMESPACE, "original-value-status");
553
554    /**
555     * Returns the value of the {@link #ORIGINAL_VALUE_STATUS
556     * ORIGINAL_VALUE_STATUS} metadata component as defined by this Property
557     * instance.
558     *
559     * @return  A ValueStatus enumerator representing the status of this field's
560     *          value just prior to being made editable in this workspace.
561     *
562     * @throws  WvcmException  if this Property instance does not define a value
563     *                         for the {@link
564     *                         #ORIGINAL_VALUE_STATUS ORIGINAL_VALUE_STATUS}
565     *                         metadata component.
566     */
567    ValueStatus getOriginalValueStatus()
568        throws WvcmException;
569
570    /**
571     * Initializes the values of this field value structure.
572     *
573     * @param  values  A list of value images that are to be the new field value
574     *                 images. May be null to indicate a null field value.
575     */
576    void initialize(java.util.List<String> values);
577
578    /**
579     * Initializes the value of this field value structure.
580     * 
581     * @param  value  The string value that is to be the new field value image.
582     *                May be null to indicate a null field value.
583     *                
584     * @throws WvcmException if the field value is a record or list of records
585     * and the specified String is not a valid StpLocation image.
586     */
587    void initialize(String value) throws WvcmException;
588
589    /**
590     * Initializes the value of this field value structure using the value
591     * object rather than its image.
592     *
593     * @param  value  The value of the field. Must be a native representation of
594     *                one of the supported field types.
595     */
596    void initialize(Object value) throws WvcmException;
597
598    /**
599     * Returns the number of individual values in an aggregated field value.
600     *
601     * @return  Returns 0 for a null value, 1 for a scalar value, and the count
602     *          of the number of individual values in a aggregated value.
603     *          
604     * @throws WvcmException if the field value is a record or list of records
605     * and the value specified as a String is not a valid StpLocation image.
606     */
607    long valueCount();
608
609    /**
610     * Returns the character image of the i-th element of an aggregated value.
611     *
612     * @param  i  The (zero-origin) index of the value whose character image is
613     *            desired. Must be zero or less than {@link #valueCount()
614     *            valueCount}.
615     *
616     * @return  The character image of the i-th element of the field value. If
617     *          the field value is null, {@link #NULL_VALUE_IMAGE
618     *          NULL_VALUE_IMAGE} is returned for index 0.
619     *
620     * @throws  WvcmException  If an i-th value exists in this fields value
621     *                         list.
622     */
623    String characterImage(int i)
624        throws WvcmException;
625
626    /**
627     * Returns the character image of the (first) field value.
628     *
629     * @return  Returns {@link #characterImage(int) characterImage(0)}.
630     *
631     * @throws  WvcmException  If the value is null (valueCount == 0).
632     */
633    String characterImage()
634        throws WvcmException;
635
636    /**
637     * The special string value returned by characterImage for a null field
638     * value
639     */
640    String NULL_VALUE_IMAGE = "<CTG:NULL_VALUE/>";
641}