/**
   * @param transDoc
   * @param transForm
   * @param lineSet
   */
  protected void processAccountingLines(
      AccountingDocument transDoc, KualiAccountingDocumentFormBase transForm, String lineSet) {
    // figure out which set of lines we're looking at
    List formLines;
    String pathPrefix;
    boolean source;
    if (lineSet.equals(KFSConstants.SOURCE)) {
      formLines = transDoc.getSourceAccountingLines();
      pathPrefix =
          KFSConstants.DOCUMENT_PROPERTY_NAME
              + "."
              + KFSConstants.EXISTING_SOURCE_ACCT_LINE_PROPERTY_NAME;
      source = true;
    } else {
      formLines = transDoc.getTargetAccountingLines();
      pathPrefix =
          KFSConstants.DOCUMENT_PROPERTY_NAME
              + "."
              + KFSConstants.EXISTING_TARGET_ACCT_LINE_PROPERTY_NAME;
      source = false;
    }

    // find and process corresponding form and baselines
    int index = 0;
    for (Iterator i = formLines.iterator(); i.hasNext(); index++) {
      AccountingLine formLine = (AccountingLine) i.next();

      // update sales tax required attribute for view
      // handleSalesTaxRequired(transDoc, formLine, source, false, index);
      checkSalesTax(transDoc, formLine, source, false, index);
    }
  }
  /**
   * Adds the given accountingLine to the appropriate form-related data structures.
   *
   * @param isSource
   * @param financialDocumentForm
   * @param line
   */
  protected void insertAccountingLine(
      boolean isSource,
      KualiAccountingDocumentFormBase financialDocumentForm,
      AccountingLine line) {
    AccountingDocument tdoc = financialDocumentForm.getFinancialDocument();
    if (isSource) {
      // add it to the document
      tdoc.addSourceAccountingLine((SourceAccountingLine) line);

      // add PK fields to sales tax if needed
      if (line.isSalesTaxRequired()) {
        populateSalesTax(line);
      }

      // Update the doc total
      if (tdoc instanceof AmountTotaling)
        ((FinancialSystemDocumentHeader) financialDocumentForm.getDocument().getDocumentHeader())
            .setFinancialDocumentTotalAmount(((AmountTotaling) tdoc).getTotalDollarAmount());
    } else {
      // add it to the document
      tdoc.addTargetAccountingLine((TargetAccountingLine) line);

      // add PK fields to sales tax if needed
      if (line.isSalesTaxRequired()) {
        populateSalesTax(line);
      }
    }
  }
  /** @param transForm */
  protected void processAccountingLineOverrides(KualiAccountingDocumentFormBase transForm) {
    processAccountingLineOverrides(transForm.getNewSourceLine());
    processAccountingLineOverrides(transForm.getNewTargetLine());
    if (transForm.hasDocumentId()) {
      AccountingDocument financialDocument = (AccountingDocument) transForm.getDocument();

      processAccountingLineOverrides(
          financialDocument, financialDocument.getSourceAccountingLines());
      processAccountingLineOverrides(
          financialDocument, financialDocument.getTargetAccountingLines());
    }
  }
  /**
   * This method refreshes the sales tax fields on a refresh or tab toggle so that all the
   * information that was there before is still there after a state change
   *
   * @param form
   */
  protected void refreshSalesTaxInfo(ActionForm form) {
    KualiAccountingDocumentFormBase accountingForm = (KualiAccountingDocumentFormBase) form;
    AccountingDocument document = (AccountingDocument) accountingForm.getDocument();
    List sourceLines = document.getSourceAccountingLines();
    List targetLines = document.getTargetAccountingLines();
    handleSalesTaxRequiredAllLines(accountingForm, sourceLines);
    handleSalesTaxRequiredAllLines(accountingForm, targetLines);

    AccountingLine newTargetLine = accountingForm.getNewTargetLine();
    AccountingLine newSourceLine = accountingForm.getNewSourceLine();
    if (newTargetLine != null) {
      handleSalesTaxRequired(document, newTargetLine, false, true, 0);
    }
    if (newSourceLine != null) {
      handleSalesTaxRequired(document, newSourceLine, true, true, 0);
    }
  }
  /**
   * Main hook point to perform rules check.
   *
   * @see
   *     org.kuali.rice.kns.rules.PromptBeforeValidationBase#doRules(org.kuali.rice.krad.document.Document)
   */
  @Override
  public boolean doPrompts(Document document) {
    AccountingDocument accountingDocument = (AccountingDocument) document;
    List<AccountingLine> accountingLines = accountingDocument.getSourceAccountingLines();
    accountingLines.addAll(accountingDocument.getTargetAccountingLines());

    CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) document;
    List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines();

    if (hasDifferentObjectSubTypes(capitalAccountingLines, accountingLines)) {
      if (!isOkHavingDifferentObjectSubTypes()) {
        event.setActionForwardName(KFSConstants.MAPPING_BASIC);
        return false;
      }
    }

    return true;
  }
  /**
   * This method determines whether we are uploading source or target lines, and then calls
   * uploadAccountingLines directly on the document object. This method handles retrieving the
   * actual upload file as an input stream into the document.
   *
   * @param isSource
   * @param form
   * @throws FileNotFoundException
   * @throws IOException
   */
  protected void uploadAccountingLines(boolean isSource, ActionForm form)
      throws FileNotFoundException, IOException {
    KualiAccountingDocumentFormBase tmpForm = (KualiAccountingDocumentFormBase) form;

    List importedLines = null;

    AccountingDocument financialDocument = tmpForm.getFinancialDocument();
    AccountingLineParser accountingLineParser = financialDocument.getAccountingLineParser();

    // import the lines
    String errorPathPrefix = null;
    try {
      if (isSource) {
        errorPathPrefix =
            KFSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSConstants.SOURCE_ACCOUNTING_LINE_ERRORS;
        FormFile sourceFile = tmpForm.getSourceFile();
        checkUploadFile(sourceFile);
        importedLines =
            accountingLineParser.importSourceAccountingLines(
                sourceFile.getFileName(), sourceFile.getInputStream(), financialDocument);
      } else {
        errorPathPrefix =
            KFSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSConstants.TARGET_ACCOUNTING_LINE_ERRORS;
        FormFile targetFile = tmpForm.getTargetFile();
        checkUploadFile(targetFile);
        importedLines =
            accountingLineParser.importTargetAccountingLines(
                targetFile.getFileName(), targetFile.getInputStream(), financialDocument);
      }
    } catch (AccountingLineParserException e) {
      GlobalVariables.getMessageMap()
          .putError(errorPathPrefix, e.getErrorKey(), e.getErrorParameters());
    }

    // add line to list for those lines which were successfully imported
    if (importedLines != null) {
      for (Iterator i = importedLines.iterator(); i.hasNext(); ) {
        AccountingLine importedLine = (AccountingLine) i.next();
        insertAccountingLine(isSource, tmpForm, importedLine);
      }
    }
  }
  /**
   * Looks up what should be the method on the AccountingDocument class that returns the group title
   *
   * @return
   */
  protected Method discoverGroupTitleMethod(AccountingDocument document) {
    Method groupTitleMethod = null;
    try {
      String methodName =
          new StringBuilder()
              .append("get")
              .append(accountingLineGroupPropertyName.substring(0, 1).toUpperCase())
              .append(accountingLineGroupPropertyName.substring(1))
              .append("SectionTitle")
              .toString();
      groupTitleMethod = document.getClass().getMethod(methodName, new Class[0]);
    } catch (SecurityException se) {
      throw new RuntimeException(se);
    } catch (NoSuchMethodException nsme) {
      throw new RuntimeException(nsme);
    }

    return groupTitleMethod;
  }
  /**
   * This method checks to see if this doctype needs sales tax If it does then it checks to see if
   * the account and object code require sales tax If it does then it returns true. Note - this is
   * hackish as we shouldn't have to call rules directly from the action class But we need to in
   * this instance because we are copying the lines before calling rules and need a way to modify
   * them before they go on
   *
   * @param accountingLine
   * @return true if sales tax check is needed, false otherwise
   */
  protected boolean isSalesTaxRequired(
      AccountingDocument financialDocument, AccountingLine accountingLine) {
    boolean required = false;
    String docType =
        SpringContext.getBean(DataDictionaryService.class)
            .getDocumentTypeNameByClass(financialDocument.getClass());
    // first we need to check just the doctype to see if it needs the sales tax check
    ParameterService parameterService = SpringContext.getBean(ParameterService.class);
    // apply the rule, see if it fails
    ParameterEvaluator docTypeSalesTaxCheckEvaluator = /*REFACTORME*/
        SpringContext.getBean(ParameterEvaluatorService.class)
            .getParameterEvaluator(
                KfsParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class,
                APPLICATION_PARAMETER.DOCTYPE_SALES_TAX_CHECK,
                docType);
    if (docTypeSalesTaxCheckEvaluator.evaluationSucceeds()) {
      required = true;
    }

    // second we need to check the account and object code combination to see if it needs sales tax
    if (required) {
      // get the object code and account
      String objCd = accountingLine.getFinancialObjectCode();
      String account = accountingLine.getAccountNumber();
      if (!StringUtils.isEmpty(objCd) && !StringUtils.isEmpty(account)) {
        String compare = account + ":" + objCd;
        ParameterEvaluator salesTaxApplicableAcctAndObjectEvaluator = /*REFACTORME*/
            SpringContext.getBean(ParameterEvaluatorService.class)
                .getParameterEvaluator(
                    KfsParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class,
                    APPLICATION_PARAMETER.SALES_TAX_APPLICABLE_ACCOUNTS_AND_OBJECT_CODES,
                    compare);
        if (!salesTaxApplicableAcctAndObjectEvaluator.evaluationSucceeds()) {
          required = false;
        }
      } else {
        // the two fields are currently empty and we don't need to check yet
        required = false;
      }
    }
    return required;
  }
  /**
   * Check for zero amount, or negative on original (non-correction) document; no sign check for
   * documents that are corrections to previous documents <strong>the accounting document must be
   * the first parameter, the accounting line must be the second parameter</strong>
   *
   * @see org.kuali.kfs.sys.document.validation.GenericValidation#validate(java.lang.Object[])
   */
  @Override
  public boolean validate(AttributedDocumentEvent event) {
    KualiDecimal amount = accountingLineForValidation.getAmount();
    String correctsDocumentId =
        accountingDocumentForValidation
            .getFinancialSystemDocumentHeader()
            .getFinancialDocumentInErrorNumber();

    if (amount != null) {
      if (KualiDecimal.ZERO.compareTo(amount) == 0) { // amount == 0
        GlobalVariables.getMessageMap()
            .putError(AMOUNT_PROPERTY_NAME, ERROR_ZERO_AMOUNT, "an accounting line");
        return false;
      } else {
        if (null == correctsDocumentId && KualiDecimal.ZERO.compareTo(amount) == 1) { // amount < 0
          GlobalVariables.getMessageMap()
              .putError(AMOUNT_PROPERTY_NAME, ERROR_INVALID_NEGATIVE_AMOUNT_NON_CORRECTION);
          return false;
        }
      }
    }

    return true;
  }
  /**
   * If there are line restrictions and the initiator override flag is turned on, we need to disable
   * the copy and error correct buttons since those would result in documents displaying the
   * restricted lines
   *
   * @see
   *     org.kuali.rice.kns.document.authorization.DocumentAuthorizer#getDocumentActions(org.kuali.rice.kns.document.Document,
   *     org.kuali.rice.kim.bo.Person, java.util.Set)
   */
  public Set<String> getDocumentActions(
      Document document, Person user, Set<String> documentActions) {
    Set<String> documentActionsToReturn =
        documentAuthorizer.getDocumentActions(document, user, documentActions);

    AccessSecurityService securityService = SpringContext.getBean(AccessSecurityService.class);

    boolean alwaysAllowInitiatorAccess =
        SpringContext.getBean(ParameterService.class)
            .getIndicatorParameter(
                SecConstants.ACCESS_SECURITY_NAMESPACE_CODE,
                SecConstants.ALL_PARAMETER_DETAIL_COMPONENT,
                SecConstants.SecurityParameterNames.ALWAYS_ALLOW_INITIATOR_LINE_ACCESS_IND);
    if (alwaysAllowInitiatorAccess) {
      // determine if any lines are view restricted
      boolean hasViewRestrictions = false;

      AccountingDocument accountingDocument = (AccountingDocument) document;
      for (Iterator iterator = accountingDocument.getSourceAccountingLines().iterator();
          iterator.hasNext(); ) {
        AccountingLine line = (AccountingLine) iterator.next();
        if (!securityService.canViewDocumentAccountingLine(accountingDocument, line, user)) {
          hasViewRestrictions = true;
          break;
        }
      }

      if (!hasViewRestrictions) {
        for (Iterator iterator = accountingDocument.getTargetAccountingLines().iterator();
            iterator.hasNext(); ) {
          AccountingLine line = (AccountingLine) iterator.next();
          if (!securityService.canViewDocumentAccountingLine(accountingDocument, line, user)) {
            hasViewRestrictions = true;
            break;
          }
        }
      }

      // if we have restrictions then disable copy and error correction
      if (hasViewRestrictions) {
        if (documentActionsToReturn.contains(KNSConstants.KUALI_ACTION_CAN_COPY)) {
          documentActionsToReturn.remove(KNSConstants.KUALI_ACTION_CAN_COPY);
          GlobalVariables.getMessageMap()
              .putInfo(
                  KFSConstants.GLOBAL_ERRORS,
                  SecKeyConstants.MESSAGE_DOCUMENT_COPY_RESTRICTED,
                  (String) null);
        }

        if (documentActionsToReturn.contains(KFSConstants.KFS_ACTION_CAN_ERROR_CORRECT)) {
          documentActionsToReturn.remove(KFSConstants.KFS_ACTION_CAN_ERROR_CORRECT);
          GlobalVariables.getMessageMap()
              .putInfo(
                  KFSConstants.GLOBAL_ERRORS,
                  SecKeyConstants.MESSAGE_DOCUMENT_ERROR_CORRECT_RESTRICTED,
                  (String) null);
        }
      }
    }

    return documentActionsToReturn;
  }