# File lib/declarative_authorization/development_support/change_analyzer.rb, line 164
      def next_step (viable_approaches, candidates, approach_checker,
            privilege, context, strategy)
        candidate = candidates.shift
        next_in_strategy = strategy[candidate.steps.length % strategy.length]

        #if @seen_states.include?([candidate.state_hash, next_in_strategy])
        #  puts "SKIPPING #{next_in_strategy}; #{candidate.inspect}"
        #end
        return if @seen_states.include?([candidate.state_hash, next_in_strategy])
        @seen_states << [candidate.state_hash, next_in_strategy]
        candidate.steps << [next_in_strategy]
        candidates << candidate

        new_approaches = []

        #puts "#{next_in_strategy} on #{candidate.inspect}"
        case next_in_strategy
        when :add_role
          # ensure non-existent name
          approach = candidate.clone_for_step(:add_role, :new_role_for_change_analyzer)
          if AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
            #AnalyzerEngine.apply_change(approach.engine, [:add_privilege, privilege, context, :new_role_for_change_analyzer])
            new_approaches << approach
          end
        when :assign_role_to_user
          candidate.users.each do |user|
            relevant_roles(candidate).each do |role|
              next if user.role_symbols.include?(role.to_sym)
              approach = candidate.clone_for_step(:assign_role_to_user, role, user)
              # beware of shallow copies!
              cloned_user = user.clone
              approach.users[approach.users.index(user)] = cloned_user
              # possible on real user objects?
              cloned_user.role_symbols << role.to_sym
              new_approaches << approach
            end
          end
        when :remove_role_from_user
          candidate.users.each do |user|
            user.role_symbols.each do |role_sym|
              approach = candidate.clone_for_step(:remove_role_from_user, role_sym, user)
              # beware of shallow copies!
              cloned_user = user.clone
              approach.users[approach.users.index(user)] = cloned_user
              # possible on real user objects?
              cloned_user.role_symbols.delete(role_sym)
              new_approaches << approach
            end
          end
        when :add_privilege
          relevant_roles(candidate).each do |role|
            approach = candidate.clone_for_step(:add_privilege, privilege, context, role)
            AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
            new_approaches << approach
          end
        when :remove_privilege
          relevant_roles(candidate).each do |role|
            approach = candidate.clone_for_step(:remove_privilege, privilege, context, role)
            if AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
              new_approaches << approach
            end
          end
        else
          raise "Unknown next strategy step #{next_in_strategy}"
        end

        new_approaches.each do |new_approach|
          if new_approach.check(approach_checker)
            unless viable_approaches.any? {|viable_approach| viable_approach.subset?(new_approach) }
              #puts "New: #{new_approach.changes.inspect}\n  #{viable_approaches.map(&:changes).inspect}"
              viable_approaches.delete_if {|viable_approach| new_approach.subset?(viable_approach)}
              viable_approaches << new_approach unless viable_approaches.find {|v_a| v_a.state_hash == new_approach.state_hash}
            end
          else
            candidates << new_approach
          end
        end

        candidates.sort!
      end