public void validate(OptionRule rule) {
        List<RequiredOption> requiredOptions = rule.getRequiredOptions();
        for (RequiredOption requiredOption : requiredOptions) {
            validate(requiredOption);

            for (Option<?> option : requiredOption.getOptions()) {
                if (SingleChoiceOption.class.isAssignableFrom(option.getClass())) {
                    // is required option and not match condition, skip validate
                    if (isConditionOption(requiredOption)
                            && !matchCondition(
                                    (RequiredOption.ConditionalRequiredOptions) requiredOption)) {
                        continue;
                    }
                    validateSingleChoice(option);
                }
            }
        }

        for (Option option : rule.getOptionalOptions()) {
            if (SingleChoiceOption.class.isAssignableFrom(option.getClass())) {
                validateSingleChoice(option);
            }
        }
    }
@Test
    public void testSimpleConditionalRequiredOptionsWithDefaultValue() {
        OptionRule rule =
                OptionRule.builder()
                        .optional(TEST_MODE)
                        .conditional(TEST_MODE, OptionTest.TestMode.TIMESTAMP, TEST_TIMESTAMP)
                        .build();
        Map<String, Object> config = new HashMap<>();
        Executable executable = () -> validate(config, rule);

        // Expression mismatch
        Assertions.assertDoesNotThrow(executable);

        // Expression match, and required options absent
        config.put(TEST_MODE.key(), "timestamp");
        assertEquals(
                "ErrorCode:[API-02], ErrorDescription:[Option item validate failed] - There are unconfigured options, the options('option.timestamp') are required"
                        + " because ['option.mode' == TIMESTAMP] is true.",
                assertThrows(OptionValidationException.class, executable).getMessage());

        // Expression match, and required options all present
        config.put(TEST_TIMESTAMP.key(), "564231238596789");
        Assertions.assertDoesNotThrow(executable);

        // Expression mismatch
        config.put(TEST_MODE.key(), "EARLIEST");
        Assertions.assertDoesNotThrow(executable);
    }