OSDN Git Service

Debug: workspace
[eos/zephyr.git] / server / class / Eos.js
1 /** * * Class variables */ 
2 // include all Eos command's info.  
3 // For seaching with O(n), the object key name is command name.  
4 var db = require('./DB.js').instance; 
5 var commandList = require(__dirname + '/../../user-specific-files/OptionControlFile/command_list.json');
6 var ocfReference = {};
7
8 commandList.forEach(function(c) {
9     ocfReference[c.name] = require(__dirname + '/../../user-specific-files/OptionControlFile/commands/' + c.name);
10 });
11 var spawn = require('child_process').spawn;
12
13
14 function hasOneProperty(options) {
15     return new Promise(function(resolve, reject) {
16         if(options.length === 0) {
17             var errorMsg = 'At least one option is required.';
18             throw new Error(errorMsg);
19         } else {
20             resolve();
21         }
22     });
23 }
24
25 function matchOption(options, ocf) {
26     return new Promise(function(resolve, reject) {
27         var ok = {};
28         var notIncludingRequiredOptions = [];
29         options.forEach(function(o) { 
30             ok[o.name] = o.arguments;
31         });
32         ocf.forEach(function(o) {
33             if(o.optionProperties && !ok[o.option]) {
34                 notIncludingRequiredOptions.push(o.option);
35             }
36         });
37
38         // check whether all required option exist 
39         if(notIncludingRequiredOptions.length > 0) {
40             var errorMsg = 'Option ' + notIncludingRequiredOptions.toString() + ' are required';
41             reject(new Error(errorMsg));
42         } else {
43             resolve();
44         }
45     });
46 }
47
48 function validArgumentsNumber(options, ocfObj) {
49     return new Promise(function(resolve, reject) {
50         options.forEach(function(o) {
51             // option number
52             var expectNum = ocfObj[o.name].optionNumber;
53             var actualNum = o.arguments.length;
54             if(expectNum !== actualNum) {
55                 reject(new Error('Invalid arguments number'));
56             }
57         });
58         resolve();
59     });
60 };
61
62 function validArgumentsType(options, ocfObj, workspace) {
63     return new Promise(function(resolve, reject) {
64         options.forEach(function(o) {
65             o.arguments.forEach(function(arg,i) {
66                 // argType
67                 var formType = ocfObj[o.name].arg[i].formType
68                 if(formType === 'select') { // This argument is filename
69                     var exist = workspace.indexOf(arg) > -1;
70                     if(!exist) {
71                         reject(new Error(arg + ' doesn\'t exist.'));
72                     }
73                 } else {
74                     var expectType = formType === 'text' ? 'string' : 'number';
75                     var actualType = typeof arg;
76                     if(expectType !== actualType) {
77                         reject(new Error('argType is invalid'));
78                     }
79                 }
80             });
81         });
82         resolve();
83     });
84 }
85
86 function validOutfileName(options, ocfObj, workspace) {
87     return new Promise(function(resolve, reject) {
88         // output file Regexp
89         var outRegExp = /out|append/;
90
91         options.forEach(function(o) {
92             o.arguments.forEach(function(arg,i) {
93                 // outFile name
94                 if(outRegExp.test(ocfObj[o.name].arg[i].argType)) {
95                     if(workspace.indexOf(o.arguments[i]) > -1) {
96                         reject(new Error('Invalid outfile name.'));
97                     }
98                 }
99             });
100         });
101         resolve();
102     });
103 }
104
105 /**
106  * validate 
107  * コマンドとオプションのバリデーション
108  * @param command
109  * @param params
110  * @returns {valid: boolean, message: string}
111  */
112 function validate(command, options, workspaceId) {
113     return new Promise(function(resolve, reject) {
114
115         var ocf;
116         if(ocfReference[command]) {
117             ocf = ocfReference[command];
118         } else {
119             var errorMsg = 'Command name is invalid';
120             reject(new Error(errorMsg));
121         }
122
123         var ocfObj = {};
124         ocf.forEach(function(o) {
125             ocfObj[o.option] = o;
126         });
127
128         var optionsObj = {};
129         if(Array.isArray(options)) {
130             options.forEach(function(o) {
131                 if(o.name && o.arguments) {
132                     if(Array.isArray(o.arguments)) {
133                         optionsObj[o.name] = o.arguments;
134                     } else {
135                         var errorMsg = 'Each "arguments" properties needs to be Array';
136                         reject(new Error(errorMsg));
137                     }
138                 } else {
139                     var errorMsg = 'Options need to include Object which have properties "name" and "arguments"';
140                     reject(new Error(errorMsg));
141                 }
142             });
143         } else {
144             var errorMsg = 'Options need to be Array';
145             reject(new Error(errorMsg));
146         }
147
148         getFiles(workspaceId)
149         .then(function(workspace) {
150
151             // validate function
152             var promises = [];
153             promises.push(hasOneProperty(options));
154             promises.push(matchOption(options, ocf));
155             promises.push(validArgumentsNumber(options, ocfObj));
156             promises.push(validArgumentsType(options, ocfObj, workspace));
157             promises.push(validOutfileName(options, ocfObj, workspace));
158
159             // do validation
160             return Promise.all(promises)
161         })
162         .catch(function(error) {
163             reject(error);
164         })
165         .then(function(r) {
166             resolve();
167         })
168     });
169 }
170
171 /**
172  * toExecString
173  *
174  * @param command
175  * @param options
176  * @returns {string}
177  */
178 function toExecString(command, options, workspaceId) {
179     var ocf = ocfReference[command]; // Array
180     var finalOptions = {};
181     //var execStr = '/Users/hiratakengo/Eos/bin/X86MAC64/'+command + ' ';
182     var execStr = command + ' ';
183     var ocfObj = {};
184     ocf.forEach(function(o) {
185         ocfObj[o.option] = o;
186     });
187
188
189     if(workspaceId === "1f83f620-c1ed-11e5-9657-7942989daa00") { // root
190         var root = __dirname + '/../../user-specific-files/workspace/';
191     }
192
193     // set default parameters
194     ocf.forEach(function(o) {
195         o.arg.forEach(function(arg) {
196             if(!(arg.initialValue === "") && arg.initialValue) {
197                 if(!(finalOptions[o.option])) {
198                     finalOptions[o.option] = [];
199                     finalOptions[o.option].push(arg.initialValue);
200                 } else {
201                     finalOptions[o.option].push(arg.initialValue);
202                 }
203             }
204         });
205     });
206
207     // set user setting parameters
208     options.forEach(function(o) {
209         var s = [];
210         var outRegExp = /out|append/;
211         o.arguments.forEach(function(arg, i) {
212             if(ocfObj[o.name].arg[i].formType === 'select' || outRegExp.test(ocfObj[o.name].arg[i].argType)) {
213                 s.push(root+arg);
214             } else {
215                 s.push(arg);
216             }
217         });
218         finalOptions[o.name] = s;
219     });
220
221     // set execution string
222     Object.keys(finalOptions).forEach(function(key) {
223         execStr += key + ' ';
224         finalOptions[key].forEach(function(arg) {
225             execStr += arg + ' ';
226         });
227     });
228
229     // remove last blank
230     execStr = execStr.slice(0,execStr.length-1);
231
232     return execStr;
233 }
234
235 /**
236  * toExecArray
237  *
238  * @param {fileId} 
239  * @returns {string}
240  */
241 function toExecArray(command, options, workspaceId) {
242     return new Promise(function(resolve, reject) {
243         var ocf = ocfReference[command]; // Array
244         var finalOptions = {};
245         var ocfObj = {};
246         ocf.forEach(function(o) {
247             ocfObj[o.option] = o;
248         });
249
250         // set default parameters
251         ocf.forEach(function(o) {
252             o.arg.forEach(function(arg) {
253                 if(!(arg.initialValue === "") && arg.initialValue) {
254                     if(!(finalOptions[o.option])) {
255                         finalOptions[o.option] = [];
256                         finalOptions[o.option].push(arg.initialValue);
257                     } else {
258                         finalOptions[o.option].push(arg.initialValue);
259                     }
260                 }
261             });
262         });
263
264         getUUIDs(workspaceId)
265         .then(function(uuids) {
266             // set user setting parameters
267             options.forEach(function(o) {
268                 var s = [];
269                 var outRegExp = /out|append/;
270                 o.arguments.forEach(function(arg, i) {
271                     if(ocfObj[o.name].arg[i].formType === 'select') {
272                         s.push(uuids[arg]);
273                     } else {
274                         s.push(arg);
275                     }
276                 });
277                 finalOptions[o.name] = s;
278             });
279             var array = Object.keys(finalOptions).reduce(function(a,b) {
280                 a.push(b);
281                 finalOptions[b].forEach(function(v) {
282                     a.push(v);
283                 });
284                 return a;
285             },[]);
286             resolve(array);
287         });
288     });
289 }
290
291 /**
292  * execute
293  *
294  * @param command
295  * @param params
296  * @returns {object}
297  */
298 function execute(command, optionsArray) {
299     return new Promise(function(resolve, reject) {
300         var workspace; 
301         if(process.env.NODE_ENV === 'debug') {
302             workspace = __dirname + '/../../user-specific-files/workspace.debug';
303         } else {
304             workspace = _dirname + '/../../user-specific-files/workspace';
305         }
306         
307         var config = {
308             cwd: workspace
309         };
310         //var runner = spawn('/Users/hiratakengo/Eos/bin/X86MAC64/'+command,optionsArray,config);
311         var runner = spawn(command,optionsArray,config);
312         //var runner = spawn(command,optionsArray);
313         //commandRet    = spawn('ls', ['-lh', '/usr']);
314         //commandRet    = spawn(command, ['-h']);
315
316         var commandRet = runner;
317
318         commandRet.stdout.on('data', function (data) {
319           console.log('stdout: ' + data);
320         });
321
322         commandRet.stderr.on('data', function (data) {
323           console.log('stderr: ' + data);
324         });
325
326         runner.on('close', function() {
327             resolve();
328         });
329     });
330 }
331
332 /**
333  * getFiles
334  * @param fileId
335  * @returns {promise} resolve(Array)
336  */
337 function getFiles(fileId) {
338     return new Promise(function(resolve, reject) {
339         if(process.env.NODE_ENV === 'test') {
340             resolve(['file1.txt', 'file2.txt']);
341         } else {
342             db.getFiles(fileId)
343             .then(function(r) {
344                 var workspace = r.map(function(f) { return f.name });
345                 resolve(workspace);
346             });
347         }
348     });
349 }
350
351 /**
352  * getUUID
353  * @param fileId 
354  * @returns {object} key: filename, value: uuid
355  */
356 function getUUIDs(fileId) {
357     return new Promise(function(resolve) {
358         db.getFiles(fileId)
359         .then(function(r) {
360             var uuids = {};
361             r.forEach(function(v) {
362                 uuids[v.dataValues.name] = v.dataValues.fileId;
363             });
364             resolve(uuids);
365         });
366     });
367 }
368
369 /**
370  * Eosコマンドをエミュレートするクラス 
371  * @varructor
372  * @returns {object}
373  * function execute(command, params) {
374  */
375 var eos = {
376     validate: validate,
377     toExecString: toExecString,
378     execute: execute,
379     getFiles: getFiles,
380     getUUIDs: getUUIDs,
381     toExecArray: toExecArray
382 }
383
384 module.exports = { instance: eos };