artdaq_node_server  v1_00_09
 All Classes Namespaces Files Variables Pages
serializer.js
1 var xmlBuilder = require('xmlbuilder')
2  , dateFormatter = require('./date_formatter')
3  , CustomType = require('./customtype')
4 
5 
15 exports.serializeMethodCall = function(method, params, encoding) {
16  var params = params || []
17 
18  var options = { version: '1.0', allowSurrogateChars: true }
19 
20  if (encoding) {
21  options.encoding = encoding
22  }
23 
24  var xml = xmlBuilder.create('methodCall', options)
25  .ele('methodName')
26  .txt(method)
27  .up()
28  .ele('params')
29 
30  params.forEach(function(param) {
31  serializeValue(param, xml.ele('param'))
32  })
33 
34  // Includes the <?xml ...> declaration
35  return xml.doc().toString()
36 }
37 
47 exports.serializeMethodResponse = function(result) {
48  var xml = xmlBuilder.create('methodResponse', { version: '1.0', allowSurrogateChars: true })
49  .ele('params')
50  .ele('param')
51 
52  serializeValue(result, xml)
53 
54  // Includes the <?xml ...> declaration
55  return xml.doc().toString()
56 }
57 
58 exports.serializeFault = function(fault) {
59  var xml = xmlBuilder.create('methodResponse', { version: '1.0', allowSurrogateChars: true })
60  .ele('fault')
61 
62  serializeValue(fault, xml)
63 
64  // Includes the <?xml ...> declaration
65  return xml.doc().toString()
66 }
67 
68 function serializeValue(value, xml) {
69  var stack = [ { value: value, xml: xml } ]
70  , current = null
71  , valueNode = null
72  , next = null
73 
74  while (stack.length > 0) {
75  current = stack[stack.length - 1]
76 
77  if (current.index !== undefined) {
78  // Iterating a compound
79  next = getNextItemsFrame(current)
80  if (next) {
81  stack.push(next)
82  }
83  else {
84  stack.pop()
85  }
86  }
87  else {
88  // we're about to add a new value (compound or simple)
89  valueNode = current.xml.ele('value')
90  switch(typeof current.value) {
91  case 'boolean':
92  appendBoolean(current.value, valueNode)
93  stack.pop()
94  break
95  case 'string':
96  appendString(current.value, valueNode)
97  stack.pop()
98  break
99  case 'number':
100  appendNumber(current.value, valueNode)
101  stack.pop()
102  break
103  case 'object':
104  if (current.value === null) {
105  valueNode.ele('nil')
106  stack.pop()
107  }
108  else if (current.value instanceof Date) {
109  appendDatetime(current.value, valueNode)
110  stack.pop()
111  }
112  else if (Buffer.isBuffer(current.value)) {
113  appendBuffer(current.value, valueNode)
114  stack.pop()
115  }
116  else if (current.value instanceof CustomType) {
117  current.value.serialize(valueNode)
118  stack.pop()
119  }
120  else {
121  if (Array.isArray(current.value)) {
122  current.xml = valueNode.ele('array').ele('data')
123  }
124  else {
125  current.xml = valueNode.ele('struct')
126  current.keys = Object.keys(current.value)
127  }
128  current.index = 0
129  next = getNextItemsFrame(current)
130  if (next) {
131  stack.push(next)
132  }
133  else {
134  stack.pop()
135  }
136  }
137  break
138  default:
139  stack.pop()
140  break
141  }
142  }
143  }
144 }
145 
146 function getNextItemsFrame(frame) {
147  var nextFrame = null
148 
149  if (frame.keys) {
150  if (frame.index < frame.keys.length) {
151  var key = frame.keys[frame.index++]
152  , member = frame.xml.ele('member').ele('name').text(key).up()
153  nextFrame = {
154  value: frame.value[key]
155  , xml: member
156  }
157  }
158  }
159  else if (frame.index < frame.value.length) {
160  nextFrame = {
161  value: frame.value[frame.index]
162  , xml: frame.xml
163  }
164  frame.index++
165  }
166 
167  return nextFrame
168 }
169 
170 function appendBoolean(value, xml) {
171  xml.ele('boolean').txt(value ? 1 : 0)
172 }
173 
174 var illegalChars = /^(?![^<&]*]]>[^<&]*)[^<&]*$/
175 function appendString(value, xml) {
176  if (value.length === 0) {
177  xml.ele('string')
178  }
179  else if (!illegalChars.test(value)) {
180  xml.ele('string').d(value)
181  }
182  else {
183  xml.ele('string').txt(value)
184  }
185 }
186 
187 function appendNumber(value, xml) {
188  if (value % 1 == 0) {
189  xml.ele('int').txt(value)
190  }
191  else {
192  xml.ele('double').txt(value)
193  }
194 }
195 
196 function appendDatetime(value, xml) {
197  xml.ele('dateTime.iso8601').txt(dateFormatter.encodeIso8601(value))
198 }
199 
200 function appendBuffer(value, xml) {
201  xml.ele('base64').txt(value.toString('base64'))
202 }