def _process(self, root): ''' Process the cache for the node. @return: CacheNode ''' assert isinstance(root, Node), 'Invalid node %s' % root cacheNode = self._struct.cacheNodes.get(CacheNode.idFor(root)) if cacheNode: return cacheNode cacheNode = CacheNode(self._struct, root) for node in iterateNodes(root): assert isinstance(node, Node), 'Invalid node %s' % node for method, attr in METHOD_NODE_ATTRIBUTE.items(): original = getattr(node, attr) if not original: continue invoker = invokerCallOf(original) if not invoker: continue assert isinstance(invoker, InvokerCall) assert isinstance(invoker.call, Call) structMethod = self._struct.methods.get(method) if not structMethod: continue assert isinstance(structMethod, StructMethod) structService = structMethod.services.get(typeFor(invoker.implementation)) if not structService: continue assert isinstance(structService, StructService) structCall = structService.calls.get(invoker.call.name) if not structCall: continue assert isinstance(structCall, StructCall) cacheCall = cacheNode.calls.get(structCall) if not cacheCall: cacheCall = cacheNode.calls[structCall] = CacheCall() nodeId = id(node) cacheInvoker = cacheCall.invokers.get(nodeId) if not cacheInvoker: cacheCall.invokers[nodeId] = CacheInvoker(invoker=original, node=node) return cacheNode
def associate(self, structure): ''' Associate the structure with the resource root node. @param structure: StructureRight The structure to associate with. @return: StructCallInvokers The associated structure with the call invokers. ''' assert isinstance(structure, StructureRight), 'Invalid structure %s' % structure callInvokers = self.callInvokers.get(structure) if not callInvokers: callInvokers = self.callInvokers[structure] = StructCallInvokers() for node in iterateNodes(self.resourcesRoot): assert isinstance(node, Node), 'Invalid node %s' % node for method, attr in METHOD_NODE_ATTRIBUTE.items(): original = getattr(node, attr) if not original: continue invoker = invokerCallOf(original) if not invoker: continue assert isinstance(invoker, InvokerCall) assert isinstance(invoker.call, Call) structMethod = structure.methods.get(method) if not structMethod: continue assert isinstance(structMethod, StructMethod) structService = structMethod.services.get(typeFor(invoker.implementation)) if not structService: continue assert isinstance(structService, StructService) structCall = structService.calls.get(invoker.call.name) if not structCall: continue callInvokers.push(structCall, node, original) return callInvokers
def alternates(self): ''' Provides the alternates. @return: dictionary{tuple(Node, Invoker): list[tuple(Node, Invoker, set(TypeProperty))]} The alternates dictionary, as a key a tuple with the node and invoker and as a value a set of the same tuples with the required property types and contains the possible alternates for the key. ''' if self._alternates is None: self._alternates = {} alternatesRepository = {(typeService, call): set(alternates) for typeService, call, alternates in self.alternate.iterate()} # First we process the node and invoker keys keys = [] for node in iterateNodes(self.resourcesRoot): for _method, attr in METHOD_NODE_ATTRIBUTE.items(): invoker = getattr(node, attr) if not invoker: continue keys.append((node, invoker)) # Then we need to find the alternates pathTypesByKey, modelTypesByKey = {}, {} for key in keys: node, invoker = key assert isinstance(node, Node), 'Invalid node %s' % node assert isinstance(invoker, Invoker), 'Invalid invoker %s' % invoker for keyAlt in keys: nodeAlt, invokerAlt = keyAlt assert isinstance(nodeAlt, Node), 'Invalid node %s' % nodeAlt assert isinstance(invokerAlt, Invoker), 'Invalid invoker %s' % invokerAlt if node == nodeAlt: continue # Same node, no need to process if invoker != invokerAlt: if invoker.method != invokerAlt.method: continue # Not the same method, no need to process if invoker.output != invokerAlt.output: continue # Not the same return, no need to process modelTypes = modelTypesByKey.get(key) if modelTypes is None: modelTypes = [inp.type for inp in invoker.inputs if isinstance(inp.type, TypeModel)] modelTypesByKey[key] = modelTypes modelTypesAlt = modelTypesByKey.get(keyAlt) if modelTypesAlt is None: modelTypesAlt = [inp.type for inp in invokerAlt.inputs if isinstance(inp.type, TypeModel)] modelTypesByKey[keyAlt] = modelTypesAlt if modelTypes != modelTypesAlt: continue # The model types don't match, no need to process pathTypes = pathTypesByKey.get(key) if pathTypes is None: pathTypes = pathTypesByKey[key] = propertyTypesOf(node, invoker) pathTypesAlt = pathTypesByKey.get(keyAlt) if pathTypesAlt is None: pathTypesAlt = pathTypesByKey[keyAlt] = propertyTypesOf(nodeAlt, invokerAlt) required = set(pathTypes) for pathType in pathTypesAlt: try: required.remove(pathType) except KeyError: # If a type is not found it means that they are not compatible required.clear() break if not required: continue # There must be at least one type required # Now we check with the alternates repository configurations if self.processWithRepository(alternatesRepository, invoker, invokerAlt): alternates = self._alternates.get(key) if alternates is None: alternates = self._alternates[key] = [] alternates.append(keyAlt + (required,)) assert log.debug('Added alternate on %s for %s', invoker, invokerAlt) or True for serviceCall, alternates in alternatesRepository.items(): if alternates: alternates = ('\t%s for %s' % serviceCallAlt for serviceCallAlt in alternates) service, call = serviceCall log.error('Invalid alternate configuration on %s for %s with:\n%s\n', service, call, '\n'.join(alternates)) return self._alternates
def alternates(self): ''' Provides the alternates. @return: dictionary{tuple(Node, Invoker): list[tuple(Node, Invoker, set(TypeProperty))]} The alternates dictionary, as a key a tuple with the node and invoker and as a value a set of the same tuples with the required property types and contains the possible alternates for the key. ''' if self._alternates is None: self._alternates = {} alternatesRepository = { (typeService, call): set(alternates) for typeService, call, alternates in self.alternate.iterate() } # First we process the node and invoker keys keys = [] for node in iterateNodes(self.resourcesRoot): for _method, attr in METHOD_NODE_ATTRIBUTE.items(): invoker = getattr(node, attr) if not invoker: continue keys.append((node, invoker)) # Then we need to find the alternates pathTypesByKey, modelTypesByKey = {}, {} for key in keys: node, invoker = key assert isinstance(node, Node), 'Invalid node %s' % node assert isinstance(invoker, Invoker), 'Invalid invoker %s' % invoker for keyAlt in keys: nodeAlt, invokerAlt = keyAlt assert isinstance(nodeAlt, Node), 'Invalid node %s' % nodeAlt assert isinstance( invokerAlt, Invoker), 'Invalid invoker %s' % invokerAlt if node == nodeAlt: continue # Same node, no need to process if invoker != invokerAlt: if invoker.method != invokerAlt.method: continue # Not the same method, no need to process if invoker.output != invokerAlt.output: continue # Not the same return, no need to process modelTypes = modelTypesByKey.get(key) if modelTypes is None: modelTypes = [ inp.type for inp in invoker.inputs if isinstance(inp.type, TypeModel) ] modelTypesByKey[key] = modelTypes modelTypesAlt = modelTypesByKey.get(keyAlt) if modelTypesAlt is None: modelTypesAlt = [ inp.type for inp in invokerAlt.inputs if isinstance(inp.type, TypeModel) ] modelTypesByKey[keyAlt] = modelTypesAlt if modelTypes != modelTypesAlt: continue # The model types don't match, no need to process pathTypes = pathTypesByKey.get(key) if pathTypes is None: pathTypes = pathTypesByKey[key] = propertyTypesOf( node, invoker) pathTypesAlt = pathTypesByKey.get(keyAlt) if pathTypesAlt is None: pathTypesAlt = pathTypesByKey[ keyAlt] = propertyTypesOf(nodeAlt, invokerAlt) required = set(pathTypes) for pathType in pathTypesAlt: try: required.remove(pathType) except KeyError: # If a type is not found it means that they are not compatible required.clear() break if not required: continue # There must be at least one type required # Now we check with the alternates repository configurations if self.processWithRepository(alternatesRepository, invoker, invokerAlt): alternates = self._alternates.get(key) if alternates is None: alternates = self._alternates[key] = [] alternates.append(keyAlt + (required, )) assert log.debug('Added alternate on %s for %s', invoker, invokerAlt) or True for serviceCall, alternates in alternatesRepository.items(): if alternates: alternates = ('\t%s for %s' % serviceCallAlt for serviceCallAlt in alternates) service, call = serviceCall log.error( 'Invalid alternate configuration on %s for %s with:\n%s\n', service, call, '\n'.join(alternates)) return self._alternates