diff --git a/deviser/base_files/BaseMatlabFile.py b/deviser/base_files/BaseMatlabFile.py index 47eae830..017a9eac 100644 --- a/deviser/base_files/BaseMatlabFile.py +++ b/deviser/base_files/BaseMatlabFile.py @@ -41,6 +41,7 @@ from . import BaseFile from ..util import strFunctions as SF +from ..util import query class BaseMatlabFile(BaseFile.BaseFile): @@ -56,7 +57,7 @@ def __init__(self, name, object_desc, filetype): self.matlab_comment_line = 68 * '%' self.long_matlab_comment_line = 78 * '%' self.short_matlab_comment_line = 32 * '%' - self.matlab_big_space = 70 * ' ' + self.matlab_big_space = 55 * ' ' self.package = object_desc['name'] self.up_pack = self.package.upper() @@ -68,6 +69,8 @@ def __init__(self, name, object_desc, filetype): self.level = object_desc['base_level'] self.version = object_desc['base_version'] self.pkg_version = object_desc['pkg_version'] + self.num_versions = 1 if 'num_versions' not in object_desc else object_desc['num_versions'] + if object_desc['required']: self.reqd_status = 'true' else: @@ -101,11 +104,11 @@ def write_file(self): self.write_line('%%%% ADD isExtension') self.write_line('%%%% ADD isExtension') # TODO both necessary? if self.filetype == 'sf': - self.write_is_extension('Fieldname') + self.write_is_extension() elif self.filetype == 'dv': - self.write_is_extension('DefaultValue') + self.write_is_extension() elif self.filetype == 'vt': - self.write_is_extension('ValueType') + self.write_is_extension() self.write_line('%%%% END isExtension') self.skip_line(2) self.write_line('%%%% ADD getFieldname') @@ -178,19 +181,16 @@ def write_value_types(self): self.write_get_class_values_types(sbmlclass) self.skip_line(2) - def write_some_common_lines(self): + def write_function_args(self): """ Utility function to write some common output. - TODO a more descriptive name wouldn't go amiss. The first line closes a matlab function argument list. """ - self.write_line(self.matlab_big_space + 'version, pkgVersion)') - self.write_more_common_lines() + self.write_line_verbatim(self.matlab_big_space + 'version, pkgVersion)') - def write_more_common_lines(self): + def write_function_setup(self): """ - Another utility function - TODO yep, this one also needs a better name! + Utility function to write some common output. """ self.up_indent() self.write_line('if (~isValidLevelVersionCombination(level,' @@ -198,7 +198,7 @@ def write_more_common_lines(self): self.up_indent() self.write_line('error (\'invalid level/version combination\');') self.down_indent() - self.write_line('end;') + self.write_line('end') self.skip_line() self.write_line('SBMLfieldnames = [];') @@ -216,9 +216,8 @@ def write_ends(self): Another utility function, used a number of times. Write the `end` keywords at the end of a code block. """ - self.down_indent() for _ in range(0, 3): - self.write_line('end;') + self.write_line('end') self.down_indent() def write_get_plugin_values_types(self, plugin): @@ -232,21 +231,43 @@ def write_get_plugin_values_types(self, plugin): 'get{0}{1}ValueType(level, ...'. format(self.up_pack, plugin['sbase'])) - self.write_some_common_lines() - num_fields = 1 - self.write_line('SBMLfieldnames = {') - self.write_line('\'uint\', ...') - for extension in plugin['extension']: - self.write_line('\'structure\', ...'.format()) - num_fields += 1 - for extension in plugin['lo_extension']: - self.write_line('\'structure\', ...') - num_fields += 1 - for attrib in plugin['attribs']: - self.write_line('{0}, ...'.format(self.get_value_type(attrib))) - num_fields += 1 - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) + self.write_function_args() + self.write_function_setup() + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if plugin['version_info'][i]: + self.write_line('SBMLfieldnames = {') + for extension in plugin['extension']: + if extension['version_info'][i]: + self.write_line('\'structure\', ...'.format()) + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute_vt(attrib, i, num_fields) + for extension in plugin['lo_extension']: + if extension['version_info'][i]: + self.write_line('\'structure\', ...') + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute_vt(attrib, i, num_fields) + for attrib in plugin['attribs']: + num_fields = self.write_attribute_vt(attrib, i, num_fields) + self.write_line('\'uint\', ...') + self.write_line('\'uint\', ...') + self.write_line('\'uint\', ...'.format(v)) + # e.g. "'qual_version', ..." + num_fields += 3 + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) + + self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() + self.write_ends() def write_get_class_values_types(self, sbmlclass): @@ -259,23 +280,32 @@ def write_get_class_values_types(self, sbmlclass): self.write_line_verbatim('function [SBMLfieldnames, nNumberFields] = ' 'get{0}ValueType(level, ...'. format(sbmlclass['name'])) - self.write_some_common_lines() - - num_fields = 9 - self.write_line('SBMLfieldnames = {') - self.write_line('\'{0}\', ...'.format(sbmlclass['typecode'])) - for _ in range(0, 3): - self.write_line('\'char\', ...') - self.write_line('\'structure\', ...') - self.write_line('\'int\', ...') - for attrib in sbmlclass['attribs']: - self.write_line('{0}, ...'.format(self.get_value_type(attrib))) - num_fields += 1 - self.write_line('\'uint\', ...') - self.write_line('\'uint\', ...') - self.write_line('\'uint\', ...') # .format(self.package)) - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) + self.write_function_args() + self.write_function_setup() + + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if sbmlclass['version_info'][i]: + self.write_line('SBMLfieldnames = {') + num_fields = 9 + self.write_line('\'{0}\', ...'.format(sbmlclass['typecode'])) + for _ in range(0, 3): + self.write_line('\'char\', ...') + self.write_line('\'structure\', ...') + self.write_line('\'int\', ...') + for attrib in sbmlclass['attribs']: + num_fields = self.write_attribute_vt(attrib, i, num_fields) + self.write_line('\'uint\', ...') + self.write_line('\'uint\', ...') + self.write_line('\'uint\', ...') # .format(self.package)) + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) + self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() self.write_ends() def get_value_type(self, attrib): @@ -290,9 +320,11 @@ def get_value_type(self, attrib): return '\'char\'' elif att_type == 'bool': return '\'bool\'' - elif att_type == 'uint' or att_type == 'int': + elif att_type == 'uint': return '\'uint\'' - elif att_type == 'lo_element': + elif att_type == 'int': + return '\'int\'' + elif att_type == 'lo_element' or att_type == 'inline_lo_element': return '\'structure\'' elif att_type == 'element': if att_name == 'math': @@ -314,27 +346,45 @@ def write_get_plugin_default_values(self, plugin): self.write_line_verbatim('function [SBMLfieldnames, nNumberFields] = ' 'get{0}{1}DefaultValues(level, ...'. format(self.up_pack, plugin['sbase'])) - self.write_some_common_lines() - - num_fields = 1 - self.write_line('SBMLfieldnames = {') - self.write_line('int32(pkgVersion), ...') - for extension in plugin['extension']: - self.write_line('[], ...'.format()) - num_fields += 1 - for extension in plugin['lo_extension']: - self.write_line('[], ...') - num_fields += 1 - for attrib in plugin['attribs']: - self.write_line('{0}, ...'.format(self.get_type(attrib))) - num_fields += 1 - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) + self.write_function_args() + self.write_function_setup() + + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if plugin['version_info'][i]: + self.write_line('SBMLfieldnames = {') + for extension in plugin['extension']: + if extension['version_info'][i]: + self.write_line('[], ...'.format()) + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute_dv(attrib, i, num_fields) + for extension in plugin['lo_extension']: + if extension['version_info'][i]: + self.write_line('[], ...') + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute_dv(attrib, i, num_fields) + for attrib in plugin['attribs']: + num_fields = self.write_attribute_dv(attrib, i, num_fields) + self.write_line('int32(3), ...') + self.write_line('int32(1), ...') + self.write_line('int32({0}), ...'.format(v)) + # e.g. "'qual_version', ..." + num_fields += 3 + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) - self.down_indent() - for _ in range(0, 3): - self.write_line('end;') self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() + + self.write_ends() def write_get_class_default_values(self, sbmlclass): """ @@ -347,23 +397,32 @@ def write_get_class_default_values(self, sbmlclass): ' = get{0}DefaultValues(level, ...'. format(sbmlclass['name'])) - self.write_some_common_lines() - - num_fields = 9 - self.write_line('SBMLfieldnames = {') - self.write_line('\'{0}\', ...'.format(sbmlclass['typecode'])) - for _ in range(0, 3): - self.write_line('\'\', ...') - self.write_line('[], ...') - self.write_line('int32(-1), ...') - for attrib in sbmlclass['attribs']: - self.write_line('{0}, ...'.format(self.get_type(attrib))) - num_fields += 1 - self.write_line('3, ...') - self.write_line('int32(version), ...') - self.write_line('int32(pkgVersion), ...') # .format(self.package)) - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) + self.write_function_args() + self.write_function_setup() + + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if sbmlclass['version_info'][i]: + self.write_line('SBMLfieldnames = {') + num_fields = 9 + self.write_line('\'{0}\', ...'.format(sbmlclass['typecode'])) + for _ in range(0, 3): + self.write_line('\'\', ...') + self.write_line('[], ...') + self.write_line('int32(-1), ...') + for attrib in sbmlclass['attribs']: + num_fields = self.write_attribute_dv(attrib, i, num_fields) + self.write_line('int32(3), ...') + self.write_line('int32(1), ...') + self.write_line('int32({0}), ...'.format(v)) + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) + self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() self.write_ends() def get_type(self, attrib): @@ -381,7 +440,7 @@ def get_type(self, attrib): return '\'\'' elif att_type in ['bool', 'uint', 'int']: return 'int32(0)' - elif att_type == 'lo_element': + elif att_type in ['lo_element', 'inline_lo_element']: return '[]' elif att_type == 'element': return '\'\'' if att_name == 'math' else '[]' @@ -390,6 +449,65 @@ def get_type(self, attrib): else: return att_type + def write_attribute_dv(self, attrib, version, num_fields): + if attrib['version_info'][version]: + if attrib['name'] == 'math': + self.write_line('\'{0}\', ...'.format(attrib['name'])) + else: + self.write_line('{0}, ...'.format(self.get_type(attrib))) + num_fields += 1 + if self.get_type(attrib) == 'int32(0)' or self.get_type(attrib) == '0/0': + self.write_line('int32(0), ...') + num_fields += 1 + return num_fields + + def write_attribute_vt(self, attrib, version, num_fields): + if attrib['version_info'][version]: + if attrib['name'] == 'math': + self.write_line('\'{0}\', ...'.format(attrib['name'])) + else: + self.write_line('{0}, ...'.format(self.get_value_type(attrib))) + num_fields += 1 + if self.get_type(attrib) == 'int32(0)' or self.get_type(attrib) == '0/0': + self.write_line('\'bool\', ...') + num_fields += 1 + return num_fields + + def get_lo_attributes(self, extension): + element = query.get_class(extension['name'], extension['root']) + return element['lo_attribs'] + + def write_attribute(self, attrib, version, num_fields): + if attrib['version_info'][version]: + if attrib['name'] == 'math': + self.write_structure_cell(attrib['name'], '', 0, 5) + else: + self.write_structure_cell(attrib['name'], self.package) + num_fields += 1 + if self.get_type(attrib) == 'int32(0)' or self.get_type(attrib) == '0/0': + self.write_structure_cell(attrib['name'], self.package, 0, 7) + num_fields += 1 + return num_fields + + def write_structure_cell(self, attrib, plugin, is_sbml=1, sbml_type=20): + if plugin == '': + if is_sbml: + self.write_line_verbatim('{0}\'{2}\', \'{2}\', \'\', {3}, {4}{1}, ...' + .format(self.open_br, self.close_br, attrib, is_sbml, sbml_type)) + else: + self.write_line_verbatim('{0}\'{2}\', \'\', \'\', {3}, {4}{1}, ...' + .format(self.open_br, self.close_br, attrib, is_sbml, sbml_type)) + + else: + if sbml_type == 7: + sbmlname = 'isSet{0}_{1}'.format(self.package, SF.lower_first(attrib)) + self.write_line_verbatim('{0}\'{6}\', \'{3}\', \'{2}\', {4}, {5}{1}, ...' + .format(self.open_br, self.close_br, plugin, attrib, is_sbml, sbml_type, + sbmlname)) + else: + self.write_line_verbatim('{0}\'{2}_{3}\', \'{3}\', \'{2}\', {4}, {5}{1}, ...' + .format(self.open_br, self.close_br, plugin, attrib, is_sbml, sbml_type)) + def write_get_plugin_fieldname(self, plugin): """ Writes a "getXXXFieldnames() Matlab function for a plugin @@ -401,31 +519,44 @@ def write_get_plugin_fieldname(self, plugin): self.write_line_verbatim('function [SBMLfieldnames, nNumberFields]' ' = get{0}{1}Fieldnames(level, ...'. format(self.up_pack, plugin['sbase'])) - - self.write_some_common_lines() # writes "nNumberFields = 0;" (etc.) - - self.write_line('SBMLfieldnames = {') - self.write_line('\'{0}_version\', ...'.format(self.package)) - # e.g. "'qual_version', ..." - num_fields = 1 - - for extension in plugin['extension']: - self.write_line('\'{0}_{1}\', ...'. - format(self.package, - SF.lower_first(extension['name']))) - num_fields += 1 - for extension in plugin['lo_extension']: - self.write_line('\'{0}_{1}\', ...'. - format(self.package, - SF.lower_first(extension['name']))) - num_fields += 1 - for attrib in plugin['attribs']: - self.write_line('\'{0}_{1}\', ...'. - format(self.package, - SF.lower_first(attrib['name']))) - num_fields += 1 - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) + self.write_function_args() + self.write_function_setup() + + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if plugin['version_info'][i]: + self.write_line('SBMLfieldnames = {') + for extension in plugin['extension']: + if extension['version_info'][i]: + self.write_structure_cell(SF.lower_first(extension['name']), self.package) + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute(attrib, i, num_fields) + + for extension in plugin['lo_extension']: + if extension['version_info'][i]: + self.write_structure_cell(SF.lower_first(extension['name']), self.package) + num_fields += 1 + attribs = self.get_lo_attributes(extension) + for attrib in attribs: + num_fields = self.write_attribute(attrib, i, num_fields) + for attrib in plugin['attribs']: + num_fields = self.write_attribute(attrib, i, num_fields) + self.write_structure_cell('level', '', 0, 0) + self.write_structure_cell('version', '', 0, 0) + self.write_structure_cell('version', self.package, 1, 20) + # e.g. "'qual_version', ..." + num_fields += 3 + + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) + self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() self.write_ends() @@ -441,29 +572,33 @@ def write_get_class_fieldname(self, sbmlclass): ' = get{0}Fieldnames(level, ...'. format(sbmlclass['name'])) - self.write_some_common_lines() - - num_fields = 9 - self.write_line('SBMLfieldnames = {') - self.write_line('\'typecode\', ...') - self.write_line('\'metaid\', ...') - self.write_line('\'notes\', ...') - self.write_line('\'annotation\', ...') - self.write_line('\'cvterms\', ...') - self.write_line('\'sboTerm\', ...') - for attrib in sbmlclass['attribs']: - if attrib['name'] == 'math': - self.write_line('\'{0}\', ...'.format(attrib['name'])) - else: - self.write_line('\'{0}_{1}\', ...'.format(self.package, - attrib['name'])) - num_fields += 1 - self.write_line('\'level\', ...') - self.write_line('\'version\', ...') - self.write_line('\'{0}_version\', ...'.format(self.package)) - self.write_line('};') - self.write_line('nNumberFields = {0};'.format(num_fields)) - + self.write_function_args() + self.write_function_setup() + + v = 1 + for i in range(0, self.num_versions): + num_fields = 0 + if sbmlclass['version_info'][i]: + self.write_line('SBMLfieldnames = {') + num_fields = 9 + self.write_structure_cell('typecode', '', 0, 0) + self.write_structure_cell('metaid', '', 1, 20) + self.write_structure_cell('notes', '', 1, 1) + self.write_structure_cell('annotation', '', 1, 2) + self.write_structure_cell('cvterms', '', 0, 4) + self.write_structure_cell('sboTerm', '', 1, 20) + for attrib in sbmlclass['attribs']: + num_fields = self.write_attribute(attrib, i, num_fields) + self.write_structure_cell('level', '', 0, 0) + self.write_structure_cell('version', '', 0, 0) + self.write_structure_cell('version', self.package, 1, 20) + self.write_line('};') + self.write_line('nNumberFields = {0};'.format(num_fields)) + self.down_indent() + v = v + 1 + if v <= self.num_versions: + self.write_line('elseif (pkgVersion == {0})'.format(v)) + self.up_indent() self.write_ends() def write_get_fieldname_function(self, functionType): @@ -521,11 +656,9 @@ def write_get_fieldname_function(self, functionType): self.write_line('end;') self.down_indent() - def write_is_extension(self, functionType): + def write_is_extension(self): """ Write an isXXXExtension() function in the Matlab file. - - TODO the functionType argument isn't used """ self.write_line('function extend = is{0}Extension(typecode)'. format(self.up_pack)) diff --git a/deviser/parseXML/ParseXML.py b/deviser/parseXML/ParseXML.py index 0e3ed1c4..94e10c1f 100644 --- a/deviser/parseXML/ParseXML.py +++ b/deviser/parseXML/ParseXML.py @@ -849,8 +849,11 @@ def update_element_description(self, node, version_count, element): :param element: element to be updated :return: nothing """ + element['version_info'][version_count] = True + # node(s) are listed within an node for attr in node.getElementsByTagName('attribute'): + # Add the dictionary for attribute `attr` to the list. element['attribs'].append( self.get_attribute_description(self, attr, version_count)) @@ -886,6 +889,11 @@ def get_element_description(self, node, version_count): minNumListOfChildren="0" maxNumListOfChildren="0" abstract="false"> ''' + version_info = [] + for i in range(0, self.num_versions): + version_info.append(False) + version_info[version_count] = True + element_name = self.get_element_class_name(self, node) # e.g. "DynElement" if not element_name: @@ -959,7 +967,8 @@ def get_element_description(self, node, version_count): 'min_lo_children': min_lo_children, 'num_versions': self.num_versions, 'version': version_count, - 'childrenOverwriteElementName': children_overwrite + 'childrenOverwriteElementName': children_overwrite, + 'version_info': version_info }) if add_decls is not None: element['addDecls'] = add_decls @@ -982,6 +991,7 @@ def update_plugin_description(self, node, version_count, plugin): :param plugin: existing plugin dict to update :return: nothing """ + plugin['version_info'][version_count] = True for reference in node.getElementsByTagName('reference'): temp = self.find_element(self.elements, self.get_value(reference, 'name')) @@ -1024,6 +1034,11 @@ def get_plugin_description(self, node, version_count): ''' + version_info = [] + for i in range(0, self.num_versions): + version_info.append(False) + version_info[version_count] = True + ext_point = self.get_value(node, 'extensionPoint') # e.g. "Model" plugin = None # check whether we have an element with this @@ -1069,7 +1084,8 @@ def get_plugin_description(self, node, version_count): plugin_dict = dict({'sbase': ext_point, 'extension': plug_elements, 'attribs': attributes, - 'lo_extension': plug_lo_elements}) + 'lo_extension': plug_lo_elements, + 'version_info': version_info}) if add_decls is not None: if os.path.exists(self.temp_dir + '/' + add_decls): @@ -1128,7 +1144,8 @@ def populate_elements_for_version(self, pkg_node): element['lo_class_name'], 'xml_name': element['elementName'], 'min_lo_children': - element['min_lo_children']})) + element['min_lo_children'], + 'version_info': element['version_info']})) self.sbml_elements.append(element) def populate_plugins_for_version(self, pkg_node): diff --git a/deviser/util/generateMatlab.py b/deviser/util/generateMatlab.py new file mode 100644 index 00000000..d9ca79a9 --- /dev/null +++ b/deviser/util/generateMatlab.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# @file generateExamples.py +# @brief function for generating code examples +# @author Frank Bergmann +# @author Sarah Keating +# +# + +import sys + +from deviser.base_files import BaseMatlabFile +from deviser.parseXML import ParseXML +from deviser.util import global_variables + + +def generate_matlab_for(filename, overwrite=True): + global_variables.running_tests = False + parser = ParseXML.ParseXML(filename) + ob = dict() + if global_variables.code_returned == \ + global_variables.return_codes['success']: + # catch a problem in the parsing + try: + ob = parser.parse_deviser_xml() + except: + global_variables.code_returned \ + = global_variables.return_codes['parsing error'] + if global_variables.code_returned == \ + global_variables.return_codes['success']: + name = ob['name'.lower()] + try: + if global_variables.is_package: + generate_matlab_code(name, ob) + except: + global_variables.code_returned \ + = global_variables.return_codes['unknown error - please report'] + + +def generate_matlab_code(name, ob): + filetypes = ['sf', 'dv', 'vt'] + for t in filetypes: + ex = BaseMatlabFile.BaseMatlabFile(name, ob, t) + ex.write_file() + ex.close_file() + + +def main(args): + if len(args) != 2: + global_variables.code_returned = \ + global_variables.return_codes['missing function argument'] + print ('Usage: generateCode.py xmlfile') + else: + generate_matlab_for(args[1]) + if global_variables.code_returned == \ + global_variables.return_codes['success']: + print('code successfully written') + else: + print('writing code failed') + + return global_variables.code_returned + +if __name__ == '__main__': + main(sys.argv)