tds.student.web.StudentContext.java Source code

Java tutorial

Introduction

Here is the source code for tds.student.web.StudentContext.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System 
 * Copyright (c) 2014 American Institutes for Research
 *     
 * Distributed under the AIR Open Source License, Version 1.0 
 * See accompanying file AIR-License-1_0.txt or at
 * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/
package tds.student.web;

import AIR.Common.TDSLogger.ITDSLogger;
import AIR.Common.Utilities.UrlEncoderDecoderUtils;
import AIR.Common.Web.Session.HttpContext;
import AIR.Common.Web.Session.MultiValueCookie;
import TDS.Shared.Security.TDSIdentity;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import tds.itemrenderer.data.AccLookup;
import tds.student.services.data.TestOpportunity;
import tds.student.sql.data.AccommodationType;
import tds.student.sql.data.AccommodationValue;
import tds.student.sql.data.Accommodations;
import tds.student.sql.data.OpportunityInfo;
import tds.student.sql.data.OpportunityInstance;
import tds.student.sql.data.TestConfig;
import tds.student.sql.data.TestSession;
import tds.student.sql.data.Testee;

/**
 * @author Milan Patel
 * 
 */
public class StudentContext {
    @Autowired
    private static ITDSLogger _tdsLogger;

    private final static String CACHE_PREFIX = "TDS_";
    private static final Logger _logger = LoggerFactory.getLogger(StudentContext.class);
    private static final String EXAM_ID_COOKIE_KEY = "EXAM_ID";
    private static final String EXAM_BROWSER_KEY = "EXAM_BROWSER_KEY";
    private static final String EXAM_CLIENT_NAME = "EXAM_CLIENT_NAME";
    private static final String EXAM_BROWSER_USER_AGENT = "EXAM_BROWSER_USER_AGENT";

    public static void throwMissingException() throws StudentContextException {
        throw new StudentContextException("Missing context info");
    }

    // TODO mpatel - implement this Method later based on Security framework
    public static boolean isAuthenticated() {
        return TDSIdentity.getCurrentTDSIdentity().isAuthenticated();
    }

    // / <summary>
    // / Check if a language is specified.
    // / </summary>
    public static boolean hasLanguage() {
        AccLookup accLookup = getAccLookup();
        return (accLookup != null && accLookup.hasType("Language"));
    }

    // / <summary>
    // / gets the language used for page internationalization (i18n)
    // / </summary>
    // / <returns>The selected language or ENU if nothing found.</returns>
    public static String getLanguage() {
        String language = null;

        // check if there are any test accommodations
        AccLookup accLookup = getAccLookup();

        // if there are test accommodations then they override what the student
        // selected on the page
        if (accLookup != null) {
            language = accLookup.getCode("Language");
            if (!StringUtils.isEmpty(language))
                return language;
        }

        return language != null ? language : "ENU";
    }

    public static void saveSession(TestSession session) {
        StudentCookie.setCookieData("S_KEY", session.getKey().toString());
        StudentCookie.setCookieData("S_ID", session.getId());
        StudentCookie.setCookieData("S_NAME", session.getName());
    }

    public static TestSession getSession() {
        if (!isAuthenticated())
            return null;

        // check if session exists
        TestSession testSession = new TestSession();
        testSession.setKey(UUID.fromString(StudentCookie.getCookieData("S_KEY")));
        testSession.setId(StudentCookie.getCookieData("S_ID"));
        testSession.setName(StudentCookie.getCookieData("S_NAME"));

        // check if session exists
        // if (testSession.getKey () == Guid.Empty) return null;
        if (testSession.getKey() == null)
            return null;

        return testSession;
    }

    public static void saveTestee(Testee testee) {
        StudentCookie.setCookieData("T_ID", testee.getId());
        StudentCookie.setCookieData("T_GR", testee.getGrade() != null ? testee.getGrade() : "");
        StudentCookie.setCookieData("T_FN", testee.getFirstName() != null ? testee.getFirstName() : "");
        StudentCookie.setCookieData("T_LN", testee.getLastName() != null ? testee.getLastName() : "");

        Map<String, String> secureValues = new HashMap<String, String>();
        secureValues.put("T_KEY", String.valueOf(testee.getKey()));
        TDSIdentity identity = TDSIdentity.createNew(testee.getId(), secureValues);
        identity.setAuthenticated(true);
        identity.saveAuthCookie();
    }

    public static Testee getTestee() {
        if (!isAuthenticated())
            return null;

        Testee testee = new Testee();

        String tKey = TDSIdentity.getCurrentTDSIdentity().get("T_KEY");

        if (tKey != null && !tKey.isEmpty()) {
            testee.setKey(Long.parseLong(tKey));
        }

        testee.setId(StudentCookie.getCookieData("T_ID"));
        testee.setGrade(StudentCookie.getCookieData("T_GR"));
        testee.setFirstName(StudentCookie.getCookieData("T_FN"));
        testee.setLastName(StudentCookie.getCookieData("T_LN"));

        // check if testee exists
        return (testee.getKey() != 0) ? testee : null;
    }

    public static void saveOppInfo(String testKey, String testID, OpportunityInfo oppInfo) {
        // TODO mpatel

        TDSIdentity.getCurrentTDSIdentity().setAuthCookieValue("O_TKEY", testKey);
        TDSIdentity.getCurrentTDSIdentity().setAuthCookieValue("O_TID", testID);

        if (oppInfo.getOppKey() != null) {
            TDSIdentity.getCurrentTDSIdentity().setAuthCookieValue("O_KEY", oppInfo.getOppKey().toString());
        }
        if (oppInfo.getBrowserKey() != null) {
            StudentCookie.setCookieData("O_BKEY", oppInfo.getBrowserKey().toString());
        }
        if (oppInfo.getExamClientName() != null) {
            TDSIdentity.getCurrentTDSIdentity().setAuthCookieValue(EXAM_CLIENT_NAME, oppInfo.getExamClientName());
        }
        if (oppInfo.getExamId() != null) {
            TDSIdentity.getCurrentTDSIdentity().setAuthCookieValue(EXAM_ID_COOKIE_KEY,
                    oppInfo.getExamId().toString());
        }
        TDSIdentity.getCurrentTDSIdentity().saveAuthCookie();
        if (oppInfo.getExamBrowserKey() != null) {
            StudentCookie.setCookieData(EXAM_BROWSER_KEY, oppInfo.getExamBrowserKey().toString());
        }
        if (oppInfo.getBrowerUserAgent() != null) {
            StudentCookie.setCookieData(EXAM_BROWSER_USER_AGENT, oppInfo.getBrowerUserAgent());
        }
    }

    // / <summary>
    // / save the opened test opportunity subject.
    // / </summary>
    public static void saveSubject(String subject) {
        StudentCookie.setCookieData("TI_S", subject);
    }

    // / <summary>
    // / get the opened test opportunity subject.
    // / </summary>
    public static String getSubject() {
        return StudentCookie.getCookieData("TI_S");
    }

    // / <summary>
    // / save the opened test opportunity grade.
    // / </summary>
    public static void saveGrade(String grade) {
        StudentCookie.setCookieData("TI_G", grade);
    }

    // / <summary>
    // / save the opened test opportunity grade.
    // / </summary>
    public static String getGrade() {
        return StudentCookie.getCookieData("TI_G");
    }

    public static OpportunityInstance getOppInstance() {
        if (!isAuthenticated()) {
            return null;
        }

        TDSIdentity tdsIdentity = TDSIdentity.getCurrentTDSIdentity();
        UUID oppKey = tdsIdentity.get("O_KEY") == null ? null : UUID.fromString(tdsIdentity.get("O_KEY"));

        UUID sessionKey = UUID.fromString(StudentCookie.getCookieData("S_KEY"));
        UUID browserKey = StudentCookie.getCookieData("O_BKEY") == null ? null
                : UUID.fromString(StudentCookie.getCookieData("O_BKEY"));

        UUID examBrowserKey = StudentCookie.getCookieData(EXAM_BROWSER_KEY) == null ? null
                : UUID.fromString(StudentCookie.getCookieData(EXAM_BROWSER_KEY));

        String browserUserAgent = StudentCookie.getCookieData(EXAM_BROWSER_USER_AGENT) == null ? null
                : StudentCookie.getCookieData(EXAM_BROWSER_USER_AGENT);

        UUID examId = tdsIdentity.get(EXAM_ID_COOKIE_KEY) == null ? null
                : UUID.fromString(tdsIdentity.get(EXAM_ID_COOKIE_KEY));

        String examClientName = tdsIdentity.get(EXAM_CLIENT_NAME);

        return new OpportunityInstance(oppKey, sessionKey, browserKey, examId, examBrowserKey, examClientName,
                browserUserAgent);
    }

    /**
     * Get the currently opened opportunity test key.
     * @return
     */
    public static String getTestKey() {
        return TDSIdentity.getCurrentTDSIdentity().get("O_TKEY");
    }

    /**
     *  Get the currently opened opportunity test id.
     * @return
     */
    public static String getTestID() {
        return TDSIdentity.getCurrentTDSIdentity().get("O_TID");
    }

    public static void saveTestConfig(TestConfig testConfig) {
        StudentCookie.setCookieData("TC_R", testConfig.getRestart());
        StudentCookie.setCookieData("TC_L", testConfig.getTestLength());
        StudentCookie.setCookieData("TC_IT", testConfig.getInterfaceTimeout());
        StudentCookie.setCookieData("TC_CLT", testConfig.getContentLoadTimeout());
        StudentCookie.setCookieData("TC_RIT", testConfig.getRequestInterfaceTimeout());
        StudentCookie.setCookieData("TC_ORM", testConfig.getOppRestartMins());
        StudentCookie.setCookieData("TC_SP", testConfig.getStartPosition());

        // new for 2012:
        StudentCookie.setCookieData("TC_P", testConfig.getPrefetch());
        StudentCookie.setCookieData("TC_SBT", testConfig.isScoreByTDS());
        StudentCookie.setCookieData("TC_VC", testConfig.isValidateCompleteness());

        StudentCookie.setCookieData("TC_MSB", testConfig.isMsb());
    }

    public static TestConfig getTestConfig() {
        TestConfig testConfig = new TestConfig();
        testConfig.setTestLength(StudentCookie.getCookieDataInt("TC_L"));
        testConfig.setInterfaceTimeout(StudentCookie.getCookieDataInt("TC_IT"));
        testConfig.setContentLoadTimeout(StudentCookie.getCookieDataInt("TC_CLT"));
        testConfig.setRequestInterfaceTimeout(StudentCookie.getCookieDataInt("TC_RIT"));
        testConfig.setOppRestartMins(StudentCookie.getCookieDataInt("TC_ORM"));
        testConfig.setStartPosition(StudentCookie.getCookieDataInt("TC_SP"));
        testConfig.setPrefetch(StudentCookie.getCookieDataInt("TC_P"));
        testConfig.setScoreByTDS(StudentCookie.getCookieDataBoolean("TC_SBT"));
        testConfig.setValidateCompleteness(StudentCookie.getCookieDataBoolean("TC_VC"));
        testConfig.setIsMsb(StudentCookie.getCookieDataBoolean("TC_MSB"));

        // check if test config exists
        return (testConfig.getTestLength() != 0) ? testConfig : null;
    }

    // / <summary>
    // / get the test opportunity information.
    // / </summary>
    // / <remarks>
    // / This is only available once you have started your test.
    // / </remarks>
    public static TestOpportunity getTestOpportunity() {
        if (!isAuthenticated())
            return null;

        // get test opp from cache
        TestOpportunity testOpp = (TestOpportunity) getCacheData("TestOpportunity");

        if (testOpp != null) {
            return testOpp;
        }

        // get opportunity data
        OpportunityInstance oppInstance = getOppInstance();
        if (oppInstance == null)
            return null;

        // get test key
        String testKey = getTestKey();
        String testID = getTestID();

        // check if test key exists
        if (testKey == null || testKey.isEmpty())
            return null;

        // get test config
        TestConfig testConfig = getTestConfig();
        if (testConfig == null)
            return null;

        // create testopp
        testOpp = new TestOpportunity(oppInstance, testKey, testID, "ENU", testConfig);

        // TODO Remove Later Test Data
        /*
         * oppInstance = new OpportunityInstance
         * (UUID.fromString("c778d1dd-3d2f-4e27-b093-a8f469b54b5b"),
         * UUID.fromString("0e0cdd71-df1f-497c-b895-7ac88be58a8c"),
         * UUID.fromString("fdd7ea11-f15c-4eec-b4cd-f0f17c773cb8")); testKey =
         * "(Hawaii)ASISample-Reading-8-Spring-2013-2013"; testOpp = new
         * TestOpportunity (oppInstance, testKey, "ENU", testConfig);
         */

        // save test opp to cache
        setCacheData("TestOpportunity", testOpp);

        return testOpp;
    }

    private static final String ACC_COOKIENAME = "TDS-Student-Accs";

    public static void saveSegmentsAccLookupAccommodations(List<AccLookup> segmentsAccommodations) {
        // clear any cached accommodations
        clearCacheData("Accommodations");

        // set accommodations to cookie as JSON
        setToCookie(ACC_COOKIENAME, segmentsAccommodations, true, true);
    }

    public static void saveSegmentsAccommodations(List<Accommodations> segmentsAccommodations) {
        // saveSegmentsAccLookupAccommodations(segmentsAccommodations.Select(A =>
        // A.GetCollection()));
        List<AccLookup> accLookUpList = new ArrayList<AccLookup>();
        CollectionUtils.collect(segmentsAccommodations, new Transformer() {
            @Override
            public Object transform(Object input) {
                Accommodations accommodations = (Accommodations) input;
                AccLookup lookup = new AccLookup(accommodations.getPosition(), accommodations.getId());

                for (AccommodationType accType : accommodations.getTypes()) {
                    for (AccommodationValue accValue : accType.getValues()) {
                        lookup.add(accType.getName(), accValue.getCode());
                    }
                }

                return lookup;
            }
        }, accLookUpList);
        saveSegmentsAccLookupAccommodations(accLookUpList);
    }

    // / <summary>
    // / get the current accommodations for global or if available a list for the
    // test/segments.
    // / </summary>
    @SuppressWarnings("unchecked")
    public static List<AccLookup> getAccommodationsList() {
        // get accs from cache
        List<AccLookup> lookupList = (List<AccLookup>) getCacheData("Accommodations");

        if (lookupList != null)
            return lookupList;

        // get accs from cookie
        //TODO EF: we cannot find why generic type does not work in getFromCookie
        // result we get back is list on LinkedHashMap.
        // As a way around we inlined code here and
        // used TypeReference<List<AccLookup>>
        //lookupList = (List<AccLookup>) getFromCookie (ACC_COOKIENAME, true, true);

        MultiValueCookie cookie = StudentCookie.getCookieByName(ACC_COOKIENAME);
        if (cookie == null || (cookie.getValue() != null && cookie.getValue().isEmpty())) {
            return lookupList;
        }

        // decode String
        String data = cookie.getValue();
        data = UrlEncoderDecoderUtils.decode(data);

        // deserialize into object
        try {
            ObjectMapper mapper = new ObjectMapper();
            //result = (T) mapper.readValue (data, Object.class);
            lookupList = mapper.readValue(data, new TypeReference<List<AccLookup>>() {
            });
        } catch (Exception ex) {
            _logger.error(ex.getMessage(), ex);
        }

        // check if there are any segment accs
        if (lookupList != null && lookupList.size() > 1) {
            for (int i = 1; i < lookupList.size(); i++) {
                AccLookup segmentAccs = lookupList.get(i);

                // for each segment accs we need to start with the test accs as the base
                AccLookup testAccs = lookupList.get(0).clone(segmentAccs.getPosition(), segmentAccs.getId());

                // then we will replace any of the test accs types with the segment accs
                testAccs.replaceWith(segmentAccs);

                // now swap in the new accs
                lookupList.set(i, testAccs);
            }
        }

        // save accommodations to cache
        if (lookupList != null) {
            setCacheData("Accommodations", lookupList);
        }

        return lookupList;
    }

    // / <summary>
    // / get the current primary accommodations (global or test).
    // / </summary>
    public static AccLookup getAccLookup() {
        List<AccLookup> accommodationsList = getAccommodationsList();

        if (accommodationsList != null && accommodationsList.size() > 0) {
            return accommodationsList.get(0);
        }

        return null;
    }

    private static void clearCacheData(String key) {
        String cacheKey = CACHE_PREFIX + key;
        if (HttpContext.getCurrentContext().containsItem(cacheKey)) {
            HttpContext.getCurrentContext().removeItem(cacheKey);
        }
    }

    private static <T> void setCacheData(String key, T value) {
        if (HttpContext.getCurrentContext() == null)
            return;

        String newKey = CACHE_PREFIX + key;
        HttpContext.getCurrentContext().setItem(newKey, value);
    }

    @SuppressWarnings("unchecked")
    private static <T> T getCacheData(String key) // where T : class
    {
        if (HttpContext.getCurrentContext() == null)
            return null;
        return (T) HttpContext.getCurrentContext().getItem(CACHE_PREFIX + key);
    }

    /***
     * Retrieve JSON object from a cookie.
     * 
     * @param cookieName
     *          - name of cookie
     * @param urlDecode
     *          - true to enable url decoding of the String
     * @param fromJson
     *          - true if the String in cookie is Json stringified
     * @return
     */
    @SuppressWarnings("unchecked")
    private static <T> T getFromCookie(String cookieName, boolean urlDecode, boolean fromJson) {
        T result = null;

        // read from cookie
        MultiValueCookie cookie = StudentCookie.getCookieByName(cookieName);
        if (cookie == null || (cookie.getValue() != null && cookie.getValue().isEmpty())) {
            return result;
        }

        // decode String
        String data = cookie.getValue();
        if (urlDecode) {
            // data = UrlEncoderDecoderUtils.decode (data);
        }

        // deserialize into object
        if (fromJson) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                //result = (T) mapper.readValue (data, Object.class);
                result = mapper.readValue(data, new TypeReference<T>() {
                });
            } catch (Exception ex) {
                _tdsLogger.applicationError(ex.getMessage(), "getFromCookie", null, ex);
            }
        } else {
            result = (T) data;
        }

        return result;
    }

    private static <T> void setToCookie(String cookieName, T value, boolean urlDecode, boolean fromJson) {
        String data = "";

        // serialize into String
        if (fromJson) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                data = mapper.writeValueAsString(value);
            } catch (Exception e) {
                _logger.error(e.getMessage(), e);
            }
        } else {
            data = value.toString();
        }

        // TODO Sajib: make sure you tell shiva to remove this hack once
        // AccommodationService has been fixed up.
        if (StringUtils.equalsIgnoreCase(ACC_COOKIENAME, cookieName)) {
            if (StringUtils.isEmpty(data))
                data = "[]";
        }

        // encode String
        if (urlDecode) {
            //  data = UrlEncoderDecoderUtils.encode (data);
        }

        // save to cookie
        MultiValueCookie cookie = new MultiValueCookie(cookieName, data);
        HttpContext.getCurrentContext().getCookies().add(cookie);
    }
}