-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcloUtils.js
360 lines (307 loc) · 14 KB
/
cloUtils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
var DIR = './file';
var fs = require('fs');
var zip = require('adm-zip');
var path = require('path');
var async = require('async');
var moment = require('moment');
var archiver = require('archiver');
//Lê o arquivo MANIFEST.MF e monta um objeto com a versão do MANIFEST e com
// lista de arquivos executáveis contidas no OAC.
var lerManifest = function(zip) {
var mf = zip.getEntry("MANIFEST.MF");
if (mf) {
var data = {};
data.fileNames = [];
var mfContent = zip.readAsText(mf).toString().split("\n");
data.version = mfContent[0].toString().split(": ")[1];
switch (data.version) {
case '1.0':
mfContent.forEach(function(line) {
if(line.startsWith("Executable-File-Directory")) {
data.fileNames.push(line.split(": ")[1]);
} else if (line.startsWith("Executable-File")) {
var lastFileName = data.fileNames.length - 1;
data.fileNames[lastFileName] = data.fileNames[lastFileName].concat('/' + line.split(": ")[1]);
}
});
break;
default:
return null;
}
return data;
} else {
return null;
}
}
//Gera, a partir dos dados informados, o arquivo compactado que representará o OAC
var gerarArquivoOAC = function(idDescritorDeArquivoExecutavel, pathArquivoExecutavel, descritorDeComponentes, userId, grauDeLiberdade, callback) {
//Monta o arquivo compactado que representará o OAC
var oac = archiver.create('zip');
var inicioLeituraFilesystem = moment().utc();
//Adiciona ao arquivo compactado os arquivos referenciados pelos Componentes do OAC
descritorDeComponentes.scenes.forEach(function(scene) {
scene.components.forEach(function(component) {
if (component.hasOwnProperty("source")) {
//Adiciona, no diretório "components/", o arquivo referenciado pelo campo "source"
oac.file(component.source, { "name": "components/" + path.basename(component.source) });
//E atualiza a referência do campo
component.source = "./components/" + path.basename(component.source);
}
});
});
var fimLeituraFilesystem = moment().utc();
console.log(fimLeituraFilesystem.diff(inicioLeituraFilesystem, "milliseconds") + " ### Tempo de leitura do filesystem ###");
//Adiciona o DescritorDeComponentes
oac.append(JSON.stringify(descritorDeComponentes), { "name": path.basename(pathArquivoExecutavel).replace(path.extname(pathArquivoExecutavel), ".json") });
//Adiciona o Arquivo Executável
oac.file(pathArquivoExecutavel, { "name": path.basename(pathArquivoExecutavel) });
//Adiciona o token.txt
oac.append(idDescritorDeArquivoExecutavel + " " + userId + " " + grauDeLiberdade, { "name": "token.txt" });
//Retorna o arquivo criado
oac.finalize();
callback(oac);
return;
}
//Gera, a partir dos dados informados, o arquivo compactado que representará a Versão Customizada
var gerarArquivoVersaoCustomizada = function(descritorDeVersao, descritorDeComponentesRaiz, pathArquivoExecutavel, userId, degreeOfFreedom, callback) {
//Monta o arquivo compactado que representará a Versão Customizada
var versaoCustomizada = archiver.create('zip');
var idSourceVersion = descritorDeVersao._id;
var inicioRealizacaoMerge = moment().utc();
mergeCustomizations(descritorDeVersao, descritorDeComponentesRaiz, function(descritorDeComponentes) {
var fimRealizacaoMerge = moment().utc();
console.log(fimRealizacaoMerge.diff(inicioRealizacaoMerge, "milliseconds") + " ### Tempo de Realização do Merge ###");
var inicioLeituraFilesystem = moment().utc();
//Adiciona ao arquivo compactado os arquivos referenciados pelos Componentes da Versão Customizada
descritorDeComponentes.scenes.forEach(function(scene) {
scene.components.forEach(function(component) {
if (component.hasOwnProperty("source")) {
//Adiciona, no diretório "components/", o arquivo referenciado pelo campo "source"
versaoCustomizada.file(component.source, { "name": "components/" + path.basename(component.source) });
//E atualiza a referência do campo
component.source = "./components/" + path.basename(component.source);
}
});
});
var fimLeituraFilesystem = moment().utc();
console.log(fimLeituraFilesystem.diff(inicioLeituraFilesystem, "milliseconds") + " ### Tempo de leitura do filesystem ###");
//Adiciona o DescritorDeComponentes
versaoCustomizada.append(JSON.stringify(descritorDeComponentes), { "name": path.basename(pathArquivoExecutavel).replace(path.extname(pathArquivoExecutavel), ".json") });
//Adiciona o Arquivo Executável
versaoCustomizada.file(pathArquivoExecutavel, { "name": path.basename(pathArquivoExecutavel) });
//Adiciona o token.txt
versaoCustomizada.append(idSourceVersion + " " + userId + " " + degreeOfFreedom, { "name": "token.txt" });
//Retorna o arquivo criado
versaoCustomizada.finalize();
callback(versaoCustomizada);
return;
});
}
//Função que faz o merge das customizações realizadas para um determinado DescritorDeVersaoCustomizada
//com o estado inicial dos componentes
var mergeCustomizations = function(descritorDeVersao, descritorDeComponentes, callback) {
//Intera em todas as cenas que foram customizadas para a Versão Customizada
descritorDeVersao.customizations.forEach(function(customizedScene) {
descritorDeComponentes.scenes.forEach(function(scene) {
if (customizedScene.scene === scene.scene) {
//Intera em todos os componentes que foram customizadas em uma determinada cena
customizedScene.components.forEach(function(customizedComponent) {
scene.components.forEach(function(component) {
if (customizedComponent.name === component.name) {
//Substitui os valores dos atributos originais pelos os seus respectivos valores customizados
for(var key in customizedComponent) {
component[key] = customizedComponent[key];
}
}
});
});
}
});
});
//Retorna o DescritorDeComponentes com as customizações incorporadas,
//representando dessa forma o estado dos componentes para uma determinada Versão Customizada
callback(descritorDeComponentes);
return;
}
//Verifica se o Grau de Liberdade informado como parâmetro tem permissão para
//customizar um determinado atributo de componente
var checarPermissao = function(key, grauDeLiberdade) {
if(grauDeLiberdade == 4)
return true
if(grauDeLiberdade == 3)
return key == "enabled" || key == "visible" || key == "position" || key == "zindex"
|| key == "startTime" || key == "stopTime" || key == "label" || key == "text" || key == "source";
if(grauDeLiberdade == 2)
return key == "enabled" || key == "visible" || key == "position" || key == "zindex"
|| key == "startTime" || key == "stopTime";
if(grauDeLiberdade == 1)
return key == "enabled" || key == "visible" || key == "position" || key == "zindex"
}
//Identifica as Cenas diferentes entre os arquivos JSONs de Componentes da nova versão e de início da hierarquia de versão,
//retornando o Delta resultante, contendo apenas as cenas e os componentes modificados.
var getDeltaAsync = function(jsonFromFile, jsonDescritor, grauDeLiberdade, callback) {
var delta = new Array();
//Realiza o processamento das cenas em paralelo a fim de detectar
//as diferenças entre as duas versões do JSON com o estados dos Componentes.
async.each(jsonFromFile.scenes, processarCenas, function(err) {
if (err) {
console.error(new Date() + " Erro ao Processar Cenas para a Obtenção de Delta: " + err);
callback(err, null);
return;
} else {
callback(null, delta);
return;
}
});
//Processa as Cenas para o cálculo do Delta
function processarCenas(scene, sceneProcessDone) {
//Identifica a Cena no arquivo JSON com o estado dos componentes no início da hierarquia equivalente a que será processada.
jsonDescritor.scenes.forEach(function(sceneDescritor) {
//Identifica a Cena equivalente para a realização da comparação.
if(scene.scene == sceneDescritor.scene) {
var delta_scene = {}
//Processa os Componentes da Cena para o cálculo do Delta
async.each(scene.components, function processarComponentes(component, componentProcessDone) {
var componenteEncontrado = false;
//Identifica o Componente no arquivo JSON com o estado dos componentes no início da hierarquia equivalente a que será processada.
sceneDescritor.components.forEach(function(componentDescritor) {
//Identifica o Componente equivalente para a realização da comparação.
if(component.name == componentDescritor.name) {
componenteEncontrado = true;
//Obtém as diferenças entre os Componentes comparados e as armazena no Delta da Cena que está sendo processada.
getDiffComponente(component, componentDescritor, function (err, deltaComponente) {
if (err) {
console.error(new Date() + " Erro ao Verificar as Customizações Realizadas nos Componentes: " + err);
componentProcessDone(err);
return;
}
//Caso os Componentes sejam distintos, as modificações são adicionadas no Delta da Cena que está sendo processada.
if (deltaComponente) {
//Inicializa o Delta da Cena, caso necessário.
if(!delta_scene.scene) {
delta_scene.scene = scene.scene;
} if(!delta_scene.components) {
delta_scene.components = new Array();
}
//Adiciona as alterações do novo Componente ao Delta da Cena.
delta_scene.components.push(deltaComponente);
}
componentProcessDone(null);
return;
});
}
});
if(!componenteEncontrado) {
//Caso não encontre o Componente equivalente para a Comparação
componentProcessDone(new Error("Componente não encontrado em Cena"));
return;
}
}, function(err) {
if (err) {
console.error(new Date() + " Erro ao Processar Componentes para a Obtenção de Delta: " + err);
sceneProcessDone(err);
return;
}
//Adiciona o Delta da Cena processada ao Delta final resultante da comparação dos arquivos JSONs
if(delta_scene.components) {
delta.push(delta_scene);
}
sceneProcessDone(null);
});
}
});
}
//Calcula o Delta entre dois Componentes.
function getDiffComponente(componentA, componentB, callback) {
var deltaComponente = {};
for(var key in componentA) {
if(!componentB.hasOwnProperty(key) ||
(key == 'source' && path.basename(componentA[key]) != path.basename(componentB[key])) ||
(key != 'source' && componentA[key] != componentB[key])) {
//É verificado se o usuário que realiza a inclusão da Versão Customizada
//possui Grau de Liberdade compatível com as modificações
if (checarPermissao(key, grauDeLiberdade)) {
deltaComponente[key] = componentA[key];
} else {
//Se as alterações não forem compatíveis com o Grau de Liberdade,
//a inclusão deve ser cancelada
callback(new Error("Customizações não compatíveis com o Grau de Liberdade"), null);
return;
}
}
}
//Retorna o Delta entre os componentes, caso existam diferenças.
if(Object.keys(deltaComponente).length > 0) {
deltaComponente.name = componentA.name;
callback(null, deltaComponente);
return;
} else {
callback(null, null);
return;
}
}
}
//@deprecated
//Compara os componentes scene por scene e retorna o delta.
var getDelta = function(jsonFromFile, jsonDescritor, grauDeLiberdade, callback) {
console.warn("Chamando Função Obsoleta.");
var delta = new Array();
//Lê arquivo JSON com o estado dos componentes do arquivo compactado
for(var k = 0; k < jsonFromFile.scenes.length; k++) {
//Lê arquivo JSON com o estado dos componentes no início da hierarquia
for(var j = 0; j < jsonDescritor.scenes.length; j++)
{
//Se as scenes forem iguais, inicializa-se a variável delta, que conterá a diferença entre as scenes.
if(jsonFromFile.scenes[k].scene == jsonDescritor.scenes[j].scene)
{
var delta_scene = {}
//Compara-se os componentes de cada arquivo. Se tiverem os mesmos nomes, armazena-se a diferença entre eles na variável obj.
for(var a = 0; a < jsonFromFile.scenes[k].components.length; a++)
{
for(var b = 0; b < jsonDescritor.scenes[j].components.length; b++)
{
var obj = {}
if(jsonDescritor.scenes[j].components[b].name == jsonFromFile.scenes[k].components[a].name)
{
for(var key in jsonFromFile.scenes[k].components[a])
{
if(!jsonDescritor.scenes[j].components[b].hasOwnProperty(key) ||
(key == 'source' && path.basename(jsonFromFile.scenes[k].components[a][key]) != path.basename(jsonDescritor.scenes[j].components[b][key])) ||
(key != 'source' && jsonFromFile.scenes[k].components[a][key] != jsonDescritor.scenes[j].components[b][key])) {
//É verificado se o usuário que realiza a inclusão da Versão Customizada
//possui Grau de Liberdade compatível com as modificações
if (checarPermissao(key, grauDeLiberdade)) {
obj[key] = jsonFromFile.scenes[k].components[a][key]
} else {
//Se as alterações não forem compatíveis com o Grau de Liberdade,
//a inclusão deve ser cancelada
callback(new Error("Customizações não compatíveis com o Grau de Liberdade"), null);
return;
}
}
}
//Se o tamanho da variável obj for maior que zero, armazena-se nela o nome do componente e adiciona-o à variável delta.
if(Object.keys(obj).length > 0)
{
obj.name = jsonFromFile.scenes[k].components[a].name
if(!delta_scene.scene)
delta_scene.scene = jsonFromFile.scenes[k].scene
if(!delta_scene.components)
delta_scene.components = []
delta_scene.components.push(obj)
}
}
}
}
if(delta_scene.components)
delta.push(delta_scene)
}
}
}
callback(null, delta);
return;
}
module.exports.lerManifest = lerManifest;
module.exports.gerarArquivoOAC = gerarArquivoOAC;
module.exports.gerarArquivoVersaoCustomizada = gerarArquivoVersaoCustomizada;
module.exports.getDeltaAsync = getDeltaAsync;