protected Trigger parseTriggerConfig(String configValue) throws BadTriggerConfigException {

    BadTriggerConfigException badPeriodicTiggerException = null;
    BadTriggerConfigException badCronTiggerException = null;
    try {
      return tryExpressionAsPeriodicTrigger(configValue);
    } catch (BadTriggerConfigException e) {
      badPeriodicTiggerException = e;
    }

    try {
      return tryExpressionAsCronTrigger(configValue);
    } catch (BadTriggerConfigException e) {
      badCronTiggerException = e;
    }

    throw new BadTriggerConfigException(
        "All trigger config parsing attempts failed. First reason: ["
            + badPeriodicTiggerException.getMessage()
            + "]. Second reason: ["
            + badCronTiggerException.getMessage()
            + "]",
        configValue);
  }
  protected Trigger tryExpressionAsPeriodicTrigger(String configValue)
      throws BadTriggerConfigException {
    BadTriggerConfigException longParseException = null;
    try {
      final long period = Long.parseLong(configValue);
      if (period < 0) {
        return new DisabledTrigger();
      }
      // millis since that's what @Scheduled methods were historically
      // configured in
      return new PeriodicTrigger(period, TimeUnit.MILLISECONDS);
    } catch (NumberFormatException e) {
      longParseException =
          new BadTriggerConfigException(
              "Config [" + configValue + "] did not parse to a long.", configValue, e);
    } catch (IllegalArgumentException e) {
      longParseException =
          new BadTriggerConfigException(
              "Config [" + configValue + "] could not be used to initialize a PeriodicTrigger",
              configValue,
              e);
    }

    final Matcher matcher = PERIODIC_TRIGGER_WITH_INITIAL_DELAY_PATTERN.matcher(configValue);
    if (!(matcher.matches())) {
      throw new BadTriggerConfigException(
          "Trigger expression could not be parsed as either a"
              + " simple period or as a period with an initial "
              + "offset. Original parse failure: ["
              + longParseException.getMessage()
              + "]. To be considered a period with an offset, "
              + "the expression must match this regexp"
              + "(without brackets): ["
              + PERIODIC_TRIGGER_WITH_INITIAL_DELAY_PATTERN
              + "]",
          configValue);
    }

    try {
      final String periodStr = matcher.group(1);
      final long periodLong = Long.parseLong(periodStr);

      if (periodLong < 0) {
        return new DisabledTrigger();
      }

      final String offsetStr = matcher.group(2);
      final long offsetLong = Long.parseLong(offsetStr);

      final PeriodicTrigger trigger = new PeriodicTrigger(periodLong, TimeUnit.MILLISECONDS);
      trigger.setInitialDelay(offsetLong);
      return trigger;
    } catch (NumberFormatException e) {
      throw new BadTriggerConfigException(
          "Trigger expression could not be parsed as either a"
              + " simple period or as a period with an initial "
              + "offset. Original parse failure: ["
              + longParseException.getMessage()
              + "]. To be considered a period with an initial "
              + "delay, the expression must match this regexp"
              + "(without brackets): ["
              + PERIODIC_TRIGGER_WITH_INITIAL_DELAY_PATTERN
              + "]",
          configValue,
          e);
    } catch (IllegalArgumentException e) {
      throw new BadTriggerConfigException(
          "Trigger expression parsed as a period [{}] with an "
              + "initial delay [{}] but could not be used to "
              + "initialize a PeriodicTrigger",
          configValue,
          e);
    }
  }