org.sakaiproject.tool.assessment.rsf.producers.BeginAssessmentProducer.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.tool.assessment.rsf.producers.BeginAssessmentProducer.java

Source

/**********************************************************************************
 * $URL$
 * $Id$
 **********************************************************************************
 *
 * Copyright (c) 2006, 2007, 2008, 2009 The Sakai Foundation
 * 
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **********************************************************************************/

package org.sakaiproject.tool.assessment.rsf.producers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.tool.assessment.data.dao.authz.AuthorizationData;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentMetaDataIfc;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade;
import org.sakaiproject.tool.assessment.rsf.params.BeginAssessmentViewParameters;
import org.sakaiproject.tool.assessment.services.PersistenceService;
import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService;
import org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean;
import org.sakaiproject.tool.assessment.ui.bean.shared.PersonBean;
import org.sakaiproject.tool.assessment.ui.listener.delivery.BeginDeliveryActionListener;
import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;

import uk.org.ponder.messageutil.MessageLocator;
import uk.org.ponder.rsf.components.UIBranchContainer;
import uk.org.ponder.rsf.components.UICommand;
import uk.org.ponder.rsf.components.UIContainer;
import uk.org.ponder.rsf.components.UIForm;
import uk.org.ponder.rsf.components.UIOutput;
import uk.org.ponder.rsf.components.decorators.UIFreeAttributeDecorator;
import uk.org.ponder.rsf.components.decorators.UITooltipDecorator;
import uk.org.ponder.rsf.flow.jsfnav.NavigationCase;
import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter;
import uk.org.ponder.rsf.view.ComponentChecker;
import uk.org.ponder.rsf.view.DefaultView;
import uk.org.ponder.rsf.view.ViewComponentProducer;
import uk.org.ponder.rsf.viewstate.SimpleViewParameters;
import uk.org.ponder.rsf.viewstate.ViewParameters;
import uk.org.ponder.rsf.viewstate.ViewParamsReporter;

/**
 * Producer to show basic Assessment info and allow the user (student) to begin the assessment if
 * they want. Also ensures that the user is logged in and has the proper authorization as well as
 * that the assessment is currently available.
 * 
 * This code contains some parts I'd rather not have to do in order to pass control off from RSF to
 * JSF... please don't judge, but feel free to propose better solutions or rewrite delivery in RSF
 * completely ;-)
 * 
 * @author Joshua Ryan  josh@asu.edu   alt^I
 * 
 */
public class BeginAssessmentProducer
        implements ViewComponentProducer, NavigationCaseReporter, DefaultView, ViewParamsReporter {

    public HttpServletRequest httpServletRequest;
    public HttpServletResponse httpServletResponse;
    public MessageLocator messageLocator;

    private static Log log = LogFactory.getLog(BeginAssessmentProducer.class);

    public static final String VIEW_ID = "BeginTakingAssessment";

    public String getViewID() {
        return VIEW_ID;
    }

    public void fillComponents(UIContainer tofill, ViewParameters viewparams, ComponentChecker checker) {
        BeginAssessmentViewParameters params = null;
        String alias = "";
        if (viewparams != null) {
            params = (BeginAssessmentViewParameters) viewparams;
            alias = params.pubReference;
        } else {
            log.warn("Something bad... we have no viewparams");
            return;
        }

        //Begin cut and past (with small deviations) from existing LoginServlet that currently does
        //the job of url aliased assessment delivery in Samigo, some of this could possibly be removed
        //unless this just replaces the LoginServlet someday.

        HttpSession httpSession = httpServletRequest.getSession(true);
        httpSession.setMaxInactiveInterval(3600); // one hour
        PersonBean person = (PersonBean) ContextUtil.lookupBeanFromExternalServlet("person", httpServletRequest,
                httpServletResponse);
        // we are going to use the delivery bean to flag that this access is via url
        // this is the flag that we will use in deliverAssessment.jsp to decide what
        // button to display - daisyf
        DeliveryBean delivery = (DeliveryBean) ContextUtil.lookupBeanFromExternalServlet("delivery",
                httpServletRequest, httpServletResponse);
        // For SAK-7132. 
        // As this class is only used for taking assessment via URL, 
        // there should not be any assessment grading data at this point
        delivery.setAssessmentGrading(null);
        delivery.setActionString("takeAssessmentViaUrl");

        // reset timer in case this is a timed assessment
        delivery.setTimeElapse("0");
        delivery.setLastTimer(0);
        delivery.setTimeLimit("0");
        delivery.setBeginAssessment(true);

        delivery.setNumberRetake(-1);
        delivery.setActualNumberRetake(-1);

        // set path
        delivery.setContextPath(httpServletRequest.getContextPath());

        // 1. get publishedAssessment and check if anonymous is allowed
        // 2. If so, goto welcome.faces
        // 3. If not, goto login.faces
        // both pages will set agentId and then direct user to BeginAssessment
        PublishedAssessmentService service = new PublishedAssessmentService();
        PublishedAssessmentFacade pub = null;
        try {
            pub = service.getPublishedAssessment(alias);
        } catch (Exception e) {
            log.warn("Something bad... can't find publisehd assessment " + e);
            return;
        }

        delivery.setAssessmentId(pub.getPublishedAssessmentId().toString());
        delivery.setAssessmentTitle(pub.getTitle());
        delivery.setHonorPledge(pub.getAssessmentMetaDataByLabel("honorpledge_isInstructorEditable") != null && pub
                .getAssessmentMetaDataByLabel("honorpledge_isInstructorEditable").toLowerCase().equals("true"));
        delivery.setPublishedAssessment(pub);

        String path = null;

        String agentIdString = "";
        boolean isAuthorized = false;
        boolean isAuthenticated = false;

        // Determine if assessment accept Anonymous Users. If so, starting in version 2.0.1
        // all users will be authenticated as anonymous for the assessment in this case.
        //boolean anonymousAllowed = false;
        String releaseTo = pub.getAssessmentAccessControl().getReleaseTo();
        if (releaseTo != null && releaseTo.indexOf("Anonymous Users") > -1) {
            //anonymousAllowed = true;
            agentIdString = AgentFacade.createAnonymous();
            isAuthenticated = true;
            isAuthorized = true;
            delivery.setAnonymousLogin(true);
            person.setAnonymousId(agentIdString);
        } else { // check membership
            agentIdString = httpServletRequest.getRemoteUser();
            isAuthenticated = (agentIdString != null && !("").equals(agentIdString));
            if (isAuthenticated) {
                isAuthorized = checkMembership(pub);
                // in 2.2, agentId is differnt from httpServletRequest.getRemoteUser()
                agentIdString = AgentFacade.getAgentString();
            }
        }

        log.debug("*** agentIdString: " + agentIdString);

        // check if assessment is available
        // We are getting the total no. of submission (for grade) per assessment
        // by the given agent at the same time
        boolean assessmentIsAvailable = assessmentIsAvailable(service, agentIdString, pub, delivery);
        if (isAuthorized) {
            if (!assessmentIsAvailable) {
                UIBranchContainer.make(tofill, "assessmentNotAvailable:");
                // TODO added info on why
            } else {
                // if assessment is available, set it in delivery bean for display in deliverAssessment.jsp
                BeginDeliveryActionListener listener = new BeginDeliveryActionListener();
                listener.processAction(null);

                UIForm form = UIForm.make(tofill, "takeAssessmentForm:");

                String url = "/samigo-app/servlet/Login?id="
                        + pub.getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.ALIAS) + "&fromDirect=true";

                UICommand.make(form, "takeAssessment", messageLocator.getMessage("begin_assessment_"), null)
                        .decorate(new UITooltipDecorator(messageLocator.getMessage("begin_assessment_")))
                        .decorate(new UIFreeAttributeDecorator("onclick", "window.location.href='" + url + "'"));
                //UILink.make(form, "takeAssessment", url);

                UIOutput.make(form, "assessmentTitle", delivery.getAssessmentTitle());
                UIOutput.make(form, "courseName", delivery.getCourseName());
                UIOutput.make(form, "creatorName", delivery.getCreatorName());

                if (delivery.getHasTimeLimit()) {
                    UIBranchContainer timeLimit = UIBranchContainer.make(form, "timeLimit:");
                    UIOutput.make(timeLimit, "timeLimit", delivery.getTimeLimit());
                    UIOutput.make(timeLimit, "timeLimitHour", delivery.getTimeLimit_hour() + "");
                    UIOutput.make(timeLimit, "timeLimitMin", delivery.getTimeLimit_minute() + "");
                } else {
                    UIBranchContainer noTimeLimit = UIBranchContainer.make(form, "noTimeLimit:");
                    UIOutput.make(noTimeLimit, "timeLimit", delivery.getTimeLimit());
                }

                if (!delivery.getAnonymousLogin() && !delivery.getSettings().isUnlimitedAttempts()) {
                    UIBranchContainer limited = UIBranchContainer.make(tofill, "limited:");
                    UIOutput.make(limited, "maxAttempts", delivery.getSettings().getMaxAttempts() + "");
                    UIOutput.make(limited, "remaining", delivery.getSubmissionsRemaining() + "");
                } else if (!delivery.getAnonymousLogin() && delivery.getSettings().isUnlimitedAttempts()) {
                    UIBranchContainer.make(tofill, "unlimited:");
                }

                if (delivery.getDueDate() != null) {
                    UIBranchContainer duedate = UIBranchContainer.make(tofill, "duedate:");
                    UIOutput.make(duedate, "duedate", delivery.getDueDateString());
                }
            }
        } else { // notAuthorized
            if (!isAuthenticated) {
                delivery.setActionString(null);
                try {
                    path = "/authn/login?url=" + URLEncoder
                            .encode(httpServletRequest.getRequestURL().toString() + "?pubId=" + alias, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    log.error("Encoding not suppoorted, " + e.getMessage());
                }
                log.info("** servlet path=" + httpServletRequest.getRequestURL().toString());
                String url = httpServletRequest.getRequestURL().toString();
                String context = httpServletRequest.getContextPath();
                String finalUrl = url.substring(0, url.lastIndexOf(context)) + path;
                log.info("**** finalUrl = " + finalUrl);
                try {
                    httpServletResponse.sendRedirect(finalUrl);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else { //isAuthenticated but not authorized
                UIBranchContainer.make(tofill, "accessDenied:");
                // TODO added info on why
            }
        }

        //End cut and paste from LoginServlet (with small deviations)
    }

    private boolean checkMembership(PublishedAssessmentFacade pub) {
        boolean isMember = false;
        // get list of site that this published assessment has been released to
        List l = PersistenceService.getInstance().getAuthzQueriesFacade().getAuthorizationByFunctionAndQualifier(
                "VIEW_PUBLISHED_ASSESSMENT", pub.getPublishedAssessmentId().toString());
        for (int i = 0; i < l.size(); i++) {
            String siteId = ((AuthorizationData) l.get(i)).getAgentIdString();
            isMember = PersistenceService.getInstance().getAuthzQueriesFacade().checkMembership(siteId);
            if (isMember)
                break;
        }
        return isMember;
    }

    // check if assessment is available based on criteria like
    // dueDate
    public boolean assessmentIsAvailable(PublishedAssessmentService service, String agentIdString,
            PublishedAssessmentFacade pub, DeliveryBean delivery) {
        boolean assessmentIsAvailable = false;
        String nextAction = delivery.checkBeforeProceed();
        log.debug("nextAction=" + nextAction);
        if (("safeToProceed").equals(nextAction)) {
            assessmentIsAvailable = true;
        }
        return assessmentIsAvailable;
    }

    public ViewParameters getViewParameters() {
        return new BeginAssessmentViewParameters();
    }

    public List reportNavigationCases() {
        List togo = new ArrayList();
        togo.add(new NavigationCase(null, new SimpleViewParameters(VIEW_ID)));

        return togo;
    }

    public void setMessageLocator(MessageLocator messageLocator) {
        this.messageLocator = messageLocator;
    }
}