Exemple #1
0
    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
Exemple #2
0
 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