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    
014    package com.ibm.rational.wvcm.stp.cq;
015    
016    import static com.ibm.rational.wvcm.stpex.StpExBase.METADATA_NAMESPACE;
017    
018    import java.util.EnumMap;
019    
020    import javax.wvcm.WvcmException;
021    
022    import com.ibm.rational.wvcm.stp.StpProperty;
023    import com.ibm.rational.wvcm.stp.cq.CqQuery.DisplayField;
024    import com.ibm.rational.wvcm.stp.cq.CqQuery.DisplayField.FieldType;
025    import com.ibm.rational.wvcm.stpex.StpExBase;
026    import com.ibm.rational.wvcm.stpex.StpExEnumeration;
027    import 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     */
034    public 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    }