public ShellCommand lookupCommand(String discriminator, List<Token> tokens) throws CLIException
    {
        List<ShellCommand> collectedTable = commandsByName(discriminator);
        // reduction
        List<ShellCommand> reducedTable = new ArrayList<ShellCommand>();
        for (ShellCommand cs : collectedTable)
        {
            if (cs.getMethod().getParameterTypes().length == tokens.size() - 1
                    || (cs.getMethod().isVarArgs() && (cs.getMethod().getParameterTypes().length <= tokens.size() - 1)))
            {
                reducedTable.add(cs);
            }
        }
        // selection
        if (collectedTable.size() == 0)
        {
            throw CLIException.createCommandNotFound(discriminator);
        }
        else if (reducedTable.size() == 0)
        {
            throw CLIException.createCommandNotFoundForArgNum(discriminator, tokens.size() - 1);
        }
        else if (reducedTable.size() > 1)
        {
            throw CLIException.createAmbiguousCommandExc(discriminator, tokens.size() - 1);
        }
        else
        {
            return reducedTable.get(0);
        }
    }