UNPKG

webgme-gridlabd

Version:

Metamodel, visualization, and model generators for gridlab-d in WebGME. Allows graphical model-driven development and simulation of power grids and power generation / transmission / distribution / storage systems.

445 lines (405 loc) 11.9 kB
/*globals define*/ /*jshint node:true, browser:true*/ /** * Generated by PluginGenerator 1.7.0 from webgme on Thu May 05 2016 13:51:44 GMT-0700 (PDT). */ define([ 'js/Constants', 'text!assets/decoratorSVGList.json', 'plugin/PluginConfig', 'text!./metadata.json', 'plugin/PluginBase', 'js/Utils/SvgManager', 'gridlabd/meta', 'q' ], function ( CONSTANTS, DecoratorSVGList, PluginConfig, pluginMetadata, PluginBase, svgManager, MetaTypes, Q) { 'use strict'; pluginMetadata = JSON.parse(pluginMetadata); DecoratorSVGList = JSON.parse(DecoratorSVGList); /** * Initializes a new instance of UpdateGLDMeta. * @class * @augments {PluginBase} * @classdesc This class represents the plugin UpdateGLDMeta. * @constructor */ var UpdateGLDMeta = function () { // Call base class' constructor. PluginBase.call(this); this.pluginMetadata = pluginMetadata; this.metaTypes = MetaTypes; }; /** * 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} */ UpdateGLDMeta.metadata = pluginMetadata; // Prototypical inheritance from PluginBase. UpdateGLDMeta.prototype = Object.create(PluginBase.prototype); UpdateGLDMeta.prototype.constructor = UpdateGLDMeta; /** * 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, plugin.PluginResult)} callback - the result callback */ UpdateGLDMeta.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; self.updateMETA(self.metaTypes); var currentConfig = self.getCurrentConfig(), metaFileHash = currentConfig.gldModHelp; self.metaSetName = ''; self.blobClient.getMetadata(metaFileHash) .then(function(glmMetaData) { var splitName = glmMetaData.name.split("."); var newName = ""; for (var i=0;i<splitName.length-1;i++) { newName += splitName[i]; } self.metaSetName = newName; self.logger.info('loaded: ' + self.metaSetName); return self.blobClient.getObjectAsString(metaFileHash); }) .then(function(metaFile) { return self.parseObjectsFromFile(metaFile); }) .then(function() { return self.createModelArtifacts(); }) .then(function() { return self.save('UpdateGLDMeta updated model meta.'); }) .then(function() { self.result.setSuccess(true); callback(null, self.result); }) .catch(function(err) { self.logger.error('ERROR:: '+err); self.result.setSuccess(false); callback(null, self.result); }); }; UpdateGLDMeta.prototype.parseObjectsFromFile = function(fileStr) { var self = this, class_regex = /class (\w+) {/g, class_end_regex = /}$/gm, lines = fileStr.split('\n'), results, objects = {}, currentObj, objStrings = [], depth = 0; lines.map((line) => { if (results = class_regex.exec(line)) { depth++; if (depth === 1) { var name = results[1]; if (objects[name] === undefined) { //self.logger.info('got class: ' + name); currentObj = { name: name, attributes: [], pointers: [], base: undefined }; objStrings = []; } } } else if (class_end_regex.test(line)) { if (depth === 1) { currentObj = self.parseObjectString(currentObj, objStrings); objects[currentObj.name] = currentObj; objStrings = []; } depth--; } else if (depth === 1) { objStrings.push(line); } }); self.objects = objects; }; UpdateGLDMeta.prototype.parseObjectString = function (obj, lines) { var self = this; var convertAttrToType = function(attr) { if (attr == 'complex' || attr == 'set' || attr == 'enumeration' || attr == 'loadshape' || attr == 'enduse' || attr == 'timestamp' || attr.indexOf('char') > -1) return 'string'; else if (attr.indexOf('int') > -1) return 'integer'; else if (attr == 'double') return 'float'; else if (attr == 'bool') return 'bool'; else return undefined; }; var isPointer = function(attr) { return attr == 'object'; }; var isParent = function(attr) { return attr == 'parent'; }; lines.map((line) => { var attr_regex = /(\w+)\s([\w]+)(\[\S+\])?;/g, enum_set_regex = /(enumeration|set)\s\{([\S ]+)\}\s(\w+);/g, value_regex = /(\w+)=(\d+)/gi, results; if (results = attr_regex.exec(line)) { var kind = convertAttrToType(results[1]); if (kind == undefined) { // must be object or parent if (isParent(results[1])) { obj.base = results[2]; } else if (isPointer(results[1])) { var ptr = { name: results[2], min: 0, max: 1 }; obj.pointers.push(ptr); } } else { var attr = { name: results[2], type: kind, units: results[3] }; obj.attributes.push(attr); //obj[attr.name] = attr; } } else if (results = enum_set_regex.exec(line)) { var kind = convertAttrToType(results[1]), enums = []; var vals = value_regex.exec(results[2]); while (vals) { enums.push(vals[1]); vals = value_regex.exec(results[2]); } if (results[1] == 'set' && // need to combine the entries enums.indexOf('UNKNOWN') == -1) { var combinations = function (string) { var result = []; var loop = function (start,depth,prefix) { for(var i=start; i<string.length; i++) { var next = prefix+string[i]; if (depth > 0) loop(i+1,depth-1,next); else result.push(next); } } for(var i=0; i<string.length; i++) { loop(0,i,''); } return result; } var singles = enums.filter(function(v) { return v.length == 1; }); var multiples = enums.filter(function(v) { return v.length > 1; }); enums = multiples.concat(combinations(singles.join(''))); } var attr = { name: results[3], type: kind, "enum": enums }; obj.attributes.push(attr); //obj[attr.name] = attr; } }); //self.logger.info(JSON.stringify(obj, null, 2)); return obj; }; var prevY = 100; UpdateGLDMeta.prototype.createModelArtifacts = function() { var self = this, names = Object.keys(self.objects); // create the meta sheet var sheetsRegistry = this.core.getRegistry(self.rootNode, 'MetaSheets'); sheetsRegistry = JSON.parse(JSON.stringify(sheetsRegistry)); sheetsRegistry.push({ SetID: this.metaSetName, order: sheetsRegistry.length, title: this.metaSetName }); self.core.setRegistry(self.rootNode, 'MetaSheets', sheetsRegistry); self.core.createSet(this.rootNode, this.metaSetName); prevY = 0; self.createdObjects = []; self.nodeMap = {}; names.map((name) => { var obj = self.objects[name]; if (self.createdObjects.indexOf(obj.name) == -1) { var base = obj.base; var bases = []; while (base) { bases.push(base); base = self.objects[base].base; } //self.logger.info('bases: ' + bases); for (var i= bases.length-1; i>=0; i--) { if (self.createdObjects.indexOf(bases[i]) == -1) { var b = self.objects[bases[i]]; self.createMetaNode(b.name, b.base, b.attributes, b.pointers); self.createdObjects.push(bases[i]); } } self.createMetaNode( obj.name, obj.base, obj.attributes, obj.pointers ); self.createdObjects.push(name); } }); }; UpdateGLDMeta.prototype.createMetaNode = function(name, base, attrs, ptrs) { if (this.META[name] || this.nodeMap[name]) { this.logger.warn('"' + name + '" already exists!'); return; } if (!this.META.Language) { throw new String('Must have Language folder!'); } if (!this.META.Object) { throw new String('Must have Object base type!!'); } // set METAAspectSet of the ROOT node (means it is META) // adds to the meta sheet // : core.addMember(self.rootNode, 'MetaAspectSet', node) // adds to a tab of the meta sheet // : var set = self.core.getSetNames(self.rootNode).find(name => name !== 'MetaAspectSet'); // : core.addMember(this.rootNode, set, node); // need to position the nodes in the meta sheet! // means we can create meta-sheets for each of the loaded files! :D // USEFUL FUNCTIONS: // core.setAspectMetaTarget(node, name, target) // core.getFCO(node) // core.getAllMetaNodes(node) // core.getChildrenMeta(node) // core.getAttributeNames(node) // core.getAttributeMeta(node, name) // core.getBase(node) // core.getBaseType(node) // core.getPointerNames(node) // core.getPointerMeta(node, name) // core.getRegistryNames(node) // core.getRegistry(node, name) // core.getSetNames(node) // require: // META.Language // META.Model // META.Object // META.Module // META.Class // META.Parent if (!base) { base = this.META.Object; } else { base = this.nodeMap[base]; } var node = this.core.createNode({ parent: this.META.Language, base: base }); this.core.setAttribute(node, 'name', name); this.nodeMap[name] = node; // add to the META sheet this.core.addMember(this.rootNode, 'MetaAspectSet', node); // add to the specific sheet this.core.addMember(this.rootNode, this.metaSetName, node); this.core.setMemberRegistry( this.rootNode, this.metaSetName, this.core.getPath(node), 'position', {x: prevY, y: prevY} // diagonal so that lots of attributes don't obscure ); // position the node based on the position of the most recently created node on that sheet this.core.setRegistry(node, 'position', {x: 100, y: prevY}) //var iconName = CONSTANTS.ASSETS_DECORATOR_SVG_FOLDER + name + '.svg'; var iconName = 'svgs/' + name + '.svg'; if ( DecoratorSVGList.indexOf( iconName ) > -1 ) { this.core.setRegistry(node, 'SVGIcon', iconName); } this.core.setRegistry(node, 'decorator', 'SVGDecorator'); prevY += 100; // set the attributes if (attrs) { attrs.forEach((attr, index) => { var name = attr.name; var desc = attr; desc.argindex = index; this.addAttribute(name, node, desc); }); } // set the pointers if (ptrs) { ptrs.map((ptr) => { var name = ptr.name; var desc = ptr; this.addPointer(name, node, desc); }); } }; UpdateGLDMeta.prototype.addAttribute = function(name, node, desc) { var initial, schema = {}; schema.type = desc.type || 'integer'; if (desc.min !== undefined) { schema.min = +desc.min; } if (desc.max !== undefined) { schema.max = +desc.max; } if (desc.infer) { schema.infer = desc.infer; } if (desc.enum) { schema.enum = desc.enum; } schema.argindex = desc.argindex; this.core.setAttributeMeta(node, name, schema); // determine and set the initial value for the attribute initial = desc.hasOwnProperty('default') ? desc.default : desc.min || null; if (schema.type === 'boolean') { initial = initial !== null ? initial : false; } if (initial !== null) { this.core.setAttribute(node, name, initial); } }; UpdateGLDMeta.prototype.addPointer = function(name, node, desc) { if (name == 'from') name = 'src'; else if (name == 'to') name = 'dst'; this.core.setPointerMetaLimits(node, name, 0, 1); this.core.setPointerMetaTarget(node, name, this.META.Object, 0, 1); this.core.setPointer(node, name, null); }; return UpdateGLDMeta; });