Exemple #1
0
def model_setup():

    rset = ResourceSet()
    resource = rset.get_resource(URI('metamodel.ecore'))
    mm_root = resource.contents[0]

    mm_root.nsURI = 'ghmde'
    mm_root.nsPrefix = 'model'
    mm_root.name = 'ghmde'

    rset.metamodel_registry[mm_root.nsURI] = mm_root

    print(mm_root.nsURI)

    MyMetamodel = DynamicEPackage(
        mm_root)  # We create a DynamicEPackage for the loaded root

    file_instance = MyMetamodel.File()

    print(file_instance)

    A = mm_root.getEClassifier('Model')

    # nuovo
    instance = A()

    dictionary = {}
    dictionary['model'] = instance
    dictionary['meta-model'] = MyMetamodel

    return dictionary
Exemple #2
0
def test_ecoreinheritance_loading():
    rset = ResourceSet()
    ecore_file = path.join('tests', 'xmi', 'xmi-tests', 'EcoreInheritance.ecore')
    resource = rset.get_resource(URI(ecore_file))
    root = DynamicEPackage(resource.contents[0])
    assert Ecore.EModelElement.eAnnotations in root.A.eAllStructuralFeatures()
    a = root.A()
    assert isinstance(a, Ecore.EModelElement)
    assert Ecore.EModelElement.eAnnotations in root.B.eAllStructuralFeatures()
    b = root.B()
    assert isinstance(b, Ecore.EModelElement)
    assert a.eAnnotations == {}
    assert b.eAnnotations == {}
    def __init__(self, name=None):
        # create a resourceSet that hold the contents of the esdl.ecore model and the instances we use/create
        self.rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        self.rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the esdl.ecore from the tmp folder
        esdl_model_resource = self.rset.get_resource(
            URI('tmp/esdl/esdl.ecore'))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        self.rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
        self.esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', self.esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        self.esdl.Item.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Carrier.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Geometry.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.id, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: '{}: ({})'.format(
            'QuantityAndUnitReference', EnergySystemHandler.attr_to_dict(x))
        self.esdl.KPI.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.ProfileElement.python_class.__repr__ = lambda x: 'ProfileElement ({})'.format(
            EnergySystemHandler.attr_to_dict(x))

        if name:
            self.name = name
            self.load_energy_system(name)
Exemple #4
0
def test_dynamic_removal_eclasses(complexmm):
    ComplexMM = DynamicEPackage(complexmm)
    assert ComplexMM.Root

    complexmm.eClassifiers.remove(ComplexMM.Root)
    with pytest.raises(AttributeError):
        ComplexMM.Root

    assert ComplexMM.A
    complexmm.eClassifiers[0].delete()
    with pytest.raises(AttributeError):
        ComplexMM.A
def get_infrastructure_model_access(ecore_uri='./infrastructure.ecore',
                                    http_uri=False):
    """Return handler to instanciate classes of a metamodel."""
    rset = ResourceSet()
    uri = URI(ecore_uri)
    if http_uri:
        uri = HttpURI(ecore_uri)

    resource = rset.get_resources(uri)
    mm_root = resource.contents[0]  # We get the root (an EPackage here)

    return DynamicEPackage(mm_root)
Exemple #6
0
    def load_energy_system(self, name):
        # create a resourceSet that hold the contents of the esdl.ecore model and the instances we use/create
        rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the lastest esdl.ecore from github
        esdl_model_resource = rset.get_resource(
            HttpURI(
                'https://raw.githubusercontent.com/EnergyTransition/ESDL/master/esdl/model/esdl.ecore'
            ))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
        esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        esdl.Item.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.Carrier.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.Geometry.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.id, EnergySystemHandler.attr_to_dict(x))
        esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: '{}: ({})'.format(
            'QuantityAndUnitReference', EnergySystemHandler.attr_to_dict(x))
        esdl.KPI.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.ProfileElement.python_class.__repr__ = lambda x: 'ProfileElement ({})'.format(
            EnergySystemHandler.attr_to_dict(x))

        # load the ESDL file
        resource = rset.get_resource(URI(name))
        es = resource.contents[0]
        # At this point, the model instance is loaded!

        # get notifications of changes in the EnergySystem model
        #observer = PrintNotification(es)
        #observer2 = PrintNotification(es.instance[0].area)

        # also return the esdlm and rset reference, so we can create esdl classes and store them as strings
        return es, resource, esdl, rset
def load_metamodel():
    """
    Load and return a statechart metamodel and its resource set.

    :return: a tuple (metamodel, resource set)
    """
    filepath = os.path.join(os.path.dirname(__file__), 'amola.ecore')

    rset = ResourceSet()
    resource = rset.get_resource(URI(filepath))
    metamodel = resource.contents[0]
    rset.metamodel_registry[metamodel.nsURI] = metamodel

    return DynamicEPackage(metamodel), rset
Exemple #8
0
def test_xmi_save_none_value_for_containement(tmpdir):
    rset = ResourceSet()
    ecore_path = os.path.join('tests', 'xmi', 'xmi-tests', 'root.ecore')
    resource = rset.get_resource(ecore_path)
    root = resource.contents[0]
    rset.metamodel_registry[root.nsURI] = root
    mm = DynamicEPackage(root)

    a = mm.A()
    a.b = None

    f = tmpdir.mkdir('pyecore-tmp').join('none_in_containment.xmi')
    resource = rset.create_resource(URI(str(f)))
    resource.append(a)
    resource.save()

    rset = ResourceSet()
    rset.metamodel_registry[root.nsURI] = root
    resource = rset.get_resource(URI(str(f)))

    assert resource.contents[0] is not None
    assert resource.contents[0].b is None
    assert len(resource.contents[0]._isset) == 0

    # We save with the explicit option fo saving none values
    resource = rset.create_resource(URI(str(f)))
    resource.append(a)
    resource.save()
    resource.save(options={XMIOptions.SERIALIZE_DEFAULT_VALUES: True})

    rset = ResourceSet()
    rset.metamodel_registry[root.nsURI] = root
    resource = rset.get_resource(URI(str(f)))

    assert resource.contents[0] is not None
    assert resource.contents[0].b is None
    assert len(resource.contents[0]._isset) == 1
Exemple #9
0
def test_dynamic_addition_eclasses(complexmm):
    ComplexMM = DynamicEPackage(complexmm)
    E = EClass('E')
    complexmm.eClassifiers.append(E)
    assert ComplexMM.E

    F = EClass('F')
    complexmm.eSubpackages[0].eClassifiers.append(F)
    assert ComplexMM.inner.F

    G = EClass('G')
    H = EClass('H')
    complexmm.eClassifiers.extend([G, H])
    assert ComplexMM.G
    assert ComplexMM.H
Exemple #10
0
def load():

    #return model_root
    rset = ResourceSet()

    resource = rset.get_resource(URI('metamodel.ecore'))
    mm_root = resource.contents[0]
    rset.metamodel_registry[mm_root.nsURI] = mm_root

    resource = rset.get_resource(URI('model.xmi'))
    model_root = resource.contents[0]
    MyMetamodel = DynamicEPackage(mm_root)


#main_model_creator() #debug
Exemple #11
0
def get_energysystem_from_esdl(fname):
    rset = ResourceSet()

    # Read the lastest esdl.ecore from github
    resource = rset.get_resource(
        HttpURI(
            'https://raw.githubusercontent.com/EnergyTransition/ESDL/master/esdl/model/esdl.ecore'
        ))
    esdl_model = resource.contents[0]
    rset.metamodel_registry[esdl_model.nsURI] = esdl_model

    # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
    esdl = DynamicEPackage(esdl_model)
    resource = rset.get_resource(URI(fname))
    return resource.contents[0]
Exemple #12
0
def simplemm():
    A = EClass('A')
    B = EClass('B')
    A.eStructuralFeatures.append(EAttribute('name', EString))
    A.eStructuralFeatures.append(EAttribute('number', EInt))
    A.eStructuralFeatures.append(EReference('b', B))
    A.eStructuralFeatures.append(
        EAttribute('names', EString, upper=-1, unique=False))
    A.eStructuralFeatures.append(
        EAttribute('ints', EInt, upper=-1, unique=False))
    A.eStructuralFeatures.append(
        EReference('inners', B, upper=-1, unique=False, containment=True))
    A.eStructuralFeatures.append(EReference('cols', B, upper=-1, unique=False))
    pack = EPackage('pack', nsURI='http://pack/1.0', nsPrefix='pack')
    pack.eClassifiers.extend([A, B])
    return DynamicEPackage(pack)
Exemple #13
0
def mm():
    Root = EClass('Root')
    A = EClass('A')
    B = EClass('B')
    Root.eStructuralFeatures.append(
        EReference('a_s', A, upper=-1, containment=True))
    Root.eStructuralFeatures.append(
        EReference('bs', B, upper=-1, containment=True))
    A.eStructuralFeatures.append(EAttribute('name', EString))
    simple_tob = EReference('simple_tob', eType=B, containment=True)
    A.eStructuralFeatures.append(simple_tob)
    A.eStructuralFeatures.append(
        EReference('many_tob', eType=B, containment=True, upper=-1))
    B.eStructuralFeatures.append(EReference('toa', A))
    B.eStructuralFeatures.append(
        EReference('inverseA', A, eOpposite=simple_tob))
    package = EPackage(name='package')
    package.eClassifiers.extend([Root, A, B])
    return DynamicEPackage(package)
    def _init_metamodel(self):
            self.rset = ResourceSet()

            # Assign files with the .esdl extension to the XMLResource instead of default XMI
            self.rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

            # Read esdl.ecore as meta model
            logger.info('Initalizing ESDL metamodel for documentation from {}'.format(self.esdlEcoreFile))
            mm_uri = URI(self.esdlEcoreFile)
            if self.esdlEcoreFile[:4] == 'http':
                mm_uri = HttpURI(self.esdlEcoreFile)
            esdl_model_resource = self.rset.get_resource(mm_uri)

            esdl_model = esdl_model_resource.contents[0]
            self.esdl_model = esdl_model
            # logger.debug('Namespace: {}'.format(esdl_model.nsURI))
            self.rset.metamodel_registry[esdl_model.nsURI] = esdl_model

            # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
            self.esdl = DynamicEPackage(esdl_model)
            logger.info("Initialized ESDL version {}".format(self.get_esdl_version()))
Exemple #15
0
def test_xmi_with_iD_attribute(tmpdir):
    mm_file = os.path.join('tests', 'xmi', 'xmi-tests', 'A.ecore')
    rset = ResourceSet()
    mm = rset.get_resource(mm_file).contents[0]
    rset.metamodel_registry[mm.nsURI] = mm

    mm_dyn = DynamicEPackage(mm)
    root = mm_dyn.Root()
    a = mm_dyn.A()
    b = mm_dyn.B()
    b.nameID = 'uniqueNameForB'
    a.tob = b

    root.a.append(a)
    root.b.append(b)

    localdir = tmpdir.mkdir('pyecore-tmp')
    f1 = localdir.join('model_iD_simple.xmi')
    resource = rset.create_resource(str(f1))
    resource.append(root)
    resource.save()

    root2 = mm_dyn.Root()
    root2.b.append(b)

    f2 = localdir.join('model_iD.xmi')
    f3 = localdir.join('model_iD.xmi')
    resource = rset.create_resource(str(f2))
    resource2 = rset.create_resource(str(f3))

    resource.append(root)
    resource2.append(root2)

    resource2.save()
    resource.save()

    rset = ResourceSet()
    rset.metamodel_registry[mm.nsURI] = mm
    rset.get_resource(str(f1))
    rset.get_resource(str(f2))
    rset.get_resource(str(f3))
Exemple #16
0
def test_static_init_dynamic_epackage_bad_value(generated_library):
    with pytest.raises(Ecore.BadValueError):
        DynamicEPackage(generated_library)
def test_static_init_dynamicEPackage_bad_value():
    with pytest.raises(BadValueError):
        DynamicEPackage(library)
def test_static_init_dynamicEPackage_from_static_epackage():
    dyn = DynamicEPackage(library)
    assert library.Writer.eClass is dyn.Writer
Exemple #19
0
 def importMetaModel(rset, filename):
     pkg = rset.get_resource(URI(filename)).contents[0]
     register(rset, pkg)
     return DynamicEPackage(pkg)
Exemple #20
0
class EnergySystemHandler:
    """Class to handle (load, read, and update) an ESDL Energy System"""

    # TODO: CAN WE USE THE THING FROM THE VENDOR MODULE?
    # TODO: extract this to a simple module (NO CLASS) and just import the (self.)esdl
    # somewhere and define all the lookup there - because the lookup does not need
    # this whole class right?? just the self.esdl and that has nothing to do with the
    # actual esdl??
    def __init__(self, name=None):
        # create a resourceSet that hold the contents of the esdl.ecore model and the
        # instances we use/create
        self.rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        self.rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the esdl.ecore from the tmp folder
        esdl_model_resource = self.rset.get_resource(URI('vendor/esdl/esdl.ecore'))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        self.rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to
        # build Energy Systems
        self.esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', self.esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects
        # (includes all Assets and EnergyAssets)
        # self.esdl.Item.python_class.__repr__ = lambda x: format_repr(x.name, x)
        self.esdl.Carrier.python_class.__repr__ = lambda x: format_repr(x.name, x)
        self.esdl.Geometry.python_class.__repr__ = lambda x: format_repr(x.name, x)
        self.esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: format_repr(x.id, x)
        self.esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: format_repr('QuantityAndUnitReference', x)
        self.esdl.KPI.python_class.__repr__ = lambda x: format_repr(x.name, x)
        self.esdl.ProfileElement.python_class.__repr__ = lambda x: format_repr('ProfileElement', x)

        if name:
            self.name = name
            self.load_energy_system(name)

    @staticmethod
    def generate_uuid():
        ''' Creates a uuid: useful for generating unique IDs '''
        return str(uuid.uuid4())


    def load_energy_system(self, name):
        ''' Load an ESDL file '''
        self.resource = self.rset.get_resource(URI(name))
        self.es = self.resource.contents[0]


    def add_data_source(self, name, description):
        ''' Adds a data_source to the ESDL containing a name and description'''
        data_source = self.esdl.DataSource(id='data_source', name=name, description=description)
        self.es.dataSource = data_source


    def get_quantity_and_units(self):
        '''
        Returns quantity and units

        Add energy system information to the energy system if it is not there yet
        Energy System information can be used to globally define the quantity and units of this
        system, instead of defining them manually per KPI in each area: this fosters reuse
        (but is not necessary)
        '''
        if not self.get_by_id('energy_system_information') is None:
            return self.get_by_id('quantity_and_units')

        self.__add_energy_system_information()
        q_and_u = self.esdl.QuantityAndUnits(id='quantity_and_units')
        self.es.energySystemInformation.quantityAndUnits = q_and_u

        return q_and_u

    def __add_energy_system_information(self):
        '''Add Energy System Information'''
        esi = self.esdl.EnergySystemInformation(id='energy_system_information')
        self.es.energySystemInformation = esi


    def add_measures(self):
        ''' Add Measures object to Energy System '''
        # Create new Measures object
        measures = self.esdl.Measures(id='measures')
        self.es.instance[0].area.measures = measures


    def append_measure(self, measure):
        ''' Append measure to Measures object '''
        self.es.instance[0].area.measures.measure.append(measure)


    def append_asset_to_measure(self, measure, asset):
        ''' Append asset measure to Measures object '''
        measure.asset.append(asset)
        self.es.instance[0].area.measures.measure.append(measure)

    ######## KPIs ########

    def add_kpis(self):
        ''' Add KPIs object to Energy System '''
        # create new KPIs object
        kpis = self.esdl.KPIs(id='kpis', description='KPIs')
        self.es.instance[0].area.KPIs = kpis


    def create_kpi(self, kpi_type, kpi_id, name, q_and_u):
        ''' Create new KPI object '''
        return getattr(self.esdl, kpi_type)(
            id=kpi_id,
            name=name,
            quantityAndUnit=q_and_u
        )


    def add_kpi(self, kpi):
        ''' Add KPI to KPIs object '''
        self.es.instance[0].area.KPIs.kpi.append(kpi)


    def get_kpi_by_id(self, kpi_id):
        ''' Returns a specific KPI by id, see also get_by_id for a faster method '''
        for kpi in self.es.instance[0].area.KPIs.kpi:
            if kpi.id == kpi_id:
                return kpi

        return None


    def get_kpi_by_name(self, name):
        ''' Returns a specific KPI by name '''
        for kpi in self.es.instance[0].area.KPIs.kpi:
            if kpi.name == name:
                return kpi

        return None

    ######### LOOKUP ##########

    def get_by_id(self, object_id):
        '''
        Using this function you can query for objects by ID
        After loading an ESDL-file, all objects that have an ID defines are stored in
        resource.uuid_dict automatically
        Note: If you add things later to the resource, it won't be added automatically to
        this dictionary though. Use get_by_id_slow() for that
        '''
        if object_id in self.resource.uuid_dict:
            return self.resource.uuid_dict[object_id]

        return None


    def get_by_id_slow(self, object_id):
        '''
        This function iterates over all the contents of the Energy System and is much slower
        than get_by_id()
        '''
        for child in self.es.eAllContents():
            if hasattr(child, 'id') and child.id == object_id:
                return child

        return None

    def get_assets_of_type(self, esdl_type, area=None):
        '''Get a list of assets of a specific ESDL type in the specified area or asset'''
        assets = area.asset if not area is None else self.es.instance[0].area.asset
        esdl_asset = getattr(self.esdl, esdl_type)

        return [asset for asset in assets if isinstance(asset, esdl_asset)]

    def has_assets_of_type(self, esdl_type, area=None):
        ''' Boolean, see get_assets_of_type '''
        assets = area.asset if not area is None else self.es.instance[0].area.asset

        try:
            next((asset for asset in assets if isinstance(asset, getattr(self.esdl, esdl_type))))
            return True
        except StopIteration:
            return False

    def get_assets_of_type_and_attribute_value(self, esdl_type, area, attr, val):
        '''
        Returns a list of assets of a specific ESDL type in the specified area or asset
        filtered by a specified attribute-value combination

        Params:
            esdl_type (str): The type of asset
            area (esdl.Area): The area that contains the assets to be filtered
            attr (str): The attribute that should be evaluated
            val (str): The value that the attribute should have

        Returns:
            list[esdl.Asset]
        '''
        esdl_asset = getattr(self.esdl, esdl_type)

        return [asset for asset in area.asset
                if isinstance(asset, esdl_asset) and str(getattr(asset, attr)) == val]

    def has_assets_of_type_and_attribute_value(self, esdl_type, area, attr, val):
        '''
        Works like get_of_type_and_attribute_value, but only checks if the first item
        can be generated

        Params:
            esdl_type (str): The type of asset
            area (esdl.Area): The area that contains the assets to be filtered
            attr (str): The attribute that should be evaluated
            val (str): The value that the attribute should have

        Returns:
            bool
        '''
        try:
            next((asset for asset in area.asset
                if isinstance(asset, getattr(self.esdl, esdl_type))
                and str(getattr(asset, attr)) == val))
            return True
        except StopIteration:
            return False

    def get_potentials_of_type(self, esdl_type):
        ''' Get a list of potentials of a specific ESDL type in the main instance's area '''
        potentials = []

        for current_potential in self.es.instance[0].area.potential:
            if isinstance(current_potential, esdl_type):
                potentials.append(current_potential)
        return potentials

    def get_all_instances_of_type(self, esdl_type):
        '''
        Returns a generator of all assets or potentials of a specific type.
        Not only the ones defined in the main Instance's Area e.g. QuantityAndUnits can be
        defined in the KPI of an Area or in the EnergySystemInformation object this
        function returns all of them at once.

        Params:
            esdl_type (str): The type of asset

        Returns:
            generator of assets or potentials
        '''
        yield from getattr(self.esdl, esdl_type).allInstances(resources=(self.resource,))

    def get_all_instances_of_type_and_attribute_value(self, esdl_type, attr, val):
        '''
        Returns a generator of all assets or potentials of a specific type.
        Not only the ones defined in the main Instance's Area e.g. QuantityAndUnits can be
        defined in the KPI of an Area or in the EnergySystemInformation object this
        function returns all of them at once.

        The assets are then filtered for a specific attribute-value combination

        Params:
            esdl_type (str): The type of asset
            attr (str): The attribute that should be evaluated
            val (str): The value that the attribute should have

        Returns:
            generator of assets or potentials
        '''
        yield from (inst for inst in self.get_all_instances_of_type(esdl_type)
                if str(getattr(inst, attr)) == val)

    def get_all_instances_of_type_and_sector(self, esdl_type, sector_id):
        '''
        Returns a generator of all assets or potentials of a specific type.
        Not only the ones defined in the main Instance's Area e.g. QuantityAndUnits can be
        defined in the KPI of an Area or in the EnergySystemInformation object this
        function returns all of them at once.

        The assets are then filtered for a specific combination on an attribute and it's ID.

        Params:
            esdl_type (str): The type of asset
            sector_id (str | list[str]): The value of the sectors id, e.g. REF for Refineries

        Returns:
            generator of assets or potentials
        '''
        yield from (inst for inst in self.get_all_instances_of_type(esdl_type)
                if self.in_sector(inst, sector_id))

    def get_all_instances_of_type_and_carrier(self, esdl_type, carrier_id):
        '''
        Returns a generator of all assets or potentials of a specific type.
        Not only the ones defined in the main Instance's Area e.g. QuantityAndUnits can be
        defined in the KPI of an Area or in the EnergySystemInformation object this
        function returns all of them at once.

        The assets are then filtered for having the specified carrier as input.

        Params:
            esdl_type (str): The type of asset
            carrier_id (str | list[str]): The value of the carriers id, e.g. HTLH for network gas

        Returns:
            generator of assets or potentials
        '''
        yield from (inst for inst in self.get_all_instances_of_type(esdl_type)
                if self.has_carrier(inst, carrier_id))

    def get_all_instances_of_type_carrier_and_sector(self, esdl_type, sector_id, carrier_id):
        '''
        Returns a generator of all assets or potentials of a specific type.
        Not only the ones defined in the main Instance's Area e.g. QuantityAndUnits can be
        defined in the KPI of an Area or in the EnergySystemInformation object this
        function returns all of them at once.

        The assets are then filtered for given sectors and carriers.

        Params:
            esdl_type (str): The type of asset
            sector_id (str | list[str]): The value of the sectors id, e.g. REF for Refineries
            carrier_id (str | list[str]): The value of the carriers id, e.g. HTLH for network gas

        Returns:
            generator of assets or potentials
        '''
        yield from (inst for inst in self.get_all_instances_of_type(esdl_type)
                if self.in_sector(inst, sector_id) and self.has_carrier(inst, carrier_id))

    def has_carrier(self, asset, carrier_id):
        '''Carrier id may also be a list'''
        for port in asset.port:
            if not isinstance(port, self.esdl.InPort): continue

            if port.carrier.id == carrier_id:
                return True

            if isinstance(carrier_id, list) and port.carrier.id in carrier_id:
                return True

        return False

    def in_sector(self, asset, sector_id):
        '''
        Returns Boolean depending on if the asset is in the sector or not. Also checks if the assets
        parents have a sector set, if 'sector' is not an attribute of the asset directly.

        Params:
            asset (pyecore.ecore.Object): The asset that is to be checked.
            sector_id (str | list[str]): The id of the sector, e.g. REF for Refineries.

        Returns:
            bool
        '''
        if asset.sector and equal_or_in(asset.sector.id, sector_id):
            return True

        for port in asset.port:
            if not isinstance(port, self.esdl.OutPort): continue

            for connection in port.connectedTo:
                if not getattr(connection.energyasset, 'sector', None): continue

                if equal_or_in(connection.energyasset.sector.id, sector_id):
                    return True

        return False


    def get_asset_attribute(self, esdl_type, attr, area=None):
        '''
        Create a readable list of the attributes of an ESDL class
        Scoped to a specific area, if one is given

        Returns:
            list[dict] with formatted assets
        '''
        assets = area.asset if not area is None else self.es.instance[0].area.asset

        return [self.__format_asset(ass, attr) for ass in assets if isinstance(ass, esdl_type)]


    def __format_asset(self, current_asset, attribute):
        return {
            'name': current_asset.name,  # name
            'attribute': {
                'key': attribute,
                'value': getattr(current_asset, attribute)
            }
        }

    ######### LOAD & SAVE ##########

    def save(self, filename):
        ''' Saves the energy system to a file '''
        uri = URI(filename)
        fileresource = self.rset.create_resource(uri)
        # add the current energy system
        fileresource.append(self.es)
        # save the resource
        fileresource.save()
        # return the resource
        return fileresource


    def get_as_string(self):
        '''
        Returns the current energy system as an XML string

        Note: does not change the 'active' resource so save() will still save as a file
        '''
        # to use strings as resources, we simulate a string as being a file
        uri = StringURI('tmp/anyname.esdl')
        # create the string resource
        stringresource = self.rset.create_resource(uri)
        # add the current energy system
        stringresource.append(self.es)
        # save the resource
        stringresource.save()
        # remove the temporary resource in the resource set
        self.rset.remove_resource(stringresource)
        # return the string
        return uri.getvalue()


    def get_as_stream(self):
        '''
        Returns the current energy system as a BytesIO stream
        '''
        # to use strings as resources, we simulate a string as being a file
        uri = StringURI('tmp/anyname.esdl')
        # create the string resource
        stringresource = self.rset.create_resource(uri)
        # add the current energy system
        stringresource.append(self.es)
        # save the resource
        stringresource.save()
        # remove the temporary resource in the resource set
        self.rset.remove_resource(stringresource)
        # return the string
        return uri.get_stream()

    @classmethod
    def from_string(cls, esdl_string):
        '''
        Create a new EnergySystemHandler based on an EnergySystem esdl_string (using UTF-8 encoding)
        '''
        try:
            handler = EnergySystemHandler()
            handler.resource = handler.rset.create_resource(
                StringURI('loadfromstring', esdl_string)
            )
            handler.resource.load()
            handler.es = handler.resource.contents[0]
            return handler
        except Exception as exception:
            raise EnergysystemParseError('ESDL could not be parsed') from exception
def test_static_init_dynamic_epackage(generated_library):
    package = DynamicEPackage(generated_library)
    assert package.Book is not None
class EnergySystemHandler:
    """Class to handle (load, read, and update) an ESDL Energy System"""
    def __init__(self, name=None):
        # create a resourceSet that hold the contents of the esdl.ecore model and the instances we use/create
        self.rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        self.rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the esdl.ecore from the tmp folder
        esdl_model_resource = self.rset.get_resource(
            URI('tmp/esdl/esdl.ecore'))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        self.rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
        self.esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', self.esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        self.esdl.Item.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Carrier.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Geometry.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.id, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: '{}: ({})'.format(
            'QuantityAndUnitReference', EnergySystemHandler.attr_to_dict(x))
        self.esdl.KPI.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.ProfileElement.python_class.__repr__ = lambda x: 'ProfileElement ({})'.format(
            EnergySystemHandler.attr_to_dict(x))

        if name:
            self.name = name
            self.load_energy_system(name)

    # Creates a dict of all the attributes of an ESDL object
    @staticmethod
    def attr_to_dict(esdl_object):
        d = dict()
        d['esdlType'] = esdl_object.eClass.name
        for attr in dir(esdl_object):
            attr_value = esdl_object.eGet(attr)
            if attr_value is not None:
                d[attr] = attr_value
        return d

    # Creates a uuid: useful for generating unique IDs
    @staticmethod
    def generate_uuid():
        return str(uuid.uuid4())

    def load_energy_system(self, name):
        # load the ESDL file
        self.resource = self.rset.get_resource(URI(name))
        self.es = self.resource.contents[0]

    # Add Energy System Information
    def add_energy_system_information(self):
        esi = self.esdl.EnergySystemInformation(id='energy_system_information')
        self.es.energySystemInformation = esi

    def add_data_source(self, name, description):
        data_source = self.esdl.DataSource(id='data_source',
                                           name=name,
                                           description=description)
        self.es.dataSource = data_source

    # Add energy system information to the energy system if it is not there yet
    # Energy System information can be used to globally define the quantity and units of this system,
    # instead of defining them manually per KPI in each area: this fosters reuse (but is not necessary)
    def get_quantity_and_units(self):
        q_and_u = None

        if self.get_by_id('energy_system_information') is None:
            self.add_energy_system_information()

            q_and_u = self.esdl.QuantityAndUnits(id='quantity_and_units')
            self.es.energySystemInformation.quantityAndUnits = q_and_u

        else:
            q_and_u = self.get_by_id('quantity_and_units')

        return q_and_u

    # Add Measures object to Energy System
    def add_measures(self):
        # Create new Measures object
        measures = self.esdl.Measures(id='measures')
        self.es.instance[0].area.measures = measures

    # Append measure to Measures object
    def append_measure(self, measure):
        self.es.instance[0].area.measures.measure.append(measure)

    # Append asset measure to Measures object
    def append_asset_to_measure(self, measure, asset):
        measure.asset.append(asset)
        self.es.instance[0].area.measures.measure.append(measure)

    # Add KPIs object to Energy System
    def add_kpis(self):
        # create new KPIs object
        kpis = self.esdl.KPIs(id='kpis', description='KPIs')
        self.es.instance[0].area.KPIs = kpis

    # Create new KPI object
    def create_kpi(self, kpi_type, kpi_id, name, q_and_u):
        return getattr(self.esdl, kpi_type)(id=kpi_id,
                                            name=name,
                                            quantityAndUnit=q_and_u)

    # Add KPI to KPIs object
    def add_kpi(self, kpi):
        self.es.instance[0].area.KPIs.kpi.append(kpi)

    # Get a list of assets of a specific ESDL type in the main instance's area
    # def get_assets_of_type(self, esdl_type):
    #     assets = []
    #
    #     for current_asset in self.es.instance[0].area.asset:
    #         if isinstance(current_asset, esdl_type):
    #             assets.append(current_asset)
    #     return assets

    # Get a list of assets of a specific ESDL type in the specified area or asset
    def get_assets_of_type(self, area, esdl_type):
        assets = []

        for current_asset in area.asset:
            if isinstance(current_asset, esdl_type):
                assets.append(current_asset)

        return assets

    # Get a list of assets of a specific ESDL type in the specified area or asset
    # filtered by a specified attribute-value combination
    def get_assets_of_type_and_attribute_value(self, area, esdl_type,
                                               attribute, value):
        assets = []

        for current_asset in area.asset:
            if isinstance(current_asset, esdl_type):
                if str(getattr(current_asset, attribute)) == value:
                    assets.append(current_asset)
        return assets

    # Get a list of potentials of a specific ESDL type in the main instance's area
    def get_potentials_of_type(self, esdl_type):
        potentials = []

        for current_potential in self.es.instance[0].area.potential:
            if isinstance(current_potential, esdl_type):
                potentials.append(current_potential)
        return potentials

    # returns a generator of all assets or potentials of a specific type. Not only the ones defined in the main Instance's Area
    # e.g. QuantityAndUnits can be defined in the KPI of an Area or in the EnergySystemInformation object
    # this function returns all of them at once
    def get_all_instances_of_type(self, esdl_type):
        return esdl_type.allInstances()

    # Using this function you can query for objects by ID
    # After loading an ESDL-file, all objects that have an ID defines are stored in resource.uuid_dict automatically
    # Note: If you add things later to the resource, it won't be added automatically to this dictionary though.
    # Use get_by_id_slow() for that
    def get_by_id(self, id):
        if id in self.resource.uuid_dict:
            return self.resource.uuid_dict[id]
        else:
            return None

    # This function iterates over all the contents of the Energy System and is much slower than get_by_id()
    def get_by_id_slow(self, id):
        for child in self.es.eAllContents():
            if hasattr(child, 'id'):
                if child.id == id:
                    return child

    # create a readable list of the attributes of an ESDL class
    def get_asset_attribute(self, esdl_type, attribute):
        asset_data = []

        for current_asset in self.es.instance[0].area.asset:

            if isinstance(current_asset, esdl_type):
                asset_data.append({
                    'name': current_asset.name,  # name
                    'attribute': {
                        'key': attribute,
                        'value': getattr(current_asset, attribute)
                    }
                })

        return asset_data

    # create a readable list of the attributes of an ESDL class
    # (scoped to a specific area)
    def get_asset_attribute(self, area, esdl_type, attribute):
        asset_data = []

        for current_asset in area.asset:

            if isinstance(current_asset, esdl_type):
                asset_data.append({
                    'name': current_asset.name,  # name
                    'attribute': {
                        'key': attribute,
                        'value': getattr(current_asset, attribute)
                    }
                })

        return asset_data

    # returns a specific KPI by id, see also get_by_id for a faster method
    def get_kpi_by_id(self, id):
        for kpi in self.es.instance[0].area.KPIs.kpi:
            if kpi.id == id:
                return kpi

    # returns a specific KPI by name
    def get_kpi_by_name(self, name):
        for kpi in self.es.instance[0].area.KPIs.kpi:
            if kpi.name == name:
                return kpi

    # save the resource
    def save(self, filename):
        uri = URI(filename)
        fileresource = self.rset.create_resource(uri)
        # add the current energy system
        fileresource.append(self.es)
        # save the resource
        fileresource.save()
        # return the resource
        return fileresource

    # get the energy system as a XML String
    # does not change the 'active' resource
    # so save() will still save as a file
    def get_as_string(self):
        # to use strings as resources, we simulate a string as being a file
        uri = StringURI('tmp/anyname.esdl')
        # create the string resource
        stringresource = self.rset.create_resource(uri)
        # add the current energy system
        stringresource.append(self.es)
        # save the resource
        stringresource.save()
        # remove the temporary resource in the resource set
        self.rset.remove_resource(stringresource)
        # return the string
        return uri.getvalue()

    def get_as_stream(self):
        # to use strings as resources, we simulate a string as being a file
        uri = StringURI('tmp/anyname.esdl')
        # create the string resource
        stringresource = self.rset.create_resource(uri)
        # add the current energy system
        stringresource.append(self.es)
        # save the resource
        stringresource.save()
        # remove the temporary resource in the resource set
        self.rset.remove_resource(stringresource)
        # return the string
        return uri.get_stream()

    # load an EnergySystem from a string (using UTF-8 encoding)
    def load_from_string(self, string):
        uri = StringURI('loadfromstring', string)
        # this overrides the current loaded resource
        self.resource = self.rset.create_resource(uri)
        self.resource.load()
        self.es = self.resource.contents[0]
        return self.es
Exemple #23
0
def test_dynamic_access_eclasses(simplemm):
    SimpleMM = DynamicEPackage(simplemm)
    assert SimpleMM.A
    assert SimpleMM.B
Exemple #24
0
def test_dynamic_access_innerpackage(complexmm):
    ComplexMM = DynamicEPackage(complexmm)
    assert ComplexMM.A
    assert ComplexMM.B
    assert ComplexMM.inner.C
    assert ComplexMM.inner.D
Exemple #25
0
from pyecore.resources.resource import HttpURI, ResourceSet
from pyecore.utils import DynamicEPackage
from pyecore.ecore import EcoreUtils
import pyecore.behavior as behavior

# Load metamodel
rset = ResourceSet()
uri = HttpURI('https://raw.githubusercontent.com/gemoc/ale-lang/master/'
              'examples/minifsm/model/MiniFsm.ecore')
package_root = rset.get_resource(uri).contents[0]
rset.metamodel_registry[package_root.nsURI] = package_root

fsm = DynamicEPackage(package_root)


# Code for each overridden/added method
@fsm.Transition.behavior
def is_activated(self):
    return (self.fsm.currentEvent == self.event
            and self.incoming == self.fsm.currentState)


@fsm.State.behavior
def execute(self):
    print('Execute', self.name)


@fsm.FSM.behavior
def handle(self, event):
    print('Handle', event)
    self.currentEvent = event