View Javadoc

1   package org.lsst.ccs.bus;
2   
3   import org.lsst.ccs.utilities.beanutils.Optional;
4   import org.lsst.ccs.utilities.logging.Logger;
5   
6   import java.io.Serializable;
7   import java.util.Collections;
8   import java.util.List;
9   
10  /**
11   * A  key-value pair.
12   * The value can be a specific <TT>CodedData</TT>
13   * that codes data that is not of a "well known type".
14   * @author bamade
15   */
16  // Date: 23/12/2013
17  
18  public class KeyData implements Serializable {
19      /**
20       * the value of data can be of a "well known type" (known to everybody)
21       * and so is coded directly otherwise it is encoded in a <TT>CodedData</TT> object.
22       */
23      public static class CodedData implements Serializable {
24          /**
25           * the canonical name of the class of the coded object.
26           */
27          String className;
28          /**
29           * just anything
30           */
31          Object content;
32          /**
33           * a list of key-value
34           */
35          List<KeyData> listKV;
36  
37          public CodedData(String className) {
38              this.className = className;
39          }
40  
41          @Override
42          public String toString() {
43              return "CodedData{" +
44                      "className='" + className + '\'' +
45                      ", content=" + content +
46                      ", listKV=" + listKV +
47                      '}';
48          }
49      }
50      public static Logger logger = Logger.getLogger("org.lsst.ccs.bus") ;
51  
52      private String key;
53      private Object data;
54  
55      public KeyData(String key, Object data) {
56          this.key = key;
57          this.data = data;
58      }
59  
60      public String getKey() {
61          return this.key;
62      }
63  
64      public List<KeyData> getContentAsRawList() {
65          List<KeyData> listRes = null;
66          if (data instanceof CodedData) {
67              listRes = ((CodedData) data).listKV;
68          }
69          if (listRes == null) {
70              return Collections.emptyList();
71          }
72          return listRes;
73      }
74  
75      /**
76       * returns a list of key-values that can be directly used byt a trending database:
77       * each key (the name of fields in a composite object) is prepended with the actual key
78       * of this object (if overall key is "position" you may get something like "position.x" and "position.y"
79       * as keys in the list)
80       *
81       * @return
82       */
83      public List<KeyData> getContentAsList() {
84          return StatusCodec.asSimpleKeyValueList(key, data);
85      }
86  
87      /**
88       * returns the value of the contained object if its class is accessible to the current
89       * ClassLoader. Otherwise the <TT>Optional</TT> object is empty.
90       * @return
91       */
92      public Optional<Object> getValue() {
93          Object obj = null;
94          try {
95              obj = StatusCodec.decode(data);
96          } catch (Exception e) {
97              //todo: log!
98              logger.warn("can't decode " + getKey(),e) ;
99          }
100         if(obj == null) return Optional.empty() ;
101         return Optional.of(obj);
102     }
103 
104 
105     /**
106      * Big objects can be kept in database as Blobs.
107      * Objects that are <TT>Serializable</TT> but not decomposable (in key-value list)
108      * are stored in a byte array.
109      * @implSpec to be decided: do we need to return a "crystallized" version of a decomposable object too?
110      * @return
111      */
112     public Optional<byte[]> getCrystallizedData() {
113         byte[] res = null;
114         if (data instanceof CodedData) {
115             CodedData obj = ((CodedData) data);
116             if (obj.content instanceof byte[]) {
117                 res = (byte[]) obj.content;
118             }
119         }
120         return Optional.of(res);
121     }
122 
123     public String getUpdatedKey(String globalName) {
124         String newKey;
125         if (this.key.length() == 0) {
126             return globalName;
127         } else {
128             return globalName + '/' + this.key;
129         }
130     }
131 
132     public Object getRawValue() {
133         return this.data;
134     }
135 
136     @Override
137     public String toString() {
138         return "{" +
139                 "key='" + key + '\'' +
140                 ", data=" + data +
141                 '}';
142     }
143 }