componentregistry.py (6038B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\spacecomponents\common\componentregistry.py 2 from __future__ import absolute_import 3 from collections import defaultdict 4 from ccpProfile import TimedFunction 5 from .componentmessenger import ComponentMessenger 6 from eveexceptions.exceptionEater import ExceptionEater 7 from spacecomponents.common.componentclass import ComponentClass 8 from spacecomponents.common.data import get_space_component_names_for_type, get_space_component_for_type 9 10 class UnregisteredComponentError(Exception): 11 pass 12 13 14 class ComponentInstanceAlreadyExists(Exception): 15 pass 16 17 18 def ExportCall(func): 19 func.isExportedComponentCall = True 20 return func 21 22 23 class ComponentRegistry(object): 24 asyncFuncs = None 25 26 def __init__(self, asyncFuncs, eventLogger, componentClassTypes, typeIDToClassMapping): 27 self.asyncFuncs = asyncFuncs 28 self.eventLogger = eventLogger 29 self.componentClassTypes = {componentName:ComponentClass(componentName, componentClass) for componentName, componentClass in componentClassTypes.iteritems()} 30 self.componentNames = tuple(self.componentClassTypes.keys()) 31 self.typeIDToClassMapping = typeIDToClassMapping 32 self.itemIDToComponentInstances = {} 33 self.componentNameToItemIDs = defaultdict(dict) 34 self.messenger = ComponentMessenger() 35 36 @TimedFunction('SpaceComponent::ComponentRegistry::GetComponentClassesForTypeID') 37 def GetComponentClassesForTypeID(self, typeID): 38 componentClassesForTypeID = self.typeIDToClassMapping.get(typeID, None) 39 if componentClassesForTypeID is None: 40 componentClassesForTypeID = self.RegisterComponentsForType(typeID) 41 return componentClassesForTypeID 42 43 @TimedFunction('SpaceComponent::ComponentRegistry::RegisterComponentsForType') 44 def RegisterComponentsForType(self, typeID): 45 componentNames = get_space_component_names_for_type(typeID, component_names=self.componentNames) 46 componentClassesForTypeID = [] 47 for componentName in componentNames: 48 componentClassesForTypeID.append(self.componentClassTypes[componentName]) 49 50 self.typeIDToClassMapping[typeID] = componentClassesForTypeID 51 return componentClassesForTypeID 52 53 def GetComponentsByItemID(self, itemID): 54 return self.itemIDToComponentInstances[itemID] 55 56 def GetAllComponentInstancesWithAttribute(self, itemID, attribute): 57 components_by_name = self.GetComponentsByItemID(itemID) 58 instances_with_attribute = [ instance for instance in components_by_name.itervalues() if hasattr(instance, attribute) ] 59 return instances_with_attribute 60 61 def CreateComponentInstances(self, itemID, typeID): 62 componentClassesForTypeID = self.GetComponentClassesForTypeID(typeID) 63 components = self._GetComponentsByItemId(itemID) 64 for componentClass in componentClassesForTypeID: 65 if componentClass.componentName in components: 66 continue 67 attributes = get_space_component_for_type(typeID, componentClass.componentName) 68 with ExceptionEater('Error creating a component %s' % componentClass.componentName): 69 instance = componentClass.factoryMethod(itemID, typeID, attributes, self) 70 components[componentClass.componentName] = instance 71 self.componentNameToItemIDs[componentClass.componentName][itemID] = instance 72 73 return components 74 75 def _GetComponentsByItemId(self, itemId): 76 if itemId in self.itemIDToComponentInstances: 77 components = self.itemIDToComponentInstances[itemId] 78 else: 79 components = {} 80 self.itemIDToComponentInstances[itemId] = components 81 return components 82 83 def AddComponentInstanceToItem(self, componentName, itemId, typeID, attributes): 84 components = self._GetComponentsByItemId(itemId) 85 componentClass = self.componentClassTypes[componentName] 86 instance = componentClass.factoryMethod(itemId, typeID, attributes, self) 87 components[componentName] = instance 88 self.componentNameToItemIDs[componentName][itemId] = instance 89 return instance 90 91 def DeleteComponentInstances(self, itemID): 92 self.messenger.DeleteSubscriptionsForItem(itemID) 93 instance = self.itemIDToComponentInstances.pop(itemID) 94 for componentName in instance: 95 del self.componentNameToItemIDs[componentName][itemID] 96 97 def GetInstancesWithComponentClass(self, componentName): 98 return self.componentNameToItemIDs[componentName].values() 99 100 def SendMessageToItem(self, itemID, messageName, *args, **kwargs): 101 self.messenger.SendMessageToItem(itemID, messageName, *args, **kwargs) 102 103 def SendMessageToAllItems(self, messageName, *args, **kwargs): 104 self.messenger.SendMessageToAllItems(messageName, *args, **kwargs) 105 106 def SubscribeToItemMessage(self, itemID, messageName, messageHandler): 107 self.GetComponentsByItemID(itemID) 108 self.messenger.SubscribeToItemMessage(itemID, messageName, messageHandler) 109 110 def GetComponentForItem(self, itemID, componentClassID): 111 return self.itemIDToComponentInstances[itemID][componentClassID] 112 113 def UnsubscribeFromItemMessage(self, itemID, messageName, messageHandler): 114 self.messenger.UnsubscribeFromItemMessage(itemID, messageName, messageHandler) 115 116 def CallComponent(self, session, itemID, componentClassName, methodName, *args, **kwargs): 117 try: 118 component = self.GetComponentForItem(itemID, componentClassName) 119 except KeyError: 120 return 121 122 method = getattr(component, methodName) 123 if not getattr(method, 'isExportedComponentCall', False): 124 raise RuntimeError("The method '%s' is not exported on component '%s'" % (methodName, componentClassName)) 125 return method(session, *args, **kwargs) 126 127 @staticmethod 128 def GetServiceForComponent(serviceName): 129 return sm.GetService(serviceName)