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
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)
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)
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
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
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
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
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]
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)
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()))
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))
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
def importMetaModel(rset, filename): pkg = rset.get_resource(URI(filename)).contents[0] register(rset, pkg) return DynamicEPackage(pkg)
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
def test_dynamic_access_eclasses(simplemm): SimpleMM = DynamicEPackage(simplemm) assert SimpleMM.A assert SimpleMM.B
def test_dynamic_access_innerpackage(complexmm): ComplexMM = DynamicEPackage(complexmm) assert ComplexMM.A assert ComplexMM.B assert ComplexMM.inner.C assert ComplexMM.inner.D
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