<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _update_function_transition_graph(self, src_node_key, dst_node_key, jumpkind='Ijk_Boring', ins_addr=None, stmt_idx=None, confirmed=None):
 """ Update transition graphs of functions in function manager based on information passed in. :param str jumpkind: Jumpkind. :param CFGNode src_node: Source CFGNode :param CFGNode dst_node: Destionation CFGNode :param int ret_addr: The theoretical return address for calls :return: None """


        if dst_node_key is not None:
            dst_node = self._graph_get_node(dst_node_key, terminator_for_nonexistent_node=True)
            dst_node_addr = dst_node.addr
            dst_codenode = dst_node.to_codenode()
            dst_node_func_addr = dst_node.function_address
        else:
            dst_node = None
            dst_node_addr = None
            dst_codenode = None
            dst_node_func_addr = None

        if src_node_key is None:
            if dst_node is None:
                raise ValueError("Either src_node_key or dst_node_key must be specified.")
            self.kb.functions.function(dst_node.function_address, create=True)._register_nodes(True,
                                                                                               dst_codenode
                                                                                               )
            return

        src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)

        # Update the transition graph of current function
        if jumpkind == "Ijk_Call":
            ret_addr = src_node.return_target
            ret_node = self.kb.functions.function(
                src_node.function_address,
                create=True
            )._get_block(ret_addr).codenode if ret_addr else None

            self.kb.functions._add_call_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_addr=dst_node_addr,
                retn_node=ret_node,
                syscall=False,
                ins_addr=ins_addr,
                stmt_idx=stmt_idx,
            )

        if jumpkind.startswith('Ijk_Sys'):

            self.kb.functions._add_call_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_addr=dst_node_addr,
                retn_node=src_node.to_codenode(),  # For syscalls, they are returning to the address of themselves
                syscall=True,
                ins_addr=ins_addr,
                stmt_idx=stmt_idx,
            )

        elif jumpkind == 'Ijk_Ret':
            # Create a return site for current function
            self.kb.functions._add_return_from(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_node=dst_codenode,
            )

            if dst_node is not None:
                # Create a returning edge in the caller function
                self.kb.functions._add_return_from_call(
                    function_addr=dst_node_func_addr,
                    src_function_addr=src_node.function_address,
                    to_node=dst_codenode,
                )

        elif jumpkind == 'Ijk_FakeRet':
            self.kb.functions._add_fakeret_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_node=dst_codenode,
                confirmed=confirmed,
            )

        elif jumpkind in ('Ijk_Boring', 'Ijk_InvalICache'):

            src_obj = self.project.loader.find_object_containing(src_node.addr)
            dest_obj = self.project.loader.find_object_containing(dst_node.addr) if dst_node is not None else None

            if src_obj is dest_obj:
                # Jump/branch within the same object. Might be an outside jump.
                to_outside = src_node.function_address != dst_node_func_addr
            else:
                # Jump/branch between different objects. Must be an outside jump.
                to_outside = True

            if not to_outside:
                self.kb.functions._add_transition_to(
                    function_addr=src_node.function_address,
                    from_node=src_node.to_codenode(),
                    to_node=dst_codenode,
                    ins_addr=ins_addr,
                    stmt_idx=stmt_idx,
                )

            else:
                self.kb.functions._add_outside_transition_to(
                    function_addr=src_node.function_address,
                    from_node=src_node.to_codenode(),
                    to_node=dst_codenode,
                    to_function_addr=dst_node_func_addr,
                    ins_addr=ins_addr,
                    stmt_idx=stmt_idx,
                )