OSDN Git Service

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