<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _process_router(self, ri):
 """Process a router, apply latest configuration and update router_info. Get the router dict from RouterInfo and proceed to detect changes from the last known state. When new ports or deleted ports are detected, `internal_network_added()` or `internal_networks_removed()` are called accordingly. Similarly changes in ex_gw_port causes `external_gateway_added()` or `external_gateway_removed()` calls. Next, floating_ips and routes are processed. Also, latest state is stored in ri.internal_ports and ri.ex_gw_port for future comparisons. :param ri : RouterInfo object of the router being processed. :return:None :raises: networking_cisco.plugins.cisco.cfg_agent.cfg_exceptions. DriverException if the configuration operation fails. """

        try:
            ex_gw_port = ri.router.get('gw_port')
            ri.ha_info = ri.router.get('ha_info', None)
            gateway_set = ex_gw_port and not ri.ex_gw_port
            gateway_cleared = not ex_gw_port and ri.ex_gw_port
            internal_ports = ri.router.get(bc.constants.INTERFACE_KEY, [])
            # Once the gateway is set, then we know which VRF this router
            # belongs to. Keep track of it in our lists of routers, organized
            # as a dictionary by VRF name
            if gateway_set:
                self._add_rid_to_vrf_list(ri)

            new_ports, old_ports, change_details = (
                self._get_internal_port_changes(ri, internal_ports))

            list_port_ids_up = []

            non_global_router_roles = [None,
                                       c_constants.ROUTER_ROLE_HA_REDUNDANCY]
            if ri.router[ROUTER_ROLE_ATTR] in non_global_router_roles:
                self._process_new_ports(ri, new_ports, ex_gw_port,
                                        list_port_ids_up, change_details)
                self._process_old_ports(ri, old_ports, ex_gw_port,
                                        change_details)
            else:
                self._process_new_ports_global(ri, new_ports, ex_gw_port,
                                               list_port_ids_up)
                self._process_old_ports_global(ri, old_ports, ex_gw_port)

            if gateway_set:
                self._process_gateway_set(ri, ex_gw_port,
                                          list_port_ids_up)
            elif gateway_cleared:
                self._process_gateway_cleared(ri, ri.ex_gw_port)

            self._send_update_port_statuses(list_port_ids_up,
                                            bc.constants.PORT_STATUS_ACTIVE)
            if ex_gw_port:
                self._process_router_floating_ips(ri, ex_gw_port)

            global_router_roles = [c_constants.ROUTER_ROLE_GLOBAL,
                                   c_constants.ROUTER_ROLE_LOGICAL_GLOBAL]
            if ri.router[ROUTER_ROLE_ATTR] not in global_router_roles:
                self._enable_disable_ports(ri, ex_gw_port, internal_ports)

                if gateway_cleared:
                    # Remove this router from the list of routers by VRF
                    self._remove_rid_from_vrf_list(ri)

            ri.ex_gw_port = ex_gw_port
            self._routes_updated(ri)
        except cfg_exceptions.HAParamsMissingException as e:
            self._update_updated_routers_cache([ri.router_id])
            LOG.warning(e)
        except cfg_exceptions.DriverException as e:
            with excutils.save_and_reraise_exception():
                self._update_updated_routers_cache([ri.router_id])
                LOG.error(e)