def __init__(self, external_packages=None, msl_version='3.2'):
        self.logger = logging.getLogger('py_modelica_exporter::ComponentExporter')
        self.logger.setLevel(logging.DEBUG)
        # create console handler with a higher log level
        self.logger_console_handler = logging.StreamHandler()
        self.logger_console_handler.setLevel(logging.INFO)

        # create formatter and add it to the handlers
        self.logger_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.logger_console_handler.setFormatter(self.logger_formatter)

        # add the handlers to the logger
        self.logger.addHandler(self.logger_console_handler)

        # start om session
        self.omc = OMCSession()
        # start om session
        self.omc = OMCSession()

        # load all packages
        self.omc.loadModel('Modelica, {{"{0}"}}'.format(msl_version))
        self.logger.info('Modelica {0} loaded.'.format(msl_version))

        if external_packages:
            self.load_external_packages(external_packages)

        self.logger.debug('ComponentAssemblyExporter __init__ finished.')
Exemplo n.º 2
0
    def __init__(self,
                 external_packages=None,
                 export_icons=False,
                 msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger(
            'py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info(
            'Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if not os.path.isdir(icon_dir_name):
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)
Exemplo n.º 3
0
    def __init__(self, external_packages=None, msl_version='3.2'):
        """
        Create an instance of the ComponentAssemblyExporter
        """
        self.logger = logging.getLogger(
            'py_modelica_exporter::ComponentExporter')
        self.logger.setLevel(logging.DEBUG)
        # create console handler with a higher log level
        self.logger_console_handler = logging.StreamHandler()
        self.logger_console_handler.setLevel(logging.INFO)

        # create formatter and add it to the handlers
        self.logger_formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.logger_console_handler.setFormatter(self.logger_formatter)

        # add the handlers to the logger
        self.logger.addHandler(self.logger_console_handler)

        # start om session
        self.omc = OMCSession()
        # start om session
        self.omc = OMCSession()

        # load all packages
        self.omc.loadModel('Modelica, {{"{0}"}}'.format(msl_version))
        self.logger.info('Modelica {0} loaded.'.format(msl_version))

        if external_packages:
            self.load_external_packages(external_packages)

        self.logger.debug('ComponentAssemblyExporter __init__ finished.')
Exemplo n.º 4
0
class TreeExporter(object):
    def __init__(self, className):
        self.classNames = list()
        self.classNames.append(className)
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(className))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')
        # TODO: load all external packages

        self.parse_tree(className)

    def parse_tree(self, className):

        classNames = self.omc.getClassNames(className,
                                            recursive=True,
                                            sort=True)

        # filter and export only blocks and models
        for c_name in classNames:
            if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):
                class_details = dict()
                class_details['ComponentName'] = c_name
                class_details['Description'] = self.omc.getClassComment(c_name)
                self.classDetails.append(class_details)

    def json(self):
        json_result = dict()
        json_result['topLevelPackages'] = self.classNames
        json_result['classDetails'] = self.classDetails
        return json_result

    def xml(self):
        raise NotImplementedError

    def export_to_json(self, filename):
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result

    def export_to_xml(self, filename):
        raise NotImplementedError
class TreeExporter(object):

    def __init__(self, className):
        self.classNames = list()
        self.classNames.append(className)
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(className))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')
        # TODO: load all external packages

        self.parse_tree(className)

    def parse_tree(self, className):

        classNames = self.omc.getClassNames(className, recursive=True, sort=True)

        # filter and export only blocks and models
        for c_name in classNames:
            if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):
                class_details = dict()
                class_details['ComponentName'] = c_name
                class_details['Description'] = self.omc.getClassComment(c_name)
                self.classDetails.append(class_details)

    def json(self):
        json_result = dict()
        json_result['topLevelPackages'] = self.classNames
        json_result['classDetails'] = self.classDetails
        return json_result

    def xml(self):
        raise NotImplementedError

    def export_to_json(self, filename):
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result

    def export_to_xml(self, filename):
        raise NotImplementedError
def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("-l", "--library", help="External library to load.")
    parser.add_argument("-p", "--package", help="Package name to parse like: Modelica.SIunits",
                        default="Modelica.SIunits")
    args = parser.parse_args()

    omc = OMCSession()
    
    print "Loading Modelica library ..."
    success = omc.loadModel('Modelica')    
    if success:
        print "[OK]"
    else:
        print "[FAILED]"
        return
        
    if args.library:
        print "Loading External library {0} ...".format(args.library)
        cwd = os.getcwd()
        dir_name = os.path.dirname(args.library)
        os.chdir(dir_name)
        success = success and omc.loadFile(args.library)
        os.chdir(cwd)
        if success:
            print "[OK]"
        else:
            print "[FAILED]"

    if success:
        print "Getting all class names for package: {0}".format(args.package)
        modelica_classes = omc.getClassNames(args.package, recursive=True, qualified=True, sort=True)
        #print modelica_classes

        result = []
        for modelica_class in modelica_classes:
            info = {}
            info['name'] = modelica_class
            class_restriction = omc.getClassRestriction(modelica_class)
            info['class'] = class_restriction
            #info['text'] = omc.list(modelica_class)
            info['modifiers'] = {}
            print modelica_class
            modifiers = omc.getDerivedClassModifierNames(modelica_class)
            for modifier in modifiers:
                modifier_value = omc.getDerivedClassModifierValue(modelica_class, modifier)
                # ' = "value"' => 'value'
                modifier_value = modifier_value[3:].strip('"')
                info['modifiers'][modifier] = modifier_value

            getBaseClassModifiers(omc, modelica_class, info['modifiers'])

            result.append(info)
        
        output_filename = 'modelica_units.json'
        with open(output_filename, 'w') as f_p:
            json.dump(result, f_p)
        
        print 'File was generated: {0}'.format(output_filename)
Exemplo n.º 7
0
    def __init__(self, external_packages, load_MSL=True):

        self.externalPackagePaths = make_paths_safe_for_omc(external_packages)
        self.packageNames = list()
        self.failedLoadPackageNames = list()
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(
            self.externalPackagePaths))

        self.omc = OMCSession()
        self.loadPackages(self.externalPackagePaths, load_MSL=load_MSL)
        self.getClassDetails(self.packageNames)
Exemplo n.º 8
0
    def __init__(self, external_packages=None):

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.LayoutExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info(
            'Initializing LayoutExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)
    def __init__(self, external_packages=None, export_icons=False, msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.loadPackages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if os.path.isdir(icon_dir_name) == False:
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)
Exemplo n.º 10
0
    def __init__(self, className):
        self.classNames = list()
        self.classNames.append(className)
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(className))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')
        # TODO: load all external packages

        self.parse_tree(className)
Exemplo n.º 11
0
    def __init__(self, external_packages, load_msl=True):
        """
        Create an instance of the PackageExporter
        """
        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)
        self.package_names = list()
        self.failed_load_package_names = list()
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(
            self.external_package_paths))

        self.omc = OMCSession()
        self.load_packages(self.external_package_paths, load_msl=load_msl)
        self.get_class_details(self.package_names)
Exemplo n.º 12
0
    def __init__(self, class_name):
        """
        creates an instance of TreeExporter
        """
        self.class_names = list()
        self.class_names.append(class_name)
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(class_name))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')

        self.parse_tree(class_name)
Exemplo n.º 13
0
    def __init__(self, external_packages, load_MSL=True):

        self.externalPackagePaths = make_paths_safe_for_omc(external_packages)
        self.packageNames = list()
        self.failedLoadPackageNames = list()
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(self.externalPackagePaths))

        self.omc = OMCSession()
        self.loadPackages(self.externalPackagePaths, load_MSL=load_MSL)
        self.getClassDetails(self.packageNames)
Exemplo n.º 14
0
    def __init__(self, external_packages, load_msl=True):
        """
        Create an instance of the PackageExporter
        """
        self.external_package_paths = make_paths_safe_for_omc(external_packages)
        self.package_names = list()
        self.failed_load_package_names = list()
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(self.external_package_paths))

        self.omc = OMCSession()
        self.load_packages(self.external_package_paths, load_msl=load_msl)
        self.get_class_details(self.package_names)
Exemplo n.º 15
0
    def __init__(self, className):
        self.classNames = list()
        self.classNames.append(className)
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(className))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')
        # TODO: load all external packages

        self.parse_tree(className)
Exemplo n.º 16
0
    def __init__(self, class_name):
        """
        creates an instance of TreeExporter
        """
        self.class_names = list()
        self.class_names.append(class_name)
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(class_name))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')

        self.parse_tree(class_name)
Exemplo n.º 17
0
class ComponentAssemblyExporter(object):

    def __init__(self, external_packages=None, msl_version='3.2'):
        self.logger = logging.getLogger('py_modelica_exporter::ComponentExporter')
        self.logger.setLevel(logging.DEBUG)
        # create console handler with a higher log level
        self.logger_console_handler = logging.StreamHandler()
        self.logger_console_handler.setLevel(logging.INFO)

        # create formatter and add it to the handlers
        self.logger_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.logger_console_handler.setFormatter(self.logger_formatter)

        # add the handlers to the logger
        self.logger.addHandler(self.logger_console_handler)

        # start om session
        self.omc = OMCSession()
        # start om session
        self.omc = OMCSession()

        # load all packages
        self.omc.loadModel('Modelica, {{"{0}"}}'.format(msl_version))
        self.logger.info('Modelica {0} loaded.'.format(msl_version))

        if external_packages:
            self.load_external_packages(external_packages)

        self.logger.debug('ComponentAssemblyExporter __init__ finished.')

    def load_external_packages(self, external_packages):

        for package_path in (os.path.abspath(p.strip()).replace("\\", "/") for p in external_packages):
            file_name = os.path.basename(package_path)

            if file_name == 'package.mo':
                package_name = os.path.basename(os.path.dirname(package_path))
            else:
                package_name, dot_mo = os.path.splitext(file_name)

            if self.omc.loadFile(package_path):
                self.logger.info('Loaded {0} at {1}'.format(package_name, package_path))
            else:
                self.logger.error('Failed loading {0} from {1}!'.format(package_name, package_path))

    def get_component_assembly_json(self, modelica_uri):

        ca = ComponentAssembly()
        ca.name = modelica_uri.split('.')[-1]
        ca.full_name = modelica_uri
        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as ex:
            if ex.args[0] == 'Could not parse OMC response.':
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v5, v6, v7, isReplaceable, component_type, v10, v11, v12) in mo_components:

            if self.omc.isModel(mo_type) or self.omc.isBlock(mo_type):
                if v10 in ['inner', 'outer']:
                    self.logger.debug('Skipping {0} - it is {1}'.format(mo_name, v10))
                    continue
                component_shell = ComponentShell()
                component_shell.name = mo_name
                ca.component_shells.update({mo_name: component_shell})
            elif self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation
                ca.connectors.append(connector)

        for n in range(1, self.omc.getConnectionCount(modelica_uri) + 1):
            src, dst, v3 = self.omc.getNthConnection(modelica_uri, n)
            connection = Connection()
            src_name, src_parent = self._get_connector_and_parent(src)
            dst_name, dst_parent = self._get_connector_and_parent(dst)

            try:
                if src_parent:
                    connection.src_parent = src_parent
                    component_shell = ca.component_shells[src_parent]
                    assert isinstance(component_shell, ComponentShell)
                    connector = Connector()
                    connector.name = src_name
                    component_shell.connectors.append(connector)
                if dst_parent:
                    connection.dst_parent = dst_parent
                    component_shell = ca.component_shells[dst_parent]
                    assert isinstance(component_shell, ComponentShell)
                    connector = Connector()
                    connector.name = src_name
                    component_shell.connectors.append(connector)
            except KeyError as err:
                self.logger.debug('Skipping connections to {0}'.format(err.message))
                continue

            connection.src_name = src_name
            connection.dst_name = dst_name
            ca.connections.append(connection)

        return ca.json()

    def _get_connector_and_parent(self, connected):
        pieces = connected.split('.')
        parent = ""
        if len(pieces) == 2:
            parent = pieces[0]
            connector = pieces[1]
        else:
            connector = connected

        return connector, parent
Exemplo n.º 18
0
class ComponentExporter(object):
    """
    Class ComponentExporter is an interface with the OpenModelicaCompiler to facilitate extracting class information
    in a single 'Component' format
    """
    def __init__(self,
                 external_packages=None,
                 export_icons=False,
                 msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger(
            'py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info(
            'Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if not os.path.isdir(icon_dir_name):
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)

    def load_packages(self, external_package_paths):
        """
        load all external packages into the OpenModelicaCompiler so individual classes may be explored

        @param external_package_paths:
        @return:
        """

        self.omc.loadModel('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path):  # make sure the file exists
                if self.omc.loadFile(
                        package_path):  # try to load the package file
                    self.logger.info(
                        'Library loaded from : {0}'.format(package_path))
                else:
                    self.logger.warning(
                        'Failed to load: {0}'.format(package_path))
            else:
                self.logger.warning(
                    'File does not exist! Failed to load: {0}'.format(
                        package_path))

    def get_component_json(self, modelica_uri):
        """
        Extracts component and returns a dictionary
        """
        components = []
        json_result = {
            'exportedComponentClass': modelica_uri,
            'icon_path': None,
            'components': []
        }

        if self.export_icons and os.path.isdir('Icons'):
            json_result['icon_path'] = self.icon_exporter.export_icon(
                modelica_uri)

        try:
            self.extract_component_content(modelica_uri, components)
            [
                json_result['components'].append(component.json())
                for component in components
            ]

        except Exception as exception:
            component = Component()
            component.full_name = 'Exception'
            component.comment = exception.message
            json_result['components'].append(component.json())
            self.logger.info(
                'Could not get information for {0}'.format(modelica_uri))

        return json_result

    def get_icon_only(self, modelica_uri):
        """
        Extracts the icon from the Modelica class
        """
        if self.export_icons and os.path.isdir('Icons'):
            self.icon_exporter.export_icon(modelica_uri)

    def get_component_xml(self, modelica_uri):
        """
        Extracts component and returns a xml tree
        """
        components = []
        self.extract_component_content(modelica_uri, components)

        xml_result = etree.Element("Root")
        xml_result.set("ExportedComponent", modelica_uri)
        [xml_result.append(xml_node.xml()) for xml_node in components]

        return xml_result

    def extract_component_content(self, modelica_uri, components):
        """
        Recursively populates components with extracted_components,
        starting from modelica_uri and goes through the extends.
        """
        component = Component()
        component.full_name = modelica_uri
        component.comment = self.omc.getClassComment(modelica_uri)

        components.append(component)

        try:
            #mo_packages = self.omc.getPackages(modelica_uri)
            mo_replaceables = self.omc.getReplaceables(modelica_uri)
            mo_extends_packages = self.omc.getPackagesFromExtends(modelica_uri)

            for replaceable_package in mo_replaceables:
                package = Package()
                package.name = replaceable_package['name']
                package.value = replaceable_package['value']
                component.packages.append(package)

            for extends_class, extends_package in mo_extends_packages.iteritems(
            ):
                package = Package()
                package.name = extends_package['name']
                package.value = extends_package['value']
                component.packages.append(package)

        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                e_msg = 'Could not parse OMC response for getReplaceables({0}) or getPackagesFromExtends()'.format(
                    modelica_uri)
                self.logger.warning(e_msg)
                raise ParsingException

        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                self.logger.warning(
                    'Could not parse OMC response for getComponents({0})'.
                    format(modelica_uri))
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v_1, v_2, v_3,
             isReplaceable, component_type, v_5, v_6, v_7) in mo_components:

            if self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation

                modifier_names = self.omc.getComponentModifierNames(
                    modelica_uri, mo_name)
                modifiers = dict()
                modifiers['modifications'] = mo_modification
                for modifier_name in modifier_names:
                    modifier_value = self.omc.getComponentModifierValue(
                        modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    modifiers[modifier_name] = modifier_value
                    connector.modifiers = modifiers

                if (len(component.packages) != 0) and (
                        'Modelica.Fluid.Interfaces.FluidPort_' in mo_type):
                    port_redeclare = self.omc.getPortRedeclares(
                        modelica_uri, mo_type, mo_name)
                    if port_redeclare:
                        for package in component.packages:
                            if port_redeclare[1] == package.name:
                                redeclare_parameter = RedeclareParameter()
                                redeclare_parameter.name = port_redeclare[0]
                                redeclare_parameter.value = port_redeclare[1]
                                #redeclare_parameter.value = package.value

                                connector.redeclare_parameters.append(
                                    redeclare_parameter)
                                break

                component.connectors.append(connector)

            elif component_type == 'parameter':
                parameter = Parameter()
                if mo_modification != 'public':
                    parameter.is_public = False

                parameter.name = mo_name
                parameter.description = mo_annotation
                parameter.full_name = mo_type
                parameter.value = self.omc.getParameterValue(
                    modelica_uri, mo_name)

                value_type = type(parameter.value)

                if value_type == tuple:
                    parameter.dimension = len(
                        parameter.value)  # log the length of the tuple
                elif value_type == str:
                    if parameter.value == '':
                        parameter.dimension = 0  # 0 indicates an empty string
                    elif '[' in parameter.value:
                        semicolon_split = parameter.value.split(';')
                        if len(semicolon_split) > 1:
                            # this means a table with dimension (n,m); should we actually log the values? or only '-1'?
                            parameter.dimension = -1
                        else:
                            # if there are no semicolons, then this is a 1-d array (?)
                            comma_split = parameter.value.split(',')
                            parameter.dimension = len(comma_split)

                for modifier_name in self.omc.getComponentModifierNames(
                        modelica_uri, mo_name):
                    modifier_value = self.omc.getComponentModifierValue(
                        modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    parameter.modifiers.update({modifier_name: modifier_value})

                if self.omc.isType(mo_type):
                    parameter.full_name = get_parameter_base_type_and_modifiers(
                        self.omc, mo_type, parameter.modifiers)

                component.parameters.append(parameter)

            else:
                pass  # the object is not a connector or a parameter

        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            extend = Extend()
            mo_extend_class_name = self.omc.getNthInheritedClass(
                modelica_uri, i)

            if mo_extend_class_name in mo_extends_packages:
                redeclare_parameter = RedeclareParameter()
                redeclare_parameter.name = mo_extends_packages[
                    mo_extend_class_name]['name']
                redeclare_parameter.redeclare_type = 'package'
                redeclare_parameter.value = mo_extends_packages[
                    mo_extend_class_name]['value']
                extend.redeclare_parameters.append(redeclare_parameter)

            mo_extend_class_modifiers = self.omc.getExtendsModifierNames(
                modelica_uri, mo_extend_class_name)

            extend.modifiers = {}

            for extend_class_modifier in mo_extend_class_modifiers:
                if '.' in extend_class_modifier:
                    # this is a modifier
                    extend.modifiers[
                        extend_class_modifier] = self.omc.getExtendsModifierValue(
                            modelica_uri, mo_extend_class_name,
                            extend_class_modifier)
                else:
                    # this is a parameter
                    extend_parameter = Parameter()
                    extend_parameter.name = extend_class_modifier
                    extend_parameter.value = self.omc.getExtendsModifierValue(
                        modelica_uri, mo_extend_class_name,
                        extend_class_modifier)
                    extend.parameters.append(extend_parameter)

            extend.full_name = mo_extend_class_name

            component.extends.append(extend)

            self.extract_component_content(mo_extend_class_name, components)

        mo_import_count = self.omc.getImportCount(modelica_uri)
        for i in range(1, mo_import_count + 1):
            import_item = Import()

            mo_import = self.omc.getNthImport(modelica_uri, i)

            import_item.full_name = mo_import[0]
            import_item.id = mo_import[1]
            import_item.kind = mo_import[2]

            component.imports.append(import_item)
Exemplo n.º 19
0
class PackageExporter(object):
    """
    Class PackageExporter is an interface with the OpenModelicaCompiler to facilitate extraction of all classes
    contained within 'external_packages' (and the MSL)
    """
    def __init__(self, external_packages, load_msl=True):
        """
        Create an instance of the PackageExporter
        """
        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)
        self.package_names = list()
        self.failed_load_package_names = list()
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(
            self.external_package_paths))

        self.omc = OMCSession()
        self.load_packages(self.external_package_paths, load_msl=load_msl)
        self.get_class_details(self.package_names)

    def parse_argument(self, external_packages):
        """
        This will update self.external_package_paths and self.package_names
        """
        for potential_path in external_packages:
            if os.path.exists(potential_path):
                self.external_package_paths.append(potential_path)

                if os.path.basename(
                        potential_path
                ) == 'package.mo':  # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(
                        potential_path)  # get the path to the last directory
                    package_name = os.path.basename(
                        package_dir)  # get the name of the last directory
                    self.package_names.append(package_name)  # store that name
                else:
                    file_path, file_extension = os.path.splitext(
                        potential_path)
                    if file_extension == '.mo':  # make sure it is a '.mo' file
                        package_name = os.path.basename(
                            file_path)  # get the name of the file
                        self.package_names.append(
                            package_name)  # store that name
            # else:
            #     pass  # should log that this package path is invalid?

    def load_packages(self, external_package_paths, load_msl=True):
        """
        load all the external packages using OpenModelicaCompiler
        """

        if load_msl:
            if self.omc.loadModel('Modelica'):
                comment = self.omc.getClassComment('Modelica')

                import re

                modelica_version_pattern = '.*Version ([\d\.]*)'
                regex_modelica_version = re.findall(modelica_version_pattern,
                                                    comment)

                if regex_modelica_version[0]:
                    self.package_names.append('Modelica ' +
                                              regex_modelica_version[0])
                else:
                    self.package_names.append('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path):  # make sure the file exists
                if os.path.basename(
                        package_path
                ) == 'package.mo':  # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(
                        package_path)  # get the path to the last directory
                    package_name = os.path.basename(
                        package_dir
                    )  # get the name of the last directory (package_name)
                    if self.omc.loadFile(
                            package_path):  # try to load the package file
                        self.package_names.append(
                            package_name)  # log successful load
                        self.logger.info(
                            'Library loaded from : {0}'.format(package_path))
                    else:
                        self.failed_load_package_names.append(
                            "FAILED_" + package_name)  # log failure
                        self.logger.warning(
                            'Failed to load: {0}'.format(package_path))
                else:
                    file_path, file_extension = os.path.splitext(package_path)
                    if file_extension == '.mo':  # make sure it is a '.mo' file
                        package_name = os.path.basename(
                            file_path)  # get the name of the file
                        if self.omc.loadFile(
                                package_path):  # try to load the package file
                            self.package_names.append(
                                package_name)  # log successful load
                            self.logger.info(
                                'Library loaded from : {0}'.format(
                                    package_path))
                        else:
                            self.failed_load_package_names.append(
                                "FAILED_" + package_name)  # log failure
                            self.logger.warning(
                                'Failed to load: {0}'.format(package_path))
            else:
                file_path, file_extension = os.path.splitext(package_path)
                if file_extension == '.mo':  # make sure it is a '.mo' file
                    package_name = os.path.basename(
                        file_path)  # get the name of the file
                    if package_name == 'package':
                        package_name = os.path.basename(
                            os.path.dirname(file_path))

                    self.failed_load_package_names.append(package_name)
                    self.logger.warning(
                        'Failed to load: {0}'.format(package_path))

    def get_class_details(self, package_names):
        """
        Get the class details and write out a json file
        """

        for package_name in package_names:
            get_comments = False  # self.omc.getClassNames randomly (?) takes a long time to execute

            if 'Modelica' in package_name:
                class_names = self.omc.getClassNames('Modelica',
                                                     recursive=True,
                                                     sort=True)
                # get_comments = True

                # blacklist = ['.Utilities.',
                #              '.UsersGuide.',
                #              '.Examples.',
                #              '.UnitConversions.',
                #              '.Media.']

                # for c_name in class_names:
                #     # skip_it = False
                #     # for bad_name in blacklist:
                #     #     if bad_name in c_name:
                #     #         skip_it = True
                #     #         self.logger.info(c_name + " is black-listed (not a model or block)")
                #     #         break
                #     # if skip_it:
                #     #     continue
                #
                #     class_details = dict()
                #     class_details['ComponentName'] = c_name
                #     class_details['Description'] = ""  # self.omc.getClassComment(c_name)
                #     self.class_details.append(class_details)

            else:
                class_names = self.omc.getClassNames(package_name,
                                                     recursive=True,
                                                     sort=True)
                # get_comments = True

            for c_name in class_names:

                class_details = dict()
                class_details['ComponentName'] = c_name
                if get_comments:
                    class_details['Description'] = self.omc.getClassComment(
                        c_name)
                else:
                    class_details['Description'] = "None available"

                self.class_details.append(class_details)

                # model_type = self.omc.getClassRestriction(c_name)
                # if model_type in ['model', 'block']:
                # # if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):  # only blocks and models are exported
                #     class_details = dict()
                #     class_details['ComponentName'] = c_name
                #     class_details['Description'] = self.omc.getClassComment(c_name)
                #     self.class_details.append(class_details)

    def json(self):
        """
        Generate a dictionary from the Packages
        """
        json_result = dict()
        json_result[
            'topLevelPackages'] = self.package_names + self.failed_load_package_names
        json_result['classDetails'] = self.class_details
        return json_result

    def export_to_json(self, filename):
        """
        Write a json file of the Packages
        """
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result
Exemplo n.º 20
0
class TreeExporter(object):
    """
    Class TreeExporter is an interface with the OpenModelicaCompiler to facilitate extraction of all contained classes
    """
    def __init__(self, class_name):
        """
        creates an instance of TreeExporter
        """
        self.class_names = list()
        self.class_names.append(class_name)
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(class_name))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')

        self.parse_tree(class_name)

    def parse_tree(self, class_name):
        """
        gets all classes from within 'class_name'
        """

        class_names = self.omc.getClassNames(class_name,
                                             recursive=True,
                                             sort=True)

        # filter and export only blocks and models
        for c_name in class_names:
            # if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):
            class_details = dict()
            class_details['ComponentName'] = c_name
            class_details[
                'Description'] = "None available"  # self.omc.getClassComment(c_name)
            self.class_details.append(class_details)

    def json(self):
        """
        Creates a dictionary from of all the classes contained in the Tree
        """
        json_result = dict()
        json_result['topLevelPackages'] = self.class_names
        json_result['classDetails'] = self.class_details
        return json_result

    def xml(self):
        raise NotImplementedError

    def export_to_json(self, filename):
        """
        Write out a json representation of the Tree
        """
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result

    def export_to_xml(self, filename):
        raise NotImplementedError
Exemplo n.º 21
0
class ComponentExporter(object):

    def __init__(self, external_packages=None, export_icons=False, msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.loadPackages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if os.path.isdir(icon_dir_name) == False:
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)

    def loadPackages(self, external_package_paths):

        self.omc.loadModel('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path) == True:                        # make sure the file exists
                if self.omc.loadFile(package_path) == True:         # try to load the package file
                    self.logger.info('Library loaded from : {0}'.format(package_path))
                else:
                    self.logger.warning('Failed to load: {0}'.format(package_path))
            else:
                self.logger.warning('File does not exist! Failed to load: {0}'.format(package_path))

    def get_component_json(self, modelica_uri):
        """
        Extracts component and returns a dictionary
        """
        components = []
        json_result = {'exportedComponentClass': modelica_uri,
                       'icon_path': None,
                       'components': []}

        if self.export_icons and os.path.isdir('Icons'):
            json_result['icon_path'] = self.icon_exporter.export_icon(modelica_uri)

        try:
            self.extract_component_content(modelica_uri, components)
            [json_result['components'].append(component.json()) for component in components]

        except Exception as exception:
            component = Component()
            component.full_name = 'Exception'
            component.comment = exception.message
            json_result['components'].append(component.json())
            self.logger.info('Could not get information for {0}'.format(modelica_uri))

        return json_result

    def get_icon_only(self, modelica_uri):

        if self.export_icons and os.path.isdir('Icons'):
            self.icon_exporter.export_icon(modelica_uri)

    def get_component_xml(self, modelica_uri):
        """
        Extracts component and returns a xml tree
        """
        components =[]
        self.extract_component_content(modelica_uri, components)

        xml_result = etree.Element("Root")
        xml_result.set("ExportedComponent", modelica_uri)
        [xml_result.append(xml_node.xml()) for xml_node in components]

        return xml_result

    def extract_component_content(self, modelica_uri, components):
        """
        Recursively populates components with extracted_components,
        starting from modelica_uri and goes through the extends.
        """
        component = Component()
        component.full_name = modelica_uri
        component.comment = self.omc.getClassComment(modelica_uri)

        components.append(component)

        try:
            #mo_packages = self.omc.getPackages(modelica_uri)
            mo_replaceables = self.omc.getReplaceables(modelica_uri)
            mo_extends_packages = self.omc.getPackagesFromExtends(modelica_uri)

            for replaceable_package in mo_replaceables:
                package = Package()
                package.name = replaceable_package['name']
                package.value = replaceable_package['value']
                component.packages.append(package)

            for extends_class, extends_package in mo_extends_packages.iteritems():
                package = Package()
                package.name = extends_package['name']
                package.value = extends_package['value']
                component.packages.append(package)

        except ValueError as ex:
            if ex.args[0] == 'Could not parse OMC response.':
                self.logger.warning('Could not parse OMC response for getReplaceables({0}) or getPackagesFromExtends()'.format(modelica_uri))
                raise ParsingException

        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as ex:
            if ex.args[0] == 'Could not parse OMC response.':
                self.logger.warning('Could not parse OMC response for getComponents({0})'.format(modelica_uri))
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v1, v2, v3, isReplaceable, component_type, v5, v6, v7) in mo_components:

            if self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation

                modifier_names = self.omc.getComponentModifierNames(modelica_uri, mo_name)
                modifiers = dict()
                modifiers['modifications'] = mo_modification
                for modifier_name in modifier_names:
                    modifier_value = self.omc.getComponentModifierValue(modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    modifiers[modifier_name] = modifier_value
                    connector.modifiers = modifiers

                if (len(component.packages) != 0) and ('Modelica.Fluid.Interfaces.FluidPort_' in mo_type):
                    portRedeclare = self.omc.getPortRedeclares(modelica_uri, mo_type, mo_name)
                    if portRedeclare:
                        for package in component.packages:
                            if portRedeclare[1] == package.name:
                                redeclare_parameter = RedeclareParameter()
                                redeclare_parameter.name = portRedeclare[0]
                                redeclare_parameter.value = portRedeclare[1]
                                #redeclare_parameter.value = package.value

                                connector.redeclare_parameters.append(redeclare_parameter)
                                break

                component.connectors.append(connector)

            elif component_type == 'parameter':
                parameter = Parameter()
                if mo_modification != 'public':
                    parameter.is_public = False

                parameter.name = mo_name
                parameter.description = mo_annotation
                parameter.full_name = mo_type
                parameter.value = self.omc.getParameterValue(modelica_uri, mo_name)

                value_type = type(parameter.value)

                if value_type == tuple:
                    parameter.dimension = len(parameter.value)  # log the length of the tuple
                elif value_type == str:
                    if parameter.value == '':
                        parameter.dimension = 0  # 0 indicates an empty string
                    elif '[' in parameter.value:
                        semicolon_split = parameter.value.split(';')
                        if len(semicolon_split) > 1:
                            # this means a table with dimension (n,m); should we actually log the values? or only '-1'?
                            parameter.dimension = -1
                        else:
                            # if there are no semicolons, then this is a 1-d array (?)
                            comma_split = parameter.value.split(',')
                            parameter.dimension = len(comma_split)

                for modifier_name in self.omc.getComponentModifierNames(modelica_uri, mo_name):
                    modifier_value = self.omc.getComponentModifierValue(modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    parameter.modifiers.update({modifier_name: modifier_value})

                if self.omc.isType(mo_type):
                    parameter.full_name = get_parameter_base_type_and_modifiers(self.omc, mo_type, parameter.modifiers)

                component.parameters.append(parameter)

            else:
                pass # the object is not a connector or a parameter

        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            extend = Extend()
            mo_extend_class_name = self.omc.getNthInheritedClass(modelica_uri, i)

            if mo_extend_class_name in mo_extends_packages:
                redeclare_parameter = RedeclareParameter()
                redeclare_parameter.name = mo_extends_packages[mo_extend_class_name]['name']
                redeclare_parameter.redeclare_type = 'package'
                redeclare_parameter.value = mo_extends_packages[mo_extend_class_name]['value']
                extend.redeclare_parameters.append(redeclare_parameter)

            mo_extend_class_modifiers = self.omc.getExtendsModifierNames(modelica_uri, mo_extend_class_name)

            extend.modifiers = {}

            for mo_extend_class_modifier in mo_extend_class_modifiers:
                if '.' in mo_extend_class_modifier:
                    # this is a modifier
                    extend.modifiers[mo_extend_class_modifier] = self.omc.getExtendsModifierValue(modelica_uri, mo_extend_class_name, mo_extend_class_modifier)
                else:
                    # this is a parameter
                    extend_parameter = Parameter()
                    extend_parameter.name = mo_extend_class_modifier
                    extend_parameter.value = self.omc.getExtendsModifierValue(modelica_uri, mo_extend_class_name, mo_extend_class_modifier)
                    extend.parameters.append(extend_parameter)

            extend.full_name = mo_extend_class_name

            component.extends.append(extend)

            self.extract_component_content(mo_extend_class_name, components)

        # TODO: Shouldn't this be done for all components?
        mo_import_count = self.omc.getImportCount(modelica_uri)
        for i in range(1, mo_import_count + 1):
            import_item = Import()

            mo_import = self.omc.getNthImport(modelica_uri, i)

            import_item.full_name = mo_import[0]
            import_item.id = mo_import[1]
            import_item.kind = mo_import[2]

            component.imports.append(import_item)
Exemplo n.º 22
0
class TreeExporter(object):
    """
    Class TreeExporter is an interface with the OpenModelicaCompiler to facilitate extraction of all contained classes
    """

    def __init__(self, class_name):
        """
        creates an instance of TreeExporter
        """
        self.class_names = list()
        self.class_names.append(class_name)
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.TreeExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing TreeExporter({0})'.format(class_name))

        self.omc = OMCSession()

        # load all packages
        success = self.omc.loadModel('Modelica')

        self.parse_tree(class_name)

    def parse_tree(self, class_name):
        """
        gets all classes from within 'class_name'
        """

        class_names = self.omc.getClassNames(class_name, recursive=True, sort=True)

        # filter and export only blocks and models
        for c_name in class_names:
            # if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):
            class_details = dict()
            class_details['ComponentName'] = c_name
            class_details['Description'] = "None available"  # self.omc.getClassComment(c_name)
            self.class_details.append(class_details)

    def json(self):
        """
        Creates a dictionary from of all the classes contained in the Tree
        """
        json_result = dict()
        json_result['topLevelPackages'] = self.class_names
        json_result['classDetails'] = self.class_details
        return json_result

    def xml(self):
        raise NotImplementedError

    def export_to_json(self, filename):
        """
        Write out a json representation of the Tree
        """
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result

    def export_to_xml(self, filename):
        raise NotImplementedError
Exemplo n.º 23
0
class ComponentAssemblyExporter(object):
    """
    Class ComponentAssemblyExporter is an interface with the OpenModelicaCompiler to facilitate
    extracting class information in a 'ComponentAssembly' format
    """
    def __init__(self, external_packages=None, msl_version='3.2'):
        """
        Create an instance of the ComponentAssemblyExporter
        """
        self.logger = logging.getLogger(
            'py_modelica_exporter::ComponentExporter')
        self.logger.setLevel(logging.DEBUG)
        # create console handler with a higher log level
        self.logger_console_handler = logging.StreamHandler()
        self.logger_console_handler.setLevel(logging.INFO)

        # create formatter and add it to the handlers
        self.logger_formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.logger_console_handler.setFormatter(self.logger_formatter)

        # add the handlers to the logger
        self.logger.addHandler(self.logger_console_handler)

        # start om session
        self.omc = OMCSession()
        # start om session
        self.omc = OMCSession()

        # load all packages
        self.omc.loadModel('Modelica, {{"{0}"}}'.format(msl_version))
        self.logger.info('Modelica {0} loaded.'.format(msl_version))

        if external_packages:
            self.load_external_packages(external_packages)

        self.logger.debug('ComponentAssemblyExporter __init__ finished.')

    def load_external_packages(self, external_packages):
        """
        Load all the external packages
        """

        for package_path in (os.path.abspath(p.strip()).replace("\\", "/")
                             for p in external_packages):
            file_name = os.path.basename(package_path)

            if file_name == 'package.mo':
                package_name = os.path.basename(os.path.dirname(package_path))
            else:
                package_name, dot_mo = os.path.splitext(file_name)

            if self.omc.loadFile(package_path):
                self.logger.info('Loaded {0} at {1}'.format(
                    package_name, package_path))
            else:
                self.logger.error('Failed loading {0} from {1}!'.format(
                    package_name, package_path))

    def get_component_assembly_json(self, modelica_uri):
        """
        create a dictionary description of the Modelica class, enumerating all the contained classes
        """
        ca = ComponentAssembly()
        ca.name = modelica_uri.split('.')[-1]
        ca.full_name = modelica_uri
        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v5, v6, v7,
             isReplaceable, component_type, v10, v11, v12) in mo_components:

            if self.omc.isModel(mo_type) or self.omc.isBlock(mo_type):
                if v10 in ['inner', 'outer']:
                    self.logger.debug('Skipping {0} - it is {1}'.format(
                        mo_name, v10))
                    continue
                component_shell = ComponentShell()
                component_shell.name = mo_name
                ca.component_shells.update({mo_name: component_shell})
            elif self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation
                ca.connectors.append(connector)

        for n in range(1, self.omc.getConnectionCount(modelica_uri) + 1):
            src, dst, v3 = self.omc.getNthConnection(modelica_uri, n)
            connection = Connection()
            src_name, src_parent = self._get_connector_and_parent(src)
            dst_name, dst_parent = self._get_connector_and_parent(dst)

            try:
                if src_parent:
                    connection.src_parent = src_parent
                    component_shell = ca.component_shells[src_parent]
                    assert isinstance(component_shell, ComponentShell)
                    connector = Connector()
                    connector.name = src_name
                    component_shell.connectors.append(connector)
                if dst_parent:
                    connection.dst_parent = dst_parent
                    component_shell = ca.component_shells[dst_parent]
                    assert isinstance(component_shell, ComponentShell)
                    connector = Connector()
                    connector.name = src_name
                    component_shell.connectors.append(connector)
            except KeyError as err:
                self.logger.debug('Skipping connections to {0}'.format(
                    err.message))
                continue

            connection.src_name = src_name
            connection.dst_name = dst_name
            ca.connections.append(connection)

        return ca.json()

    def _get_connector_and_parent(self, connected):
        """
        Get the connection details
        """
        pieces = connected.split('.')
        parent = ""
        if len(pieces) == 2:
            parent = pieces[0]
            connector = pieces[1]
        else:
            connector = connected

        return connector, parent
Exemplo n.º 24
0
class PackageExporter(object):
    """
    Class PackageExporter is an interface with the OpenModelicaCompiler to facilitate extraction of all classes
    contained within 'external_packages' (and the MSL)
    """

    def __init__(self, external_packages, load_msl=True):
        """
        Create an instance of the PackageExporter
        """
        self.external_package_paths = make_paths_safe_for_omc(external_packages)
        self.package_names = list()
        self.failed_load_package_names = list()
        self.class_details = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(self.external_package_paths))

        self.omc = OMCSession()
        self.load_packages(self.external_package_paths, load_msl=load_msl)
        self.get_class_details(self.package_names)

    def parse_argument(self, external_packages):
        """
        This will update self.external_package_paths and self.package_names
        """
        for potential_path in external_packages:
            if os.path.exists(potential_path):
                self.external_package_paths.append(potential_path)

                if os.path.basename(potential_path) == 'package.mo':     # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(potential_path)         # get the path to the last directory
                    package_name = os.path.basename(package_dir)          # get the name of the last directory
                    self.package_names.append(package_name)       # store that name
                else:
                    file_path, file_extension = os.path.splitext(potential_path)
                    if file_extension == '.mo':                         # make sure it is a '.mo' file
                        package_name = os.path.basename(file_path)       # get the name of the file
                        self.package_names.append(package_name)   # store that name
            # else:
            #     pass  # should log that this package path is invalid?

    def load_packages(self, external_package_paths, load_msl=True):
        """
        load all the external packages using OpenModelicaCompiler
        """

        if load_msl:
            if self.omc.loadModel('Modelica'):
                comment = self.omc.getClassComment('Modelica')

                import re

                modelica_version_pattern = '.*Version ([\d\.]*)'
                regex_modelica_version = re.findall(modelica_version_pattern, comment)

                if regex_modelica_version[0]:
                    self.package_names.append('Modelica ' + regex_modelica_version[0])
                else:
                    self.package_names.append('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path):                # make sure the file exists
                if os.path.basename(package_path) == 'package.mo':  # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(package_path)     # get the path to the last directory
                    package_name = os.path.basename(package_dir)    # get the name of the last directory (package_name)
                    if self.omc.loadFile(package_path):     # try to load the package file
                        self.package_names.append(package_name)  # log successful load
                        self.logger.info('Library loaded from : {0}'.format(package_path))
                    else:
                        self.failed_load_package_names.append("FAILED_" + package_name)    # log failure
                        self.logger.warning('Failed to load: {0}'.format(package_path))
                else:
                    file_path, file_extension = os.path.splitext(package_path)
                    if file_extension == '.mo':                             # make sure it is a '.mo' file
                        package_name = os.path.basename(file_path)          # get the name of the file
                        if self.omc.loadFile(package_path):         # try to load the package file
                            self.package_names.append(package_name)  # log successful load
                            self.logger.info('Library loaded from : {0}'.format(package_path))
                        else:
                            self.failed_load_package_names.append("FAILED_" + package_name)    # log failure
                            self.logger.warning('Failed to load: {0}'.format(package_path))
            else:
                file_path, file_extension = os.path.splitext(package_path)
                if file_extension == '.mo':                            # make sure it is a '.mo' file
                    package_name = os.path.basename(file_path)          # get the name of the file
                    if package_name == 'package':
                        package_name = os.path.basename(os.path.dirname(file_path))

                    self.failed_load_package_names.append(package_name)
                    self.logger.warning('Failed to load: {0}'.format(package_path))

    def get_class_details(self, package_names):
        """
        Get the class details and write out a json file
        """

        for package_name in package_names:
            get_comments = False  # self.omc.getClassNames randomly (?) takes a long time to execute

            if 'Modelica' in package_name:
                class_names = self.omc.getClassNames('Modelica', recursive=True, sort=True)
                # get_comments = True

                # blacklist = ['.Utilities.',
                #              '.UsersGuide.',
                #              '.Examples.',
                #              '.UnitConversions.',
                #              '.Media.']

                # for c_name in class_names:
                #     # skip_it = False
                #     # for bad_name in blacklist:
                #     #     if bad_name in c_name:
                #     #         skip_it = True
                #     #         self.logger.info(c_name + " is black-listed (not a model or block)")
                #     #         break
                #     # if skip_it:
                #     #     continue
                #
                #     class_details = dict()
                #     class_details['ComponentName'] = c_name
                #     class_details['Description'] = ""  # self.omc.getClassComment(c_name)
                #     self.class_details.append(class_details)

            else:
                class_names = self.omc.getClassNames(package_name, recursive=True, sort=True)
                # get_comments = True

            for c_name in class_names:

                class_details = dict()
                class_details['ComponentName'] = c_name
                if get_comments:
                    class_details['Description'] = self.omc.getClassComment(c_name)
                else:
                    class_details['Description'] = "None available"

                self.class_details.append(class_details)

                # model_type = self.omc.getClassRestriction(c_name)
                # if model_type in ['model', 'block']:
                # # if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)):  # only blocks and models are exported
                #     class_details = dict()
                #     class_details['ComponentName'] = c_name
                #     class_details['Description'] = self.omc.getClassComment(c_name)
                #     self.class_details.append(class_details)


    def json(self):
        """
        Generate a dictionary from the Packages
        """
        json_result = dict()
        json_result['topLevelPackages'] = self.package_names + self.failed_load_package_names
        json_result['classDetails'] = self.class_details
        return json_result

    def export_to_json(self, filename):
        """
        Write a json file of the Packages
        """
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result
Exemplo n.º 25
0
class LayoutExporter(object):
    def __init__(self, external_packages=None):

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.LayoutExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info(
            'Initializing LayoutExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)

    def load_packages(self, external_package_paths):

        self.omc.loadModel('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path):  # make sure the file exists
                if self.omc.loadFile(
                        package_path):  # try to load the package file
                    self.logger.info(
                        'Library loaded from : {0}'.format(package_path))
                else:
                    self.logger.warning(
                        'Failed to load: {0}'.format(package_path))
            else:
                self.logger.warning(
                    'File does not exist! Failed to load: {0}'.format(
                        package_path))

    def get_nth_comp_location(self, modelica_uri, n):

        x_origin = 0
        y_origin = 0
        x_extent = 0
        y_extent = 0
        rotation = 0
        flip_x = False
        flip_y = False

        # get the annotation info for Nth component (index begins at 1)
        try:
            nth_component_annotation = self.omc.getNthComponentAnnotation(
                modelica_uri, n)

            x_1 = nth_component_annotation[3]
            x_2 = nth_component_annotation[5]

            if x_1 > x_2:
                flip_x = True

            y_1 = nth_component_annotation[4]
            y_2 = nth_component_annotation[6]

            if y_1 > y_2:
                flip_y = True

            x_extent = abs(x_2 - x_1)
            y_extent = abs(y_2 - y_1)

            x_origin = nth_component_annotation[1]
            y_origin = nth_component_annotation[2]

            if x_origin == 0:
                x_origin = (x_1 + x_2) / 2
            if y_origin == 0:
                y_origin = (y_1 + y_2) / 2

            rotation = nth_component_annotation[7]

        except:
            self.logger.warning(
                'Could not get annotation for Nth component of {0}, N = {1}'.
                format(modelica_uri, n))

        return x_origin, y_origin, x_extent, y_extent, rotation, flip_x, flip_y

    def extract_assembly_layout(self, modelica_uri, assembly=None):

        if not assembly:
            assembly = ComponentAssembly()
            assembly.full_name = modelica_uri
            assembly.name = modelica_uri.split('.')[-1]

        try:
            mo_components = self.omc.getComponents(modelica_uri)

        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                self.logger.warning(
                    'Could not parse OMC response for getComponents({0})'.
                    format(modelica_uri))
                raise ParsingException

        for n in range(1, len(mo_components) + 1):

            nth_component_info = self.omc.getNthComponent(modelica_uri, n)

            x_origin, y_origin, x_extent, y_extent, rotation, flip_x, flip_y = self.get_nth_comp_location(
                modelica_uri, n)

            if x_origin - 0.5 * x_extent < assembly.extent['x_min']:
                assembly.extent['x_min'] = x_origin - 0.5 * x_extent
            if x_origin + 0.5 * x_extent > assembly.extent['x_max']:
                assembly.extent['x_max'] = x_origin + 0.5 * x_extent
            if y_origin - 0.5 * y_extent < assembly.extent['y_min']:
                assembly.extent['y_min'] = y_origin - 0.5 * y_extent
            if y_origin + 0.5 * y_extent > assembly.extent['y_max']:
                assembly.extent['y_max'] = y_origin + 0.5 * y_extent

            mo_type = nth_component_info[0]

            if self.omc.isConnector(mo_type):
                #connector = Connector()
                connector = ComponentShell()
                connector.full_name = mo_type
                connector.name = nth_component_info[1]
                connector.description = nth_component_info[2]

                #connector.relative_position['x'] = x_origin
                #connector.relative_position['y'] = y_origin
                connector.position['x'] = x_origin
                connector.position['y'] = y_origin
                connector.size['width'] = x_extent
                connector.size['height'] = y_extent

                #assembly.connectors.append(connector)
                assembly.component_shells[connector.name] = connector

            # We should only get 'internal' models within assemblies
            if self.omc.isModel(mo_type) or self.omc.isBlock(mo_type):
                comp_shell = ComponentShell()
                comp_shell.full_name = mo_type
                comp_shell.name = nth_component_info[1]
                comp_shell.description = nth_component_info[2]

                comp_shell.position['x'] = x_origin
                comp_shell.position['y'] = y_origin
                comp_shell.size['width'] = x_extent
                comp_shell.size['height'] = y_extent
                comp_shell.rotation = rotation
                comp_shell.flip_x = flip_x
                comp_shell.flip_y = flip_y

                comp_shell = self.extract_comp_shell_layout(
                    mo_type, comp_shell)

                assembly.component_shells[comp_shell.name] = comp_shell

        # Get internal connections
        for n in range(1, self.omc.getConnectionCount(modelica_uri) + 1):
            src, dst, v3 = self.omc.getNthConnection(modelica_uri, n)

            src_name, src_parent = self._get_connector_and_parent(src)
            dst_name, dst_parent = self._get_connector_and_parent(dst)

            connection = Connection()

            if src_name:
                connection.src_name = src_name
            if src_parent:
                connection.src_parent = src_parent
            if dst_name:
                connection.dst_name = dst_name
            if dst_parent:
                connection.dst_parent = dst_parent

            connection.path_points = self.omc.getNthConnectionPathPoints(
                modelica_uri, n)

            assembly.connections.append(connection)

        # Get inherited members
        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            mo_extend_class_name = self.omc.getNthInheritedClass(
                modelica_uri, i)
            assembly = self.extract_assembly_layout(mo_extend_class_name,
                                                    assembly)

        return assembly

    def extract_comp_shell_layout(self, modelica_uri, comp_shell):

        try:
            mo_components = self.omc.getComponents(modelica_uri)

        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                self.logger.warning(
                    'Could not parse OMC response for getComponents({0})'.
                    format(modelica_uri))
                raise ParsingException

        for n in range(1, len(mo_components) + 1):

            nth_component_info = self.omc.getNthComponent(modelica_uri, n)

            x_origin, y_origin, x_extent, y_extent, rotation, flip_x, flip_y = self.get_nth_comp_location(
                modelica_uri, n)

            mo_type = nth_component_info[0]

            if self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = nth_component_info[1]
                connector.description = nth_component_info[2]

                connector.relative_position['x'] = x_origin
                connector.relative_position['y'] = y_origin
                connector.size['width'] = x_extent
                connector.size['height'] = y_extent

                comp_shell.connectors.append(connector)

        # Get inherited members
        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            mo_extend_class_name = self.omc.getNthInheritedClass(
                modelica_uri, i)
            comp_shell = self.extract_comp_shell_layout(
                mo_extend_class_name, comp_shell)

        return comp_shell

    def scale_layout_for_webgme(self, assembly_layout, scale=5):

        if isinstance(assembly_layout, ComponentAssembly):
            x_offset = abs(assembly_layout.extent['x_min']) + 10
            y_offset = abs(assembly_layout.extent['y_max']) + 10

            for name, comp_shell in assembly_layout.component_shells.iteritems(
            ):
                left_edge = comp_shell.position[
                    'x'] - 0.5 * comp_shell.size['width']
                top_edge = comp_shell.position[
                    'y'] + 0.5 * comp_shell.size['height']

                comp_shell.position['x'] = scale * (left_edge + x_offset)
                comp_shell.position['y'] = scale * (y_offset - top_edge)
                comp_shell.size['width'] *= scale
                comp_shell.size['height'] *= scale

                for connector in comp_shell.connectors:
                    rel_x = connector.relative_position['x']
                    rel_y = connector.relative_position['y']

                    # handle rotations, so port relative positions are correct
                    if comp_shell.rotation != 0:
                        import math

                        cos_theta = math.cos(comp_shell.rotation * math.pi /
                                             180)
                        sin_theta = math.sin(comp_shell.rotation * math.pi /
                                             180)

                        x_theta = rel_x * cos_theta - rel_y * sin_theta
                        y_theta = rel_x * sin_theta + rel_y * cos_theta

                        rel_x = x_theta
                        rel_y = y_theta

                    if comp_shell.flip_x:
                        rel_x = -rel_x

                    if comp_shell.flip_y:
                        rel_y = -rel_y

                    connector.relative_position['x'] = (
                        (rel_x + 100) / 200) * comp_shell.size['width']
                    connector.relative_position['y'] = (
                        1 - (rel_y + 100) / 200) * comp_shell.size['height']

            for connector in assembly_layout.connectors:
                connector.relative_position['x'] = scale * (
                    connector.relative_position['x'] + x_offset)
                connector.relative_position['y'] = scale * (
                    -connector.relative_position['y'] + y_offset)

            for connection in assembly_layout.connections:
                for pp in connection.path_points:
                    pp['x'] = scale * (pp['x'] + x_offset)
                    pp['y'] = scale * (-pp['y'] + y_offset)

                    # first_path_point = connection.path_points[0]
                    # last_path_point = connection.path_points[-1]
                    #
                    # connection.path_points = list()
                    # connection.path_points.append(first_path_point)
                    # connection.path_points.append(last_path_point)

    def test_omc_get_components(self, modelica_uri):

        with open('omcTest.txt', 'w') as f_out:
            components = self.omc.getComponents(modelica_uri)
            n = 0

            for tu in components:
                msg = '{0}: {1} (index in getComponents)\r'.format(
                    components.index(tu), tu)
                f_out.write(msg)

                n = n + 1
                nthComponentInfo = self.omc.getNthComponent(modelica_uri, n)
                msg = '{0}: {1} (getNthComponent)\r'.format(
                    n, nthComponentInfo)
                f_out.write(msg)

    def _get_connector_and_parent(self, connected):
        pieces = connected.split('.')
        parent = ""
        if len(pieces) == 2:
            parent = pieces[0]
            connector = pieces[1]
        else:
            connector = connected

        return connector, parent
Exemplo n.º 26
0
class PackageExporter(object):

    def __init__(self, external_packages, load_MSL=True):

        self.externalPackagePaths = make_paths_safe_for_omc(external_packages)
        self.packageNames = list()
        self.failedLoadPackageNames = list()
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(self.externalPackagePaths))

        self.omc = OMCSession()
        self.loadPackages(self.externalPackagePaths, load_MSL=load_MSL)
        self.getClassDetails(self.packageNames)

    def parseArgument(self, externalPackages):
        # this will update self.externalPackagePaths and self.externalPackageNames

        for potentialPath in externalPackages:
            if os.path.exists(potentialPath):
                self.externalPackagePaths.append(potentialPath)

                if os.path.basename(potentialPath) == 'package.mo':     # check if the file name is 'package.mo'
                    packageDir = os.path.dirname(potentialPath)         # get the path to the last directory
                    packageName = os.path.basename(packageDir)          # get the name of the last directory
                    self.packageNames.append(packageName)       # store that name
                else:
                    file_path, file_extension = os.path.splitext(potentialPath)
                    if file_extension == '.mo':                         # make sure it is a '.mo' file
                        packageName = os.path.basename(file_path)       # get the name of the file
                        self.packageNames.append(packageName)   # store that name
            else:
                pass  # should log that this package path is invalid?

    def loadPackages(self, external_package_paths, load_MSL=True):

        if load_MSL:
            if self.omc.loadModel('Modelica') == True:
                comment = self.omc.getClassComment('Modelica')

                import re
                modelica_version_pattern = '.*Version ([\d\.]*)'
                regex_modelica_version = re.findall(modelica_version_pattern, comment)

                if regex_modelica_version[0]:
                    self.packageNames.append('Modelica ' + regex_modelica_version[0])
                else:
                    self.packageNames.append('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path) == True:                # make sure the file exists
                if os.path.basename(package_path) == 'package.mo':  # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(package_path)     # get the path to the last directory
                    package_name = os.path.basename(package_dir)    # get the name of the last directory (package_name)
                    if self.omc.loadFile(package_path) == True:     # try to load the package file
                        self.packageNames.append(package_name)  # log successful load
                        self.logger.info('Library loaded from : {0}'.format(package_path))
                    else:
                        self.failedLoadPackageNames.append("FAILED_" + package_name)    # log failure
                        self.logger.warning('Failed to load: {0}'.format(package_path))
                else:
                    file_path, file_extension = os.path.splitext(package_path)
                    if file_extension == '.mo':                             # make sure it is a '.mo' file
                        package_name = os.path.basename(file_path)          # get the name of the file
                        if self.omc.loadFile(package_path) == True:         # try to load the package file
                            self.packageNames.append(package_name)  # log successful load
                            self.logger.info('Library loaded from : {0}'.format(package_path))
                        else:
                            self.failedLoadPackageNames.append("FAILED_" + package_name)    # log failure
                            self.logger.warning('Failed to load: {0}'.format(package_path))
            else:
                file_path, file_extension = os.path.splitext(package_path)
                if file_extension == '.mo':                            # make sure it is a '.mo' file
                    package_name = os.path.basename(file_path)          # get the name of the file
                    if package_name == 'package':
                        package_name = os.path.basename(os.path.dirname(file_path))

                    self.failedLoadPackageNames.append(package_name)
                    self.logger.warning('Failed to load: {0}'.format(package_path))

    def getClassDetails(self, packageNames):

        for packageName in packageNames:
            if 'Modelica' in packageName:
                classNames = self.omc.getClassNames('Modelica', recursive=True, sort=True)
            else:
                classNames = self.omc.getClassNames(packageName, recursive=True, sort=True)

            for c_name in classNames:
                if (self.omc.isModel(c_name)) or (self.omc.isBlock(c_name)): # only blocks and models are exported
                    class_details = dict()
                    class_details['ComponentName'] = c_name
                    class_details['Description'] = self.omc.getClassComment(c_name)
                    self.classDetails.append(class_details)

    def json(self):
        json_result = dict()
        json_result['topLevelPackages'] = self.packageNames + self.failedLoadPackageNames
        json_result['classDetails'] = self.classDetails
        return json_result

    def exportToJson(self, filename):
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result
Exemplo n.º 27
0
class PackageExporter(object):
    def __init__(self, external_packages, load_MSL=True):

        self.externalPackagePaths = make_paths_safe_for_omc(external_packages)
        self.packageNames = list()
        self.failedLoadPackageNames = list()
        self.classDetails = list()

        self.logger = logging.getLogger('py_modelica_exporter.PackageExporter')
        self.logger.setLevel(logging.NOTSET)
        self.logger.info('Initializing PackageExporter({0})'.format(
            self.externalPackagePaths))

        self.omc = OMCSession()
        self.loadPackages(self.externalPackagePaths, load_MSL=load_MSL)
        self.getClassDetails(self.packageNames)

    def parseArgument(self, externalPackages):
        # this will update self.externalPackagePaths and self.externalPackageNames

        for potentialPath in externalPackages:
            if os.path.exists(potentialPath):
                self.externalPackagePaths.append(potentialPath)

                if os.path.basename(
                        potentialPath
                ) == 'package.mo':  # check if the file name is 'package.mo'
                    packageDir = os.path.dirname(
                        potentialPath)  # get the path to the last directory
                    packageName = os.path.basename(
                        packageDir)  # get the name of the last directory
                    self.packageNames.append(packageName)  # store that name
                else:
                    file_path, file_extension = os.path.splitext(potentialPath)
                    if file_extension == '.mo':  # make sure it is a '.mo' file
                        packageName = os.path.basename(
                            file_path)  # get the name of the file
                        self.packageNames.append(
                            packageName)  # store that name
            else:
                pass  # should log that this package path is invalid?

    def loadPackages(self, external_package_paths, load_MSL=True):

        if load_MSL:
            if self.omc.loadModel('Modelica') == True:
                comment = self.omc.getClassComment('Modelica')

                import re

                modelica_version_pattern = '.*Version ([\d\.]*)'
                regex_modelica_version = re.findall(modelica_version_pattern,
                                                    comment)

                if regex_modelica_version[0]:
                    self.packageNames.append('Modelica ' +
                                             regex_modelica_version[0])
                else:
                    self.packageNames.append('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(
                    package_path) == True:  # make sure the file exists
                if os.path.basename(
                        package_path
                ) == 'package.mo':  # check if the file name is 'package.mo'
                    package_dir = os.path.dirname(
                        package_path)  # get the path to the last directory
                    package_name = os.path.basename(
                        package_dir
                    )  # get the name of the last directory (package_name)
                    if self.omc.loadFile(
                            package_path
                    ) == True:  # try to load the package file
                        self.packageNames.append(
                            package_name)  # log successful load
                        self.logger.info(
                            'Library loaded from : {0}'.format(package_path))
                    else:
                        self.failedLoadPackageNames.append(
                            "FAILED_" + package_name)  # log failure
                        self.logger.warning(
                            'Failed to load: {0}'.format(package_path))
                else:
                    file_path, file_extension = os.path.splitext(package_path)
                    if file_extension == '.mo':  # make sure it is a '.mo' file
                        package_name = os.path.basename(
                            file_path)  # get the name of the file
                        if self.omc.loadFile(
                                package_path
                        ) == True:  # try to load the package file
                            self.packageNames.append(
                                package_name)  # log successful load
                            self.logger.info(
                                'Library loaded from : {0}'.format(
                                    package_path))
                        else:
                            self.failedLoadPackageNames.append(
                                "FAILED_" + package_name)  # log failure
                            self.logger.warning(
                                'Failed to load: {0}'.format(package_path))
            else:
                file_path, file_extension = os.path.splitext(package_path)
                if file_extension == '.mo':  # make sure it is a '.mo' file
                    package_name = os.path.basename(
                        file_path)  # get the name of the file
                    if package_name == 'package':
                        package_name = os.path.basename(
                            os.path.dirname(file_path))

                    self.failedLoadPackageNames.append(package_name)
                    self.logger.warning(
                        'Failed to load: {0}'.format(package_path))

    def getClassDetails(self, packageNames):

        for packageName in packageNames:
            if 'Modelica' in packageName:
                classNames = self.omc.getClassNames('Modelica',
                                                    recursive=True,
                                                    sort=True)
            else:
                classNames = self.omc.getClassNames(packageName,
                                                    recursive=True,
                                                    sort=True)

            for c_name in classNames:
                if (self.omc.isModel(c_name)) or (self.omc.isBlock(
                        c_name)):  # only blocks and models are exported
                    class_details = dict()
                    class_details['ComponentName'] = c_name
                    class_details['Description'] = self.omc.getClassComment(
                        c_name)
                    self.classDetails.append(class_details)

    def json(self):
        json_result = dict()
        json_result[
            'topLevelPackages'] = self.packageNames + self.failedLoadPackageNames
        json_result['classDetails'] = self.classDetails
        return json_result

    def exportToJson(self, filename):
        json_result = self.json()

        with open(filename, 'w') as f_p:
            json.dump(json_result, f_p, indent=4)

        return json_result