OSDN Git Service

10aff92edd968bd8cc9bf5c8c543d159e3256e86
[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                     } else {
277                         s.push(arg);
278                     }
279                 });
280                 finalOptions[o.name] = s;
281             });
282             var array = Object.keys(finalOptions).reduce(function(a,b) {
283                 a.push(b);
284                 finalOptions[b].forEach(function(v) {
285                     a.push(v);
286                 });
287                 return a;
288             },[]);
289             resolve(array);
290         });
291     });
292 }
293
294 /**
295  * execute
296  *
297  * @param command
298  * @param params
299  * @returns {object}
300  */
301 function execute(command, optionsArray) {
302     return new Promise(function(resolve, reject) {
303         var workspace; 
304         if(process.env.NODE_ENV === 'debug') {
305             workspace = __dirname + '/../../user-specific-files/workspace.debug';
306         } else {
307             workspace = _dirname + '/../../user-specific-files/workspace';
308         }
309         
310         var config = {
311             cwd: workspace
312         };
313         var runner = spawn(command,optionsArray,config);
314         
315         runner.on('close', function() {
316             resolve();
317         });
318     });
319 }
320
321 /**
322  * getFiles
323  * @param fileId
324  * @returns {promise} resolve(Array)
325  */
326 function getFiles(fileId) {
327     return new Promise(function(resolve, reject) {
328         if(process.env.NODE_ENV === 'test') {
329             resolve(['file1.txt', 'file2.txt']);
330         } else {
331             db.getFiles(fileId)
332             .then(function(r) {
333                 var workspace = r.map(function(f) { return f.name });
334                 resolve(workspace);
335             });
336         }
337     });
338 }
339
340 /**
341  * getUUID
342  * @param fileId 
343  * @returns {object} key: filename, value: uuid
344  */
345 function getUUIDs(fileId) {
346     return new Promise(function(resolve) {
347         db.getFiles(fileId)
348         .then(function(r) {
349             var uuids = {};
350             r.forEach(function(v) {
351                 uuids[v.dataValues.name] = v.dataValues.fileId;
352             });
353             resolve(uuids);
354         });
355     });
356 }
357
358 /**
359  * Eosコマンドをエミュレートするクラス 
360  * @varructor
361  * @returns {object}
362  * function execute(command, params) {
363  */
364 var eos = {
365     validate: validate,
366     toExecString: toExecString,
367     execute: execute,
368     getFiles: getFiles,
369     getUUIDs: getUUIDs,
370     toExecArray: toExecArray
371 }
372
373 module.exports = { instance: eos };