/**
  * State/province processing function. This function will ignore errorHandlingMode since the
  * return type is StateProvinceEnum.
  *
  * @param stateProvinceStr stateProvince string to be processed
  * @param result optional ProcessingResult
  * @return matching StateProvinceEnum or null
  */
 public StateProvinceEnum process(String stateProvinceStr, ProcessingResult result) {
   if (StringUtils.isBlank(stateProvinceStr)) {
     return null;
   }
   ParseResult<String> parsingResult = parse(stateProvinceStr);
   if (parsingResult.isSuccessful() && parsingResult.getConfidence().equals(CONFIDENCE.DEFINITE)) {
     // using reflection to invoke fromCode(String), the cost is higher than calling directly
     // CanadaProvince.fromCode(String) but this will work for all StateProvinceEnum implementation
     try {
       StateProvinceEnum spe =
           (StateProvinceEnum) fromCodeMethod.invoke(null, parsingResult.getPayload());
       return spe;
     } catch (IllegalArgumentException e) {
       logger.error("StateProvinceEnum fromCode Method access error", e);
     } catch (IllegalAccessException e) {
       logger.error("StateProvinceEnum fromCode Method access error", e);
     } catch (InvocationTargetException e) {
       logger.error("StateProvinceEnum fromCode Method access error", e);
     }
   } else {
     if (result != null) {
       result.addError(
           MessageFormat.format(
               resourceBundle.getString("stateProvince.error.notFound"),
               stateProvinceStr,
               associatedCountry.getTitle()));
     }
   }
   return null;
 }
  /**
   * NoSuchElementException could be thrown if something is wrong with the dictionary file or the
   * StateProvinceEnum implementation. NullPointerException will be thrown if the dictionary can not
   * be found.
   *
   * @param targetCountry used to retrieve the dictionary file
   * @param stateProvince class of the concrete enum
   * @param stateProvinceName name of the field holding the stateprovince value
   * @param errorHandlingMode
   */
  public StateProvinceProcessor(
      Country targetCountry,
      Class<T> stateProvinceClass,
      String stateProvinceName,
      ErrorHandlingModeEnum errorHandlingMode) {
    super(
        false,
        new InputStream[] {
          StateProvinceProcessor.class.getResourceAsStream(
              "/dictionaries/geography/"
                  + targetCountry.getIso2LetterCode()
                  + "_StateProvinceName.txt")
        });
    this.associatedCountry = targetCountry;
    this.errorHandlingMode = errorHandlingMode;
    this.stateProvinceName = stateProvinceName;
    try {
      // make sure we can find the fromCode(String) method for this enum
      fromCodeMethod = stateProvinceClass.getMethod("fromCode", String.class);
    } catch (SecurityException e) {
      fromCodeMethod = null;
    } catch (NoSuchMethodException e) {
      fromCodeMethod = null;
    }

    StateProvinceEnum[] statesProvinces = stateProvinceClass.getEnumConstants();
    if (statesProvinces == null || statesProvinces.length <= 0 || fromCodeMethod == null) {
      String errorText =
          "No well-formed StateProvinceEnum found for country "
              + targetCountry.getTitle()
              + " and Class "
              + stateProvinceClass;
      logger.error(errorText);
      throw new NoSuchElementException(errorText);
    }

    for (StateProvinceEnum cp : statesProvinces) {
      add(cp.getName(), cp.getCode());
      add(cp.getCode(), cp.getCode());
    }

    // always a default Locale
    setLocale(Locale.ENGLISH);
  }