/**
   * Tokenize the input line with the given deliminator and populate the given object with values of
   * the tokens
   *
   * @param targetObject the target object
   * @param line the input line
   * @param delim the deminator that separates the fields in the given line
   * @param keyFields the specified fields
   */
  public static void convertLineToBusinessObject(
      Object targetObject, String line, int[] fieldLength, List<String> keyFields) {
    String[] tokens = new String[fieldLength.length];

    int currentPosition = 0;
    for (int i = 0; i < fieldLength.length; i++) {
      currentPosition = i <= 0 ? 0 : fieldLength[i - 1] + currentPosition;
      tokens[i] = StringUtils.mid(line, currentPosition, fieldLength[i]).trim();
    }
    ObjectUtil.buildObject(targetObject, tokens, keyFields);
  }
  /**
   * Populate the given fields of the target object with the corresponding field values of source
   * object
   *
   * @param targetObject the target object
   * @param sourceObject the source object
   * @param keyFields the given fields of the target object that need to be popluated
   */
  public static void buildObject(Object targetObject, Object sourceObject, List<String> keyFields) {
    if (sourceObject.getClass().isArray()) {
      buildObject(targetObject, sourceObject, keyFields);
      return;
    }

    for (String propertyName : keyFields) {
      if (PropertyUtils.isReadable(sourceObject, propertyName)
          && PropertyUtils.isWriteable(targetObject, propertyName)) {
        try {
          Object propertyValue = PropertyUtils.getProperty(sourceObject, propertyName);
          PropertyUtils.setProperty(targetObject, propertyName, propertyValue);
        } catch (Exception e) {
          LOG.debug(e);
        }
      }
    }
  }
 /**
  * Tokenize the input line with the given deliminator and populate the given object with values of
  * the tokens
  *
  * @param targetObject the target object
  * @param line the input line
  * @param delim the deminator that separates the fields in the given line
  * @param keyFields the specified fields
  */
 public static void convertLineToBusinessObject(
     Object targetObject, String line, String delim, List<String> keyFields) {
   String[] tokens = StringUtils.split(line, delim);
   ObjectUtil.buildObject(targetObject, tokens, keyFields);
 }
 /**
  * Tokenize the input line with the given deliminator and populate the given object with values of
  * the tokens
  *
  * @param targetObject the target object
  * @param line the input line
  * @param delim the deminator that separates the fields in the given line
  * @param keyFields the specified fields
  */
 public static void convertLineToBusinessObject(
     Object targetObject, String line, String delim, String fieldNames) {
   List<String> tokens = split(line, delim);
   List<String> keyFields = Arrays.asList(StringUtils.split(fieldNames, delim));
   ObjectUtil.buildObject(targetObject, tokens.toArray(), keyFields);
 }
  /**
   * update a given collection entry with the pending entry obtained from the given field values and
   * isApproved
   *
   * @param entryCollection the given entry collection
   * @param fieldValues the given field values
   * @param isApproved indicate if the resulting pending entry has been approved
   * @param isConsolidated indicate if the collection entries have been consolidated
   */
  protected void updateCollection(
      Collection entryCollection,
      Map fieldValues,
      boolean isApproved,
      boolean isConsolidated,
      Class clazz) {
    // go through the pending entries to update the balance collection
    Iterator<LaborLedgerPendingEntry> pendingEntryIterator =
        laborLedgerPendingEntryService.findPendingLedgerEntriesForLedgerBalance(
            fieldValues, isApproved);

    while (pendingEntryIterator.hasNext()) {
      LaborLedgerPendingEntry pendingEntry = pendingEntryIterator.next();

      // if consolidated, change the following fields into the default values for consolidation
      if (isConsolidated) {
        pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER);
        pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
        pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
      }

      if (LedgerBalance.class.isAssignableFrom(clazz)) {
        try {
          LedgerBalance ledgerBalance =
              laborLedgerBalanceService.findLedgerBalance(entryCollection, pendingEntry);
          if (ledgerBalance == null) {

            Object newLedgerBalance = clazz.newInstance();
            ObjectUtil.buildObject(newLedgerBalance, pendingEntry);

            ledgerBalance = (LedgerBalance) newLedgerBalance;
            entryCollection.add(ledgerBalance);
          }
          laborLedgerBalanceService.updateLedgerBalance(ledgerBalance, pendingEntry);
          ledgerBalance
              .getDummyBusinessObject()
              .setConsolidationOption(isConsolidated ? Constant.CONSOLIDATION : Constant.DETAIL);
          ledgerBalance
              .getDummyBusinessObject()
              .setPendingEntryOption(
                  isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY);
        } catch (Exception e) {
          LOG.error("cannot create a new object of type: " + clazz.getName() + "/n" + e);
        }
      } else if (LedgerEntry.class.isAssignableFrom(clazz)) {
        LedgerEntry ledgerEntry = new LedgerEntry();
        ObjectUtil.buildObject(ledgerEntry, pendingEntry);

        ledgerEntry
            .getDummyBusinessObject()
            .setConsolidationOption(isConsolidated ? Constant.CONSOLIDATION : Constant.DETAIL);
        ledgerEntry
            .getDummyBusinessObject()
            .setPendingEntryOption(
                isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY);

        entryCollection.add(ledgerEntry);
      } else {
        LOG.warn("The class, " + clazz.getName() + ", is unregistered with the method.");
        return;
      }
    }
  }