/**************************************************************** * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) * ============================================================= * License Information: http://lamsfoundation.org/licensing/lams/2.0/ * * 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. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * * http://www.gnu.org/licenses/gpl.txt * **************************************************************** */ package org.lamsfoundation.lams.tool.peerreview.service; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; import org.lamsfoundation.lams.rating.dto.StyledCriteriaRatingDTO; import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; import org.lamsfoundation.lams.rating.model.RatingCriteria; import org.lamsfoundation.lams.rating.service.IRatingService; import org.lamsfoundation.lams.rest.RestTags; import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolCompletionStatus; import org.lamsfoundation.lams.tool.ToolContentManager; import org.lamsfoundation.lams.tool.ToolOutput; import org.lamsfoundation.lams.tool.ToolOutputDefinition; import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; import org.lamsfoundation.lams.tool.ToolSessionManager; import org.lamsfoundation.lams.tool.exception.DataMissingException; import org.lamsfoundation.lams.tool.exception.ToolException; import org.lamsfoundation.lams.tool.peerreview.PeerreviewConstants; import org.lamsfoundation.lams.tool.peerreview.dao.PeerreviewDAO; import org.lamsfoundation.lams.tool.peerreview.dao.PeerreviewSessionDAO; import org.lamsfoundation.lams.tool.peerreview.dao.PeerreviewUserDAO; import org.lamsfoundation.lams.tool.peerreview.dto.GroupSummary; import org.lamsfoundation.lams.tool.peerreview.dto.PeerreviewStatisticsDTO; import org.lamsfoundation.lams.tool.peerreview.model.Peerreview; import org.lamsfoundation.lams.tool.peerreview.model.PeerreviewSession; import org.lamsfoundation.lams.tool.peerreview.model.PeerreviewUser; import org.lamsfoundation.lams.tool.peerreview.util.EmailAnalysisBuilder; import org.lamsfoundation.lams.tool.peerreview.util.SpreadsheetBuilder; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.excel.ExcelCell; import org.lamsfoundation.lams.util.excel.ExcelSheet; import org.springframework.web.util.HtmlUtils; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** * @author Andrey Balan */ public class PeerreviewServiceImpl implements IPeerreviewService, ToolContentManager, ToolSessionManager, ToolRestManager { private static Logger log = Logger.getLogger(PeerreviewServiceImpl.class.getName()); private PeerreviewDAO peerreviewDao; private PeerreviewUserDAO peerreviewUserDao; private PeerreviewSessionDAO peerreviewSessionDao; // tool service private IToolContentHandler peerreviewToolContentHandler; private MessageService messageService; // system services private ILamsToolService toolService; private IUserManagementService userManagementService; private IExportToolContentService exportContentService; private ICoreNotebookService coreNotebookService; private IRatingService ratingService; private IEventNotificationService eventNotificationService; private SortedSet<Long> creatingUsersForSessionIds; PeerreviewServiceImpl() { creatingUsersForSessionIds = Collections.synchronizedSortedSet(new TreeSet<Long>()); } // ******************************************************************************* // Service method // ******************************************************************************* @Override public Peerreview getPeerreviewByContentId(Long contentId) { Peerreview rs = peerreviewDao.getByContentId(contentId); if (rs == null) { log.debug("Could not find the content by given ID:" + contentId); } return rs; } @Override public Peerreview getDefaultContent(Long contentId) throws PeerreviewApplicationException { if (contentId == null) { String error = messageService.getMessage("error.msg.default.content.not.find"); log.error(error); throw new PeerreviewApplicationException(error); } Peerreview defaultContent = getDefaultPeerreview(); // save default content by given ID. Peerreview content = new Peerreview(); content = Peerreview.newInstance(defaultContent, contentId); return content; } @Override public void updateUser(PeerreviewUser peerreviewUser) { peerreviewUserDao.insertOrUpdate(peerreviewUser); } @Override public PeerreviewUser getUserByIDAndContent(Long userId, Long contentId) { return peerreviewUserDao.getUserByUserIDAndContentID(userId, contentId); } @Override public PeerreviewUser getUserByIDAndSession(Long userId, Long sessionId) { return peerreviewUserDao.getUserByUserIDAndSessionID(userId, sessionId); } @Override public void saveOrUpdatePeerreview(Peerreview peerreview) { peerreviewDao.insertOrUpdate(peerreview); } @Override public Peerreview getPeerreviewBySessionId(Long sessionId) { PeerreviewSession session = peerreviewSessionDao.getSessionBySessionId(sessionId); // to skip CGLib problem Long contentId = session.getPeerreview().getContentId(); Peerreview res = peerreviewDao.getByContentId(contentId); return res; } @Override public PeerreviewSession getPeerreviewSessionBySessionId(Long sessionId) { return peerreviewSessionDao.getSessionBySessionId(sessionId); } @Override public void saveOrUpdatePeerreviewSession(PeerreviewSession resSession) { peerreviewSessionDao.insertOrUpdate(resSession); } @Override public void markUserFinished(Long toolSessionId, Long userId) { PeerreviewUser user = peerreviewUserDao.getUserByUserIDAndSessionID(userId, toolSessionId); user.setSessionFinished(true); peerreviewUserDao.update(user); } @Override public String finishToolSession(Long toolSessionId, Long userId) throws PeerreviewApplicationException { markUserFinished(toolSessionId, userId); // PeerreviewSession session = peerreviewSessionDao.getSessionBySessionId(toolSessionId); // session.setStatus(PeerreviewConstants.COMPLETED); // peerreviewSessionDao.saveObject(session); String nextUrl = null; try { nextUrl = this.leaveToolSession(toolSessionId, userId); } catch (DataMissingException e) { throw new PeerreviewApplicationException(e); } catch (ToolException e) { throw new PeerreviewApplicationException(e); } return nextUrl; } @Override public List<GroupSummary> getGroupSummaries(Long contentId) { List<GroupSummary> groupList = new ArrayList<>(); // get all sessions in a peerreview and retrieve all peerreview items under this session // plus initial peerreview items by author creating (resItemList) List<PeerreviewSession> sessionList = peerreviewSessionDao.getByContentId(contentId); for (PeerreviewSession session : sessionList) { // one new group for one session. GroupSummary group = new GroupSummary(); group.setSessionId(session.getSessionId()); group.setSessionName(session.getSessionName()); groupList.add(group); } return groupList; } @Override public int getCountUsersBySession(final Long toolSessionId, final Long excludeUserId) { return peerreviewUserDao.getCountUsersBySession(toolSessionId, excludeUserId); } @Override public int getCountUsersBySession(final Long toolSessionId) { return peerreviewUserDao.getCountUsersBySession(toolSessionId); } @Override public Long createNotebookEntry(Long sessionId, Integer notebookToolType, String toolSignature, Integer userId, String entryText) { return coreNotebookService.createNotebookEntry(sessionId, notebookToolType, toolSignature, userId, "", entryText); } @Override public NotebookEntry getEntry(Long sessionId, Integer idType, String signature, Integer userID) { List<NotebookEntry> list = coreNotebookService.getEntry(sessionId, idType, signature, userID); if ((list == null) || list.isEmpty()) { return null; } else { return list.get(0); } } @Override public void updateEntry(NotebookEntry notebookEntry) { coreNotebookService.updateEntry(notebookEntry); } @Override public PeerreviewUser getUser(Long uid) { return (PeerreviewUser) peerreviewUserDao.find(PeerreviewUser.class, uid); } @Override public boolean createUsersFromLesson(Long toolSessionId) throws Throwable { User currentUser = null; try { boolean wasNotInSetAlready = creatingUsersForSessionIds.add(toolSessionId); if (!wasNotInSetAlready) { return false; } PeerreviewSession session = getPeerreviewSessionBySessionId(toolSessionId); int numberPotentialLearners = toolService.getCountUsersForActivity(toolSessionId); int numberActualLearners = peerreviewUserDao.getCountUsersBySession(toolSessionId); int numUsersCreated = 0; if (numberActualLearners != numberPotentialLearners) { numUsersCreated = peerreviewUserDao.createUsersForSession(session); } if ( log.isDebugEnabled() ) { log.debug("Peer Review UserCreateThread " + toolSessionId + ": numUsersCreated "+numUsersCreated); } creatingUsersForSessionIds.remove(toolSessionId); return true; } catch (Throwable e) { creatingUsersForSessionIds.remove(toolSessionId); String message = e.getMessage() != null ? e.getMessage() : e.getClass().getName(); log.error("Exception thrown creating Peer Review users for session " + toolSessionId + " user id: " + (currentUser != null ? currentUser.getUserId().toString() : "null") + "; " + message, e); e.printStackTrace(); throw (e); } } @Override public void setUserHidden(Long toolContentId, Long userUid, boolean isHidden) { PeerreviewUser user = peerreviewUserDao.getUserByUid(userUid); if (user == null) { return; } //If user is marked as hidden - it will automatically remove all rating left by him to prevent statistics mess up. if (isHidden) { ratingService.removeUserCommitsByContent(toolContentId, user.getUserId().intValue()); } user.setHidden(isHidden); peerreviewUserDao.update(user); } @Override public int rateItems(RatingCriteria ratingCriteria, Long toolSessionId, Integer userId, Map<Long, Float> newRatings) { return ratingService.rateItems(ratingCriteria, toolSessionId, userId, newRatings); } @Override public void commentItem(RatingCriteria ratingCriteria, Long toolSessionId, Integer userId, Long itemId, String comment) { ratingService.commentItem(ratingCriteria, toolSessionId, userId, itemId, comment); } @Override public RatingCriteria getCriteriaByCriteriaId(Long ratingCriteriaId) { return ratingService.getCriteriaByCriteriaId(ratingCriteriaId); } @Override public StyledCriteriaRatingDTO getUsersRatingsCommentsByCriteriaIdDTO(Long toolContentId, Long toolSessionId, RatingCriteria criteria, Long currentUserId, boolean skipRatings, int sorting, String searchString, boolean getAllUsers, boolean getByUser) { if (skipRatings) { return ratingService.convertToStyledDTO(criteria, currentUserId, getAllUsers, null); } List<Object[]> rawData = peerreviewUserDao.getRatingsComments(toolContentId, toolSessionId, criteria, currentUserId, null, null, sorting, searchString, getByUser, ratingService, userManagementService); for (Object[] raw : rawData) { raw[raw.length - 2] = HtmlUtils.htmlEscape((String) raw[raw.length - 2]); } // if !getByUser -> is get current user's ratings from other users -> // convertToStyledJSON.getAllUsers needs to be true otherwise current user (the only one in the set!) is dropped return ratingService.convertToStyledDTO(criteria, currentUserId, !getByUser || getAllUsers, rawData); } @Override public ArrayNode getUsersRatingsCommentsByCriteriaIdJSON(Long toolContentId, Long toolSessionId, RatingCriteria criteria, Long currentUserId, Integer page, Integer size, int sorting, String searchString, boolean getAllUsers, boolean getByUser, boolean needRatesPerUser) { List<Object[]> rawData = peerreviewUserDao.getRatingsComments(toolContentId, toolSessionId, criteria, currentUserId, page, size, sorting, searchString, getByUser, ratingService, userManagementService); for (Object[] raw : rawData) { raw[raw.length - 2] = HtmlUtils.htmlEscape((String) raw[raw.length - 2]); } // if !getByUser -> is get current user's ratings from other users -> // convertToStyledJSON.getAllUsers needs to be true otherwise current user (the only one in the set!) is dropped return ratingService.convertToStyledJSON(criteria, toolSessionId, currentUserId, !getByUser || getAllUsers, rawData, needRatesPerUser); } @Override public List<Object[]> getDetailedRatingsComments(Long toolContentId, Long toolSessionId, Long criteriaId, Long itemId) { NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); numberFormat.setMaximumFractionDigits(1); // raw data: user_id, comment, rating, first_name, last_name List<Object[]> rawData = peerreviewUserDao.getDetailedRatingsComments(toolContentId, toolSessionId, criteriaId, itemId); for (Object[] raw : rawData) { raw[2] = (raw[2] == null ? null : numberFormat.format(raw[2])); // format rating // format name StringBuilder description = new StringBuilder((String) raw[3]).append(" ").append((String) raw[4]); raw[4] = HtmlUtils.htmlEscape(description.toString()); } return rawData; } @Override public List<Object[]> getCommentsCounts(Long toolContentId, Long toolSessionId, RatingCriteria criteria, Integer page, Integer size, int sorting, String searchString) { List<Object[]> rawData = peerreviewUserDao.getCommentsCounts(toolContentId, toolSessionId, criteria, page, size, sorting, searchString, userManagementService); // raw data: user_id, comment_count, first_name last_name, portrait id for (Object[] raw : rawData) { raw[2] = HtmlUtils.htmlEscape((String) raw[2]); } return rawData; } @Override public boolean isGroupedActivity(long toolContentID) { return toolService.isGroupedActivity(toolContentID); } @Override public void auditLogStartEditingActivityInMonitor(long toolContentID) { toolService.auditLogStartEditingActivityInMonitor(toolContentID); } @Override public boolean isLastActivity(Long toolSessionId) { return toolService.isLastActivity(toolSessionId); } @Override public String getLocalisedMessage(String key, Object[] args) { return messageService.getMessage(key, args); } @Override public List<PeerreviewStatisticsDTO> getStatistics(Long toolContentId) { return peerreviewDao.getStatistics(toolContentId); } @Override public List<Object[]> getUserNotebookEntriesForTablesorter(Long toolSessionId, int page, int size, int sorting, String searchString) { List<Object[]> rawData = peerreviewUserDao.getUserNotebookEntriesForTablesorter(toolSessionId, page, size, sorting, searchString, coreNotebookService, userManagementService); for (Object[] raw : rawData) { StringBuilder description = new StringBuilder((String) raw[1]).append(" ").append((String) raw[2]); raw[2] = HtmlUtils.htmlEscape(description.toString()); } return rawData; } @Override public List<Object[]> getPagedUsers(Long toolSessionId, Integer page, Integer size, int sorting, String searchString) { return peerreviewUserDao.getPagedUsers(toolSessionId, page, size, sorting, searchString); } private String getResultsEmailSubject(Peerreview peerreview) { return getLocalisedMessage("event.sent.results.subject", new Object[] { peerreview.getTitle() }); } @Override public String generateEmailReportToUser(Long toolContentId, Long sessionId, Long userId) { PeerreviewSession session = peerreviewSessionDao.getSessionBySessionId(sessionId); Peerreview peerreview = getPeerreviewByContentId(toolContentId); return new EmailAnalysisBuilder(peerreview, session, ratingService, peerreviewSessionDao, peerreviewUserDao, this, messageService).generateHTMLEMailForLearner(userId); } @Override public int emailReportToUser(Long toolContentId, Long sessionId, Long userId, String email) { PeerreviewUser user = peerreviewUserDao.getUserByUserIDAndSessionID(userId, sessionId); if ( user != null ) { eventNotificationService.sendMessage(null, userId.intValue(), IEventNotificationService.DELIVERY_METHOD_MAIL, getResultsEmailSubject(user.getSession().getPeerreview()), email, true); return 1; } else { log.error("Unable to send Peer Review email as user is not in session. SessionId="+sessionId+" userId="+userId); return 0; } } @Override public int emailReportToSessionUsers(Long toolContentId, Long sessionId) { PeerreviewSession session = peerreviewSessionDao.getSessionBySessionId(sessionId); Peerreview peerreview = getPeerreviewByContentId(toolContentId); Map<Long, String> emails = new EmailAnalysisBuilder(peerreview, session, ratingService, peerreviewSessionDao, peerreviewUserDao, this, messageService).generateHTMLEmailsForSession(); for (Map.Entry<Long, String> entry : emails.entrySet()) { eventNotificationService.sendMessage(null, entry.getKey().intValue(), IEventNotificationService.DELIVERY_METHOD_MAIL, getResultsEmailSubject(peerreview), entry.getValue(), true); } return emails.size(); } @Override public List<ExcelSheet> exportTeamReportSpreadsheet(Long toolContentId) { Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); if (peerreview == null) { log.warn("Did not find activity with toolContentId: " + toolContentId + " to remove learner content"); return null; } return new SpreadsheetBuilder(peerreview, ratingService, peerreviewSessionDao, peerreviewUserDao, this) .generateTeamReport(); } @Override public int[] getNumberPossibleRatings(Long toolContentId, Long toolSessionId, Long userId) { int[] retValue = new int[2]; ArrayList<Long> itemIds = new ArrayList<>(1); itemIds.add(userId); Map<Long, Long> numRatingsForUserMap = ratingService.countUsersRatedEachItem(toolContentId, toolSessionId, itemIds, -1); Long numRatingsForUser = numRatingsForUserMap.get(userId); retValue[0] = numRatingsForUser != null ? numRatingsForUser.intValue() : 0; int numUsersInSession = peerreviewUserDao.getCountUsersBySession(toolSessionId, -1L); Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); retValue[1] = peerreview.isSelfReview() ? numUsersInSession : numUsersInSession - 1; return retValue; } // ***************************************************************************** // private methods // ***************************************************************************** private Peerreview getDefaultPeerreview() throws PeerreviewApplicationException { Long defaultPeerreviewId = new Long( toolService.getToolDefaultContentIdBySignature(PeerreviewConstants.TOOL_SIGNATURE)); if (defaultPeerreviewId.equals(0L)) { String error = new StringBuilder("Could not retrieve default content id for this tool ") .append(PeerreviewConstants.TOOL_SIGNATURE).toString(); log.error(error); throw new PeerreviewApplicationException(error); } Peerreview defaultPeerreview = getPeerreviewByContentId(defaultPeerreviewId); if (defaultPeerreview == null) { String error = new StringBuilder("Could not retrieve default content id for this tool ") .append(PeerreviewConstants.TOOL_SIGNATURE).append(" Looking for id ").append(defaultPeerreviewId) .toString(); log.error(error); throw new PeerreviewApplicationException(error); } return defaultPeerreview; } // ******************************************************************************* // ToolContentManager, ToolSessionManager methods // ******************************************************************************* @Override public void exportToolContent(Long toolContentId, String rootPath) throws DataMissingException, ToolException { Peerreview toolContentObj = peerreviewDao.getByContentId(toolContentId); if (toolContentObj == null) { try { toolContentObj = getDefaultPeerreview(); } catch (PeerreviewApplicationException e) { throw new DataMissingException(e.getMessage()); } } if (toolContentObj == null) { throw new DataMissingException("Unable to find default content for the peerreview tool"); } // need to clone the Peer Review details, otherwise clearing the fields may update the database! toolContentObj = Peerreview.newInstance(toolContentObj, toolContentId); // don't export following fields for (LearnerItemRatingCriteria criteria : toolContentObj.getRatingCriterias()) { criteria.setToolContentId(null); } toolContentObj.setCreatedBy(null); // set PeerreviewToolContentHandler as null to avoid copy file node in repository again. toolContentObj = Peerreview.newInstance(toolContentObj, toolContentId); try { exportContentService.exportToolContent(toolContentId, toolContentObj, peerreviewToolContentHandler, rootPath); } catch (ExportToolContentException e) { throw new ToolException(e); } } @Override public void importToolContent(Long toolContentId, Integer newUserUid, String toolContentPath, String fromVersion, String toVersion) throws ToolException { try { // register version filter class exportContentService.registerImportVersionFilterClass(PeerreviewImportContentVersionFilter.class); Object toolPOJO = exportContentService.importToolContent(toolContentPath, peerreviewToolContentHandler, fromVersion, toVersion); if (!(toolPOJO instanceof Peerreview)) { throw new ImportToolContentException( "Import Share peerreview tool content failed. Deserialized object is " + toolPOJO); } Peerreview toolContentObj = (Peerreview) toolPOJO; // reset it to new toolContentId toolContentObj.setContentId(toolContentId); if (toolContentObj.getRatingCriterias() != null) { for (LearnerItemRatingCriteria criteria : toolContentObj.getRatingCriterias()) { criteria.setToolContentId(toolContentId); } } // reset the user PeerreviewUser user = peerreviewUserDao.getUserByUserIDAndContentID(new Long(newUserUid.longValue()), toolContentId); if (user == null) { user = new PeerreviewUser(); UserDTO sysUser = ((User) userManagementService.findById(User.class, newUserUid)).getUserDTO(); user.setFirstName(sysUser.getFirstName()); user.setLastName(sysUser.getLastName()); user.setLoginName(sysUser.getLogin()); user.setUserId(new Long(newUserUid.longValue())); user.setPeerreview(toolContentObj); } toolContentObj.setCreatedBy(user); peerreviewDao.insertOrUpdate(toolContentObj); } catch (ImportToolContentException e) { throw new ToolException(e); } } @Override public SortedMap<String, ToolOutputDefinition> getToolOutputDefinitions(Long toolContentId, int definitionType) throws ToolException { return new TreeMap<>(); } @Override public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { if (toContentId == null) { throw new ToolException("Failed to create the PeerreviewFiles tool seession"); } Peerreview peerreview = null; if (fromContentId != null) { peerreview = peerreviewDao.getByContentId(fromContentId); } if (peerreview == null) { try { peerreview = getDefaultPeerreview(); } catch (PeerreviewApplicationException e) { throw new ToolException(e); } } Peerreview toContent = Peerreview.newInstance(peerreview, toContentId); peerreviewDao.insert(toContent); } @Override public String getToolContentTitle(Long toolContentId) { return getPeerreviewByContentId(toolContentId).getTitle(); } @Override public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); if (peerreview == null) { throw new ToolException("No found tool content by given content ID:" + toolContentId); } peerreview.setDefineLater(false); } @Override public boolean isContentEdited(Long toolContentId) { return getPeerreviewByContentId(toolContentId).isDefineLater(); } @Override public boolean isReadOnly(Long toolContentId) { List<PeerreviewSession> list = peerreviewSessionDao.getByContentId(toolContentId); Iterator<PeerreviewSession> iter = list.iterator(); while (iter.hasNext()) { PeerreviewSession session = iter.next(); int sessionUsersNumber = peerreviewUserDao.getCountUsersBySession(session.getSessionId()); if (sessionUsersNumber == 0) { log.debug("Peer Review isReadOnly called. Returning true. Count of users for session id " + session.getSessionId() + " is " + sessionUsersNumber); return true; } else { log.debug("Peer Review isReadOnly called. Count of users for session id " + session.getSessionId() + " is 0"); } } log.debug("Peer Review isReadOnly called. Returning false."); return false; } @Override public void removeToolContent(Long toolContentId) throws ToolException { Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); if (peerreview == null) { log.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); return; } for (PeerreviewSession session : peerreviewSessionDao.getByContentId(toolContentId)) { List<NotebookEntry> entries = coreNotebookService.getEntry(session.getSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, PeerreviewConstants.TOOL_SIGNATURE); for (NotebookEntry entry : entries) { coreNotebookService.deleteEntry(entry); } } peerreviewDao.delete(peerreview); } @Override public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { if (log.isDebugEnabled()) { log.debug("Removing Peerreview content for user ID " + userId + " and toolContentId " + toolContentId); } Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); if (peerreview == null) { log.warn("Did not find activity with toolContentId: " + toolContentId + " to remove learner content"); return; } List<PeerreviewSession> sessions = peerreviewSessionDao.getByContentId(toolContentId); for (PeerreviewSession session : sessions) { PeerreviewUser user = peerreviewUserDao.getUserByUserIDAndSessionID(userId.longValue(), session.getSessionId()); if (user != null) { NotebookEntry entry = getEntry(session.getSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, PeerreviewConstants.TOOL_SIGNATURE, userId); if (entry != null) { peerreviewDao.deleteById(NotebookEntry.class, entry.getUid()); } } } } @Override public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentId) throws ToolException { PeerreviewSession session = new PeerreviewSession(); session.setSessionId(toolSessionId); session.setSessionName(toolSessionName); Peerreview peerreview = peerreviewDao.getByContentId(toolContentId); session.setPeerreview(peerreview); peerreviewSessionDao.insert(session); } @Override public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { if (toolSessionId == null) { log.error("Fail to leave tool Session based on null tool session id."); throw new ToolException("Fail to remove tool Session based on null tool session id."); } if (learnerId == null) { log.error("Fail to leave tool Session based on null learner."); throw new ToolException("Fail to remove tool Session based on null learner."); } PeerreviewSession session = peerreviewSessionDao.getSessionBySessionId(toolSessionId); if (session != null) { session.setStatus(PeerreviewConstants.COMPLETED); peerreviewSessionDao.update(session); } else { log.error("Fail to leave tool Session.Could not find peerreview " + "session by given session id: " + toolSessionId); throw new DataMissingException("Fail to leave tool Session." + "Could not find peerreview session by given session id: " + toolSessionId); } return toolService.completeToolSession(toolSessionId, learnerId); } @Override public List<RatingCriteria> getRatingCriterias(Long toolContentId) { return ratingService.getCriteriasByToolContentId(toolContentId); } @Override public void saveRatingCriterias(HttpServletRequest request, Collection<RatingCriteria> oldCriterias, Long toolContentId) { ratingService.saveRatingCriterias(request, oldCriterias, toolContentId); } @Override public boolean isCommentsEnabled(Long toolContentId) { return ratingService.isCommentsEnabled(toolContentId); } @Override public int getCommentsMinWordsLimit(Long toolContentId) { return ratingService.getCommentsMinWordsLimit(toolContentId); } @Override public List<RatingCriteria> getCriteriasByToolContentId(Long toolContentId) { return ratingService.getCriteriasByToolContentId(toolContentId); } @Override public List<ItemRatingDTO> getRatingCriteriaDtos(Long contentId, Long toolSessionId, Collection<Long> itemIds, boolean isCommentsByOtherUsersRequired, Long userId) { return ratingService.getRatingCriteriaDtos(contentId, toolSessionId, itemIds, isCommentsByOtherUsersRequired, userId); } @Override public List<ItemRatingDTO> getRatingCriteriaDtos(Long contentId, Long toolSessionId, Collection<Long> itemIds, boolean isCommentsByOtherUsersRequired, Long userId, boolean isCountUsersRatedEachItem) { List<ItemRatingDTO> itemRatingDTOs = getRatingCriteriaDtos(contentId, toolSessionId, itemIds, isCommentsByOtherUsersRequired, userId); if (isCountUsersRatedEachItem) { Map<Long, Long> itemIdToRatedUsersCountMap = ratingService.countUsersRatedEachItem(contentId, toolSessionId, itemIds, userId.intValue()); for (ItemRatingDTO itemRatingDTO : itemRatingDTOs) { Long itemId = itemRatingDTO.getItemId(); int countUsersRatedEachItem = itemIdToRatedUsersCountMap.get(itemId).intValue(); itemRatingDTO.setCountUsersRatedEachItem(countUsersRatedEachItem); } } return itemRatingDTOs; } @Override public int getCountItemsRatedByUser(Long toolContentId, Integer userId) { return ratingService.getCountItemsRatedByUser(toolContentId, userId); } @Override public int getCountItemsRatedByUserByCriteria(final Long criteriaId, final Integer userId) { return ratingService.getCountItemsRatedByUserByCriteria(criteriaId, userId); } @Override public ToolSessionExportOutputData exportToolSession(Long toolSessionId) throws DataMissingException, ToolException { return null; } @SuppressWarnings("rawtypes") @Override public ToolSessionExportOutputData exportToolSession(List toolSessionIds) throws DataMissingException, ToolException { return null; } @Override public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { peerreviewSessionDao.deleteBySessionId(toolSessionId); } @Override public SortedMap<String, ToolOutput> getToolOutput(List<String> names, Long toolSessionId, Long learnerId) { return new TreeMap<>(); } @Override public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { return null; } @Override public List<ToolOutput> getToolOutputs(String name, Long toolContentId) { return new ArrayList<>(); } @Override public List<ConfidenceLevelDTO> getConfidenceLevels(Long toolSessionId) { return null; } @Override public boolean isUserGroupLeader(Long userId, Long toolSessionId) { return false; } @Override public void forceCompleteUser(Long toolSessionId, User user) { // no actions required } @Override @SuppressWarnings("rawtypes") public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { return null; } // ***************************************************************************** // set methods for Spring Bean // ***************************************************************************** public void setMessageService(MessageService messageService) { this.messageService = messageService; } public void setPeerreviewDao(PeerreviewDAO peerreviewDao) { this.peerreviewDao = peerreviewDao; } public void setPeerreviewSessionDao(PeerreviewSessionDAO peerreviewSessionDao) { this.peerreviewSessionDao = peerreviewSessionDao; } public void setPeerreviewToolContentHandler(IToolContentHandler peerreviewToolContentHandler) { this.peerreviewToolContentHandler = peerreviewToolContentHandler; } public void setPeerreviewUserDao(PeerreviewUserDAO peerreviewUserDao) { this.peerreviewUserDao = peerreviewUserDao; } public void setToolService(ILamsToolService toolService) { this.toolService = toolService; } public void setExportContentService(IExportToolContentService exportContentService) { this.exportContentService = exportContentService; } public void setUserManagementService(IUserManagementService userManagementService) { this.userManagementService = userManagementService; } public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { this.coreNotebookService = coreNotebookService; } public void setRatingService(IRatingService ratingService) { this.ratingService = ratingService; } @Override public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { // db doesn't have a start/finish date for learner, and session start/finish is null PeerreviewUser learner = getUserByIDAndSession(learnerId, toolSessionId); if (learner == null) { return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); } return new ToolCompletionStatus(learner.isSessionFinished() ? ToolCompletionStatus.ACTIVITY_COMPLETED : ToolCompletionStatus.ACTIVITY_ATTEMPTED, null, null); } // ****************** REST methods ************************* public void setEventNotificationService(IEventNotificationService eventNotificationService) { this.eventNotificationService = eventNotificationService; } /** * Used by the Rest calls to create content. Mandatory fields in toolContentJSON: title, instructions, peerreview, * user fields firstName, lastName and loginName Peerreview must contain a JSONArray of JSONObject objects, which * have the following mandatory fields: title, description, type. It will create */ @Override public void createRestToolContent(Integer userID, Long toolContentID, ObjectNode toolContentJSON) { Date updateDate = new Date(); Peerreview peerreview = new Peerreview(); peerreview.setContentId(toolContentID); peerreview.setTitle(JsonUtil.optString(toolContentJSON, RestTags.TITLE)); peerreview.setInstructions(JsonUtil.optString(toolContentJSON, RestTags.INSTRUCTIONS)); peerreview.setCreated(updateDate); peerreview.setUpdated(updateDate); peerreview .setLockWhenFinished(JsonUtil.optBoolean(toolContentJSON, RestTags.LOCK_WHEN_FINISHED, Boolean.FALSE)); peerreview.setReflectOnActivity( JsonUtil.optBoolean(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); peerreview.setReflectInstructions(JsonUtil.optString(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS)); peerreview.setContentInUse(false); peerreview.setDefineLater(false); PeerreviewUser peerreviewUser = getUserByIDAndContent(userID.longValue(), toolContentID); if (peerreviewUser == null) { peerreviewUser = new PeerreviewUser(); peerreviewUser.setFirstName(JsonUtil.optString(toolContentJSON, "firstName")); peerreviewUser.setLastName(JsonUtil.optString(toolContentJSON, "lastName")); peerreviewUser.setLoginName(JsonUtil.optString(toolContentJSON, "loginName")); // peerreviewUser.setPeerreview(content); } peerreview.setCreatedBy(peerreviewUser); // not expecting to get these but add them in case an Authoring Template does want them peerreview.setMinimumRates(JsonUtil.optInt(toolContentJSON, "minimumRates", 0)); peerreview.setMaximumRates(JsonUtil.optInt(toolContentJSON, "maximumRate", 0)); peerreview.setMaximumRatesPerUser(JsonUtil.optInt(toolContentJSON, "maximumRatesPerUser", 0)); peerreview.setShowRatingsLeftForUser( JsonUtil.optBoolean(toolContentJSON, "showRatingsLeftForUser", Boolean.TRUE)); peerreview .setShowRatingsLeftByUser(JsonUtil.optBoolean(toolContentJSON, "showRatingsLeftByUser", Boolean.FALSE)); peerreview.setSelfReview(JsonUtil.optBoolean(toolContentJSON, "notifyUsersOfResults", Boolean.FALSE)); peerreview.setNotifyUsersOfResults(JsonUtil.optBoolean(toolContentJSON, "notifyUsersOfResults", Boolean.TRUE)); saveOrUpdatePeerreview(peerreview); // Criterias ArrayNode criterias = JsonUtil.optArray(toolContentJSON, "criterias"); for (int i = 0; i < criterias.size(); i++) { ObjectNode criteriaData = (ObjectNode) criterias.get(i); // allowComment true, minWords defaults to 1. allowComment is false, minWords defaults to 0 boolean allowComment = JsonUtil.optBoolean(criteriaData, "commentsEnabled", false); int minWords = JsonUtil.optInt(criteriaData, "minWordsInComment", allowComment ? 1 : 0); ratingService.saveLearnerItemRatingCriteria(toolContentID, JsonUtil.optString(criteriaData, "title"), JsonUtil.optInt(criteriaData, "orderId"), JsonUtil.optInt(criteriaData, "ratingStyle"), allowComment, minWords); } saveOrUpdatePeerreview(peerreview); } }