1 package org.lsst.ccs.bus;
2
3 import java.util.Iterator;
4
5 /**
6 * Status with additional information.
7 * <p/>
8 * This is a model for the next version of DataStatus_Deprecated
9 * <P/>
10 * Instances of this class carry a set of data with a common <TT>dataTimeStamp</TT>.
11 * Each data in this set (of type <TT>KVList</TT>) is an object with a name.
12 * Each object is encoded in a <TT>KeyData</TT> structure.
13 * <P/>
14 * Note: keep in mind that each element in the list is of the form <TT>Key-VALUE</TT>
15 * but the <TT>VALUE</TT> can be itself burst into a list of
16 * key-values (if it is a composite Object) (so do not confuse the keys!)
17 * <P/>
18 * So for example you can have
19 * <UL>
20 * <LI/> a single primitive value contained as <TT>KVList{KeyData{"MyInteger",666}}</TT>
21 * <LI/> multiple primitive values contained as <TT>KVList{KeyData{"MyInteger",666}, KeyData{"MyString, "Hello"}}</TT>
22 * <LI/> single or multiple values that can be of any type (composite objects should have some specific properties: be <TT>Serializable</TT> or be "decomposable" in a list of key-value pairs) as:
23 * <TT>KVList{KeyData{"MyInteger", 666}, i
24 * KeyData{"MyObject", CodedData{"org.lsst.ccs.MyType", ,
25 * List{KeyData{"field1", 567}, KeyData{"field2", "world"}}}}}</TT>
26 * (in that case objects of type <TT>MyType</TT> have two fields: "field1" and "field2")
27 * <BR/> the important thing here is that the object will be read as <TT>
28 * List{"MyObject.field1"=567, "MyObject.field2"="world"}
29 * </TT>
30 * </UL>
31 * Methods encapsulate and simplify this analysis:
32 * for reading <TT>KeyData</TT> objects see corresponding documentation.
33 * <P/>
34 * Instances of the current class can be "linked" together to be sent in a single message
35 * across the buses. This is used when one wants to publish different values with different timestamps
36 * in a same message.
37 *
38 * @author bamade
39 */
40 // Date: 15/04/13
41
42 public class EncodedDataStatus extends Status implements Iterable<EncodedDataStatus> {
43
44
45 private EncodedDataStatus nextStatus;
46 private final KVList content;
47 private final long dataTimeStamp;
48
49 /**
50 * creates a status with a list of Key-value pairs with the same timestamp
51 *
52 * @param timestampArg
53 * @param content
54 */
55 public EncodedDataStatus(long timestampArg, KVList content) {
56 this.dataTimeStamp = timestampArg;
57 this.content = content;
58 }
59
60 /**
61 * creates a status with a list of Key-value pairs with the same timestamp
62 * which is generated at creation time.
63 * @param content
64 */
65 public EncodedDataStatus(KVList content) {
66 this(System.currentTimeMillis(), content);
67 }
68
69 /**
70 * creates a status with a single key and value (the timestamp is also provided)
71 * @param timestamp
72 * @param key
73 * @param value
74 */
75 public EncodedDataStatus(long timestamp, String key, Object value) {
76 this(timestamp, new KVList(key, value));
77 }
78
79 /**
80 * creates a status with a single key and value (the timestamp is generated)
81 * @param key
82 * @param value
83 */
84 public EncodedDataStatus(String key, Object value) {
85 this(new KVList(key, value));
86 }
87
88 /**
89 * adds another status at the end of the linked list of status sent in a single message
90 * @param next
91 */
92 public void addStatus(EncodedDataStatus next) {
93 EncodedDataStatus dataStatus2 = this;
94 while (nextStatus != null) {
95 dataStatus2 = nextStatus;
96 }
97 nextStatus = next;
98 }
99
100 /**
101 * links another status next to this one (for sending a batch of status
102 * in a single message)
103 * @param next
104 */
105 public void setNext(EncodedDataStatus next) {
106 nextStatus = next;
107 }
108
109 /**
110 * helps iterating over a list of linked status message.
111 * <P/>
112 * So an idiom to read a message can be:
113 * <PRE>
114 * EncodedDataStatus received = ..... ;
115 * for (EncodedDataStatus dataStatus : received) {
116 * KVList list = dataStatus.getContent();
117 * for (KeyData keyData : list) {
118 * .... dataStatus.getDataTimestamp() ....
119 * .... keyData.getKey() ....
120 * // one of those Three options
121 * .... keyData.getValue() .... // Optional
122 * .... keyData.getContentAsList() ....// may be empty
123 * .... keyData.getCrystallizedData() .... // Optional
124 * }
125 * }
126 * </PRE>
127 * @return
128 */
129 @Override
130 public Iterator<EncodedDataStatus> iterator() {
131 return new Iterator<EncodedDataStatus>() {
132
133 EncodedDataStatus coming = EncodedDataStatus.this;
134
135 @Override
136 public boolean hasNext() {
137 return coming != null;
138 }
139
140 @Override
141 public EncodedDataStatus next() {
142 EncodedDataStatus res = coming;
143 coming = res.nextStatus;
144 return res;
145 }
146
147 @Override
148 public void remove() {
149 throw new UnsupportedOperationException();
150
151 }
152 };
153 }
154
155
156 public KVList getContent() {
157 return content;
158 }
159
160 public long getDataTimestamp() {
161 return this.dataTimeStamp;
162 }
163
164 @Override
165 public String toString() {
166 return super.toString() + " {" +
167 "content=" + content +
168 ", dataTimeStamp=" + dataTimeStamp +
169 "} ";
170 }
171 }