velo.ejb.seam.action.SelfServiceAccessRequestActionsBean.java Source code

Java tutorial

Introduction

Here is the source code for velo.ejb.seam.action.SelfServiceAccessRequestActionsBean.java

Source

/**
 * Copyright (c) 2000-2007, Shakarchi Asaf
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package velo.ejb.seam.action;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.application.FacesMessage;
import javax.persistence.EntityManager;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.bpm.BeginTask;
import org.jboss.seam.annotations.bpm.CreateProcess;
import org.jboss.seam.annotations.bpm.EndTask;
import org.jboss.seam.annotations.bpm.ResumeProcess;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;
import org.jbpm.graph.exe.ProcessInstance;

import velo.ejb.interfaces.AccountManagerLocal;
import velo.ejb.interfaces.EmailManagerLocal;
import velo.ejb.interfaces.RequestManagerLocal;
import velo.ejb.interfaces.UserManagerLocal;
import velo.ejb.seam.RequestHome;
import velo.entity.EmailTemplate;
import velo.entity.Request;
import velo.entity.RequestUserComment;
import velo.entity.SelfServiceAccessRequest;
import velo.entity.User;
import velo.entity.Request.RequestStatus;
import velo.exceptions.ExpressionCreationException;
import velo.exceptions.RequestCreationException;
import velo.tools.EdmEmailSender;

@Stateful
@Name("selfServiceAccessRequestActions")
public class SelfServiceAccessRequestActionsBean implements SelfServiceAccessRequestActions {
    //constants
    private final String requesterFinalRejectEmailTemplateName = "REQUESTER_FINAL_REQUEST_REJECT";
    private final String requesterFinalApproveEmailTemplateName = "REQUESTER_FINAL_REQUEST_APPROVAL";
    private final String approverNewApprovalTaskEmailTemplateName = "APPROVER_NEW_APPROVAL_TASK";
    private final String requesterSuccessRequestCreationEmailTemplateName = "REQUESTER_SUCCESS_REQUEST_CREATION";

    //@In(value="#{identity.username}")
    //String loggedUserName;

    @In
    User loggedUser;

    @Logger
    private Log log;

    @In
    FacesMessages facesMessages;

    //@PersistenceContext
    @In
    public EntityManager entityManager;

    @EJB
    public UserManagerLocal userManager;

    @EJB
    public AccountManagerLocal accountManager;

    @EJB
    public RequestManagerLocal requestManager;

    @EJB
    public EmailManagerLocal emailManager;

    @Out(scope = ScopeType.CONVERSATION, required = false)
    private SelfServiceAccessRequest selfServiceRequest = new SelfServiceAccessRequest();

    @In(required = false)
    ProcessInstance processInstance;

    @Out(scope = ScopeType.BUSINESS_PROCESS, required = false)
    long requestId;

    @In(create = true)
    RequestHome requestHome;

    @In(required = false, create = true, value = "#{selfServiceHomePageActions}")
    SelfServiceHomePageActions selfServiceHomePageActions;

    @DataModel(value = "ssMyLastRequestedRequests")
    List<Request> ssMyLastRequestedRequests;

    @DataModelSelection(value = "ssMyLastRequestedRequests")
    Request selectedRequest;

    private String approvalTaskComment;

    /**
     * @return the request
     */
    public SelfServiceAccessRequest getRequest() {
        return selfServiceRequest;
    }

    /**
     * @param request the request to set
     */
    public void setRequest(SelfServiceAccessRequest selfServiceRequest) {
        this.selfServiceRequest = selfServiceRequest;
    }

    public String accessIsRequestedForMyself() {
        //try {
        //User myself = userManager.findUserByName(loggedUserName);
        //getRequest().setRequestedAccessForUser(myself);
        getRequest().setRequestedAccessForUser(loggedUser);
        //} catch (NoResultFoundException e) {
        //facesMessages.add(FacesMessage.SEVERITY_ERROR,"Cannot request access for myself, an internal error has occured while trying to load my user named: " + loggedUser.getName() + ", error message: " + e.toString());
        //return null;
        //}

        return "myself";
    }

    public String accessIsRequestedForOtherUser() {
        return "anotherUser";
    }

    public String setUserThatHasMyAccess(User user) {
        //Make sure that the selected user is not the same as the logged user
        if (loggedUser.getName().equalsIgnoreCase(user.getName())) {
            facesMessages.add(FacesMessage.SEVERITY_WARN, "Cannot request access as youself...");

            //there's no such a transition, so the current page will re-render.
            return "stay";
        }

        getRequest().setUserThatHasMyAccess(user);

        return null;
    }

    @CreateProcess(definition = "approveSelfServiceRequest", processKey = "#{selfServiceRequest.requestId}")
    @End
    public String submitRequest() {
        log.debug("Submitting self service reuqest...");
        try {
            //validate request
            if (!selfServiceRequest.isGrantAccessImmediately()) {
                if ((selfServiceRequest.getGrantAccessDate() == null)
                        || (selfServiceRequest.getGrantAccessHour() == null)) {
                    facesMessages.add(FacesMessage.SEVERITY_WARN,
                            "Please select 'immediate access' or select a required grant access date");
                    return null;
                }
            }

            //User loggedUserFromSession = (User)Contexts.getSessionContext().get("loggedUser");
            //must to be managed, notifyEmail/Event Responses uses lazily collections (such as attrs)
            //User loggedUser = entityManager.find(User.class,loggedUserFromSession.getUserId());
            User loggedUserManaged = entityManager.find(User.class, this.loggedUser.getUserId());

            selfServiceRequest.setCreationDate(new Date());
            selfServiceRequest.setRequester(loggedUserManaged);
            log.debug("Requester is '#0'", loggedUserManaged.getName());
            selfServiceRequest.setNotes("Self Service access request");
            selfServiceRequest.setStatus(RequestStatus.PENDING_APPROVAL);

            Calendar c = Calendar.getInstance();
            if (!selfServiceRequest.isGrantAccessImmediately()) {
                log.trace(
                        "Grant access is not flagged immediately, calculating grant access date via specified date/time");
                //YUCK
                //TODO: This is a workaround, until a nice calendar gui component with timeselection will be available
                //calculate 'access grant from' date
                c.setTime(selfServiceRequest.getGrantAccessDate());

                log.trace("Grant access hour: #0, minutes: #1", selfServiceRequest.getGrantAccessHour(),
                        selfServiceRequest.getGrantAccessMinutes());
                c.set(Calendar.HOUR, Integer.parseInt(selfServiceRequest.getGrantAccessHour()));
                c.set(Calendar.MINUTE, Integer.parseInt(selfServiceRequest.getGrantAccessMinutes()));
            } else {
                log.debug(
                        "No grant access date calculation is required, since grant access immediately was flagged");
            }

            selfServiceRequest.setGrantAccessDate(c.getTime());

            //replace with submitRequest method
            selfServiceRequest = requestManager.submitRequest(selfServiceRequest);
            facesMessages.add("Request successfully submitted!");

            selfServiceRequest.setInBusinessProcess(true);

            //outject the requestId to the business context
            requestId = selfServiceRequest.getRequestId();
            log.debug("Successfully submitted request ID '#0'", requestId);

            //send email
            notifyRequesterUponSuccessRequestCreation(selfServiceRequest);

            return "submitRequest";
        } catch (RequestCreationException e) {
            facesMessages.add(FacesMessage.SEVERITY_ERROR, "Cannot create request: " + e.toString());

            //there's no such a transition, so the current page will re-render. 
            return "ERROR";
        }
    }

    //task workflow methods
    @BeginTask
    public void reviewWorkflowTask() {
        log.debug("Reviewing current task...");
        //@In annotation does not work, it cause an IllegalArgumentException when this bean is first accessed for some reason
        requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
        log.info("Injected request ID form business process: " + requestId);
    }

    @EndTask(transition = "approve")
    public void approveWorkflowTask() {
        if (getApprovalTaskComment() != null) {
            if (getApprovalTaskComment().length() > 0) {
                User loggedUser = (User) Contexts.getSessionContext().get("loggedUser");
                requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
                requestHome = new RequestHome();
                requestHome.setRequestId(requestId);
                SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();
                RequestUserComment ruc = RequestUserComment.factory(loggedUser, getApprovalTaskComment());
                ruc.setRequest(req);
                entityManager.persist(ruc);

                //fucken create two log instances, why? is something wrong with the cascading/relationships here?
                //but it is the same as request.logs, what's wrong?
                //req.addRequestUserComment(loggedUser, getApprovalTaskComment());
                //requestManager.mergeRequestEntity(req);
            }
        }

        log.info("Task approved!");
    }

    //@EndTask(transition="reject")
    public String rejectWorkflowTask() {
        log.warn("!!!!!!!!!!!!!!!: " + getApprovalTaskComment().length());
        if (getApprovalTaskComment().length() > 1) {
            User loggedUser = (User) Contexts.getSessionContext().get("loggedUser");
            requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
            requestHome = new RequestHome();
            requestHome.setRequestId(requestId);
            SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();
            RequestUserComment ruc = RequestUserComment.factory(loggedUser, getApprovalTaskComment());
            ruc.setRequest(req);
            entityManager.persist(ruc);
            processInstance.signal("reject");
            facesMessages.add("Successfully rejected request!");
            log.info("Task rejected!");
            return "/ss/Home.seam";
        } else {
            facesMessages.add("Please specify reject reason.");
            return null;
        }
    }

    public void finalRequestApproval() {
        requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
        requestHome = new RequestHome();
        requestHome.setRequestId(requestId);
        SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();
        req.setStatus(RequestStatus.APPROVED);

        //TODO: Move to some more dynamic code (logic here is too strict)
        //calculate expiration date (should be moved to somewhere else, maybe into scripts? so it can be calculated more dynamically?)
        //handle expiration access date
        Calendar expDateCal = Calendar.getInstance();
        if (req.isGrantAccessImmediately()) {
            if (req.getAccessExpirationDateAmountType().equals("HOUR")) {
                expDateCal.add(Calendar.HOUR, req.getAccessExpirationDateAmount());
            }
        } else {
            expDateCal.setTime(req.getGrantAccessDate());
            if (req.getAccessExpirationDateAmountType().equals("HOUR")) {
                expDateCal.add(Calendar.HOUR, req.getAccessExpirationDateAmount());
            }
        }

        req.setExpirationAccessDate(expDateCal.getTime());
        log.debug("Access will be expired at: " + req.getExpirationAccessDate());

        requestManager.mergeRequestEntity(req);

        //send notifications
        notifyRequesterUponFinalRequestApproval(req);

        log.info("Successfully performed final approval of request ID #0", requestId);
    }

    public void finalRequestReject() {
        requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
        requestHome = new RequestHome();
        requestHome.setRequestId(requestId);
        SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();
        req.setStatus(RequestStatus.REJECTED);
        requestManager.mergeRequestEntity(req);

        //send notifications
        notifyRequesterUponFinalRequestReject(req);

        log.info("Successfully performed final reject of request ID #0", requestId);
    }

    //exposed for the workflow!
    public String[] assignPoolActors(Integer level) {
        log.debug("Determining request's pool actors for level: " + level);
        requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");

        requestHome = new RequestHome();
        requestHome.setRequestId(requestId);
        SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();

        //notify by email
        notifyApproverUponNewApprovalTask(req, level);

        return req.getPoolActors(level);
    }

    //exposed for the workflow!
    public String isThereApproversInLevel(Integer level) {
        log.debug("Determining whether there are approvers for approvers level #0", level);

        requestId = (Long) Contexts.getBusinessProcessContext().get("requestId");
        requestHome = new RequestHome();
        requestHome.setRequestId(requestId);

        SelfServiceAccessRequest req = (SelfServiceAccessRequest) requestHome.getInstance();

        if (req.isThereApproversInLevel(level)) {
            log.debug("There are approvers in level #0, returning 'yes'", level);
            return "yes";
        } else {
            log.debug("There are NO approvers in level #0, returning 'no'", level);
            return "no";
        }
    }

    //important, cannot pass only IDs as it is not secured
    @ResumeProcess(definition = "approveSelfServiceRequest", processKey = "#{ssMyLastRequestedRequests.rowData.requestId}")
    public void cancelRequest() {
        User loggedUser = (User) Contexts.getSessionContext().get("loggedUser");
        log.info("Logged in user obj: " + loggedUser);
        log.info("Request injected obj: " + selectedRequest);
        if (selectedRequest != null)
            log.info("Selected request ID: #0", selectedRequest.getRequestId());

        //security check: after reloading, make sure the requester of the request is really the logged in person
        Request r = entityManager.find(Request.class, selectedRequest.getRequestId());
        if (!r.getRequester().equals(loggedUser)) {
            //error!
            return;
        }

        r.setStatus(RequestStatus.CANCELLED);
        r.addLog("INFO", "Request was cancelled", "The request was cancelled by the requester!");
        processInstance.end();

        entityManager.merge(r);
        readMyLastRequestedRequests();
    }

    @Factory("ssMyLastRequestedRequests")
    public void readMyLastRequestedRequests() {
        //log.info("!!!!!!!!!!!!!!(1): " + selfServiceHomePageActions);
        //log.info("!!!!!!!!!!!!!!(2): " + selfServiceHomePageActions.getMyLastRequestedRequestsList());
        selfServiceHomePageActions.getMyLastRequestedRequestsList().refresh();
        ssMyLastRequestedRequests = selfServiceHomePageActions.getMyLastRequestedRequestsList().getResultList();
    }

    /**
     * @return the approvalTaskComment
     */
    public String getApprovalTaskComment() {
        return approvalTaskComment;
    }

    /**
     * @param approvalTaskComment the approvalTaskComment to set
     */
    public void setApprovalTaskComment(String approvalTaskComment) {
        this.approvalTaskComment = approvalTaskComment;
    }

    private void notifyRequesterUponSuccessRequestCreation(SelfServiceAccessRequest request) {
        notifyRequester(requesterSuccessRequestCreationEmailTemplateName, request);
    }

    private void notifyRequesterUponFinalRequestApproval(SelfServiceAccessRequest request) {
        notifyRequester(requesterFinalApproveEmailTemplateName, request);
    }

    private void notifyRequesterUponFinalRequestReject(SelfServiceAccessRequest request) {
        notifyRequester(requesterFinalRejectEmailTemplateName, request);
    }

    private void notifyApproverUponNewApprovalTask(SelfServiceAccessRequest request, int level) {
        EmailTemplate et = emailManager.findEmailTemplate(approverNewApprovalTaskEmailTemplateName);

        if (et == null) {
            log.warn("Could not send mail, expected email template named #0 does not exist",
                    approverNewApprovalTaskEmailTemplateName);
            return;
        }
        EdmEmailSender ees = new EdmEmailSender();

        et.addContentVar("requester", request.getRequester());
        et.addContentVar("request", request);

        String parsedContent = null;
        for (User currApprover : request.getApprovers(level)) {
            et.addContentVar("approver", currApprover);

            try {
                parsedContent = et.getParsedContent();
            } catch (ExpressionCreationException e) {
                log.warn("Could not parse expressions in email template #0: #1", et.getName(), e.toString());
                log.warn("Continuing to notify the next approver...");
                continue;
            }

            try {
                Email email = ees.factoryEmail(et.getSubject(), parsedContent);

                String currApproversEmailAddress = currApprover.getEmail();
                if (currApproversEmailAddress != null) {
                    email.addTo(currApproversEmailAddress);
                    ees.addEmail(email);
                } else {
                    log.info("Approver #0 has no email address, skipping approver notification...",
                            currApprover.getName());
                }
            } catch (EmailException e) {
                log.info("Skipping approver '#0' notification: #1", currApprover.getName(), e.toString());
            }
        }

        log.debug("Prepared #0 amount of emails to send, sending mails...");
        ees.send();
    }

    private void notifyRequester(String emailTemplateName, SelfServiceAccessRequest request) {
        EmailTemplate et = emailManager.findEmailTemplate(emailTemplateName);
        if (et == null) {
            log.warn("Could not send mail, expected email template named #0 does not exist", emailTemplateName);
            return;
        }

        EdmEmailSender ees = new EdmEmailSender();
        String emailAddress = request.getRequester().getEmail();

        //set email vars
        et.addContentVar("requester", request.getRequester());
        et.addContentVar("request", request);

        String parsedContent = null;
        try {
            parsedContent = et.getParsedContent();
        } catch (ExpressionCreationException e) {
            log.warn("Could not parse expressions in email template #0: #1", et.getName(), e.toString());
        }

        if (emailAddress == null) {
            log.warn("Could not send mail, user #0 does not have an email address!",
                    request.getRequester().getName());
            return;
        }
        try {
            ees.addHtmlEmail(emailAddress, et.getSubject(), parsedContent);
            ees.send();
        } catch (EmailException e) {
            log.error("Could not send email: #0", e.toString());
        }
    }

    @Destroy
    @Remove
    public void destroy() {
    }

}