/**
   * Retrieves the current logged user based on the session key.
   *
   * @param session http session holding currently logged username.
   * @return User instance representing currently logged user.
   * @throws IllegalArgumentException if session is null.
   * @throws OPMException if there is any problem when executing the method.
   */
  protected User getCurrentUser(HttpSession session) throws OPMException {
    String signature = CLASS_NAME + "#getCurrentUser(HttpSession session)";

    LoggingHelper.logEntrance(logger, signature, new String[] {"session"}, new Object[] {session});

    Helper.checkNull(logger, signature, session, "session");

    try {
      String loggedUsername = (String) session.getAttribute(userSessionKey);

      User result = userService.getByUsername(loggedUsername);

      LoggingHelper.logExit(logger, signature, new Object[] {result});
      return result;
    } catch (IllegalArgumentException e) {
      throw LoggingHelper.logException(
          logger,
          signature,
          new OPMException(
              "The attribute of key '" + userSessionKey + "' can't be null/empty.", e));
    } catch (ClassCastException e) {
      throw LoggingHelper.logException(
          logger,
          signature,
          new OPMException("The attribute of key '" + userSessionKey + "' should be a string.", e));
    }
  }
  /**
   * This method is responsible for populating the model and view with the data about enabled
   * widgets.
   *
   * @param session current http session.
   * @param modelAndView the ModelAndView instance to populate
   * @return The populated ModelAndView instance.
   * @throws IllegalArgumentException if session or modelAndView instance is null.
   * @throws OPMException if there is any problem when executing the method.
   */
  protected ModelAndView populateModelAndView(HttpSession session, ModelAndView modelAndView)
      throws OPMException {
    String signature =
        CLASS_NAME + "#populateModelAndView(HttpSession session, ModelAndView modelAndView)";

    LoggingHelper.logEntrance(
        logger,
        signature,
        new String[] {"session", "modelAndView"},
        new Object[] {session, modelAndView});

    Helper.checkNull(logger, signature, modelAndView, "modelAndView");

    User user = getCurrentUser(session);
    if (user == null) {
      throw LoggingHelper.logException(
          logger, signature, new OPMException("The user is not logged in."));
    }
    for (String widgetId : widgetIds) {
      try {
        securityService.authorize(
            user.getUsername(), Arrays.asList(user.getRole().getName()), widgetId);
        modelAndView.addObject(widgetId, true);
      } catch (AuthorizationException e) {
        modelAndView.addObject(widgetId, false);
      }
    }

    LoggingHelper.logExit(logger, signature, new Object[] {modelAndView});
    return modelAndView;
  }
 /**
  * Checks the user request.
  *
  * @param logger the logger object.
  * @param signature the signature of the method to be logged.
  * @param invalidStates the states of user request.
  * @param messages the messages
  * @param errorMessage the error message
  * @throws ValidationException if any error occurs
  */
 public static void checkRequest(
     Logger logger,
     String signature,
     boolean[] invalidStates,
     String[] messages,
     String errorMessage)
     throws ValidationException {
   List<String> details = new ArrayList<String>();
   for (int i = 0; i < invalidStates.length; i++) {
     if (invalidStates[i]) {
       details.add(messages[i]);
     }
   }
   if (!details.isEmpty()) {
     throw LoggingHelper.logException(
         logger, signature, new ValidationException(errorMessage, details));
   }
 }
  /**
   * Resolves the exception and sets proper http code.
   *
   * @param request the http servlet request
   * @param response the http servlet response
   * @param handler the handler object
   * @param exception the thrown exception
   * @return Resulting ModelAndView to show to user
   */
  public ModelAndView resolveException(
      HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      Exception exception) {
    String signature =
        CLASS_NAME
            + "#resolveException(HttpServletRequest request, HttpServletResponse response,"
            + " Object handler, Exception exception)";

    LoggingHelper.logEntrance(
        logger,
        signature,
        new String[] {"request", "response", "handler", "exception"},
        new Object[] {request, response, handler, exception});

    ModelAndView result;
    // Perform the check only for AJAX requests
    if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
      try {
        String message = exception.getMessage();
        if (exception instanceof ValidationException) {
          response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        } else if (exception instanceof AuthorizationException) {
          response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        } else {
          response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
        // Write exception message to response
        response.getWriter().print(message);
      } catch (IOException e) {
        // Log and ignore the exception
        LoggingHelper.logException(logger, signature, e);
      }
      result = new ModelAndView();
    } else {
      // Return error page
      result = new ModelAndView("error");
    }

    LoggingHelper.logExit(logger, signature, new Object[] {result});
    return result;
  }
  /**
   * Executes the rules to the service periods to calculate their deductions. This methods also
   * merges the service period to extended service period.
   *
   * @param request that contains the service periods to calculate.
   * @return the response of the extended service periods with calculated deductions (and also
   *     earnings, mid-point etc.).
   * @throws IllegalArgumentException if the request is null.
   * @throws RuleServiceException if any error occurs when executing the rule.
   */
  @Override
  public DeductionCalculationResponse execute(DeductionCalculationRequest request)
      throws RuleServiceException {

    // log the entrance
    String signature = CLASS_NAME + "#execute(DeductionCalculationRequest request)";
    LoggingHelper.logEntrance(
        getLogger(), signature, new String[] {"request"}, new Object[] {request});

    // validate the parameters
    ServiceHelper.checkNull(request, "request");

    StatefulKnowledgeSession ksession = null;
    KnowledgeRuntimeLogger logger = null;

    try {
      // start new session and the file logger
      ksession = getKnowledgeBase().newStatefulKnowledgeSession();

      logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, getKnowledgeLogFileName());

      // Set global variables
      List<ExtendedServicePeriod> esps = new ArrayList<ExtendedServicePeriod>();
      ksession.setGlobal(EXTENDED_SERVICE_PERIODS, esps);
      ksession.setGlobal(
          SERVICE_PERIOD_SPLIT_DATES,
          servicePeriodSplitDates == null ? Collections.EMPTY_LIST : servicePeriodSplitDates);

      // Populate facts
      for (ServicePeriod sp : request.getServicePeriods()) {
        ksession.insert(sp);
      }

      // Start deduction process
      ksession.startProcess("Deduction");

      // Fire all rules
      ksession.fireAllRules();

      // populate the final result
      DeductionCalculationResponse response = new DeductionCalculationResponse();

      response.setExtendedServicePeriods(esps);

      ksession.dispose();

      // log and return
      LoggingHelper.logExit(getLogger(), signature, new Object[] {response});

      return response;

    } catch (RuntimeException e) {
      // log the exception and wrap it to RuleServiceException
      throw LoggingHelper.logException(
          getLogger(),
          signature,
          new RuleServiceException("Unable to complete rule execution.", e));
    } finally {
      // closes the resources
      if (logger != null) {
        logger.close();
      }

      if (ksession != null) {
        ksession.dispose();
      }
    }
  }