-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImportModels.js
178 lines (154 loc) · 7.11 KB
/
ImportModels.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
/*globals define*/
/*jshint node:true, browser:true*/
/**
* Generated by PluginGenerator 1.7.0 from webgme on Thu Nov 10 2016 18:22:41 GMT-0600 (Central Standard Time).
* A plugin that inherits from the PluginBase. To see source code documentation about available
* properties and methods visit %host%/docs/source/PluginBase.html.
*/
define([
'plugin/PluginConfig',
'text!./metadata.json',
'plugin/PluginBase',
'jszip',
'common/storage/util'
], function (
PluginConfig,
pluginMetadata,
PluginBase,
jszip,
storageUtil) {
'use strict';
pluginMetadata = JSON.parse(pluginMetadata);
/**
* Initializes a new instance of ImportModels.
* @class
* @augments {PluginBase}
* @classdesc This class represents the plugin ImportModels.
* @constructor
*/
var ImportModels = function () {
// Call base class' constructor.
PluginBase.call(this);
this.pluginMetadata = pluginMetadata;
};
/**
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
* This is also available at the instance at this.pluginMetadata.
* @type {object}
*/
ImportModels.metadata = pluginMetadata;
// Prototypical inheritance from PluginBase.
ImportModels.prototype = Object.create(PluginBase.prototype);
ImportModels.prototype.constructor = ImportModels;
/**
* Main function for the plugin to execute. This will perform the execution.
* Notes:
* - Always log with the provided logger.[error,warning,info,debug].
* - Do NOT put any user interaction logic UI, etc. inside this method.
* - callback always has to be called even if error happened.
*
* @param {function(string|Error|null, plugin.PluginResult)} callback - the result callback
*/
ImportModels.prototype.main = function (callback) {
// Use self to access core, project, result, logger etc from PluginBase.
// These are all instantiated at this point.
var self = this,
config = this.getCurrentConfig(),
zipHash = config.modelZip || '7ee240962a78962fce20c679911fa01682fefabd',
projectJson;
// Initially get the content of the uploaded zip file.
self.blobClient.getObject(zipHash)
.then(function (zipContent) {
var zip = new jszip(zipContent),
zipFile = zip.file('project.json');
// Extract the project.json from the zip.
// TODO: Handle the assets using blobUtil.. (If attempted to import normally they are already
// TODO: uploaded to the blob and nothing needs to be done).
if (zipFile) {
projectJson = JSON.parse(zipFile.asText());
} else {
throw new Error('No project.json found among' + JSON.stringify(Object.keys(zip.files())));
}
self.logger.info('Found project json in zip file');
// Insert the data-objects into the storage/database.
return storageUtil.insertProjectJson(self.project, { rootHash: null, objects: projectJson.objects},
{commitMessage: 'dummy commit for inserting the data-objects'});
})
.then(function () {
// At this point we know all the data was inserted into the data-base.
var closureInfo = projectJson.selectionInfo,
mapInfo,
baseRelInfo,
importResult,
key;
self.logger.info(JSON.stringify(closureInfo));
mapInfo = self.getMappedBases(closureInfo.bases);
// Overwrite the bases field with the one fitting to this project
closureInfo.bases = mapInfo.bases;
// Update the base relations to fit this model.
for (key in closureInfo.relations.preserved) {
baseRelInfo = closureInfo.relations.preserved[key];
if (baseRelInfo.base && mapInfo.orgToActual[baseRelInfo.base]) {
baseRelInfo.base = mapInfo.orgToActual[baseRelInfo.base];
}
}
// Now using the new base mappings import the models under the activeNode
importResult = self.core.importClosure(self.activeNode, closureInfo);
if (importResult instanceof Error) {
throw importResult;
}
// There was no error, save the current model.
return self.save('Imported models from webgmex-file');
})
.then(function (commitResult) {
self.logger.info('Made commit:', JSON.stringify(commitResult, null, 2));
self.result.setSuccess(true);
callback(null, self.result);
})
.catch(function (err) {
self.logger.error(err.stack);
callback(err, self.result);
});
};
ImportModels.prototype.getMappedBases = function (originalBases) {
var guidToMetaNode = {},
nameToMetaGuid = {},
result = {
bases: {},
orgToActual: {}
},
metaNode,
guid,
key;
// First we build of some info about what the current meta contains.
for (key in this.META) {
metaNode = this.META[key];
guid = this.core.getGuid(metaNode);
guidToMetaNode[guid] = metaNode;
// TODO: This only matches based on name, it could be extended with core.getFullyQualifiedName(metaNode);
// TODO: And even with more elaborate namespacing..
nameToMetaGuid[this.core.getAttribute(metaNode, 'name')] = guid;
}
// Now we map the originalBases to our meta. The rule here is that if the guid does not exist -
// we check if the current meta has at least the name and use that instead.
for (key in originalBases) {
// key is the guid of the original base as is in that project.
if (guidToMetaNode[key]) {
// The guid exists among the current meta - we can use it as is.
result.bases[key] = {}; // We know it exists and don't have to provide additional data
} else if (nameToMetaGuid[originalBases[key].name]) {
// The current meta contains the name. We are satisfied with that..
// We know it exists and don't have to provide additional data
result.bases[nameToMetaGuid[originalBases[key].name]] = {};
result.orgToActual[key] = nameToMetaGuid[originalBases[key].name];
this.logger.warn('Could not find exact guid of META-node', originalBases[key].name,
'but found same name.');
} else {
// TODO: Here more advanced rules can be added
throw new Error('Could not find suiting META-node for base ' + JSON.stringify(originalBases[key]));
}
}
return result;
};
return ImportModels;
});