Index: lams_common/db/sql/insert_types_data.sql =================================================================== RCS file: /usr/local/cvsroot/lams_common/db/sql/insert_types_data.sql,v diff -u -r1.69 -r1.70 --- lams_common/db/sql/insert_types_data.sql 28 Sep 2007 06:44:58 -0000 1.69 +++ lams_common/db/sql/insert_types_data.sql 10 Oct 2007 07:11:35 -0000 1.70 @@ -183,26 +183,26 @@ VALUES (6, 10, 'Monitor Chosen Branching', 'Select between multiple sequence activities, with the branch chosen in monitoring.', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=viewBranching&mode=teacher', NULL, - 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/branching.do?method=assignBranch', - 'monitoring/branching.do?method=assignBranch', now()); + 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/chosenBranching.do?method=assignBranch', + 'monitoring/chosenBranching.do?method=assignBranch', now()); INSERT INTO lams_system_tool (system_tool_id, learning_activity_type_id, tool_display_name, description, learner_url, learner_preview_url, learner_progress_url, export_pfolio_learner_url, export_pfolio_class_url, monitor_url, contribute_url, create_date_time) VALUES (7, 11, 'Group Based Branching', 'Select between multiple sequence activities, with the branch chosen by an existing group.', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=viewBranching&mode=teacher', NULL, - 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/branching.do?method=assignBranch', - 'monitoring/branching.do?method=assignBranch', now()); + 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/groupedBranching.do?method=viewBranching', + 'monitoring/groupedBranching.do?method=assignBranch', now()); INSERT INTO lams_system_tool (system_tool_id, learning_activity_type_id, tool_display_name, description, learner_url, learner_preview_url, learner_progress_url, export_pfolio_learner_url, export_pfolio_class_url, monitor_url, contribute_url, create_date_time) VALUES (8, 12, 'Tool Output Based Branching', 'Select between multiple sequence activities, with the branch chosen on results of another activity.', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=performBranching', 'learning/branching.do?method=viewBranching&mode=teacher', NULL, - 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/branching.do?method=assignBranch', - 'monitoring/branching.do?method=assignBranch', now()); + 'monitoring/branchingExportPortfolio?mode=teacher', 'monitoring/toolBranching.do?method=viewBranching', + 'monitoring/toolBranching.do?method=viewBranching', now()); -- Supported Locales INSERT INTO lams_supported_locale (locale_id, language_iso_code, country_iso_code, description, direction) Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java,v diff -u -r1.68 -r1.69 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java 24 Sep 2007 07:58:06 -0000 1.68 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java 10 Oct 2007 07:12:01 -0000 1.69 @@ -31,6 +31,7 @@ import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.GateActivity; +import org.lamsfoundation.lams.learningdesign.Group; import org.lamsfoundation.lams.learningdesign.GroupingActivity; import org.lamsfoundation.lams.learningdesign.ScheduleGateActivity; import org.lamsfoundation.lams.learningdesign.exception.LearningDesignProcessorException; @@ -549,6 +550,33 @@ */ public void removeUsersFromBranch(Long sequenceActivityID, String learnerIDs[]) throws LessonServiceException; + /** Has anyone started this branch / branching activity ? Irrespective of the groups. + * Used to determine if a branch mapping can be removed. */ + public boolean isActivityAttempted(Activity activity) throws LessonServiceException; + + /** Match group(s) to a branch. Doesn't necessarily check if the group is already assigned to another branch. + * Use for Group Based Branching and define later. + * + * @param sequenceActivityID Activity id of the sequenceActivity representing this branch + * @param learnerIDs the IDS of the learners to be added. + */ + public void addGroupToBranch(Long sequenceActivityID, String groupIDs[]) throws LessonServiceException; + + /** Remove group / branch mapping. Cannot be done if any users in the group have started the branch. + * Used for group based branching in define later. + * + * @param sequenceActivityID Activity id of the sequenceActivity representing this branch + * @param learnerIDs the IDS of the learners to be added. + */ + public void removeGroupFromBranch(Long sequenceActivityID, String groupIDs[]) throws LessonServiceException; + + /** + * Get all the groups that exist for the related grouping activity that have not been allocated to a branch. + * + * @param branchingActivityID Activity id of the branchingActivity + */ + public SortedSet getGroupsNotAssignedToBranch(Long branchingActivityID) throws LessonServiceException; + /** * Get the list of users who have attempted an activity. This is based on the progress engine records. * This will give the users in all tool sessions for an activity (if it is a tool activity) or @@ -557,4 +585,5 @@ */ public List getLearnersHaveAttemptedActivity(Activity activity) throws LessonServiceException; + } Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java,v diff -u -r1.118 -r1.119 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java 24 Sep 2007 07:58:06 -0000 1.118 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java 10 Oct 2007 07:12:01 -0000 1.119 @@ -2100,6 +2100,142 @@ } + /** Match group(s) to a branch. Doesn't necessarily check if the group is already assigned to another branch. + * Use for Group Based Branching and define later. + * + * @param sequenceActivityID Activity id of the sequenceActivity representing this branch + * @param learnerIDs the IDS of the learners to be added. + */ + public void addGroupToBranch(Long sequenceActivityID, String groupIDs[]) throws LessonServiceException { + + SequenceActivity branch = (SequenceActivity) getActivityById(sequenceActivityID); + if ( branch == null ) { + String error = "addGroupToBranch: Branch missing. ActivityID was "+sequenceActivityID; + log.error(error); + throw new MonitoringServiceException(error); + } + + Activity parentActivity = branch.getParentActivity(); + if ( parentActivity == null || !parentActivity.isBranchingActivity()) { + String error = "addUsersToBranch: Branching activity missing or not a branching activity. Branch was "+branch+" parent activity was "+parentActivity; + log.error(error); + throw new MonitoringServiceException(error); + } + BranchingActivity branchingActivity = (BranchingActivity) getActivityById(parentActivity.getActivityId()); + Grouping grouping = branchingActivity.getGrouping(); + + for ( String groupIDString: groupIDs) { + Long groupID = Long.parseLong(groupIDString); + + Group group = null; + Iterator groupIterator = grouping.getGroups().iterator(); + while (groupIterator.hasNext() && group == null) { + Group obj = (Group) groupIterator.next(); + if ( obj.getGroupId().equals(groupID) ) + group = obj; + } + if ( group == null ) { + String error = "addGroupToBranch: Group missing. Group ID was "+groupIDString; + log.error(error); + throw new MonitoringServiceException(error); + } + + group.allocateBranchToGroup(null, branch, branchingActivity); + groupingDAO.update(group); + } + + } + + /** Remove group / branch mapping. Cannot be done if any users in the group have started the branch. + * Used for group based branching in define later. + * + * @param sequenceActivityID Activity id of the sequenceActivity representing this branch + * @param learnerIDs the IDS of the learners to be added. + */ + public void removeGroupFromBranch(Long sequenceActivityID, String groupIDs[]) throws LessonServiceException { + + SequenceActivity branch = (SequenceActivity) getActivityById(sequenceActivityID); + if ( branch == null ) { + String error = "addUsersToBranch: Branch missing. ActivityID was "+sequenceActivityID; + log.error(error); + throw new MonitoringServiceException(error); + } + + Activity parentActivity = branch.getParentActivity(); + if ( parentActivity == null || !parentActivity.isBranchingActivity()) { + String error = "addUsersToBranch: Branching activity missing or not a branching activity. Branch was "+branch+" parent activity was "+parentActivity; + log.error(error); + throw new MonitoringServiceException(error); + } + BranchingActivity branchingActivity = (BranchingActivity) getActivityById(parentActivity.getActivityId()); + Grouping grouping = branchingActivity.getGrouping(); + + for ( String groupIDString: groupIDs) { + Long groupID = Long.parseLong(groupIDString); + + Group group = null; + Iterator groupIterator = grouping.getGroups().iterator(); + while (groupIterator.hasNext() && group == null) { + Group obj = (Group) groupIterator.next(); + if ( obj.getGroupId().equals(groupID) ) + group = obj; + } + if ( group == null ) { + String error = "removeGroupFromBranch: Group missing. Group ID was "+groupIDString; + log.error(error); + throw new MonitoringServiceException(error); + } + + // can't remove the group if someone has already started working on the branch. + if ( isActivityAttempted(branch) ) { + log.warn("removeGroupFromBranch: A group member has already started the branch. Unable to remove the group from the branch. Group ID was "+groupIDString); + } else { + group.removeGroupFromBranch(branch); + groupingDAO.update(group); + } + } + + } + + /** Has anyone started this branch / branching activity ? Irrespective of the groups. + * Used to determine if a branch mapping can be removed. */ + public boolean isActivityAttempted(Activity activity) { + Integer numAttempted = lessonService.getCountLearnersHaveAttemptedActivity(activity); + if ( log.isDebugEnabled() ) { + log.debug("isActivityAttempted: num attempts for activity "+activity.getActivityId()+" is "+numAttempted); + } + return numAttempted !=null && numAttempted.intValue() > 0; + } + + /** + * Get all the groups that exist for the related grouping activity that have not been allocated to a branch. + * + * @param branchingActivityID Activity id of the branchingActivity + */ + public SortedSet getGroupsNotAssignedToBranch(Long branchingActivityID) throws LessonServiceException { + + BranchingActivity branchingActivity = (BranchingActivity) getActivityById(branchingActivityID); + if ( branchingActivity == null ) { + String error = "getGroupsNotAssignedToBranch: Branching Activity missing missing. ActivityID was "+branchingActivityID; + log.error(error); + throw new MonitoringServiceException(error); + } + + TreeSet unassignedGroups = new TreeSet(); + + Grouping grouping = branchingActivity.getGrouping(); + Iterator groupIterator = grouping.getGroups().iterator(); + while (groupIterator.hasNext() ) { + Group group = (Group) groupIterator.next(); + if ( group.getBranchActivities() == null || group.getBranchActivities().size()==0 ) { + unassignedGroups.add(group); + } + } + + return unassignedGroups; + + } + /** * Get the list of users who have attempted an activity. This is based on the progress engine records. * This will give the users in all tool sessions for an activity (if it is a tool activity) or Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java 10 Oct 2007 07:12:15 -0000 1.1 @@ -0,0 +1,175 @@ +/**************************************************************** + * 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 version 2.0 + * 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 + * **************************************************************** + */ + +/* $Id: BranchingAction.java,v 1.1 2007/10/10 07:12:15 fmalikoff Exp $ */ +package org.lamsfoundation.lams.monitoring.web; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.BranchingActivity; +import org.lamsfoundation.lams.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.BranchActivityEntry; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; +import org.lamsfoundation.lams.monitoring.BranchDTO; +import org.lamsfoundation.lams.monitoring.BranchingDTO; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; +import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** +* The action servlet that provides the support for the +* +*
    +*
  • View only screen for Group Based and Tool Based branching
  • +*
  • Class export portfolio page for all branching types +*
+* +* Due to how XDoclet works, we have to have a separate subclass of BranchingAction +* for each branching type, and include the XDoclet tags in the subclasses. +* +* @author Fiona Malikoff +*/ +public class BranchingAction extends LamsDispatchAction { + + //--------------------------------------------------------------------- + + private static final String VIEW_BRANCHES_SCREEN = "viewBranches"; + public static final String PARAM_BRANCHING_DTO = "branching"; + public static final String PARAM_SHOW_GROUP_NAME = "showGroupName"; + /** If localFiles = true will be written to a local file for export portfolio */ + public static final String PARAM_LOCAL_FILES= "localFiles"; + + /** + * Export Portfolio Page + */ + public ActionForward exportPortfolio(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) throws IOException, + ServletException + { + long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); + long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + BranchingActivity activity = (BranchingActivity) monitoringService.getActivityById(activityId, BranchingActivity.class); + return viewBranching(activity, lessonId, true, mapping, request, monitoringService); + } + + /** + * Display the view screen, irrespective of the branching type. + */ + public ActionForward viewBranching(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) throws IOException, + ServletException + { + long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); + long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + BranchingActivity activity = (BranchingActivity) monitoringService.getActivityById(activityId, BranchingActivity.class); + return viewBranching(activity, lessonId, false, mapping, request, monitoringService); + } + + protected ActionForward viewBranching(BranchingActivity activity, Long lessonId, boolean useLocalFiles, + ActionMapping mapping, HttpServletRequest request, IMonitoringService monitoringService) throws IOException, ServletException { + + // in general the progress engine expects the activity and lesson id to be in the request, + // so follow that standard. + request.setAttribute(AttributeNames.PARAM_ACTIVITY_ID, activity.getActivityId()); + request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); + request.setAttribute(AttributeNames.PARAM_TITLE, activity.getTitle()); + request.setAttribute(PARAM_LOCAL_FILES, useLocalFiles); + + // only show the group names if this is a group based branching activity - the names + // are meaningless for chosen and tool based branching + BranchingDTO dto = getBranchingDTO(activity, monitoringService); + request.setAttribute(PARAM_BRANCHING_DTO, dto); + request.setAttribute(PARAM_SHOW_GROUP_NAME, activity.isGroupBranchingActivity()); + if ( log.isDebugEnabled() ) { + log.debug("viewBranching: Branching activity "+dto); + } + return mapping.findForward(VIEW_BRANCHES_SCREEN); + } + + // Can't do this in BranchingDTO (although that's where it should be) as we have + // to get the SequenceActivities via the getActivityById to get around Hibernate + // not allowing us to cast the cglib classes. + private BranchingDTO getBranchingDTO(BranchingActivity activity, IMonitoringService monitoringService) { + BranchingDTO dto = new BranchingDTO(); + + dto.setBranchActivityId(activity.getActivityId()); + dto.setBranchActivityName(activity.getTitle()); + + TreeSet branches = new TreeSet(); + Iterator iter = activity.getActivities().iterator(); + while (iter.hasNext()) { + Activity childActivity = iter.next(); + SequenceActivity branch = (SequenceActivity) monitoringService.getActivityById(childActivity.getActivityId(), SequenceActivity.class); + Set mappingEntries = branch.getBranchEntries(); + + // If it is a grouped based or teacher chosen branching, the users will be in groups. + // If not get the user based on the progress engine and create a dummy group. + // Can't use tool session as sequence activities don't have a tool session! + SortedSet groups = new TreeSet(); + if ( activity.isChosenBranchingActivity() || activity.isGroupBranchingActivity() ) { + for ( BranchActivityEntry entry : mappingEntries ) { + Group group = entry.getGroup(); + groups.add(group); + } + } else { + Group group = new Group(); + if ( group.getUsers() == null ) { + group.setUsers(new HashSet()); + } + List learners = monitoringService.getLearnersHaveAttemptedActivity(branch); + group.getUsers().addAll(learners); + groups.add(group); + } + branches.add(new BranchDTO(branch, groups)); + } + dto.setBranches(branches); + return dto; + } + + + } Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ChosenBranchingAJAXAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ChosenBranchingAJAXAction.java,v diff -u -r1.8 -r1.9 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ChosenBranchingAJAXAction.java 24 Sep 2007 07:58:06 -0000 1.8 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ChosenBranchingAJAXAction.java 10 Oct 2007 07:12:15 -0000 1.9 @@ -25,18 +25,14 @@ package org.lamsfoundation.lams.monitoring.web; import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; @@ -48,67 +44,40 @@ import org.lamsfoundation.lams.learningdesign.BranchActivityEntry; import org.lamsfoundation.lams.learningdesign.SequenceActivity; import org.lamsfoundation.lams.lesson.service.LessonServiceException; -import org.lamsfoundation.lams.monitoring.BranchDTO; -import org.lamsfoundation.lams.monitoring.BranchingDTO; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; -import org.lamsfoundation.lams.monitoring.service.MonitoringServiceException; import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; import org.lamsfoundation.lams.usermanagement.User; -import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.util.LastNameAlphabeticComparator; import org.lamsfoundation.lams.util.WebUtil; -import org.lamsfoundation.lams.web.action.LamsDispatchAction; -import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; /** * The action servlet that provides the support for the *
    *
  • AJAX based Chosen Branching screen
  • -*
  • View only screen for Group Based and Tool Based branching
  • -*
  • Class export portfolio page for all branching types *
* * @author Fiona Malikoff * ----------------XDoclet Tags-------------------- * -* @struts:action path="/branching" +* @struts:action path="/chosenBranching" * parameter="method" * validate="false" * @struts.action-forward name = "chosenSelection" path = "/branching/chosenSelection.jsp" * @struts.action-forward name = "viewBranches" path = ".viewBranches" -* + * ----------------XDoclet Tags-------------------- */ -public class ChosenBranchingAJAXAction extends LamsDispatchAction { +public class ChosenBranchingAJAXAction extends BranchingAction { //--------------------------------------------------------------------- private static final String CHOSEN_SELECTION_SCREEN = "chosenSelection"; - private static final String VIEW_BRANCHES_SCREEN = "viewBranches"; - public static final String PARAM_TYPE = "type"; - public static final String PARAM_BRANCHING_DTO = "branching"; public static final String PARAM_BRANCH_ID = "branchID"; public static final String PARAM_MAY_DELETE = "mayDelete"; public static final String PARAM_MEMBERS = "members"; - public static final String PARAM_SHOW_GROUP_NAME = "showGroupName"; - /** If localFiles = true will be written to a local file for export portfolio */ - public static final String PARAM_LOCAL_FILES= "localFiles"; - private void writeAJAXResponse(HttpServletResponse response, String output) throws IOException { - response.setContentType("text/html"); - PrintWriter writer = response.getWriter(); - // set it to unicode - if (output != null && output.length()>0) { - writer.println(output); - } - } - - private void writeAJAXOKResponse(HttpServletResponse response) throws IOException { - writeAJAXResponse(response, "OK"); - } - /** * Start the process of doing the chosen grouping * @@ -132,71 +101,19 @@ request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); request.setAttribute(AttributeNames.PARAM_TITLE, activity.getTitle()); - // can we still move users? check each group for tool sessions. - Iterator iter = activity.getActivities().iterator(); - boolean mayMoveUser = true; - while (iter.hasNext()) { - Activity childActivity = iter.next(); - SequenceActivity branch = (SequenceActivity) monitoringService.getActivityById(childActivity.getActivityId(), SequenceActivity.class); - Set mappingEntries = branch.getBranchEntries(); - for ( BranchActivityEntry entry : mappingEntries ) { - mayMoveUser = mayMoveUser && entry.getGroup().mayBeDeleted(); - } - } - request.setAttribute(PARAM_MAY_DELETE, mayMoveUser); + // can we still move users? + boolean usersStartedBranching = monitoringService.isActivityAttempted(activity); + request.setAttribute(PARAM_MAY_DELETE, ! usersStartedBranching); return mapping.findForward(CHOSEN_SELECTION_SCREEN); } else { - // go to a view only screen for group based and tool based grouping + // something gone wrong - shouldn't be here so revert to standard screen for viewing branching. return viewBranching(activity, lessonId, false, mapping, request, monitoringService); } } - - /** - * Export Portfolio Page - */ - public ActionForward exportPortfolio(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); - - IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); - BranchingActivity activity = (BranchingActivity) monitoringService.getActivityById(activityId, BranchingActivity.class); - return viewBranching(activity, lessonId, true, mapping, request, monitoringService); - } - - - /** - * Display the view screen, irrespective of the branching type. - * - * Input parameters: activityID - */ - private ActionForward viewBranching(BranchingActivity activity, Long lessonId, boolean useLocalFiles, - ActionMapping mapping, HttpServletRequest request, IMonitoringService monitoringService) throws IOException, ServletException { - - // in general the progress engine expects the activity and lesson id to be in the request, - // so follow that standard. - request.setAttribute(AttributeNames.PARAM_ACTIVITY_ID, activity.getActivityId()); - request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); - request.setAttribute(AttributeNames.PARAM_TITLE, activity.getTitle()); - request.setAttribute(PARAM_LOCAL_FILES, useLocalFiles); - - // only show the group names if this is a group based branching activity - the names - // are meaningless for chosen and tool based branching - BranchingDTO dto = getBranchingDTO(activity, monitoringService); - request.setAttribute(PARAM_BRANCHING_DTO, dto); - request.setAttribute(PARAM_SHOW_GROUP_NAME, activity.isGroupBranchingActivity()); - if ( log.isDebugEnabled() ) { - log.debug("viewBranching: Branching activity "+dto); - } - return mapping.findForward(VIEW_BRANCHES_SCREEN); - } + /** * Get a list of branch names, their associated group id and the number of users in the group. Designed to respond to an AJAX call. @@ -290,7 +207,7 @@ Group group = branch.getSoleGroupForBranch(); - String userOutput = null; + String userOutput = ""; if ( group != null ) { SortedSet sortedUsers = new TreeSet(new LastNameAlphabeticComparator()); sortedUsers.addAll(group.getUsers()); @@ -378,45 +295,6 @@ return null; } - // Can't do this in BranchingDTO (although that's where it should be) as we have - // to get the SequenceActivities via the getActivityById to get around Hibernate - // not allowing us to cast the cglib classes. - private BranchingDTO getBranchingDTO(BranchingActivity activity, IMonitoringService monitoringService) { - BranchingDTO dto = new BranchingDTO(); - - dto.setBranchActivityId(activity.getActivityId()); - dto.setBranchActivityName(activity.getTitle()); - - TreeSet branches = new TreeSet(); - Iterator iter = activity.getActivities().iterator(); - while (iter.hasNext()) { - Activity childActivity = iter.next(); - SequenceActivity branch = (SequenceActivity) monitoringService.getActivityById(childActivity.getActivityId(), SequenceActivity.class); - Set mappingEntries = branch.getBranchEntries(); - - // If it is a grouped based or teacher chosen branching, the users will be in groups. - // If not get the user based on the progress engine and create a dummy group. - // Can't use tool session as sequence activities don't have a tool session! - SortedSet groups = new TreeSet(); - if ( activity.isChosenBranchingActivity() || activity.isGroupBranchingActivity() ) { - for ( BranchActivityEntry entry : mappingEntries ) { - Group group = entry.getGroup(); - groups.add(group); - } - } else { - Group group = new Group(); - if ( group.getUsers() == null ) { - group.setUsers(new HashSet()); - } - List learners = monitoringService.getLearnersHaveAttemptedActivity(branch); - group.getUsers().addAll(learners); - groups.add(group); - } - branches.add(new BranchDTO(branch, groups)); - } - dto.setBranches(branches); - return dto; - } } Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupBasedBranchingAJAXAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupBasedBranchingAJAXAction.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupBasedBranchingAJAXAction.java 10 Oct 2007 07:12:15 -0000 1.1 @@ -0,0 +1,283 @@ +/**************************************************************** + * 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 version 2.0 + * 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 + * **************************************************************** + */ + +/* $Id: GroupBasedBranchingAJAXAction.java,v 1.1 2007/10/10 07:12:15 fmalikoff Exp $ */ +package org.lamsfoundation.lams.monitoring.web; + +import java.io.IOException; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.ActivityTitleComparator; +import org.lamsfoundation.lams.learningdesign.BranchingActivity; +import org.lamsfoundation.lams.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; +import org.lamsfoundation.lams.lesson.service.LessonServiceException; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; +import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** +* The action servlet that provides the support for the +*
    +*
  • AJAX based Groups Based Branching screen
  • +*
+* +* @author Fiona Malikoff + +* ----------------XDoclet Tags-------------------- +* +* @struts:action path="/groupedBranching" +* parameter="method" +* validate="false" +* @struts.action-forward name = "groupedSelection" path = "/branching/groupedSelection.jsp" +* @struts.action-forward name = "viewBranches" path = ".viewBranches" +* +* ----------------XDoclet Tags-------------------- +*/ +public class GroupBasedBranchingAJAXAction extends BranchingAction { + + //--------------------------------------------------------------------- + + private static final String GROUPED_SELECTION_SCREEN = "groupedSelection"; + public static final String PARAM_BRANCH_ID = "branchID"; + public static final String PARAM_MAY_DELETE = "mayDelete"; + public static final String PARAM_GROUPS = "groups"; + + /** + * Start the process of doing the group to branch mapping. Used for define later. + * + * Input parameters: activityID + */ + public ActionForward assignBranch(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + Long activityID = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + BranchingActivity activity = (BranchingActivity) monitoringService.getActivityById(activityID, BranchingActivity.class); + + if ( activity.isGroupBranchingActivity() ) { + + // in general the progress engine expects the activity and lesson id to be in the request, + // so follow that standard. + request.setAttribute(AttributeNames.PARAM_ACTIVITY_ID, activityID); + request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); + request.setAttribute(AttributeNames.PARAM_TITLE, activity.getTitle()); + + // can we still move groups? Only allowed if no users have started the branching activity + boolean usersStartedBranching = monitoringService.isActivityAttempted(activity); + request.setAttribute(PARAM_MAY_DELETE, ! usersStartedBranching); + + return mapping.findForward(GROUPED_SELECTION_SCREEN); + + } else { + // something gone wrong - shouldn't be here so revert to standard screen for viewing branching. + return viewBranching(activity, lessonId, false, mapping, request, monitoringService); + } + + } + + + /** + * Get a list of branch names, their associated group id and the number of groups for this branch. Designed to respond to an AJAX call. + * + * Input parameters: activityID (which is the branching activity id) + * + * Output format: "branchid,name,num groups;branchid,groupid,name,num groups" + */ + public ActionForward getBranches(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // get the branching data and sort it. + Long activityID = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + BranchingActivity activity = (BranchingActivity) monitoringService.getActivityById(activityID); + + TreeSet sortedBranches = new TreeSet(new ActivityTitleComparator()); + sortedBranches.addAll(activity.getActivities()); + + // build the output string to return to the chosen branching page. + // there should only ever be one group for each branch in chosen branching + String branchesOutput = ""; + + boolean first = true; + for ( Activity childActivity : sortedBranches ) { + + SequenceActivity branch = (SequenceActivity) monitoringService.getActivityById(childActivity.getActivityId(), SequenceActivity.class); + + Long branchId = branch.getActivityId(); + String name = branch.getTitle(); + + SortedSet groups = branch.getGroupsForBranch(); + int numberOfGroups = groups !=null ? groups.size() : 0; + + if ( ! first ) { + branchesOutput=branchesOutput+";"; + } else { + first = false; + } + + branchesOutput=branchesOutput+branchId+","+name+","+numberOfGroups; + } + + if ( log.isDebugEnabled() ) { + log.debug("getBranches activity id "+activityID+" returning "+branchesOutput); + } + + writeAJAXResponse(response, branchesOutput); + return null; + } + + /** + * Get a list of all the class members who aren't grouped yet. Designed to respond to an AJAX call. + * + * Input parameters: activityID (which is the branching activity id) + * + * Output format: "groupid,groupname;groupid,groupname" + */ + public ActionForward getGroupsNotAssignedToBranch(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // get the grouping data and sort it. + Long activityID = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + SortedSet groups = monitoringService.getGroupsNotAssignedToBranch(activityID); + String groupOutput = buildGroupString(groups); + writeAJAXResponse(response, groupOutput); + return null; + + } + + /** + * Get a list of groups associated with this branch. Designed to respond to an AJAX call. + * + * Input parameters: branchID which is sequence activity id + * + * Output format: "groupid,groupname;" + */ + public ActionForward getBranchGroups(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + Long branchID = WebUtil.readLongParam(request, PARAM_BRANCH_ID); + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + SequenceActivity branch = (SequenceActivity) monitoringService.getActivityById(branchID); + + SortedSet groups = branch.getGroupsForBranch(); + String groupOutput = buildGroupString(groups); + + if ( log.isDebugEnabled() ) { + log.debug("getBranchGroups branch id "+branchID+" returning "+groupOutput); + } + + writeAJAXResponse(response, groupOutput); + return null; + } + + + /** + * @param groups + * @return + */ + private String buildGroupString(SortedSet groups) { + String groupOutput = ""; + boolean first = true; + + for ( Group group : groups ) { + if ( ! first ) { + groupOutput=groupOutput+";"; + } else { + first = false; + } + groupOutput=groupOutput+group.getGroupId()+","+group.getGroupName(); + } + return groupOutput; + } + + /** + * Add groups to a branch. Designed to respond to an AJAX call. + * + * Input parameters: branchID, groups: comma separated list of group ids + * + * Output format: no data returned - just the header + */ + public ActionForward addGroups(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, LessonServiceException { + + Long branchID = WebUtil.readLongParam(request, PARAM_BRANCH_ID); + + String groups = WebUtil.readStrParam(request, PARAM_GROUPS, true); + if ( groups != null ) { + String[] groupsSplit = groups.split(","); + + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + monitoringService.addGroupToBranch(branchID, groupsSplit); + } + + writeAJAXOKResponse(response); + return null; + } + + /** + * Remove a list of users from a group. Designed to respond to an AJAX call. + * + * Input parameters: branchID, groups: comma separated list of group ids + * + * Output format: no data returned - just the header + */ + public ActionForward removeGroups(ActionMapping mapping, + ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, LessonServiceException { + + Long branchID = WebUtil.readLongParam(request, PARAM_BRANCH_ID); + + String groups = WebUtil.readStrParam(request, PARAM_GROUPS, true); + if ( groups != null ) { + String[] groupsSplit = groups.split(","); + + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet().getServletContext()); + monitoringService.removeGroupFromBranch(branchID, groupsSplit); + } + + writeAJAXOKResponse(response); + return null; + } + + + + } Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java,v diff -u -r1.8 -r1.9 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java 11 Sep 2007 01:36:57 -0000 1.8 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java 10 Oct 2007 07:12:15 -0000 1.9 @@ -98,20 +98,6 @@ } - private void writeAJAXResponse(HttpServletResponse response, String output) throws IOException { - // set it to unicode (LDEV-1275) - response.setContentType("text/html;charset=utf-8"); - PrintWriter writer = response.getWriter(); - - if (output.length()>0) { - writer.println(output); - } - } - - private void writeAJAXOKResponse(HttpServletResponse response) throws IOException { - writeAJAXResponse(response, "OK"); - } - private Grouping getGrouping(GroupingActivity activity) { Grouping grouping = activity.getCreateGrouping(); if ( grouping == null ) { Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ToolOutputBranchingAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ToolOutputBranchingAction.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ToolOutputBranchingAction.java 10 Oct 2007 07:12:15 -0000 1.1 @@ -0,0 +1,41 @@ +/**************************************************************** + * 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 version 2.0 + * 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 + * **************************************************************** + */ + +/* $Id: ToolOutputBranchingAction.java,v 1.1 2007/10/10 07:12:15 fmalikoff Exp $ */ +package org.lamsfoundation.lams.monitoring.web; + +/** +* The action servlet that provides the support for the tool output based branching. +* +* @author Fiona Malikoff +* ----------------XDoclet Tags-------------------- +* +* @struts:action path="/toolBranching" +* parameter="method" +* validate="false" +* @struts.action-forward name = "viewBranches" path = ".viewBranches" +* +* ----------------XDoclet Tags-------------------- +*/ +public class ToolOutputBranchingAction extends BranchingAction{ + +} Index: lams_monitoring/web/WEB-INF/struts/struts-config.xml =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/web/WEB-INF/struts/Attic/struts-config.xml,v diff -u -r1.18 -r1.19 --- lams_monitoring/web/WEB-INF/struts/struts-config.xml 9 Jul 2007 05:41:50 -0000 1.18 +++ lams_monitoring/web/WEB-INF/struts/struts-config.xml 10 Oct 2007 07:12:40 -0000 1.19 @@ -61,7 +61,25 @@ /> + + + + + + + "; + url="/chosenBranching.do?method=getBranches&activityID="; if (window.XMLHttpRequest) { // Non-IE browsers branchRequest = new XMLHttpRequest(); branchRequest.onreadystatechange = updateBranches; @@ -109,7 +109,7 @@ function getNonmembers(){ displayLoadingMessage(); - url="/branching.do?method=getClassMembersNotGrouped&lessonID=&activityID="; + url="/chosenBranching.do?method=getClassMembersNotGrouped&lessonID=&activityID="; if (window.XMLHttpRequest) { // Non-IE browsers nonmembersRequest = new XMLHttpRequest(); nonmembersRequest.onreadystatechange = updateNonmembers; @@ -152,7 +152,7 @@ function getMembers(branch){ displayLoadingMessage(); - url="/branching.do?method=getBranchMembers&branchID="+branch.value; + url="/chosenBranching.do?method=getBranchMembers&branchID="+branch.value; if (window.XMLHttpRequest) { // Non-IE browsers memberRequest = new XMLHttpRequest(); memberRequest.onreadystatechange = updateMembers; @@ -205,7 +205,7 @@ members = members + "," + nonmembersSelectObj.options[i].value; } } - url="/branching.do?method=addMembers&branchID="+document.getElementById("branches").value+"&members="+members.substr(1); + url="/chosenBranching.do?method=addMembers&branchID="+document.getElementById("branches").value+"&members="+members.substr(1); if (window.XMLHttpRequest) { // Non-IE browsers addmbrsRequest = new XMLHttpRequest(); addmbrsRequest.onreadystatechange = membersAdded; @@ -255,7 +255,7 @@ nonmembers = nonmembers + "," + membersSelectObj.options[i].value; } } - url="/branching.do?method=removeMembers&branchID="+document.getElementById("branches").value+"&members="+nonmembers.substr(1); + url="/chosenBranching.do?method=removeMembers&branchID="+document.getElementById("branches").value+"&members="+nonmembers.substr(1); if (window.XMLHttpRequest) { // Non-IE browsers rmmbrsRequest = new XMLHttpRequest(); rmmbrsRequest.onreadystatechange = membersRemoved; Index: lams_monitoring/web/branching/groupedSelection.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/web/branching/groupedSelection.jsp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_monitoring/web/branching/groupedSelection.jsp 10 Oct 2007 07:12:40 -0000 1.1 @@ -0,0 +1,373 @@ + <%-- +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 version 2 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 +--%> +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> + +<%@ taglib uri="tags-tiles" prefix="tiles" %> +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-core" prefix="c" %> +<%@ taglib uri="tags-lams" prefix="lams" %> + + + + + + + <c:out value="${title}"/> + + + + + + + + + +
+ +

+ +

+ +
+ + +

+
+ +

 

+ +

+ + + + + + + + + + + + + + + + + +
+ + + + + +
+   + + " onclick="addMembersToBranch()" disabled="true"/> + + " onclick="removeMembersFromBranch()" disabled="true"/> +
+ <%@ include file="../template/finishbutton.jsp" %> +
+ +
+ + + + + + +