Index: lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java =================================================================== diff -u -rc82a07c323413bc81bf2c072b7dbeafa6d9e3776 -rdd2804fae0fea44b5b713a8024f75e2a45aceada --- lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision c82a07c323413bc81bf2c072b7dbeafa6d9e3776) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision dd2804fae0fea44b5b713a8024f75e2a45aceada) @@ -108,1564 +108,1719 @@ import org.springframework.beans.factory.BeanFactoryAware; /** - * @author Manpreet Minhas + * @author Manpreet Minhas */ public class AuthoringService implements IAuthoringService, BeanFactoryAware { - protected Logger log = Logger.getLogger(AuthoringService.class); + protected Logger log = Logger.getLogger(AuthoringService.class); - /** Required DAO's */ - protected LearningDesignDAO learningDesignDAO; - protected LearningLibraryDAO learningLibraryDAO; - protected ActivityDAO activityDAO; - protected BaseDAO baseDAO; - protected TransitionDAO transitionDAO; - protected ToolDAO toolDAO; - protected LicenseDAO licenseDAO; - protected GroupingDAO groupingDAO; - protected GroupDAO groupDAO; - protected CompetenceDAO competenceDAO; - protected CompetenceMappingDAO competenceMappingDAO; - protected SystemToolDAO systemToolDAO; - protected ILamsCoreToolService lamsCoreToolService; - protected ILearningDesignService learningDesignService; - protected MessageService messageService; - protected ILessonService lessonService; - protected IMonitoringService monitoringService; - protected IWorkspaceManagementService workspaceManagementService; + /** Required DAO's */ + protected LearningDesignDAO learningDesignDAO; - protected ToolContentIDGenerator contentIDGenerator; + protected LearningLibraryDAO learningLibraryDAO; - /** The bean factory is used to create ObjectExtractor objects */ - protected BeanFactory beanFactory; + protected ActivityDAO activityDAO; - public AuthoringService() { + protected BaseDAO baseDAO; - } + protected TransitionDAO transitionDAO; - /********************************************** - * Setter Methods - * *******************************************/ - /** - * Set i18n MessageService - */ - public void setMessageService(MessageService messageService) { - this.messageService = messageService; - } + protected ToolDAO toolDAO; - /** - * @param groupDAO The groupDAO to set. - */ - public void setGroupDAO(GroupDAO groupDAO) { - this.groupDAO = groupDAO; - } + protected LicenseDAO licenseDAO; - public void setGroupingDAO(GroupingDAO groupingDAO) { - this.groupingDAO = groupingDAO; - } + protected GroupingDAO groupingDAO; - /** - * - * @return - */ - public CompetenceDAO getCompetenceDAO() { - return competenceDAO; - } + protected GroupDAO groupDAO; - /** - * - * @param competenceDAO - */ - public void setCompetenceDAO(CompetenceDAO competenceDAO) { - this.competenceDAO = competenceDAO; - } + protected CompetenceDAO competenceDAO; - /** - * - * @return - */ - public CompetenceMappingDAO getCompetenceMappingDAO() { - return competenceMappingDAO; - } + protected CompetenceMappingDAO competenceMappingDAO; - /** - * - * @param competenceMappingDAO - */ - public void setCompetenceMappingDAO(CompetenceMappingDAO competenceMappingDAO) { - this.competenceMappingDAO = competenceMappingDAO; - } + protected SystemToolDAO systemToolDAO; - /** - * @param transitionDAO The transitionDAO to set - */ - public void setTransitionDAO(TransitionDAO transitionDAO) { - this.transitionDAO = transitionDAO; - } + protected ILamsCoreToolService lamsCoreToolService; - /** - * @param learningDesignDAO The learningDesignDAO to set. - */ - public void setLearningDesignDAO(LearningDesignDAO learningDesignDAO) { - this.learningDesignDAO = learningDesignDAO; - } + protected ILearningDesignService learningDesignService; - /** - * @param learningLibraryDAO The learningLibraryDAO to set. - */ - public void setLearningLibraryDAO(LearningLibraryDAO learningLibraryDAO) { - this.learningLibraryDAO = learningLibraryDAO; - } + protected MessageService messageService; - /** - * @param baseDAO The baseDAO to set. - */ - public void setBaseDAO(BaseDAO baseDAO) { - this.baseDAO = baseDAO; - } + protected ILessonService lessonService; - /** - * @param activityDAO The activityDAO to set. - */ - public void setActivityDAO(ActivityDAO activityDAO) { - this.activityDAO = activityDAO; - } + protected IMonitoringService monitoringService; - /** - * @param toolDAO The toolDAO to set - */ - public void setToolDAO(ToolDAO toolDAO) { - this.toolDAO = toolDAO; - } + protected IWorkspaceManagementService workspaceManagementService; - /** - * @param toolDAO The toolDAO to set - */ - public void setSystemToolDAO(SystemToolDAO systemToolDAO) { - this.systemToolDAO = systemToolDAO; - } + protected ToolContentIDGenerator contentIDGenerator; - /** - * @param licenseDAO The licenseDAO to set - */ - public void setLicenseDAO(LicenseDAO licenseDAO) { - this.licenseDAO = licenseDAO; - } + /** The bean factory is used to create ObjectExtractor objects */ + protected BeanFactory beanFactory; - public ILamsCoreToolService getLamsCoreToolService() { - return lamsCoreToolService; - } + public AuthoringService() { - public void setLamsCoreToolService(ILamsCoreToolService lamsCoreToolService) { - this.lamsCoreToolService = lamsCoreToolService; - } + } - public ILearningDesignService getLearningDesignService() { - return learningDesignService; - } + /********************************************** + * Setter Methods + * *******************************************/ + /** + * Set i18n MessageService + */ + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } - /** - * @param learningDesignService The Learning Design Validator Service - */ - public void setLearningDesignService(ILearningDesignService learningDesignService) { - this.learningDesignService = learningDesignService; - } + /** + * @param groupDAO + * The groupDAO to set. + */ + public void setGroupDAO(GroupDAO groupDAO) { + this.groupDAO = groupDAO; + } - public MessageService getMessageService() { - return messageService; - } + public void setGroupingDAO(GroupingDAO groupingDAO) { + this.groupingDAO = groupingDAO; + } - public ILessonService getLessonService() { - return lessonService; - } + /** + * + * @return + */ + public CompetenceDAO getCompetenceDAO() { + return competenceDAO; + } - public void setLessonService(ILessonService lessonService) { - this.lessonService = lessonService; - } + /** + * + * @param competenceDAO + */ + public void setCompetenceDAO(CompetenceDAO competenceDAO) { + this.competenceDAO = competenceDAO; + } - public void setMonitoringService(IMonitoringService monitoringService) { - this.monitoringService = monitoringService; - } + /** + * + * @return + */ + public CompetenceMappingDAO getCompetenceMappingDAO() { + return competenceMappingDAO; + } - public void setWorkspaceManagementService(IWorkspaceManagementService workspaceManagementService) { - this.workspaceManagementService = workspaceManagementService; - } + /** + * + * @param competenceMappingDAO + */ + public void setCompetenceMappingDAO(CompetenceMappingDAO competenceMappingDAO) { + this.competenceMappingDAO = competenceMappingDAO; + } - /** - * @param contentIDGenerator The contentIDGenerator to set. - */ - public void setContentIDGenerator(ToolContentIDGenerator contentIDGenerator) { - this.contentIDGenerator = contentIDGenerator; - } + /** + * @param transitionDAO + * The transitionDAO to set + */ + public void setTransitionDAO(TransitionDAO transitionDAO) { + this.transitionDAO = transitionDAO; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesign(java.lang.Long) - */ - public LearningDesign getLearningDesign(Long learningDesignID) { - return learningDesignDAO.getLearningDesignById(learningDesignID); - } + /** + * @param learningDesignDAO + * The learningDesignDAO to set. + */ + public void setLearningDesignDAO(LearningDesignDAO learningDesignDAO) { + this.learningDesignDAO = learningDesignDAO; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#saveLearningDesign(org.lamsfoundation.lams.learningdesign.LearningDesign) - */ - public void saveLearningDesign(LearningDesign learningDesign) { - learningDesignDAO.insertOrUpdate(learningDesign); - } + /** + * @param learningLibraryDAO + * The learningLibraryDAO to set. + */ + public void setLearningLibraryDAO(LearningLibraryDAO learningLibraryDAO) { + this.learningLibraryDAO = learningLibraryDAO; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningDesigns() - */ - public List getAllLearningDesigns() { - return learningDesignDAO.getAllLearningDesigns(); - } + /** + * @param baseDAO + * The baseDAO to set. + */ + public void setBaseDAO(BaseDAO baseDAO) { + this.baseDAO = baseDAO; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningLibraries() - */ - public List getAllLearningLibraries() { - return learningLibraryDAO.getAllLearningLibraries(); - } + /** + * @param activityDAO + * The activityDAO to set. + */ + public void setActivityDAO(ActivityDAO activityDAO) { + this.activityDAO = activityDAO; + } - public BeanFactory getBeanFactory() { - return beanFactory; - } + /** + * @param toolDAO + * The toolDAO to set + */ + public void setToolDAO(ToolDAO toolDAO) { + this.toolDAO = toolDAO; + } - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } + /** + * @param toolDAO + * The toolDAO to set + */ + public void setSystemToolDAO(SystemToolDAO systemToolDAO) { + this.systemToolDAO = systemToolDAO; + } - /********************************************** - * Utility/Service Methods - * *******************************************/ + /** + * @param licenseDAO + * The licenseDAO to set + */ + public void setLicenseDAO(LicenseDAO licenseDAO) { + this.licenseDAO = licenseDAO; + } - /** - * Helper method to retrieve the user data. Gets the id from the user details - * in the shared session - * @return the user id - */ - public static Integer getUserId() { - HttpSession ss = SessionManager.getSession(); - UserDTO learner = (UserDTO) ss.getAttribute(AttributeNames.USER); - return learner != null ? learner.getUserID() : null; - } + public ILamsCoreToolService getLamsCoreToolService() { + return lamsCoreToolService; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getToolOutputDefinitions(java.lang.Long) - */ - public String getToolOutputDefinitions(Long toolContentID) throws IOException { + public void setLamsCoreToolService(ILamsCoreToolService lamsCoreToolService) { + this.lamsCoreToolService = lamsCoreToolService; + } - SortedMap defns = lamsCoreToolService.getOutputDefinitionsFromTool(toolContentID); + public ILearningDesignService getLearningDesignService() { + return learningDesignService; + } - ArrayList defnDTOList = new ArrayList(defns != null ? defns.size() : 0); - if (defns != null) { - for (ToolOutputDefinition defn : defns.values()) { - defnDTOList.add(new ToolOutputDefinitionDTO(defn)); - } - } + /** + * @param learningDesignService + * The Learning Design Validator Service + */ + public void setLearningDesignService(ILearningDesignService learningDesignService) { + this.learningDesignService = learningDesignService; + } - FlashMessage flashMessage = new FlashMessage("getToolOutputDefinitions", defnDTOList); - return flashMessage.serializeMessage(); - } + public MessageService getMessageService() { + return messageService; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesignDetails(java.lang.Long, java.lang.Long) - */ - public String getLearningDesignDetails(Long learningDesignID, String languageCode) throws IOException { - FlashMessage flashMessage = null; + public ILessonService getLessonService() { + return lessonService; + } - LearningDesignDTO learningDesignDTO = learningDesignService.getLearningDesignDTO(learningDesignID, languageCode); + public void setLessonService(ILessonService lessonService) { + this.lessonService = lessonService; + } - if (learningDesignDTO == null) { - flashMessage = FlashMessage.getNoSuchLearningDesignExists("getLearningDesignDetails", learningDesignID); - } - else { - flashMessage = new FlashMessage("getLearningDesignDetails", learningDesignDTO); - } - return flashMessage.serializeMessage(); - } + public void setMonitoringService(IMonitoringService monitoringService) { + this.monitoringService = monitoringService; + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#isLearningDesignAvailable(LearningDesign, java.lang.Integer) - */ - public boolean isLearningDesignAvailable(LearningDesign design, Integer userID) throws LearningDesignException, IOException { - if (design == null) { - throw new LearningDesignException(FlashMessage.getNoSuchLearningDesignExists("getLearningDesignDetails", - design.getLearningDesignId()).serializeMessage()); - } + public void setWorkspaceManagementService(IWorkspaceManagementService workspaceManagementService) { + this.workspaceManagementService = workspaceManagementService; + } - if (design.getEditOverrideUser() != null && design.getEditOverrideLock() != null) { - return design.getEditOverrideUser().getUserId().equals(userID) ? true : !design.getEditOverrideLock(); - } - else { - return true; - } - } + /** + * @param contentIDGenerator + * The contentIDGenerator to set. + */ + public void setContentIDGenerator(ToolContentIDGenerator contentIDGenerator) { + this.contentIDGenerator = contentIDGenerator; + } - private void setLessonLock(LearningDesign design, boolean lock) { - Lesson lesson = null; + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesign(java.lang.Long) + */ + public LearningDesign getLearningDesign(Long learningDesignID) { + return learningDesignDAO.getLearningDesignById(learningDesignID); + } - // lock active lesson - Set lessons = design.getLessons(); - Iterator it = lessons.iterator(); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#saveLearningDesign(org.lamsfoundation.lams.learningdesign.LearningDesign) + */ + public void saveLearningDesign(LearningDesign learningDesign) { + learningDesignDAO.insertOrUpdate(learningDesign); + } - while (it.hasNext()) { - lesson = (Lesson) it.next(); - lesson.setLockedForEdit(lock); - } - } + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningDesigns() + */ + public List getAllLearningDesigns() { + return learningDesignDAO.getAllLearningDesigns(); + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#setupEditOnFlyLock(LearningDesign, java.lang.Integer) - */ - public boolean setupEditOnFlyLock(Long learningDesignID, Integer userID) throws LearningDesignException, UserException, - IOException { - User user = (User) baseDAO.find(User.class, userID); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningLibraries() + */ + public List getAllLearningLibraries() { + return learningLibraryDAO.getAllLearningLibraries(); + } - LearningDesign design = learningDesignID != null ? getLearningDesign(learningDesignID) : null; + public BeanFactory getBeanFactory() { + return beanFactory; + } - if (isLearningDesignAvailable(design, userID)) { + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } - if (design.getLessons().isEmpty()) { - throw new LearningDesignException("There are no lessons attached to the design."); // TODO: add error msg - } - else if (user == null) { - throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); - } + /********************************************** + * Utility/Service Methods + * *******************************************/ - setLessonLock(design, true); + /** + * Helper method to retrieve the user data. Gets the id from the user + * details in the shared session + * + * @return the user id + */ + public static Integer getUserId() { + HttpSession ss = SessionManager.getSession(); + UserDTO learner = (UserDTO) ss.getAttribute(AttributeNames.USER); + return learner != null ? learner.getUserID() : null; + } - // lock Learning Design - design.setEditOverrideLock(true); - design.setEditOverrideUser(user); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getToolOutputDefinitions(java.lang.Long) + */ + public String getToolOutputDefinitions(Long toolContentID) throws IOException { - learningDesignDAO.update(design); + SortedMap defns = lamsCoreToolService.getOutputDefinitionsFromTool(toolContentID); - return true; - } - else { - return false; - } + ArrayList defnDTOList = new ArrayList(defns != null ? defns + .size() : 0); + if (defns != null) { + for (ToolOutputDefinition defn : defns.values()) { + defnDTOList.add(new ToolOutputDefinitionDTO(defn)); + } } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#setupEditOnFlyGate(java.lang.Long, java.lang.Integer) - */ - public String setupEditOnFlyGate(Long learningDesignID, Integer userID) throws UserException, IOException { - User user = (User) baseDAO.find(User.class, userID); - LearningDesign design = learningDesignID != null ? getLearningDesign(learningDesignID) : null; + FlashMessage flashMessage = new FlashMessage("getToolOutputDefinitions", defnDTOList); + return flashMessage.serializeMessage(); + } - if (user == null) { - throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); - } + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesignDetails(java.lang.Long, + * java.lang.Long) + */ + public String getLearningDesignDetails(Long learningDesignID, String languageCode) throws IOException { + FlashMessage flashMessage = null; - EditOnFlyProcessor processor = new EditOnFlyProcessor(design, activityDAO); /* parse Learning Design to find last read-only Activity */ - processor.parseLearningDesign(); + LearningDesignDTO learningDesignDTO = learningDesignService + .getLearningDesignDTO(learningDesignID, languageCode); - ArrayList activities = processor.getLastReadOnlyActivity(); - addSystemGateAfterActivity(activities, design); /* add new System Gate after last read-only Activity */ + if (learningDesignDTO == null) { + flashMessage = FlashMessage.getNoSuchLearningDesignExists("getLearningDesignDetails", learningDesignID); + } else { + flashMessage = new FlashMessage("getLearningDesignDetails", learningDesignDTO); + } + return flashMessage.serializeMessage(); + } - setLessonLock(design, false); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#isLearningDesignAvailable(LearningDesign, + * java.lang.Integer) + */ + public boolean isLearningDesignAvailable(LearningDesign design, Integer userID) throws LearningDesignException, + IOException { + if (design == null) { + throw new LearningDesignException(FlashMessage.getNoSuchLearningDesignExists("getLearningDesignDetails", + design.getLearningDesignId()).serializeMessage()); + } - learningDesignDAO.update(design); + if (design.getEditOverrideUser() != null && design.getEditOverrideLock() != null) { + return design.getEditOverrideUser().getUserId().equals(userID) ? true : !design.getEditOverrideLock(); + } else { + return true; + } + } - return new FlashMessage("setupEditOnFlyGate", true).serializeMessage(); + private void setLessonLock(LearningDesign design, boolean lock) { + Lesson lesson = null; + + // lock active lesson + Set lessons = design.getLessons(); + Iterator it = lessons.iterator(); + + while (it.hasNext()) { + lesson = (Lesson) it.next(); + lesson.setLockedForEdit(lock); } + } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#finishEditOnFly(java.lang.Long, java.lang.Integer) - */ - public String finishEditOnFly(Long learningDesignID, Integer userID, boolean cancelled) throws IOException { - FlashMessage flashMessage = null; - Lesson lesson = null; + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#setupEditOnFlyLock(LearningDesign, + * java.lang.Integer) + */ + public boolean setupEditOnFlyLock(Long learningDesignID, Integer userID) throws LearningDesignException, + UserException, IOException { + User user = (User) baseDAO.find(User.class, userID); - LearningDesign design = learningDesignID != null ? learningDesignDAO.getLearningDesignById(learningDesignID) : null; + LearningDesign design = learningDesignID != null ? getLearningDesign(learningDesignID) : null; - User user = (User) baseDAO.find(User.class, userID); - if (user == null) { - flashMessage = FlashMessage.getNoSuchUserExists("finishEditOnFly", userID); - } + if (isLearningDesignAvailable(design, userID)) { - if (design != null) { /* only the user who is editing the design may unlock it */ - if (design.getEditOverrideUser().equals(user)) { - design.setEditOverrideLock(false); - design.setEditOverrideUser(null); + if (design.getLessons().isEmpty()) { + throw new LearningDesignException("There are no lessons attached to the design."); // TODO: + // add + // error + // msg + } else if (user == null) { + throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); + } - Set lessons = design.getLessons(); /* unlock lesson */ + setLessonLock(design, true); - Iterator it = lessons.iterator(); - while (it.hasNext()) { - lesson = (Lesson) it.next(); - lesson.setLockedForEdit(false); - } + // lock Learning Design + design.setEditOverrideLock(true); + design.setEditOverrideUser(user); - EditOnFlyProcessor processor = new EditOnFlyProcessor(design, activityDAO); /* parse Learning Design to find last read-only Activity (hopefully the system gate in this case) */ - processor.parseLearningDesign(); + learningDesignDAO.update(design); - ArrayList activities = processor.getLastReadOnlyActivity(); + return true; + } else { + return false; + } + } - GateActivity gate = null; /* open and release waiting list on system gate */ + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#setupEditOnFlyGate(java.lang.Long, + * java.lang.Integer) + */ + public String setupEditOnFlyGate(Long learningDesignID, Integer userID) throws UserException, IOException { + User user = (User) baseDAO.find(User.class, userID); + LearningDesign design = learningDesignID != null ? getLearningDesign(learningDesignID) : null; - if (activities != null) { - if (!activities.isEmpty() && activities.get(0).isGateActivity()) { - gate = (GateActivity) activities.get(0); - } - } + if (user == null) { + throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); + } - if (gate != null) { - design = removeTempSystemGate(gate, design); /* remove inputted system gate */ - } + // parse Learning Design to find last read - only Activity + EditOnFlyProcessor processor = new EditOnFlyProcessor(design, activityDAO); - // LDEV-1899 only mark learners uncompleted if a change was saved - if (!cancelled) { - lessonService.performMarkLessonUncompleted(lesson.getLessonId()); /* the lesson may now have additional activities on the end, so clear any completed flags */ - } + processor.parseLearningDesign(); - initialiseToolActivityForRuntime(design, lesson); - learningDesignDAO.insertOrUpdate(design); + ArrayList activities = processor.getLastReadOnlyActivity(); - flashMessage = new FlashMessage("finishEditOnFly", lesson.getLessonId()); + // add new System Gate after last read-only Activity + addSystemGateAfterActivity(activities, design); - } - else { - flashMessage = FlashMessage.getNoSuchUserExists("finishEditOnFly", userID); - } - } - else { + setLessonLock(design, false); - flashMessage = FlashMessage.getNoSuchLearningDesignExists("finishEditOnFly", learningDesignID); - } + learningDesignDAO.update(design); - return flashMessage.serializeMessage(); + return new FlashMessage("setupEditOnFlyGate", true).serializeMessage(); + } + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#finishEditOnFly(java.lang.Long, + * java.lang.Integer) + */ + public String finishEditOnFly(Long learningDesignID, Integer userID, boolean cancelled) throws IOException { + FlashMessage flashMessage = null; + Lesson lesson = null; + + LearningDesign design = learningDesignID != null ? learningDesignDAO.getLearningDesignById(learningDesignID) + : null; + + User user = (User) baseDAO.find(User.class, userID); + if (user == null) { + flashMessage = FlashMessage.getNoSuchUserExists("finishEditOnFly", userID); } - /** - * Remove a temp. System Gate from the design. Requires removing the gate from any learner progress entries - should only - * be a current activity but remove it from previous and next, just in case. - * - * This will leave a "hole" in the learner progress, but the progress engine can take care of that. - * @param gate - * @param design - * @return Learning Design with removed System Gate - */ - public LearningDesign removeTempSystemGate(GateActivity gate, LearningDesign design) { - Transition toTransition = gate.getTransitionTo(); /* get transitions */ - Transition fromTransition = gate.getTransitionFrom(); + if (design != null) { /* + * only the user who is editing the design may + * unlock it + */ + if (design.getEditOverrideUser().equals(user)) { + design.setEditOverrideLock(false); + design.setEditOverrideUser(null); - if (toTransition != null && fromTransition != null) { /* rearrange to-transition and/or delete redundant transition */ - toTransition.setToActivity(fromTransition.getToActivity()); - toTransition.setToUIID(toTransition.getToActivity().getActivityUIID()); + Set lessons = design.getLessons(); /* unlock lesson */ - design.getTransitions().remove(fromTransition); - transitionDAO.update(toTransition); + Iterator it = lessons.iterator(); + while (it.hasNext()) { + lesson = (Lesson) it.next(); + lesson.setLockedForEdit(false); + } + /* + * parse Learning Design to find last read - only Activity ( + * hopefully the system gate in this case ) + */ + EditOnFlyProcessor processor = new EditOnFlyProcessor(design, activityDAO); + + processor.parseLearningDesign(); + + ArrayList activities = processor.getLastReadOnlyActivity(); + + // open and release waiting list on system gate + GateActivity gate = null; + + if (activities != null) { + if (!activities.isEmpty() && activities.get(0).isGateActivity()) { + gate = (GateActivity) activities.get(0); + } } - else if (toTransition != null && fromTransition == null) { - design.getTransitions().remove(toTransition); + + if (gate != null) { + // remove inputted system gate + design = removeTempSystemGate(gate, design); } - else if (toTransition == null && fromTransition != null) { - design.setFirstActivity(fromTransition.getToActivity()); - design.getTransitions().remove(fromTransition); + + // LDEV-1899 only mark learners uncompleted if a change was + // saved + if (!cancelled) { + // the lesson may now have additional activities on the end, + // so clear any completed flags + lessonService.performMarkLessonUncompleted(lesson.getLessonId()); } - design.getActivities().remove(gate); /* remove temp system gate */ + initialiseToolActivityForRuntime(design, lesson); + learningDesignDAO.insertOrUpdate(design); - design.setDesignVersion(design.getDesignVersion() + 1); /* increment design version field */ + flashMessage = new FlashMessage("finishEditOnFly", lesson.getLessonId()); - lessonService.removeProgressReferencesToActivity(gate); /* need to remove it from any learner progress entries */ + } else { + flashMessage = FlashMessage.getNoSuchUserExists("finishEditOnFly", userID); + } + } else { - return design; + flashMessage = FlashMessage.getNoSuchLearningDesignExists("finishEditOnFly", learningDesignID); } - /** - * Add a temp. System Gate. to the design. - * - * @param activities - * @param design - */ - public void addSystemGateAfterActivity(ArrayList activities, LearningDesign design) { - GateActivity gate = null; + return flashMessage.serializeMessage(); - Integer syncType = new Integer(Activity.SYSTEM_GATE_ACTIVITY_TYPE); - Integer activityType = new Integer(Activity.SYSTEM_GATE_ACTIVITY_TYPE); - Integer maxId = design.getMaxID(); - String title = "System Gate"; /* messageService.getMessage(MSG_KEY_SYNC_GATE); */ + } - SystemTool systemTool = systemToolDAO.getSystemToolByID(SystemTool.SYSTEM_GATE); - Activity activity = activities.isEmpty() ? null : (Activity) activities.get(0); + /** + * Remove a temp. System Gate from the design. Requires removing the gate + * from any learner progress entries - should only be a current activity but + * remove it from previous and next, just in case. + * + * This will leave a "hole" in the learner progress, but the progress engine + * can take care of that. + * + * @param gate + * @param design + * @return Learning Design with removed System Gate + */ + public LearningDesign removeTempSystemGate(GateActivity gate, LearningDesign design) { + // get transitions + Transition toTransition = gate.getTransitionTo(); + Transition fromTransition = gate.getTransitionFrom(); - try { /* create new System Gate Activity */ - gate = (GateActivity) Activity.getActivityInstance(syncType.intValue()); - gate.setActivityTypeId(activityType.intValue()); - gate.setActivityCategoryID(Activity.CATEGORY_SYSTEM); - gate.setSystemTool(systemTool); - gate.setActivityUIID(++maxId); - gate.setTitle(title != null ? title : "Gate"); - gate.setGateOpen(false); - gate.setWaitingLearners(null); - gate.setGateActivityLevelId(GateActivity.LEARNER_GATE_LEVEL); - gate.setApplyGrouping(false); // not nullable so default to false - gate.setGroupingSupportType(Activity.GROUPING_SUPPORT_OPTIONAL); - gate.setOrderId(null); - gate.setDefineLater(Boolean.FALSE); - gate.setCreateDateTime(new Date()); - gate.setRunOffline(Boolean.FALSE); - gate.setReadOnly(Boolean.TRUE); - gate.setLearningDesign(design); + // rearrange to-transition and/or delete redundant transition + if (toTransition != null && fromTransition != null) { - design.getActivities().add(gate); - baseDAO.insert(gate); + toTransition.setToActivity(fromTransition.getToActivity()); + toTransition.setToUIID(toTransition.getToActivity().getActivityUIID()); - Transition fromTransition; - Transition newTransition = new Transition(); - Activity toActivity = null; + design.getTransitions().remove(fromTransition); + transitionDAO.update(toTransition); - if (activity != null) { - fromTransition = activity.getTransitionFrom(); /* update transitions */ + } else if (toTransition != null && fromTransition == null) { + design.getTransitions().remove(toTransition); + } else if (toTransition == null && fromTransition != null) { + design.setFirstActivity(fromTransition.getToActivity()); + design.getTransitions().remove(fromTransition); + } - if (fromTransition != null) { - toActivity = fromTransition.getToActivity(); + // remove temp system gate + design.getActivities().remove(gate); - fromTransition.setToActivity(gate); - fromTransition.setToUIID(gate.getActivityUIID()); + // increment design version field + design.setDesignVersion(design.getDesignVersion() + 1); - newTransition.setTransitionUIID(++maxId); - newTransition.setFromActivity(gate); - newTransition.setFromUIID(gate.getActivityUIID()); - newTransition.setToActivity(toActivity); - newTransition.setToUIID(toActivity.getActivityUIID()); - newTransition.setLearningDesign(design); + // need to remove it from any learner progress entries + lessonService.removeProgressReferencesToActivity(gate); - gate.setTransitionFrom(newTransition); + return design; + } - toActivity.setTransitionTo(newTransition); + /** + * Add a temp. System Gate. to the design. + * + * @param activities + * @param design + */ + public void addSystemGateAfterActivity(ArrayList activities, LearningDesign design) { + GateActivity gate = null; - Integer x1 = activity.getXcoord() != null ? activity.getXcoord() : 0; /* set x/y position for Gate */ - Integer x2 = toActivity.getXcoord() != null ? toActivity.getXcoord() : 0; + Integer syncType = new Integer(Activity.SYSTEM_GATE_ACTIVITY_TYPE); + Integer activityType = new Integer(Activity.SYSTEM_GATE_ACTIVITY_TYPE); + Integer maxId = design.getMaxID(); + // messageService.getMessage(MSG_KEY_SYNC_GATE ); + String title = "System Gate"; - gate.setXcoord(new Integer((x1.intValue() + 123 + x2.intValue()) / 2 - 13)); + SystemTool systemTool = systemToolDAO.getSystemToolByID(SystemTool.SYSTEM_GATE); + Activity activity = activities.isEmpty() ? null : (Activity) activities.get(0); - Integer y1 = activity.getYcoord() != null ? activity.getYcoord() : 0; - Integer y2 = toActivity.getYcoord() != null ? toActivity.getYcoord() : 0; + try { /* create new System Gate Activity */ + gate = (GateActivity) Activity.getActivityInstance(syncType.intValue()); + gate.setActivityTypeId(activityType.intValue()); + gate.setActivityCategoryID(Activity.CATEGORY_SYSTEM); + gate.setSystemTool(systemTool); + gate.setActivityUIID(++maxId); + gate.setTitle(title != null ? title : "Gate"); + gate.setGateOpen(false); + gate.setWaitingLearners(null); + gate.setGateActivityLevelId(GateActivity.LEARNER_GATE_LEVEL); + gate.setApplyGrouping(false); // not nullable so default to false + gate.setGroupingSupportType(Activity.GROUPING_SUPPORT_OPTIONAL); + gate.setOrderId(null); + gate.setDefineLater(Boolean.FALSE); + gate.setCreateDateTime(new Date()); + gate.setRunOffline(Boolean.FALSE); + gate.setReadOnly(Boolean.TRUE); + gate.setLearningDesign(design); - gate.setYcoord(new Integer((y1.intValue() + 50 + y2.intValue()) / 2)); + design.getActivities().add(gate); + baseDAO.insert(gate); - } - else { - //fromTransition = newTransition; + Transition fromTransition; + Transition newTransition = new Transition(); + Activity toActivity = null; - newTransition.setTransitionUIID(++maxId); - newTransition.setFromActivity(activity); - newTransition.setFromUIID(activity.getActivityUIID()); - newTransition.setToActivity(gate); - newTransition.setToUIID(gate.getActivityUIID()); - newTransition.setLearningDesign(design); + if (activity != null) { + // update transitions + fromTransition = activity.getTransitionFrom(); - activity.setTransitionFrom(fromTransition); - gate.setTransitionTo(fromTransition); + if (fromTransition != null) { + toActivity = fromTransition.getToActivity(); - Integer x1 = activity.getTransitionTo() != null ? activity.getTransitionTo().getFromActivity().getXcoord() - : 0; /* set x/y position for Gate */ - Integer x2 = activity.getXcoord() != null ? activity.getXcoord() : 0; + fromTransition.setToActivity(gate); + fromTransition.setToUIID(gate.getActivityUIID()); - if (x1 != null && x2 != null) { - gate.setXcoord(x2 >= x1 ? new Integer(x2.intValue() + 123 + 13 + 20) : new Integer( - x2.intValue() - 13 - 20)); - } - else { - gate.setXcoord(new Integer(x2.intValue() + 123 + 13 + 20)); - } + newTransition.setTransitionUIID(++maxId); + newTransition.setFromActivity(gate); + newTransition.setFromUIID(gate.getActivityUIID()); + newTransition.setToActivity(toActivity); + newTransition.setToUIID(toActivity.getActivityUIID()); + newTransition.setLearningDesign(design); - gate.setYcoord(activity.getYcoord() + 25); - } + gate.setTransitionFrom(newTransition); - } - else { - fromTransition = newTransition; /* no read-only activities insert gate at start of sequence */ - toActivity = design.getFirstActivity(); + toActivity.setTransitionTo(newTransition); - newTransition.setTransitionUIID(++maxId); - newTransition.setToActivity(toActivity); - newTransition.setToUIID(toActivity.getActivityUIID()); - newTransition.setFromActivity(gate); - newTransition.setFromUIID(gate.getActivityUIID()); - newTransition.setLearningDesign(design); + // set x / y position for Gate + Integer x1 = activity.getXcoord() != null ? activity.getXcoord() : 0; - gate.setTransitionFrom(fromTransition); - toActivity.setTransitionTo(fromTransition); + Integer x2 = toActivity.getXcoord() != null ? toActivity.getXcoord() : 0; - gate.setGateOpen(false); /* keep gate door closed to stop learner's from going past this point */ + gate.setXcoord(new Integer((x1.intValue() + 123 + x2.intValue()) / 2 - 13)); - design.setFirstActivity(gate); /* set gate as first activity in sequence */ + Integer y1 = activity.getYcoord() != null ? activity.getYcoord() : 0; + Integer y2 = toActivity.getYcoord() != null ? toActivity.getYcoord() : 0; - Integer x1 = toActivity.getXcoord() != null ? toActivity.getXcoord() : 0; /* set x/y position for Gate */ - Integer x2 = toActivity.getTransitionFrom() != null ? toActivity.getTransitionFrom().getToActivity().getXcoord() - : null; + gate.setYcoord(new Integer((y1.intValue() + 50 + y2.intValue()) / 2)); - if (x1 != null && x2 != null) { - gate.setXcoord(x2 >= x1 ? new Integer(x1.intValue() - 13 - 20) : new Integer(x1.intValue() + 123 + 13 + 20)); - } - else { - gate.setXcoord(new Integer(x1.intValue() - 13 - 20)); - } + } else { + // fromTransition = newTransition; - gate.setYcoord(toActivity.getYcoord() + 25); - } + newTransition.setTransitionUIID(++maxId); + newTransition.setFromActivity(activity); + newTransition.setFromUIID(activity.getActivityUIID()); + newTransition.setToActivity(gate); + newTransition.setToUIID(gate.getActivityUIID()); + newTransition.setLearningDesign(design); - design.getTransitions().add(newTransition); - design.setMaxID(maxId); + activity.setTransitionFrom(fromTransition); + gate.setTransitionTo(fromTransition); - design.setDesignVersion(design.getDesignVersion() + 1); /* increment design version field */ + Integer x1 = activity.getTransitionTo() != null ? activity.getTransitionTo().getFromActivity() + .getXcoord() : 0; /* set x/y position for Gate */ + Integer x2 = activity.getXcoord() != null ? activity.getXcoord() : 0; - if (gate != null) { - activityDAO.update(gate); - } - if (activity != null) { - activityDAO.update(activity); - } - if (toActivity != null) { - activityDAO.update(toActivity); - } + if (x1 != null && x2 != null) { + gate.setXcoord(x2 >= x1 ? new Integer(x2.intValue() + 123 + 13 + 20) : new Integer(x2 + .intValue() - 13 - 20)); + } else { + gate.setXcoord(new Integer(x2.intValue() + 123 + 13 + 20)); + } - if (fromTransition != null && !fromTransition.equals(newTransition)) { - baseDAO.update(fromTransition); - } - if (newTransition != null) { - baseDAO.insert(newTransition); - } - if (design != null) { - learningDesignDAO.insertOrUpdate(design); - } - + gate.setYcoord(activity.getYcoord() + 25); } - catch (NullPointerException npe) { - log.error(npe.getMessage(), npe); - } - } + } else { + // no read-only activities insert gate at start of sequence + fromTransition = newTransition; - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getFirstUnattemptedActivity(org.lamsfoundation.lams.learningdesign.LearningDesign) - */ - public Activity getFirstUnattemptedActivity(LearningDesign design) throws LearningDesignException { - Activity activity = design.getFirstActivity(); + toActivity = design.getFirstActivity(); - while (activity.getReadOnly() && activity.getTransitionFrom() != null) { - activity = activity.getTransitionFrom().getToActivity(); - } + newTransition.setTransitionUIID(++maxId); + newTransition.setToActivity(toActivity); + newTransition.setToUIID(toActivity.getActivityUIID()); + newTransition.setFromActivity(gate); + newTransition.setFromUIID(gate.getActivityUIID()); + newTransition.setLearningDesign(design); - return activity; - } + gate.setTransitionFrom(fromTransition); + toActivity.setTransitionTo(fromTransition); - private void initialiseToolActivityForRuntime(LearningDesign design, Lesson lesson) throws MonitoringServiceException { - Date now = new Date(); + // keep gate door closed to stop learner's from going past this + // point + gate.setGateOpen(false); - Set activities = design.getActivities(); - for (Iterator i = activities.iterator(); i.hasNext();) { - Activity activity = (Activity) i.next(); + // set gate as first activity in sequence + design.setFirstActivity(gate); - if (activity.isInitialised()) { - if (!activity.isActivityReadOnly() && activity.isToolActivity()) { - // Activity is initialised so it was set up previously. So its tool content will be okay - // but the run offline flags and define later flags might have been changed, so they need to be updated - // Content ID shouldn't change, but we update it in case it does change while we update the status flags. - ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity.getActivityId()); - Long newContentId = lamsCoreToolService.notifyToolOfStatusFlags(toolActivity); - toolActivity.setToolContentId(newContentId); - } + // set x / y position for Gate + Integer x1 = toActivity.getXcoord() != null ? toActivity.getXcoord() : 0; - } - else { - // this is a new activity - need to set up the content, do any scheduling, etc - // always have to copy the tool content, even though it may point to unique content - that way if the - // teacher has double clicked on the tool icon (and hence set up a tool content id) but not saved any content - // the code in copyToolContent will ensure that there is content for this activity. So we end up with a few - // unused records - we are trading database space for reliability. If we don't ensure that there is always - // a content record, then shortcomings in the createToolSession code may throw exceptions. - if (activity.isToolActivity()) { - ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity.getActivityId()); - Long newContentId = lamsCoreToolService.notifyToolToCopyContent(toolActivity, true, null); - toolActivity.setToolContentId(newContentId); + Integer x2 = toActivity.getTransitionFrom() != null ? toActivity.getTransitionFrom().getToActivity() + .getXcoord() : null; - } - else { - Integer newMaxId = monitoringService.startSystemActivity(activity, design.getMaxID(), now, lesson - .getLessonName()); - if (newMaxId != null) { - design.setMaxID(newMaxId); - } - } - activity.setInitialised(Boolean.TRUE); - activityDAO.update(activity); - } + if (x1 != null && x2 != null) { + gate.setXcoord(x2 >= x1 ? new Integer(x1.intValue() - 13 - 20) : new Integer( + x1.intValue() + 123 + 13 + 20)); + } else { + gate.setXcoord(new Integer(x1.intValue() - 13 - 20)); } - } - public LearningDesign copyLearningDesign(Long originalDesignID, Integer copyType, Integer userID, Integer workspaceFolderID, - boolean setOriginalDesign) throws UserException, LearningDesignException, WorkspaceFolderException, IOException { + gate.setYcoord(toActivity.getYcoord() + 25); + } - LearningDesign originalDesign = learningDesignDAO.getLearningDesignById(originalDesignID); - if (originalDesign == null) { - throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", - new Object[] { originalDesignID })); - } + design.getTransitions().add(newTransition); + design.setMaxID(maxId); - User user = (User) baseDAO.find(User.class, userID); - if (user == null) { - throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); - } + // increment design version field + design.setDesignVersion(design.getDesignVersion() + 1); - WorkspaceFolder workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); - if (workspaceFolder == null) { - throw new WorkspaceFolderException(messageService.getMessage("no.such.workspace.exist", - new Object[] { workspaceFolderID })); - } + if (gate != null) { + activityDAO.update(gate); + } + if (activity != null) { + activityDAO.update(activity); + } + if (toActivity != null) { + activityDAO.update(toActivity); + } - if (!workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolder.getWorkspaceFolderId(), user - .getUserId())) { - throw new UserAccessDeniedException("User with user_id of " + user.getUserId() - + " is not authorized to copy a learning design into the workspace folder " - + workspaceFolder.getWorkspaceFolderId()); - } + if (fromTransition != null && !fromTransition.equals(newTransition)) { + baseDAO.update(fromTransition); + } + if (newTransition != null) { + baseDAO.insert(newTransition); + } + if (design != null) { + learningDesignDAO.insertOrUpdate(design); + } - return copyLearningDesign(originalDesign, copyType, user, workspaceFolder, setOriginalDesign, null, null); + } catch (NullPointerException npe) { + log.error(npe.getMessage(), npe); } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyLearningDesign(org.lamsfoundation.lams.learningdesign.LearningDesign, java.lang.Integer, org.lamsfoundation.lams.usermanagement.User, org.lamsfoundation.lams.usermanagement.WorkspaceFolder, java.lang.Boolean, java.lang.String) - */ - public LearningDesign copyLearningDesign(LearningDesign originalLearningDesign, Integer copyType, User user, - WorkspaceFolder workspaceFolder, boolean setOriginalDesign, String newDesignName, String customCSV) + } - { - String newTitle = newDesignName; - if (newTitle == null) { - newTitle = getUniqueNameForLearningDesign(originalLearningDesign.getTitle(), - workspaceFolder != null ? workspaceFolder.getWorkspaceFolderId() : null); - } + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getFirstUnattemptedActivity(org.lamsfoundation.lams.learningdesign.LearningDesign) + */ + public Activity getFirstUnattemptedActivity(LearningDesign design) throws LearningDesignException { + Activity activity = design.getFirstActivity(); - LearningDesign newLearningDesign = LearningDesign.createLearningDesignCopy(originalLearningDesign, copyType, - setOriginalDesign); - newLearningDesign.setTitle(newTitle); - newLearningDesign.setUser(user); - newLearningDesign.setWorkspaceFolder(workspaceFolder); - newLearningDesign.setEditOverrideLock(false); // clear the live edit flag - learningDesignDAO.insert(newLearningDesign); - - updateDesignCompetences(originalLearningDesign, newLearningDesign, false); - HashMap newActivities = updateDesignActivities(originalLearningDesign, newLearningDesign, 0, customCSV); - updateDesignTransitions(originalLearningDesign, newLearningDesign, newActivities, 0); - - // set first activity assumes that the transitions are all set up correctly. - newLearningDesign.setFirstActivity(newLearningDesign.calculateFirstActivity()); - newLearningDesign.setLearningDesignUIID(originalLearningDesign.getLearningDesignUIID()); - - updateCompetenceMappings(newLearningDesign.getCompetences(), newActivities); - - return newLearningDesign; + while (activity.getReadOnly() && activity.getTransitionFrom() != null) { + activity = activity.getTransitionFrom().getToActivity(); } - /** - * @throws UserException - * @throws WorkspaceFolderException - * @throws IOException - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#insertLearningDesign(java.lang.Long, java.lang.Long, java.lang.Integer, java.lang.Boolean, java.lang.String, java.lang.Integer) - */ - public LearningDesign insertLearningDesign(Long originalDesignID, Long designToImportID, Integer userID, - boolean createNewLearningDesign, String newDesignName, Integer workspaceFolderID, String customCSV) - throws UserException, WorkspaceFolderException, IOException { + return activity; + } - User user = (User) baseDAO.find(User.class, userID); - if (user == null) { - throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); - } + private void initialiseToolActivityForRuntime(LearningDesign design, Lesson lesson) + throws MonitoringServiceException { + Date now = new Date(); - LearningDesign mainDesign = learningDesignDAO.getLearningDesignById(originalDesignID); - if (mainDesign == null) { - throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", - new Object[] { originalDesignID })); - } + Set activities = design.getActivities(); + for (Iterator i = activities.iterator(); i.hasNext();) { + Activity activity = (Activity) i.next(); - LearningDesign designToImport = learningDesignDAO.getLearningDesignById(designToImportID); - if (designToImport == null) { - throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", - new Object[] { designToImportID })); + if (activity.isInitialised()) { + if (!activity.isActivityReadOnly() && activity.isToolActivity()) { + // Activity is initialised so it was set up previously. So + // its tool content will be okay + // but the run offline flags and define later flags might + // have been changed, so they need to be updated + // Content ID shouldn't change, but we update it in case it + // does change while we update the status flags. + ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity + .getActivityId()); + Long newContentId = lamsCoreToolService.notifyToolOfStatusFlags(toolActivity); + toolActivity.setToolContentId(newContentId); } - if (createNewLearningDesign) { - WorkspaceFolder workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); - if (workspaceFolder == null) { - throw new WorkspaceFolderException(messageService.getMessage("no.such.workspace.exist", - new Object[] { workspaceFolderID })); - } - if (!workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolder.getWorkspaceFolderId(), user - .getUserId())) { - throw new UserAccessDeniedException("User with user_id of " + user.getUserId() - + " is not authorized to store a copy a learning design into the workspace folder " + workspaceFolder); - } + } else { + // this is a new activity - need to set up the content, do any + // scheduling, etc + // always have to copy the tool content, even though it may + // point to unique content - that way if the + // teacher has double clicked on the tool icon (and hence set up + // a tool content id) but not saved any content + // the code in copyToolContent will ensure that there is content + // for this activity. So we end up with a few + // unused records - we are trading database space for + // reliability. If we don't ensure that there is always + // a content record, then shortcomings in the createToolSession + // code may throw exceptions. + if (activity.isToolActivity()) { + ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity + .getActivityId()); + Long newContentId = lamsCoreToolService.notifyToolToCopyContent(toolActivity, true, null); + toolActivity.setToolContentId(newContentId); - mainDesign = copyLearningDesign(mainDesign, LearningDesign.COPY_TYPE_NONE, user, workspaceFolder, false, - newDesignName, customCSV); + } else { + Integer newMaxId = monitoringService.startSystemActivity(activity, design.getMaxID(), now, lesson + .getLessonName()); + if (newMaxId != null) { + design.setMaxID(newMaxId); + } } - else { - // updating the existing design so check the rights to the folder containing the design. If this is in live edit mode - boolean authorised = workspaceManagementService.isUserAuthorizedToModifyFolderContents(mainDesign - .getWorkspaceFolder().getWorkspaceFolderId(), user.getUserId()); - if (!authorised) { - authorised = mainDesign.getEditOverrideLock() != null && mainDesign.getEditOverrideLock().booleanValue() - && userID.equals(mainDesign.getEditOverrideUser().getUserId()); - } - if (!authorised) { - throw new UserAccessDeniedException("User with user_id of " + user.getUserId() - + " is not authorized to update a learning design into the workspace folder " - + mainDesign.getWorkspaceFolder()); - } - } + activity.setInitialised(Boolean.TRUE); + activityDAO.update(activity); + } + } + } - // now dump the import design into our main sequence. Leave the first activity ui id for the design as it is. - int uiidOffset = mainDesign.getMaxID().intValue(); - updateDesignCompetences(designToImport, mainDesign, true); - HashMap newActivities = updateDesignActivities(designToImport, mainDesign, uiidOffset, customCSV); - updateDesignTransitions(designToImport, mainDesign, newActivities, uiidOffset); - mainDesign.setMaxID(LearningDesign.addOffset(designToImport.getMaxID(), uiidOffset)); - mainDesign.setValidDesign(Boolean.FALSE); - learningDesignDAO.update(mainDesign); + public LearningDesign copyLearningDesign(Long originalDesignID, Integer copyType, Integer userID, + Integer workspaceFolderID, boolean setOriginalDesign) throws UserException, LearningDesignException, + WorkspaceFolderException, IOException { - insertCompetenceMappings(mainDesign.getCompetences(), designToImport.getCompetences(), newActivities); + LearningDesign originalDesign = learningDesignDAO.getLearningDesignById(originalDesignID); + if (originalDesign == null) { + throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", + new Object[] { originalDesignID })); + } - return mainDesign; + User user = (User) baseDAO.find(User.class, userID); + if (user == null) { + throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); + } + WorkspaceFolder workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); + if (workspaceFolder == null) { + throw new WorkspaceFolderException(messageService.getMessage("no.such.workspace.exist", + new Object[] { workspaceFolderID })); } - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyLearningDesignToolContent(org.lamsfoundation.lams.learningdesign.LearningDesign, org.lamsfoundation.lams.learningdesign.LearningDesign, java.lang.Integer) - */ - private LearningDesign copyLearningDesignToolContent(LearningDesign design, LearningDesign originalLearningDesign, - Integer copyType) throws LearningDesignException { - - for (Iterator i = design.getActivities().iterator(); i.hasNext();) { - Activity currentActivity = (Activity) i.next(); - if (currentActivity.isToolActivity()) { - copyActivityToolContent(currentActivity, design.getCopyTypeID(), originalLearningDesign.getLearningDesignId(), - null); - } - } - - return design; + if (!workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolder.getWorkspaceFolderId(), + user.getUserId())) { + throw new UserAccessDeniedException("User with user_id of " + user.getUserId() + + " is not authorized to copy a learning design into the workspace folder " + + workspaceFolder.getWorkspaceFolderId()); } - /** - * @param originalLearningDesign - * @param copyType - * @param currentActivity - */ - private void copyActivityToolContent(Activity activity, Integer ldCopyType, Long originalLearningDesignId, String customCSV) { - try { - ToolActivity toolActivity = (ToolActivity) activity; - // copy the content, but don't set the define later flags if it is preview - Long newContentId = lamsCoreToolService.notifyToolToCopyContent(toolActivity, - ldCopyType != LearningDesign.COPY_TYPE_PREVIEW, customCSV); - toolActivity.setToolContentId(newContentId); + return copyLearningDesign(originalDesign, copyType, user, workspaceFolder, setOriginalDesign, null, null); + } - // clear read only field - toolActivity.setReadOnly(false); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyLearningDesign(org.lamsfoundation.lams.learningdesign.LearningDesign, + * java.lang.Integer, org.lamsfoundation.lams.usermanagement.User, + * org.lamsfoundation.lams.usermanagement.WorkspaceFolder, + * java.lang.Boolean, java.lang.String) + */ + public LearningDesign copyLearningDesign(LearningDesign originalLearningDesign, Integer copyType, User user, + WorkspaceFolder workspaceFolder, boolean setOriginalDesign, String newDesignName, String customCSV) - } - catch (DataMissingException e) { - String error = "Unable to copy a design / initialise the lesson. Data is missing for activity " - + activity.getActivityUIID() + " in learning design " + originalLearningDesignId - + " default content may be missing for the tool. Error was " + e.getMessage(); - log.error(error, e); - throw new LearningDesignException(error, e); - } - catch (ToolException e) { - String error = "Unable to copy a design / initialise the lesson. Tool encountered an error copying the data is missing for activity " - + activity.getActivityUIID() - + " in learning design " - + originalLearningDesignId - + " default content may be missing for the tool. Error was " + e.getMessage(); - log.error(error, e); - throw new LearningDesignException(error, e); - } + { + String newTitle = newDesignName; + if (newTitle == null) { + newTitle = getUniqueNameForLearningDesign(originalLearningDesign.getTitle(), + workspaceFolder != null ? workspaceFolder.getWorkspaceFolderId() : null); } - /** - * Updates the Activity information in the newLearningDesign based - * on the originalLearningDesign. This any grouping details. - * - * As new activities are created, the UIID is incremented by the uiidOffset. If we are just copying a sequence this will - * be set to 0. But if we are importing a sequence into another sequence, this will be an offset value so we new ids guaranteed - * to be outside of the range of the main sequence (this may mean gaps in the uiids but that doesn't matter). - * - * @param originalLearningDesign The LearningDesign to be copied - * @param newLearningDesign The copy of the originalLearningDesign - * @return Map of all the new activities, where the key is the UIID value. This is used as an input to updateDesignTransitions - */ - private HashMap updateDesignActivities(LearningDesign originalLearningDesign, - LearningDesign newLearningDesign, int uiidOffset, String customCSV) { - HashMap newActivities = new HashMap(); // key is UIID - HashMap newGroupings = new HashMap(); // key is UIID + LearningDesign newLearningDesign = LearningDesign.createLearningDesignCopy(originalLearningDesign, copyType, + setOriginalDesign); + newLearningDesign.setTitle(newTitle); + newLearningDesign.setUser(user); + newLearningDesign.setWorkspaceFolder(workspaceFolder); + newLearningDesign.setEditOverrideLock(false); // clear the live edit + // flag + learningDesignDAO.insert(newLearningDesign); - // as we create the activities, we need to record any "first child" UIID's for the sequence activity to process later - Map firstChildUIIDToSequence = new HashMap(); + updateDesignCompetences(originalLearningDesign, newLearningDesign, false); + HashMap newActivities = updateDesignActivities(originalLearningDesign, newLearningDesign, 0, + customCSV); + updateDesignTransitions(originalLearningDesign, newLearningDesign, newActivities, 0); - Set oldParentActivities = originalLearningDesign.getParentActivities(); - if (oldParentActivities != null) { - Iterator iterator = oldParentActivities.iterator(); - while (iterator.hasNext()) { - processActivity((Activity) iterator.next(), newLearningDesign, newActivities, newGroupings, null, - originalLearningDesign.getLearningDesignId(), uiidOffset, customCSV); - } - } + // set first activity assumes that the transitions are all set up + // correctly. + newLearningDesign.setFirstActivity(newLearningDesign.calculateFirstActivity()); + newLearningDesign.setLearningDesignUIID(originalLearningDesign.getLearningDesignUIID()); - Collection activities = newActivities.values(); + updateCompetenceMappings(newLearningDesign.getCompetences(), newActivities); - // Go back and find all the grouped activities and assign them the new groupings, based on the UIID. Can't - // be done as we go as the grouping activity may be processed after the grouped activity. - for (Activity activity : activities) { - if (activity.getGroupingUIID() != null) { - activity.setGrouping(newGroupings.get(activity.getGroupingUIID())); - } - } + return newLearningDesign; + } - // fix up any old "default activity" in the complex activities and the input activities - // and fix any branch mappings - for (Activity activity : activities) { - if (activity.isComplexActivity()) { - ComplexActivity newComplex = (ComplexActivity) activity; - Activity oldDefaultActivity = newComplex.getDefaultActivity(); - if (oldDefaultActivity != null) { - Activity newDefaultActivity = newActivities.get(LearningDesign.addOffset( - oldDefaultActivity.getActivityUIID(), uiidOffset)); - newComplex.setDefaultActivity(newDefaultActivity); - } - } + /** + * @throws UserException + * @throws WorkspaceFolderException + * @throws IOException + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#insertLearningDesign(java.lang.Long, + * java.lang.Long, java.lang.Integer, java.lang.Boolean, + * java.lang.String, java.lang.Integer) + */ + public LearningDesign insertLearningDesign(Long originalDesignID, Long designToImportID, Integer userID, + boolean createNewLearningDesign, String newDesignName, Integer workspaceFolderID, String customCSV) + throws UserException, WorkspaceFolderException, IOException { - if (activity.isSequenceActivity()) { - SequenceActivity newSequenceActivity = (SequenceActivity) activity; - // Need to check if the sets are not null as these are new objects and Hibernate may not have backed them with collections yet. - if (newSequenceActivity.getBranchEntries() != null && newSequenceActivity.getBranchEntries().size() > 0) { + User user = (User) baseDAO.find(User.class, userID); + if (user == null) { + throw new UserException(messageService.getMessage("no.such.user.exist", new Object[] { userID })); + } - Activity parentActivity = newSequenceActivity.getParentActivity(); - if (parentActivity.isChosenBranchingActivity() || parentActivity.isGroupBranchingActivity() - && parentActivity.getDefineLater() != null && parentActivity.getDefineLater().booleanValue()) { - // Don't have any preset up entries for a teacher chosen or a define later group based branching. - // Must be copying a design that was run previously. - newSequenceActivity.getBranchEntries().clear(); + LearningDesign mainDesign = learningDesignDAO.getLearningDesignById(originalDesignID); + if (mainDesign == null) { + throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", + new Object[] { originalDesignID })); + } - } - else { - Iterator beIter = newSequenceActivity.getBranchEntries().iterator(); - while (beIter.hasNext()) { - // sequence activity will be correct but the branching activity and the grouping will be wrong - // the condition was copied by the sequence activity copy - BranchActivityEntry entry = (BranchActivityEntry) beIter.next(); - BranchingActivity oldBranchingActivity = (BranchingActivity) entry.getBranchingActivity(); - entry.setBranchingActivity(newActivities.get(LearningDesign.addOffset(oldBranchingActivity - .getActivityUIID(), uiidOffset))); - Group oldGroup = entry.getGroup(); - if (oldGroup != null) { - Grouping oldGrouping = oldGroup.getGrouping(); - Grouping newGrouping = newGroupings.get(LearningDesign.addOffset(oldGrouping.getGroupingUIID(), - uiidOffset)); - if (newGrouping != null) { - entry.setGroup(newGrouping.getGroup(LearningDesign.addOffset(oldGroup.getGroupUIID(), - uiidOffset))); - } - } - } + LearningDesign designToImport = learningDesignDAO.getLearningDesignById(designToImportID); + if (designToImport == null) { + throw new LearningDesignException(messageService.getMessage("no.such.learningdesign.exist", + new Object[] { designToImportID })); + } - } - } - } + if (createNewLearningDesign) { + WorkspaceFolder workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); + if (workspaceFolder == null) { + throw new WorkspaceFolderException(messageService.getMessage("no.such.workspace.exist", + new Object[] { workspaceFolderID })); + } + if (!workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolder + .getWorkspaceFolderId(), user.getUserId())) { + throw new UserAccessDeniedException("User with user_id of " + user.getUserId() + + " is not authorized to store a copy a learning design into the workspace folder " + + workspaceFolder); + } - if (activity.getInputActivities() != null && activity.getInputActivities().size() > 0) { - Set newInputActivities = new HashSet(); - Iterator inputIter = activity.getInputActivities().iterator(); - while (inputIter.hasNext()) { - Activity elem = (Activity) inputIter.next(); - newInputActivities.add(newActivities.get(LearningDesign.addOffset(elem.getActivityUIID(), uiidOffset))); - } - activity.getInputActivities().clear(); - activity.getInputActivities().addAll(newInputActivities); - } - } + mainDesign = copyLearningDesign(mainDesign, LearningDesign.COPY_TYPE_NONE, user, workspaceFolder, false, + newDesignName, customCSV); + } else { + // updating the existing design so check the rights to the folder + // containing the design. If this is in live edit mode + boolean authorised = workspaceManagementService.isUserAuthorizedToModifyFolderContents(mainDesign + .getWorkspaceFolder().getWorkspaceFolderId(), user.getUserId()); + if (!authorised) { + authorised = mainDesign.getEditOverrideLock() != null + && mainDesign.getEditOverrideLock().booleanValue() + && userID.equals(mainDesign.getEditOverrideUser().getUserId()); + } + if (!authorised) { + throw new UserAccessDeniedException("User with user_id of " + user.getUserId() + + " is not authorized to update a learning design into the workspace folder " + + mainDesign.getWorkspaceFolder()); + } + } - // The activities collection in the learning design may already exist (as we have already done a save on the design). - // If so, we can't just override the existing collection as the cascade causes an error. - // newLearningDesign.getActivities() will create a new TreeSet(new ActivityOrderComparator()) if there isn't an existing set - // If the uiidOffset is > 0, then we are adding activities, so we don't want to clear first. - if (uiidOffset == 0) { - newLearningDesign.getActivities().clear(); - } - newLearningDesign.getActivities().addAll(activities); + // now dump the import design into our main sequence. Leave the first + // activity ui id for the design as it is. + int uiidOffset = mainDesign.getMaxID().intValue(); + updateDesignCompetences(designToImport, mainDesign, true); + HashMap newActivities = updateDesignActivities(designToImport, mainDesign, uiidOffset, + customCSV); + updateDesignTransitions(designToImport, mainDesign, newActivities, uiidOffset); + mainDesign.setMaxID(LearningDesign.addOffset(designToImport.getMaxID(), uiidOffset)); + mainDesign.setValidDesign(Boolean.FALSE); + learningDesignDAO.update(mainDesign); - // On very rare occasions, we've had Hibernate try to save the branching entries before saving the branching activity - // which throws an exception as the branch_activity_id is null. So force any branching activities to save first. - // And yes, this IS a hack. (See LDEV-1786) - for (Activity activity : activities) { - if (activity.isBranchingActivity()) { - activityDAO.insert(activity); - } - } + insertCompetenceMappings(mainDesign.getCompetences(), designToImport.getCompetences(), newActivities); - return newActivities; + return mainDesign; + } + + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyLearningDesignToolContent(org.lamsfoundation.lams.learningdesign.LearningDesign, + * org.lamsfoundation.lams.learningdesign.LearningDesign, + * java.lang.Integer) + */ + private LearningDesign copyLearningDesignToolContent(LearningDesign design, LearningDesign originalLearningDesign, + Integer copyType) throws LearningDesignException { + + for (Iterator i = design.getActivities().iterator(); i.hasNext();) { + Activity currentActivity = (Activity) i.next(); + if (currentActivity.isToolActivity()) { + copyActivityToolContent(currentActivity, design.getCopyTypeID(), originalLearningDesign + .getLearningDesignId(), null); + } } - /** As part of updateDesignActivities(), process an activity and, via recursive calls, the activity's child activities. Need to keep track - * of any new groupings created so we can go back and update the grouped activities with their new groupings at the end. Also copies the - * tool content. - * - * @param activity Activity to process. May not be null. - * @param newLearningDesign The new learning design. May not be null. - * @param newActivities Temporary set of new activities - as activities are processed they are added to the set. May not be null. - * @param newGroupings Temporary set of new groupings. Key is the grouping UUID. May not be null. - * @param parentActivity This activity's parent activity (if one exists). May be null. - */ - private void processActivity(Activity activity, LearningDesign newLearningDesign, Map newActivities, - Map newGroupings, Activity parentActivity, Long originalLearningDesignId, int uiidOffset, - String customCSV) { - Activity newActivity = getActivityCopy(activity, newGroupings, uiidOffset); - newActivity.setActivityUIID(newActivity.getActivityUIID()); - newActivity.setLearningDesign(newLearningDesign); - newActivity.setReadOnly(false); - if (parentActivity != null) { - newActivity.setParentActivity(parentActivity); - newActivity.setParentUIID(parentActivity.getActivityUIID()); - } - newActivities.put(newActivity.getActivityUIID(), newActivity); + return design; + } - if (newActivity.isToolActivity()) { - copyActivityToolContent(newActivity, newLearningDesign.getCopyTypeID(), originalLearningDesignId, customCSV); - } + /** + * @param originalLearningDesign + * @param copyType + * @param currentActivity + */ + private void copyActivityToolContent(Activity activity, Integer ldCopyType, Long originalLearningDesignId, + String customCSV) { + try { + ToolActivity toolActivity = (ToolActivity) activity; + // copy the content, but don't set the define later flags if it is + // preview + Long newContentId = lamsCoreToolService.notifyToolToCopyContent(toolActivity, + ldCopyType != LearningDesign.COPY_TYPE_PREVIEW, customCSV); + toolActivity.setToolContentId(newContentId); - Set oldChildActivities = getChildActivities(activity); - if (oldChildActivities != null) { - Iterator childIterator = oldChildActivities.iterator(); - while (childIterator.hasNext()) { - processActivity((Activity) childIterator.next(), newLearningDesign, newActivities, newGroupings, newActivity, - originalLearningDesignId, uiidOffset, customCSV); - } - } + // clear read only field + toolActivity.setReadOnly(false); + + } catch (DataMissingException e) { + String error = "Unable to copy a design / initialise the lesson. Data is missing for activity " + + activity.getActivityUIID() + " in learning design " + originalLearningDesignId + + " default content may be missing for the tool. Error was " + e.getMessage(); + log.error(error, e); + throw new LearningDesignException(error, e); + } catch (ToolException e) { + String error = "Unable to copy a design / initialise the lesson. Tool encountered an error copying the data is missing for activity " + + activity.getActivityUIID() + + " in learning design " + + originalLearningDesignId + + " default content may be missing for the tool. Error was " + e.getMessage(); + log.error(error, e); + throw new LearningDesignException(error, e); } + } - /** - * Updates the Transition information in the newLearningDesign based - * on the originalLearningDesign - * - * @param originalLearningDesign The LearningDesign to be copied - * @param newLearningDesign The copy of the originalLearningDesign - */ - public void updateDesignTransitions(LearningDesign originalLearningDesign, LearningDesign newLearningDesign, - HashMap newActivities, int uiidOffset) { - HashSet newTransitions = new HashSet(); - Set oldTransitions = originalLearningDesign.getTransitions(); - Iterator iterator = oldTransitions.iterator(); - while (iterator.hasNext()) { - Transition transition = (Transition) iterator.next(); - Transition newTransition = Transition.createCopy(transition, uiidOffset); - Activity toActivity = null; - Activity fromActivity = null; - if (newTransition.getToUIID() != null) { - toActivity = newActivities.get(newTransition.getToUIID()); - toActivity.setTransitionTo(newTransition); - } - if (newTransition.getFromUIID() != null) { - fromActivity = newActivities.get(newTransition.getFromUIID()); - fromActivity.setTransitionFrom(newTransition); - } - newTransition.setToActivity(toActivity); - newTransition.setFromActivity(fromActivity); - newTransition.setLearningDesign(newLearningDesign); - transitionDAO.insert(newTransition); - newTransitions.add(newTransition); - } + /** + * Updates the Activity information in the newLearningDesign based on the + * originalLearningDesign. This any grouping details. + * + * As new activities are created, the UIID is incremented by the uiidOffset. + * If we are just copying a sequence this will be set to 0. But if we are + * importing a sequence into another sequence, this will be an offset value + * so we new ids guaranteed to be outside of the range of the main sequence + * (this may mean gaps in the uiids but that doesn't matter). + * + * @param originalLearningDesign + * The LearningDesign to be copied + * @param newLearningDesign + * The copy of the originalLearningDesign + * @return Map of all the new activities, where the key is the UIID value. + * This is used as an input to updateDesignTransitions + */ + private HashMap updateDesignActivities(LearningDesign originalLearningDesign, + LearningDesign newLearningDesign, int uiidOffset, String customCSV) { + HashMap newActivities = new HashMap(); // key + // is + // UIID + HashMap newGroupings = new HashMap(); // key + // is + // UIID - // The transitions collection in the learning design may already exist (as we have already done a save on the design). - // If so, we can't just override the existing collection as the cascade causes an error. - // If the uiidOffset is > 0, then we are adding transitions (rather than replacing), so we don't want to clear first. - if (newLearningDesign.getTransitions() != null) { - if (uiidOffset == 0) { - newLearningDesign.getTransitions().clear(); - } - newLearningDesign.getTransitions().addAll(newTransitions); - } - else { - newLearningDesign.setTransitions(newTransitions); - } + // as we create the activities, we need to record any "first child" + // UIID's for the sequence activity to process later + Map firstChildUIIDToSequence = new HashMap(); + Set oldParentActivities = originalLearningDesign.getParentActivities(); + if (oldParentActivities != null) { + Iterator iterator = oldParentActivities.iterator(); + while (iterator.hasNext()) { + processActivity((Activity) iterator.next(), newLearningDesign, newActivities, newGroupings, null, + originalLearningDesign.getLearningDesignId(), uiidOffset, customCSV); + } } - /** - * Updates the competence information in the newLearningDesign based - * on the originalLearningDesign - * - * @param originalLearningDesign The LearningDesign to be copied - * @param newLearningDesign The copy of the originalLearningDesign - */ - public void updateDesignCompetences(LearningDesign originalLearningDesign, LearningDesign newLearningDesign, boolean insert) { - HashSet newCompeteces = new HashSet(); + Collection activities = newActivities.values(); - Set oldCompetences = originalLearningDesign.getCompetences(); - for (Competence competence : oldCompetences) { - Competence newCompetence = competence.createCopy(competence); - newCompetence.setLearningDesign(newLearningDesign); + // Go back and find all the grouped activities and assign them the new + // groupings, based on the UIID. Can't + // be done as we go as the grouping activity may be processed after the + // grouped activity. + for (Activity activity : activities) { + if (activity.getGroupingUIID() != null) { + activity.setGrouping(newGroupings.get(activity.getGroupingUIID())); + } + } - // check for existing competences to prevent duplicates - if (competenceDAO.getCompetence(newLearningDesign, newCompetence.getTitle()) == null) { - competenceDAO.saveOrUpdate(newCompetence); - } - newCompeteces.add(newCompetence); + // fix up any old "default activity" in the complex activities and the + // input activities + // and fix any branch mappings + for (Activity activity : activities) { + if (activity.isComplexActivity()) { + ComplexActivity newComplex = (ComplexActivity) activity; + Activity oldDefaultActivity = newComplex.getDefaultActivity(); + if (oldDefaultActivity != null) { + Activity newDefaultActivity = newActivities.get(LearningDesign.addOffset(oldDefaultActivity + .getActivityUIID(), uiidOffset)); + newComplex.setDefaultActivity(newDefaultActivity); } + } - if (newLearningDesign.getCompetences() != null) { - if (!insert) { - newLearningDesign.getCompetences().clear(); - newLearningDesign.getCompetences().addAll(newCompeteces); - } - else { - // handle inserting sequences - for (Competence newCompetence : newCompeteces) { - boolean alreadyExistsInLD = false; - for (Competence existingCompetence : originalLearningDesign.getCompetences()) { - if (newCompetence.getTitle().equals(existingCompetence.getTitle())) { - alreadyExistsInLD = true; - break; - } - } - if (!alreadyExistsInLD) { - newLearningDesign.getCompetences().add(newCompetence); - } + if (activity.isSequenceActivity()) { + SequenceActivity newSequenceActivity = (SequenceActivity) activity; + // Need to check if the sets are not null as these are new + // objects and Hibernate may not have backed them with + // collections yet. + if (newSequenceActivity.getBranchEntries() != null && newSequenceActivity.getBranchEntries().size() > 0) { + + Activity parentActivity = newSequenceActivity.getParentActivity(); + if (parentActivity.isChosenBranchingActivity() || parentActivity.isGroupBranchingActivity() + && parentActivity.getDefineLater() != null + && parentActivity.getDefineLater().booleanValue()) { + // Don't have any preset up entries for a teacher chosen + // or a define later group based branching. + // Must be copying a design that was run previously. + newSequenceActivity.getBranchEntries().clear(); + + } else { + Iterator beIter = newSequenceActivity.getBranchEntries().iterator(); + while (beIter.hasNext()) { + // sequence activity will be correct but the + // branching activity and the grouping will be wrong + // the condition was copied by the sequence activity + // copy + BranchActivityEntry entry = (BranchActivityEntry) beIter.next(); + BranchingActivity oldBranchingActivity = (BranchingActivity) entry.getBranchingActivity(); + entry.setBranchingActivity(newActivities.get(LearningDesign.addOffset(oldBranchingActivity + .getActivityUIID(), uiidOffset))); + Group oldGroup = entry.getGroup(); + if (oldGroup != null) { + Grouping oldGrouping = oldGroup.getGrouping(); + Grouping newGrouping = newGroupings.get(LearningDesign.addOffset(oldGrouping + .getGroupingUIID(), uiidOffset)); + if (newGrouping != null) { + entry.setGroup(newGrouping.getGroup(LearningDesign.addOffset(oldGroup + .getGroupUIID(), uiidOffset))); } + } } + } } - else { - newLearningDesign.setCompetences(newCompeteces); + } + + if (activity.getInputActivities() != null && activity.getInputActivities().size() > 0) { + Set newInputActivities = new HashSet(); + Iterator inputIter = activity.getInputActivities().iterator(); + while (inputIter.hasNext()) { + Activity elem = (Activity) inputIter.next(); + newInputActivities.add(newActivities.get(LearningDesign.addOffset(elem.getActivityUIID(), + uiidOffset))); } + activity.getInputActivities().clear(); + activity.getInputActivities().addAll(newInputActivities); + } + } + // The activities collection in the learning design may already exist + // (as we have already done a save on the design). + // If so, we can't just override the existing collection as the cascade + // causes an error. + // newLearningDesign.getActivities() will create a new TreeSet(new + // ActivityOrderComparator()) if there isn't an existing set + // If the uiidOffset is > 0, then we are adding activities, so we don't + // want to clear first. + if (uiidOffset == 0) { + newLearningDesign.getActivities().clear(); } + newLearningDesign.getActivities().addAll(activities); - public void insertCompetenceMappings(Set oldCompetences, Set newCompetences, - HashMap newActivities) { + // On very rare occasions, we've had Hibernate try to save the branching + // entries before saving the branching activity + // which throws an exception as the branch_activity_id is null. So force + // any branching activities to save first. + // And yes, this IS a hack. (See LDEV-1786) + for (Activity activity : activities) { + if (activity.isBranchingActivity()) { + activityDAO.insert(activity); + } + } - for (Integer activityKey : newActivities.keySet()) { - Activity activity = newActivities.get(activityKey); - if (activity.isToolActivity()) { - Set newCompetenceMappings = new HashSet(); - ToolActivity newToolActivity = (ToolActivity) activity; - if (newToolActivity.getCompetenceMappings() != null) { - for (CompetenceMapping competenceMapping : newToolActivity.getCompetenceMappings()) { - CompetenceMapping newMapping = new CompetenceMapping(); - newMapping.setToolActivity(newToolActivity); + return newActivities; - // Check if competence mapping title already exists as a competence in the original sequence - // If so, simply use the existing competence to map to. - if (oldCompetences != null && oldCompetences.size() > 0 - && getCompetenceFromSet(oldCompetences, competenceMapping.getCompetence().getTitle()) != null) { - newMapping.setCompetence(getCompetenceFromSet(oldCompetences, competenceMapping.getCompetence() - .getTitle())); - competenceMappingDAO.insert(newMapping); - newCompetenceMappings.add(newMapping); - } - // If competence was not already existing in the ld, add a new mappping - else if (newCompetences != null && newCompetences.size() > 0 - && getCompetenceFromSet(newCompetences, competenceMapping.getCompetence().getTitle()) != null) { - newMapping.setCompetence(getCompetenceFromSet(newCompetences, competenceMapping.getCompetence() - .getTitle())); - competenceMappingDAO.insert(newMapping); - newCompetenceMappings.add(newMapping); - } - } - } - newToolActivity.getCompetenceMappings().addAll(newCompetenceMappings); - } - } + } + + /** + * As part of updateDesignActivities(), process an activity and, via + * recursive calls, the activity's child activities. Need to keep track of + * any new groupings created so we can go back and update the grouped + * activities with their new groupings at the end. Also copies the tool + * content. + * + * @param activity + * Activity to process. May not be null. + * @param newLearningDesign + * The new learning design. May not be null. + * @param newActivities + * Temporary set of new activities - as activities are processed + * they are added to the set. May not be null. + * @param newGroupings + * Temporary set of new groupings. Key is the grouping UUID. May + * not be null. + * @param parentActivity + * This activity's parent activity (if one exists). May be null. + */ + private void processActivity(Activity activity, LearningDesign newLearningDesign, + Map newActivities, Map newGroupings, Activity parentActivity, + Long originalLearningDesignId, int uiidOffset, String customCSV) { + Activity newActivity = getActivityCopy(activity, newGroupings, uiidOffset); + newActivity.setActivityUIID(newActivity.getActivityUIID()); + newActivity.setLearningDesign(newLearningDesign); + newActivity.setReadOnly(false); + if (parentActivity != null) { + newActivity.setParentActivity(parentActivity); + newActivity.setParentUIID(parentActivity.getActivityUIID()); } + newActivities.put(newActivity.getActivityUIID(), newActivity); - public Competence getCompetenceFromSet(Set competences, String title) { - Competence ret = null; - for (Competence competence : competences) { - if (competence.getTitle().equals(title)) { - ret = competence; - break; - } - } - return ret; + if (newActivity.isToolActivity()) { + copyActivityToolContent(newActivity, newLearningDesign.getCopyTypeID(), originalLearningDesignId, customCSV); } - /** - * Updates the competence information in the newLearningDesign based - * on the originalLearningDesign - * - * @param originalLearningDesign The LearningDesign to be copied - * @param newLearningDesign The copy of the originalLearningDesign - */ - public void updateCompetenceMappings(Set newCompetences, HashMap newActivities) { - for (Integer activityKey : newActivities.keySet()) { - Activity activity = newActivities.get(activityKey); - if (activity.isToolActivity()) { - Set newCompetenceMappings = new HashSet(); - ToolActivity newToolActivity = (ToolActivity) activity; - if (newToolActivity.getCompetenceMappings() != null) { - for (CompetenceMapping competenceMapping : newToolActivity.getCompetenceMappings()) { - CompetenceMapping newMapping = new CompetenceMapping(); - if (newCompetences != null) { - for (Competence newCompetence : newCompetences) { - if (competenceMapping.getCompetence().getTitle().equals(newCompetence.getTitle()) - ) { - newMapping.setToolActivity(newToolActivity); - newMapping.setCompetence(newCompetence); - competenceMappingDAO.insert(newMapping); - newCompetenceMappings.add(newMapping); - } - } - } - } - } - newToolActivity.getCompetenceMappings().addAll(newCompetenceMappings); - //activityDAO.update(newToolActivity); - } - } + Set oldChildActivities = getChildActivities(activity); + if (oldChildActivities != null) { + Iterator childIterator = oldChildActivities.iterator(); + while (childIterator.hasNext()) { + processActivity((Activity) childIterator.next(), newLearningDesign, newActivities, newGroupings, + newActivity, originalLearningDesignId, uiidOffset, customCSV); + } } + } - /** - * Determines the type of activity and returns a deep-copy of the same - * - * @param activity The object to be deep-copied - * @param newGroupings Temporary set of new groupings. Key is the grouping UUID. May not be null. - * @return Activity The new deep-copied Activity object - */ - private Activity getActivityCopy(final Activity activity, Map newGroupings, int uiidOffset) { - if (Activity.GROUPING_ACTIVITY_TYPE == activity.getActivityTypeId().intValue()) { - GroupingActivity newGroupingActivity = (GroupingActivity) activity.createCopy(uiidOffset); - // now we need to manually add the grouping to the session, as we can't easily - // set up a cascade - Grouping grouping = newGroupingActivity.getCreateGrouping(); - grouping.setGroupingUIID(grouping.getGroupingUIID()); - if (grouping != null) { - groupingDAO.insert(grouping); - newGroupings.put(grouping.getGroupingUIID(), grouping); - } - return newGroupingActivity; - } - else { - return activity.createCopy(uiidOffset); - } + /** + * Updates the Transition information in the newLearningDesign based on the + * originalLearningDesign + * + * @param originalLearningDesign + * The LearningDesign to be copied + * @param newLearningDesign + * The copy of the originalLearningDesign + */ + public void updateDesignTransitions(LearningDesign originalLearningDesign, LearningDesign newLearningDesign, + HashMap newActivities, int uiidOffset) { + HashSet newTransitions = new HashSet(); + Set oldTransitions = originalLearningDesign.getTransitions(); + Iterator iterator = oldTransitions.iterator(); + while (iterator.hasNext()) { + Transition transition = (Transition) iterator.next(); + Transition newTransition = Transition.createCopy(transition, uiidOffset); + Activity toActivity = null; + Activity fromActivity = null; + if (newTransition.getToUIID() != null) { + toActivity = newActivities.get(newTransition.getToUIID()); + toActivity.setTransitionTo(newTransition); + } + if (newTransition.getFromUIID() != null) { + fromActivity = newActivities.get(newTransition.getFromUIID()); + fromActivity.setTransitionFrom(newTransition); + } + newTransition.setToActivity(toActivity); + newTransition.setFromActivity(fromActivity); + newTransition.setLearningDesign(newLearningDesign); + transitionDAO.insert(newTransition); + newTransitions.add(newTransition); } - /** - * Returns a set of child activities for the given parent activity - * - * @param parentActivity The parent activity - * @return HashSet Set of the activities that belong to the parentActivity - */ - private HashSet getChildActivities(Activity parentActivity) { - HashSet childActivities = new HashSet(); - List list = activityDAO.getActivitiesByParentActivityId(parentActivity.getActivityId()); - if (list != null) { - childActivities.addAll(list); - } - return childActivities; + // The transitions collection in the learning design may already exist + // (as we have already done a save on the design). + // If so, we can't just override the existing collection as the cascade + // causes an error. + // If the uiidOffset is > 0, then we are adding transitions (rather than + // replacing), so we don't want to clear first. + if (newLearningDesign.getTransitions() != null) { + if (uiidOffset == 0) { + newLearningDesign.getTransitions().clear(); + } + newLearningDesign.getTransitions().addAll(newTransitions); + } else { + newLearningDesign.setTransitions(newTransitions); } - /** - * This method saves a new Learning Design to the database. - * It received a WDDX packet from flash, deserializes it - * and then finally persists it to the database. - * - * A user may update an existing learning design if they have user/owner rights to the - * folder or they are doing live edit. A user may create a new learning design only if they - * have user/owner rights to the folder. - * - * Note: it does not validate the design - that must be done - * separately. - * - * @param wddxPacket The WDDX packet received from Flash - * @return Long learning design id - * @throws Exception - */ - public Long storeLearningDesignDetails(String wddxPacket) throws Exception { + } - Hashtable table = (Hashtable) WDDXProcessor.deserialize(wddxPacket); - Integer workspaceFolderID = WDDXProcessor.convertToInteger(table, WDDXTAGS.WORKSPACE_FOLDER_ID); + /** + * Updates the competence information in the newLearningDesign based on the + * originalLearningDesign + * + * @param originalLearningDesign + * The LearningDesign to be copied + * @param newLearningDesign + * The copy of the originalLearningDesign + */ + public void updateDesignCompetences(LearningDesign originalLearningDesign, LearningDesign newLearningDesign, + boolean insert) { + HashSet newCompeteces = new HashSet(); - User user = null; - Integer userID = getUserId(); - if (userID != null) { - user = (User) baseDAO.find(User.class, userID); - } - if (user == null) { - throw new UserException("UserID missing or user not found."); - } + Set oldCompetences = originalLearningDesign.getCompetences(); + for (Competence competence : oldCompetences) { + Competence newCompetence = competence.createCopy(competence); + newCompetence.setLearningDesign(newLearningDesign); - WorkspaceFolder workspaceFolder = null; - boolean authorised = false; - if (workspaceFolderID != null) { - workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); - authorised = workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolderID, userID); - } + // check for existing competences to prevent duplicates + if (competenceDAO.getCompetence(newLearningDesign, newCompetence.getTitle()) == null) { + competenceDAO.saveOrUpdate(newCompetence); + } + newCompeteces.add(newCompetence); + } - Long learningDesignId = WDDXProcessor.convertToLong(table, "learningDesignID"); - LearningDesign existingLearningDesign = learningDesignId != null ? learningDesignDAO - .getLearningDesignById(learningDesignId) : null; - if (!authorised && existingLearningDesign != null && Boolean.TRUE.equals(existingLearningDesign.getEditOverrideLock())) { - authorised = userID.equals(existingLearningDesign.getEditOverrideUser().getUserId()); + if (newLearningDesign.getCompetences() != null) { + if (!insert) { + newLearningDesign.getCompetences().clear(); + newLearningDesign.getCompetences().addAll(newCompeteces); + } else { + // handle inserting sequences + for (Competence newCompetence : newCompeteces) { + boolean alreadyExistsInLD = false; + for (Competence existingCompetence : originalLearningDesign.getCompetences()) { + if (newCompetence.getTitle().equals(existingCompetence.getTitle())) { + alreadyExistsInLD = true; + break; + } + } + if (!alreadyExistsInLD) { + newLearningDesign.getCompetences().add(newCompetence); + } } - if (!authorised) { - throw new UserException("User with user_id of " + userID - + " is not authorized to store a design in this workspace folder " + workspaceFolderID); - } + } - IObjectExtractor extractor = (IObjectExtractor) beanFactory.getBean(IObjectExtractor.OBJECT_EXTRACTOR_SPRING_BEANNAME); - LearningDesign design = extractor.extractSaveLearningDesign(table, existingLearningDesign, workspaceFolder, user); + } else { + newLearningDesign.setCompetences(newCompeteces); + } - if (extractor.getMode().intValue() == 1) { - copyLearningDesignToolContent(design, design, design.getCopyTypeID()); - } + } - return design.getLearningDesignId(); + public void insertCompetenceMappings(Set oldCompetences, Set newCompetences, + HashMap newActivities) { + + for (Integer activityKey : newActivities.keySet()) { + Activity activity = newActivities.get(activityKey); + if (activity.isToolActivity()) { + Set newCompetenceMappings = new HashSet(); + ToolActivity newToolActivity = (ToolActivity) activity; + if (newToolActivity.getCompetenceMappings() != null) { + for (CompetenceMapping competenceMapping : newToolActivity.getCompetenceMappings()) { + CompetenceMapping newMapping = new CompetenceMapping(); + newMapping.setToolActivity(newToolActivity); + + // Check if competence mapping title already exists as a + // competence in the original sequence + // If so, simply use the existing competence to map to. + if (oldCompetences != null + && oldCompetences.size() > 0 + && getCompetenceFromSet(oldCompetences, competenceMapping.getCompetence().getTitle()) != null) { + newMapping.setCompetence(getCompetenceFromSet(oldCompetences, competenceMapping + .getCompetence().getTitle())); + competenceMappingDAO.insert(newMapping); + newCompetenceMappings.add(newMapping); + } + // If competence was not already existing in the ld, add + // a new mappping + else if (newCompetences != null + && newCompetences.size() > 0 + && getCompetenceFromSet(newCompetences, competenceMapping.getCompetence().getTitle()) != null) { + newMapping.setCompetence(getCompetenceFromSet(newCompetences, competenceMapping + .getCompetence().getTitle())); + competenceMappingDAO.insert(newMapping); + newCompetenceMappings.add(newMapping); + } + } + } + newToolActivity.getCompetenceMappings().addAll(newCompetenceMappings); + } } + } - /** - * Validate the learning design, updating the valid flag appropriately. - * - * This needs to be run in a separate transaction to storeLearningDesignDetails to - * ensure the database is fully updated before the validation occurs (due to some - * quirks we are finding using Hibernate) - * - * @param learningDesignId - * @throws Exception - */ - public Vector validateLearningDesign(Long learningDesignId) { - LearningDesign learningDesign = learningDesignDAO.getLearningDesignById(learningDesignId); - Vector listOfValidationErrorDTOs = learningDesignService.validateLearningDesign(learningDesign); - Boolean valid = listOfValidationErrorDTOs.size() > 0 ? Boolean.FALSE : Boolean.TRUE; - learningDesign.setValidDesign(valid); - learningDesignDAO.insertOrUpdate(learningDesign); - return listOfValidationErrorDTOs; + public Competence getCompetenceFromSet(Set competences, String title) { + Competence ret = null; + for (Competence competence : competences) { + if (competence.getTitle().equals(title)) { + ret = competence; + break; + } } + return ret; + } - public Vector getToolActivities(Long learningDesignId, String languageCode) { - LearningDesign learningDesign = learningDesignDAO.getLearningDesignById(learningDesignId); - Vector listOfAuthoringActivityDTOs = new Vector(); - - for (Iterator i = learningDesign.getActivities().iterator(); i.hasNext();) { - Activity currentActivity = (Activity) i.next(); - if (currentActivity.isToolActivity()) { - try { - // Normally we pass in an array for the branch mappings as the second parameter to new AuthoringActivityDTO() - // but we don't need to in this case as it is only doing it for tool activities, and the extra parameter is only - // used for branching activities - ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(currentActivity - .getActivityId()); - AuthoringActivityDTO activityDTO = new AuthoringActivityDTO(toolActivity, null, languageCode); - listOfAuthoringActivityDTOs.add(activityDTO); + /** + * Updates the competence information in the newLearningDesign based on the + * originalLearningDesign + * + * @param originalLearningDesign + * The LearningDesign to be copied + * @param newLearningDesign + * The copy of the originalLearningDesign + */ + public void updateCompetenceMappings(Set newCompetences, HashMap newActivities) { + for (Integer activityKey : newActivities.keySet()) { + Activity activity = newActivities.get(activityKey); + if (activity.isToolActivity()) { + Set newCompetenceMappings = new HashSet(); + ToolActivity newToolActivity = (ToolActivity) activity; + if (newToolActivity.getCompetenceMappings() != null) { + for (CompetenceMapping competenceMapping : newToolActivity.getCompetenceMappings()) { + CompetenceMapping newMapping = new CompetenceMapping(); + if (newCompetences != null) { + for (Competence newCompetence : newCompetences) { + if (competenceMapping.getCompetence().getTitle().equals(newCompetence.getTitle())) { + newMapping.setToolActivity(newToolActivity); + newMapping.setCompetence(newCompetence); + competenceMappingDAO.insert(newMapping); + newCompetenceMappings.add(newMapping); } - catch (ToolException e) { - String error = "" + e.getMessage(); - log.error(error, e); - throw new LearningDesignException(error, e); - } + } } + } } + newToolActivity.getCompetenceMappings().addAll(newCompetenceMappings); + // activityDAO.update(newToolActivity); + } + } + } - return listOfAuthoringActivityDTOs; + /** + * Determines the type of activity and returns a deep-copy of the same + * + * @param activity + * The object to be deep-copied + * @param newGroupings + * Temporary set of new groupings. Key is the grouping UUID. May + * not be null. + * @return Activity The new deep-copied Activity object + */ + private Activity getActivityCopy(final Activity activity, Map newGroupings, int uiidOffset) { + if (Activity.GROUPING_ACTIVITY_TYPE == activity.getActivityTypeId().intValue()) { + GroupingActivity newGroupingActivity = (GroupingActivity) activity.createCopy(uiidOffset); + // now we need to manually add the grouping to the session, as we + // can't easily + // set up a cascade + Grouping grouping = newGroupingActivity.getCreateGrouping(); + grouping.setGroupingUIID(grouping.getGroupingUIID()); + if (grouping != null) { + groupingDAO.insert(grouping); + newGroupings.put(grouping.getGroupingUIID(), grouping); + } + return newGroupingActivity; + } else { + return activity.createCopy(uiidOffset); } + } - /** - * (non-Javadoc) - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningDesignDetails() - */ - public String getAllLearningDesignDetails() throws IOException { - Iterator iterator = getAllLearningDesigns().iterator(); - ArrayList arrayList = createDesignDetailsPacket(iterator); - FlashMessage flashMessage = new FlashMessage("getAllLearningDesignDetails", arrayList); - return flashMessage.serializeMessage(); + /** + * Returns a set of child activities for the given parent activity + * + * @param parentActivity + * The parent activity + * @return HashSet Set of the activities that belong to the parentActivity + */ + private HashSet getChildActivities(Activity parentActivity) { + HashSet childActivities = new HashSet(); + List list = activityDAO.getActivitiesByParentActivityId(parentActivity.getActivityId()); + if (list != null) { + childActivities.addAll(list); } + return childActivities; + } - /** - * This is a utility method used by the method - * getAllLearningDesignDetails to pack the - * required information in a data transfer object. - * - * @param iterator - * @return Hashtable The required information in a Hashtable - */ - private ArrayList createDesignDetailsPacket(Iterator iterator) { - ArrayList arrayList = new ArrayList(); - while (iterator.hasNext()) { - LearningDesign learningDesign = (LearningDesign) iterator.next(); - DesignDetailDTO designDetailDTO = learningDesign.getDesignDetailDTO(); - arrayList.add(designDetailDTO); - } - return arrayList; + /** + * This method saves a new Learning Design to the database. It received a + * WDDX packet from flash, deserializes it and then finally persists it to + * the database. + * + * A user may update an existing learning design if they have user/owner + * rights to the folder or they are doing live edit. A user may create a new + * learning design only if they have user/owner rights to the folder. + * + * Note: it does not validate the design - that must be done separately. + * + * @param wddxPacket + * The WDDX packet received from Flash + * @return Long learning design id + * @throws Exception + */ + public Long storeLearningDesignDetails(String wddxPacket) throws Exception { + + Hashtable table = (Hashtable) WDDXProcessor.deserialize(wddxPacket); + Integer workspaceFolderID = WDDXProcessor.convertToInteger(table, WDDXTAGS.WORKSPACE_FOLDER_ID); + + User user = null; + Integer userID = getUserId(); + if (userID != null) { + user = (User) baseDAO.find(User.class, userID); } + if (user == null) { + throw new UserException("UserID missing or user not found."); + } - /** - * (non-Javadoc) - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesignsForUser(java.lang.Long) - */ - public String getLearningDesignsForUser(Long userID) throws IOException { - List list = learningDesignDAO.getLearningDesignByUserId(userID); - ArrayList arrayList = createDesignDetailsPacket(list.iterator()); - FlashMessage flashMessage = new FlashMessage("getLearningDesignsForUser", arrayList); - return flashMessage.serializeMessage(); + WorkspaceFolder workspaceFolder = null; + boolean authorised = false; + if (workspaceFolderID != null) { + workspaceFolder = (WorkspaceFolder) baseDAO.find(WorkspaceFolder.class, workspaceFolderID); + authorised = workspaceManagementService.isUserAuthorizedToModifyFolderContents(workspaceFolderID, userID); } - /** - * (non-Javadoc) - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningLibraryDetails() - */ - public String getAllLearningLibraryDetails(String languageCode) throws IOException { - FlashMessage flashMessage = new FlashMessage("getAllLearningLibraryDetails", learningDesignService - .getAllLearningLibraryDetails(languageCode)); - return flashMessage.serializeMessage(); + Long learningDesignId = WDDXProcessor.convertToLong(table, "learningDesignID"); + LearningDesign existingLearningDesign = learningDesignId != null ? learningDesignDAO + .getLearningDesignById(learningDesignId) : null; + if (!authorised && existingLearningDesign != null + && Boolean.TRUE.equals(existingLearningDesign.getEditOverrideLock())) { + authorised = userID.equals(existingLearningDesign.getEditOverrideUser().getUserId()); } + if (!authorised) { + throw new UserException("User with user_id of " + userID + + " is not authorized to store a design in this workspace folder " + workspaceFolderID); + } - /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getToolContentID(java.lang.Long) */ + IObjectExtractor extractor = (IObjectExtractor) beanFactory + .getBean(IObjectExtractor.OBJECT_EXTRACTOR_SPRING_BEANNAME); + LearningDesign design = extractor.extractSaveLearningDesign(table, existingLearningDesign, workspaceFolder, + user); - public String getToolContentID(Long toolID) throws IOException { - Tool tool = toolDAO.getToolByID(toolID); - if (tool == null) { - log.error("The toolID " + toolID + " is not valid. A Tool with tool id " + toolID - + " does not exist on the database."); - return FlashMessage.getNoSuchTool("getToolContentID", toolID).serializeMessage(); - } + if (extractor.getMode().intValue() == 1) { + copyLearningDesignToolContent(design, design, design.getCopyTypeID()); + } - Long newContentID = contentIDGenerator.getNextToolContentIDFor(tool); - FlashMessage flashMessage = new FlashMessage("getToolContentID", newContentID); + return design.getLearningDesignId(); + } - return flashMessage.serializeMessage(); - } + /** + * Validate the learning design, updating the valid flag appropriately. + * + * This needs to be run in a separate transaction to + * storeLearningDesignDetails to ensure the database is fully updated before + * the validation occurs (due to some quirks we are finding using Hibernate) + * + * @param learningDesignId + * @throws Exception + */ + public Vector validateLearningDesign(Long learningDesignId) { + LearningDesign learningDesign = learningDesignDAO.getLearningDesignById(learningDesignId); + Vector listOfValidationErrorDTOs = learningDesignService + .validateLearningDesign(learningDesign); + Boolean valid = listOfValidationErrorDTOs.size() > 0 ? Boolean.FALSE : Boolean.TRUE; + learningDesign.setValidDesign(valid); + learningDesignDAO.insertOrUpdate(learningDesign); + return listOfValidationErrorDTOs; + } - /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyToolContent(java.lang.Long) */ - public String copyToolContent(Long toolContentID, String customCSV) throws IOException { - Long newContentID = lamsCoreToolService.notifyToolToCopyContent(toolContentID, customCSV); - FlashMessage flashMessage = new FlashMessage("copyToolContent", newContentID); - return flashMessage.serializeMessage(); - } + public Vector getToolActivities(Long learningDesignId, String languageCode) { + LearningDesign learningDesign = learningDesignDAO.getLearningDesignById(learningDesignId); + Vector listOfAuthoringActivityDTOs = new Vector(); - /** - * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyMultipleToolContent(java.lang.Integer, java.util.List) - */ - public String copyMultipleToolContent(Integer userId, List toolContentIds, String customCSV) { - StringBuffer idMap = new StringBuffer(); - for (Long oldToolContentId : toolContentIds) { - if (oldToolContentId != null) { - Long newToolContentId = lamsCoreToolService.notifyToolToCopyContent(oldToolContentId, customCSV); - idMap.append(oldToolContentId); - idMap.append('='); - idMap.append(newToolContentId); - idMap.append(','); - } + for (Iterator i = learningDesign.getActivities().iterator(); i.hasNext();) { + Activity currentActivity = (Activity) i.next(); + if (currentActivity.isToolActivity()) { + try { + // Normally we pass in an array for the branch mappings as + // the second parameter to new AuthoringActivityDTO() + // but we don't need to in this case as it is only doing it + // for tool activities, and the extra parameter is only + // used for branching activities + ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(currentActivity + .getActivityId()); + AuthoringActivityDTO activityDTO = new AuthoringActivityDTO(toolActivity, null, languageCode); + listOfAuthoringActivityDTOs.add(activityDTO); + } catch (ToolException e) { + String error = "" + e.getMessage(); + log.error(error, e); + throw new LearningDesignException(error, e); } - // return the id list, stripping off the trailing , - return idMap.length() > 0 ? idMap.substring(0, idMap.length() - 1) : ""; + } } - /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAvailableLicenses() */ - public Vector getAvailableLicenses() { - List licenses = licenseDAO.findAll(License.class); - Vector licenseDTOList = new Vector(licenses.size()); - Iterator iter = licenses.iterator(); - while (iter.hasNext()) { - License element = (License) iter.next(); - licenseDTOList.add(element.getLicenseDTO(Configuration.get(ConfigurationKeys.SERVER_URL))); - } - return licenseDTOList; + return listOfAuthoringActivityDTOs; + } + + /** + * (non-Javadoc) + * + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningDesignDetails() + */ + public String getAllLearningDesignDetails() throws IOException { + Iterator iterator = getAllLearningDesigns().iterator(); + ArrayList arrayList = createDesignDetailsPacket(iterator); + FlashMessage flashMessage = new FlashMessage("getAllLearningDesignDetails", arrayList); + return flashMessage.serializeMessage(); + } + + /** + * This is a utility method used by the method + * getAllLearningDesignDetails to pack the required information + * in a data transfer object. + * + * @param iterator + * @return Hashtable The required information in a Hashtable + */ + private ArrayList createDesignDetailsPacket(Iterator iterator) { + ArrayList arrayList = new ArrayList(); + while (iterator.hasNext()) { + LearningDesign learningDesign = (LearningDesign) iterator.next(); + DesignDetailDTO designDetailDTO = learningDesign.getDesignDetailDTO(); + arrayList.add(designDetailDTO); } + return arrayList; + } - /** Delete a learning design from the database. Does not remove any content stored in tools - - * that is done by the LamsCoreToolService */ - public void deleteLearningDesign(LearningDesign design) { - if (design == null) { - log.error("deleteLearningDesign: unable to delete learning design as design is null."); - return; - } + /** + * (non-Javadoc) + * + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getLearningDesignsForUser(java.lang.Long) + */ + public String getLearningDesignsForUser(Long userID) throws IOException { + List list = learningDesignDAO.getLearningDesignByUserId(userID); + ArrayList arrayList = createDesignDetailsPacket(list.iterator()); + FlashMessage flashMessage = new FlashMessage("getLearningDesignsForUser", arrayList); + return flashMessage.serializeMessage(); + } - // remove all the tool content for the learning design - Set acts = design.getActivities(); - Iterator iter = acts.iterator(); - while (iter.hasNext()) { - Activity activity = (Activity) iter.next(); - if (activity.isToolActivity()) { - try { - ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity.getActivityId()); - lamsCoreToolService.notifyToolToDeleteContent(toolActivity); - } - catch (ToolException e) { - log.error("Unable to delete tool content for activity" + activity + " as activity threw an exception", e); - } - } - } + /** + * (non-Javadoc) + * + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAllLearningLibraryDetails() + */ + public String getAllLearningLibraryDetails(String languageCode) throws IOException { + FlashMessage flashMessage = new FlashMessage("getAllLearningLibraryDetails", learningDesignService + .getAllLearningLibraryDetails(languageCode)); + return flashMessage.serializeMessage(); + } - // remove the learning design - learningDesignDAO.delete(design); + /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getToolContentID(java.lang.Long) */ + + public String getToolContentID(Long toolID) throws IOException { + Tool tool = toolDAO.getToolByID(toolID); + if (tool == null) { + log.error("The toolID " + toolID + " is not valid. A Tool with tool id " + toolID + + " does not exist on the database."); + return FlashMessage.getNoSuchTool("getToolContentID", toolID).serializeMessage(); } - /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#generateUniqueContentFolder() */ - public String generateUniqueContentFolder() throws FileUtilException, IOException { + Long newContentID = contentIDGenerator.getNextToolContentIDFor(tool); + FlashMessage flashMessage = new FlashMessage("getToolContentID", newContentID); - String newUniqueContentFolderID = FileUtil.generateUniqueContentFolderID(); + return flashMessage.serializeMessage(); + } - FlashMessage flashMessage = new FlashMessage("createUniqueContentFolder", newUniqueContentFolderID); + /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyToolContent(java.lang.Long) */ + public String copyToolContent(Long toolContentID, String customCSV) throws IOException { + Long newContentID = lamsCoreToolService.notifyToolToCopyContent(toolContentID, customCSV); + FlashMessage flashMessage = new FlashMessage("copyToolContent", newContentID); + return flashMessage.serializeMessage(); + } - return flashMessage.serializeMessage(); + /** + * @see org.lamsfoundation.lams.authoring.service.IAuthoringService#copyMultipleToolContent(java.lang.Integer, + * java.util.List) + */ + public String copyMultipleToolContent(Integer userId, List toolContentIds, String customCSV) { + StringBuffer idMap = new StringBuffer(); + for (Long oldToolContentId : toolContentIds) { + if (oldToolContentId != null) { + Long newToolContentId = lamsCoreToolService.notifyToolToCopyContent(oldToolContentId, customCSV); + idMap.append(oldToolContentId); + idMap.append('='); + idMap.append(newToolContentId); + idMap.append(','); + } } + // return the id list, stripping off the trailing , + return idMap.length() > 0 ? idMap.substring(0, idMap.length() - 1) : ""; + } - /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getHelpURL() */ - public String getHelpURL() throws Exception { + /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getAvailableLicenses() */ + public Vector getAvailableLicenses() { + List licenses = licenseDAO.findAll(License.class); + Vector licenseDTOList = new Vector(licenses.size()); + Iterator iter = licenses.iterator(); + while (iter.hasNext()) { + License element = (License) iter.next(); + licenseDTOList.add(element.getLicenseDTO(Configuration.get(ConfigurationKeys.SERVER_URL))); + } + return licenseDTOList; + } - FlashMessage flashMessage = null; + /** + * Delete a learning design from the database. Does not remove any content + * stored in tools - that is done by the LamsCoreToolService + */ + public void deleteLearningDesign(LearningDesign design) { + if (design == null) { + log.error("deleteLearningDesign: unable to delete learning design as design is null."); + return; + } - String helpURL = Configuration.get(ConfigurationKeys.HELP_URL); - if (helpURL != null) { - flashMessage = new FlashMessage("getHelpURL", helpURL); + // remove all the tool content for the learning design + Set acts = design.getActivities(); + Iterator iter = acts.iterator(); + while (iter.hasNext()) { + Activity activity = (Activity) iter.next(); + if (activity.isToolActivity()) { + try { + ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(activity + .getActivityId()); + lamsCoreToolService.notifyToolToDeleteContent(toolActivity); + } catch (ToolException e) { + log.error("Unable to delete tool content for activity" + activity + + " as activity threw an exception", e); } - else { - throw new Exception(); - } + } + } - return flashMessage.serializeMessage(); + // remove the learning design + learningDesignDAO.delete(design); + } + + /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#generateUniqueContentFolder() */ + public String generateUniqueContentFolder() throws FileUtilException, IOException { + + String newUniqueContentFolderID = FileUtil.generateUniqueContentFolderID(); + + FlashMessage flashMessage = new FlashMessage("createUniqueContentFolder", newUniqueContentFolderID); + + return flashMessage.serializeMessage(); + } + + /** @see org.lamsfoundation.lams.authoring.service.IAuthoringService#getHelpURL() */ + public String getHelpURL() throws Exception { + + FlashMessage flashMessage = null; + + String helpURL = Configuration.get(ConfigurationKeys.HELP_URL); + if (helpURL != null) { + flashMessage = new FlashMessage("getHelpURL", helpURL); + } else { + throw new Exception(); } - /** - * Get a unique name for a learning design, based on the names of the learning designs in the folder. - * If the learning design has duplicated name in same folder, then the new name will have a timestamp. - * The new name format will be oldname_ddMMYYYY_idx. The idx will be auto incremental index number, start from 1. - * Warning - this may be quite intensive as it gets all the learning designs in a folder. - * @param originalLearningDesign - * @param workspaceFolder - * @param copyType - * @return - */ - public String getUniqueNameForLearningDesign(String originalTitle, Integer workspaceFolderId) { + return flashMessage.serializeMessage(); + } - String newName = originalTitle; - if (workspaceFolderId != null) { - List ldTitleList = learningDesignDAO.getLearningDesignTitlesByWorkspaceFolder(workspaceFolderId); - int idx = 1; + /** + * Get a unique name for a learning design, based on the names of the + * learning designs in the folder. If the learning design has duplicated + * name in same folder, then the new name will have a timestamp. The new + * name format will be oldname_ddMMYYYY_idx. The idx will be auto + * incremental index number, start from 1. Warning - this may be quite + * intensive as it gets all the learning designs in a folder. + * + * @param originalLearningDesign + * @param workspaceFolder + * @param copyType + * @return + */ + public String getUniqueNameForLearningDesign(String originalTitle, Integer workspaceFolderId) { - Calendar calendar = Calendar.getInstance(); - int mth = calendar.get(Calendar.MONTH) + 1; - String mthStr = new Integer(mth).toString(); - if (mth < 10) { - mthStr = "0" + mthStr; - } - int day = calendar.get(Calendar.DAY_OF_MONTH); - String dayStr = new Integer(day).toString(); - if (day < 10) { - dayStr = "0" + dayStr; - } - String nameMid = dayStr + mthStr + calendar.get(Calendar.YEAR); - while (ldTitleList.contains(newName)) { - newName = originalTitle + "_" + nameMid + "_" + idx; - idx++; - } - } - return newName; + String newName = originalTitle; + if (workspaceFolderId != null) { + List ldTitleList = learningDesignDAO.getLearningDesignTitlesByWorkspaceFolder(workspaceFolderId); + int idx = 1; + + Calendar calendar = Calendar.getInstance(); + int mth = calendar.get(Calendar.MONTH) + 1; + String mthStr = new Integer(mth).toString(); + if (mth < 10) { + mthStr = "0" + mthStr; + } + int day = calendar.get(Calendar.DAY_OF_MONTH); + String dayStr = new Integer(day).toString(); + if (day < 10) { + dayStr = "0" + dayStr; + } + String nameMid = dayStr + mthStr + calendar.get(Calendar.YEAR); + while (ldTitleList.contains(newName)) { + newName = originalTitle + "_" + nameMid + "_" + idx; + idx++; + } } + return newName; + } } \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/authoring/service/IAuthoringService.java =================================================================== diff -u -rc82a07c323413bc81bf2c072b7dbeafa6d9e3776 -rdd2804fae0fea44b5b713a8024f75e2a45aceada --- lams_central/src/java/org/lamsfoundation/lams/authoring/service/IAuthoringService.java (.../IAuthoringService.java) (revision c82a07c323413bc81bf2c072b7dbeafa6d9e3776) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/service/IAuthoringService.java (.../IAuthoringService.java) (revision dd2804fae0fea44b5b713a8024f75e2a45aceada) @@ -25,8 +25,6 @@ import java.io.IOException; import java.util.List; -import java.util.Map; -import java.util.SortedMap; import java.util.Vector; import org.lamsfoundation.lams.learningdesign.Activity; @@ -37,323 +35,391 @@ import org.lamsfoundation.lams.learningdesign.exception.LearningDesignException; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.WorkspaceFolder; -import org.lamsfoundation.lams.usermanagement.exception.UserAccessDeniedException; import org.lamsfoundation.lams.usermanagement.exception.UserException; import org.lamsfoundation.lams.usermanagement.exception.WorkspaceFolderException; -import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.FileUtilException; +import org.lamsfoundation.lams.util.MessageService; /** - * @author Manpreet Minhas + * @author Manpreet Minhas */ public interface IAuthoringService { - - /** Message key returned by the storeLearningDesignDetails() method */ - public static final String STORE_LD_MESSAGE_KEY = "storeLearningDesignDetails"; - public static final String INSERT_LD_MESSAGE_KEY = "insertLearningDesign"; - public static final String START_EDIT_ON_FLY_MESSAGE_KEY = "startEditOnFly"; - public static final String COPY_TOOL_CONTENT_MESSAGE_KEY = "copyMultipleToolContent"; - /** - * Returns a populated LearningDesign object corresponding to the given learningDesignID - * - * @param learningDesignID The learning_design_id of the design which has to be fetched - * @return LearningDesign The populated LearningDesign object corresponding to the given learningDesignID - */ - public LearningDesign getLearningDesign(Long learningDesignID); - - - /** - * Create a copy of learning design as per the requested learning design - * and saves it in the given workspacefolder. Does not set the original - * - * @param originalLearningDesign The source learning design id. - * @param copyType purpose of copying the design. Can have one of the follwing values - *
    - *
  • LearningDesign.COPY_TYPE_NONE (for authoring enviornment)
  • - *
  • LearningDesign.COPY_TYPE_LESSON (for monitoring enviornment while creating a Lesson)
  • - *
  • LearningDesign.COPY_TYPE_PREVIEW (for previewing purposes)
  • - *
- * @param user The user who has sent this request(author/teacher) - * @param setOriginalDesign If true, then sets the originalLearningDesign field in the new design - * @param custom comma separated values used for tool adapters - * @return LearningDesign The new copy of learning design. - */ - public LearningDesign copyLearningDesign(LearningDesign originalLearningDesign,Integer copyType,User user, - WorkspaceFolder workspaceFolder, boolean setOriginalDesign, String newDesignName, String customCSV) ; - - /** - * Create a copy of learning design as per the requested learning design - * and saves it in the given workspacefolder. Designed to be called when user tries - * to copy a learning design using the Flash interface. Does not set the original - * learning design field, so it should not be used for creating lesson learning designs. - * - * @param originalLearningDesingID the source learning design id. - * @param copyType purpose of copying the design. Can have one of the follwing values - *
    - *
  • LearningDesign.COPY_TYPE_NONE (for authoring enviornment)
  • - *
  • LearningDesign.COPY_TYPE_LESSON (for monitoring enviornment while creating a Lesson)
  • - *
  • LearningDesign.COPY_TYPE_PREVIEW (for previewing purposes)
  • - *
- * @param userID The user_id of the user who has sent this request(author/teacher) - * @param workspaceFolderID The workspacefolder where this copy of the design would be saved - * @param setOriginalDesign If true, then sets the originalLearningDesign field in the new design - * @return new LearningDesign - */ - public LearningDesign copyLearningDesign(Long originalLearningDesignID,Integer copyType, - Integer userID, Integer workspaceFolder, boolean setOriginalDesign) - throws UserException, LearningDesignException, WorkspaceFolderException, IOException; - - /** - * Insert a learning design into another learning design. This is a copy and paste type of copy - it just dumps the contents (with modified - * activity ui ids) in the main learning design. It doesn't wrap up the contents in a sequence activity. Always sets the type to COPY_TYPE_NONE. - * @param originalDesignID The design to be "modified". Required. - * @param designToImportID The design to be imported into originalLearningDesign. Required. - * @param userId Current User. Required. - * @param customCSV The custom CSV required to insert tool adapter tools, so their content can be copied in the external server - * @param createNewLearningDesign If true, then a copy of the originalLearningDesign is made and the copy modified. If it is false, then - * the originalLearningDesign is modified. Required. - * @param newDesignName New name for the design if a new design is being create. Optional. - * @param workspaceFolderID The folder in which to put the new learning design if createNewLearningDesign = true. May be null if createNewLearningDesign = false + /** Message key returned by the storeLearningDesignDetails() method */ + public static final String STORE_LD_MESSAGE_KEY = "storeLearningDesignDetails"; + + public static final String INSERT_LD_MESSAGE_KEY = "insertLearningDesign"; + + public static final String START_EDIT_ON_FLY_MESSAGE_KEY = "startEditOnFly"; + + public static final String COPY_TOOL_CONTENT_MESSAGE_KEY = "copyMultipleToolContent"; + + /** + * Returns a populated LearningDesign object corresponding to the given + * learningDesignID + * + * @param learningDesignID + * The learning_design_id of the design which has to be fetched + * @return LearningDesign The populated LearningDesign object corresponding + * to the given learningDesignID + */ + public LearningDesign getLearningDesign(Long learningDesignID); + + /** + * Create a copy of learning design as per the requested learning design and + * saves it in the given workspacefolder. Does not set the original + * + * @param originalLearningDesign + * The source learning design id. + * @param copyType + * purpose of copying the design. Can have one of the follwing + * values + *
    + *
  • LearningDesign.COPY_TYPE_NONE (for authoring enviornment)
  • + *
  • LearningDesign.COPY_TYPE_LESSON (for monitoring + * enviornment while creating a Lesson)
  • + *
  • LearningDesign.COPY_TYPE_PREVIEW (for previewing purposes) + *
  • + *
+ * @param user + * The user who has sent this request(author/teacher) + * @param setOriginalDesign + * If true, then sets the originalLearningDesign field in the new + * design + * @param custom + * comma separated values used for tool adapters + * @return LearningDesign The new copy of learning design. + */ + public LearningDesign copyLearningDesign(LearningDesign originalLearningDesign, Integer copyType, User user, + WorkspaceFolder workspaceFolder, boolean setOriginalDesign, String newDesignName, String customCSV); + + /** + * Create a copy of learning design as per the requested learning design and + * saves it in the given workspacefolder. Designed to be called when user + * tries to copy a learning design using the Flash interface. Does not set + * the original learning design field, so it should not be used for creating + * lesson learning designs. + * + * @param originalLearningDesingID + * the source learning design id. + * @param copyType + * purpose of copying the design. Can have one of the follwing + * values + *
    + *
  • LearningDesign.COPY_TYPE_NONE (for authoring enviornment)
  • + *
  • LearningDesign.COPY_TYPE_LESSON (for monitoring + * enviornment while creating a Lesson)
  • + *
  • LearningDesign.COPY_TYPE_PREVIEW (for previewing purposes) + *
  • + *
+ * @param userID + * The user_id of the user who has sent this + * request(author/teacher) + * @param workspaceFolderID + * The workspacefolder where this copy of the design would be + * saved + * @param setOriginalDesign + * If true, then sets the originalLearningDesign field in the new + * design + * @return new LearningDesign + */ + public LearningDesign copyLearningDesign(Long originalLearningDesignID, Integer copyType, Integer userID, + Integer workspaceFolder, boolean setOriginalDesign) throws UserException, LearningDesignException, + WorkspaceFolderException, IOException; + + /** + * Insert a learning design into another learning design. This is a copy and + * paste type of copy - it just dumps the contents (with modified activity + * ui ids) in the main learning design. It doesn't wrap up the contents in a + * sequence activity. Always sets the type to COPY_TYPE_NONE. + * + * @param originalDesignID + * The design to be "modified". Required. + * @param designToImportID + * The design to be imported into originalLearningDesign. + * Required. + * @param userId + * Current User. Required. + * @param customCSV + * The custom CSV required to insert tool adapter tools, so their + * content can be copied in the external server + * @param createNewLearningDesign + * If true, then a copy of the originalLearningDesign is made and + * the copy modified. If it is false, then the + * originalLearningDesign is modified. Required. + * @param newDesignName + * New name for the design if a new design is being create. + * Optional. + * @param workspaceFolderID + * The folder in which to put the new learning design if + * createNewLearningDesign = true. May be null if + * createNewLearningDesign = false * @return New / updated learning design - */ - public LearningDesign insertLearningDesign(Long originalDesignID, Long designToImportID, Integer userID, - boolean createNewLearningDesign, String newDesignName, Integer workspaceFolderID, String customCSV) throws UserException, LearningDesignException, - WorkspaceFolderException, IOException; + */ + public LearningDesign insertLearningDesign(Long originalDesignID, Long designToImportID, Integer userID, + boolean createNewLearningDesign, String newDesignName, Integer workspaceFolderID, String customCSV) + throws UserException, LearningDesignException, WorkspaceFolderException, IOException; - /** - * @return List Returns the list of all the available LearningDesign's - * */ - public List getAllLearningDesigns(); - - /** - * @return List Returns a list of all available Learning Libraries - */ - public List getAllLearningLibraries(); - - /** - * Returns a string representing the requested LearningDesign in WDDX format - * - * @param learningDesignID The learning_design_id of the design whose WDDX packet is requested - * @return String The requested LearningDesign in WDDX format - * @throws Exception - */ - public String getLearningDesignDetails(Long learningDesignID, String languageCode)throws IOException; - - /** - * This method saves a new Learning Design to the database. - * It received a WDDX packet from flash, deserializes it - * and then finally persists it to the database. - * - * Note: it does not validate the design - that must be done - * separately. - * - * @param wddxPacket The WDDX packet to be stored in the database - * @return Long learning design id - * @throws Exception - */ - public Long storeLearningDesignDetails(String wddxPacket) throws Exception; - - /** - * Validate the learning design, updating the valid flag appropriately. - * - * This needs to be run in a separate transaction to storeLearningDesignDetails to - * ensure the database is fully updated before the validation occurs (due to some - * quirks we are finding using Hibernate) - * - * @param learningDesignId - * @throws Exception - */ - public Vector validateLearningDesign(Long learningDesignId); - - /** - * - * @param learningDesignId - * @return - */ - public Vector getToolActivities(Long learningDesignId, String languageCode); - - /** - * This method returns a output definitions of the Tool - * in WDDX format. - * - * @return String The required definitions in WDDX format - * @throws IOException - */ - public String getToolOutputDefinitions(Long toolContentID)throws IOException; - - /** - * This method returns a list of all available Learning Designs - * in WDDX format. - * - * @return String The required list in WDDX format - * @throws IOException - */ - public String getAllLearningDesignDetails()throws IOException; - - /** - * Saves the LearningDesign to the database. Will update if already saved. - * Used when a design is run. - * @param learningDesign The LearningDesign to be saved - * */ - public void saveLearningDesign(LearningDesign learningDesign); + /** + * @return List Returns the list of all the available LearningDesign's + * */ + public List getAllLearningDesigns(); - /** - * Returns a list of LearningDesign's - * in WDDX format, belonging to the given user - * - * @param user The user_id of the User for whom the designs are to be fetched - * @return The requested list of LearningDesign's in WDDX format - * @throws IOException - */ - public String getLearningDesignsForUser(Long userID) throws IOException; - - /** - * This method returns a list of all available system libraries in - * WDDX format. - * - * @return String The required information in WDDX format - * @throws IOException - */ - public String getAllLearningLibraryDetails(String languageCode)throws IOException; - - /** - * Returns a string representing the new tool content id in - * WDDX format. - * - * Typically, when a user clicks on an activity to edit the tool contnet, - * it must have a tool content id passed to it. This method uses the - * ToolContentIDGenerator to generate the new tool content id and passes - * this value back to flash in WDDX format. - * - * @param toolID The toolID in which to generate the new tool content id for - * @return String The new tool content id in WDDX Format - */ - public String getToolContentID(Long toolID) throws IOException; + /** + * @return List Returns a list of all available Learning Libraries + */ + public List getAllLearningLibraries(); - /** - * Calls an appropriate tool to copy the content indicated by toolContentId. - * Returns a string representing the new tool content id in WDDX format. - * - * The is called when the user copies and pastes a tool activity icon in authoring. - * It should only be called on a ToolActivity - never a Gate or Grouping or - * Complex activity. - * - * @param toolContentID The toolContentID indicating the content to copy - * @param customCSV The customCSV if this is a tool adapter tool. - * @return String The new tool content id in WDDX Format - */ - public String copyToolContent(Long toolContentID, String customCSV) throws IOException; - - /** - * Calls an appropriate tools to copy the content indicated by toolContentIds. Batch - * version of String copyToolContent(Long toolContentID). Returns a map containing - * the old and new ids, and this is converted to a WDDX format in the calling servlet. - * - * The is called when the user copies and pastes a complex activity icon in authoring. - * Authoring calls this method to copy all the contained tool activities' content - * in one go. - * - * It should only be called on a ToolActivity - never a Gate or Grouping or - * Complex activity. - * - * @param userId Id of the user requesting the copy - * @param customCSV the customCSV required to copy tool adapter tools - * @param toolContentIDs The toolContentIDs indicating the content to copy - * @return New Id map in format oldId1=newId1,oldId2=newId2,oldId3=newId3 - */ - public String copyMultipleToolContent(Integer userId,List toolContentIds, String customCSV); - - /** Get the available licenses. This will include our supported Creative Common - * licenses and an "OTHER" license which may be used for user entered license details. - * The picture url supplied should be a full URL i.e. if it was a relative URL in the - * database, it should have been converted to a complete server URL (starting http://) - * before sending to the client. - * - * @return Vector of LicenseDTO objects. It is a Vector to ensure compatibility with WDDX - */ - public Vector getAvailableLicenses(); - - /** Delete a learning design from the database. Does not remove any content stored in tools - - * that is done by the LamsCoreToolService */ - public void deleteLearningDesign(LearningDesign design); + /** + * Returns a string representing the requested LearningDesign in WDDX format + * + * @param learningDesignID + * The learning_design_id of the design whose WDDX packet is + * requested + * @return String The requested LearningDesign in WDDX format + * @throws Exception + */ + public String getLearningDesignDetails(Long learningDesignID, String languageCode) throws IOException; - /** - * Generates a unique content folder for the newly created design to store - * - * @return String The unique content folder id in WDDX Format - */ - public String generateUniqueContentFolder() throws FileUtilException, IOException; - - /** - * Prepares a LearningDesign to be ready for Edit-On-The-Fly (Editing). - * Return a string representing the updated learning design in WDDX format. - * - * @param design The learning design whose WDDX packet is requested - * @param userID user_id of the User who will be editing the design. - * @throws UserException - * @throws LearningDesignException - * @throws IOException - */ - public String setupEditOnFlyGate(Long learningDesignID, Integer userID) throws UserException, LearningDesignException, IOException; - public boolean setupEditOnFlyLock(Long learningDesignID, Integer userID) throws LearningDesignException, UserException, IOException; - - /** - * - * - * @param learningDesignID The learning_design_id of the design for which editing has finished. - * @param userID user_id of the User who has finished editing the design. - * @param cancelled flag specifying whether user cancelled or saved the edit - * @return wddx packet. - * @throws IOException - */ - public String finishEditOnFly(Long learningDesignID, Integer userID, boolean cancelled) throws IOException; - - /** - * - * @param gate - */ - public LearningDesign removeTempSystemGate(GateActivity gate, LearningDesign design); - - /** - * - * @param design - * @return - * @throws LearningDesignException - */ - public Activity getFirstUnattemptedActivity(LearningDesign design) throws LearningDesignException; - - /** - * - * @param design - * @param userID - * @return - * @throws LearningDesignException - * @throws IOException - */ - public boolean isLearningDesignAvailable(LearningDesign design, Integer userID) throws LearningDesignException, IOException; - - /** - * Returns the generic help url from configuration - * - * @return String Generic help url - * @throws Exception - */ - public String getHelpURL() throws Exception; + /** + * This method saves a new Learning Design to the database. It received a + * WDDX packet from flash, deserializes it and then finally persists it to + * the database. + * + * Note: it does not validate the design - that must be done separately. + * + * @param wddxPacket + * The WDDX packet to be stored in the database + * @return Long learning design id + * @throws Exception + */ + public Long storeLearningDesignDetails(String wddxPacket) throws Exception; - /** Get the message service, which gives access to the I18N text */ - public MessageService getMessageService(); + /** + * Validate the learning design, updating the valid flag appropriately. + * + * This needs to be run in a separate transaction to + * storeLearningDesignDetails to ensure the database is fully updated before + * the validation occurs (due to some quirks we are finding using Hibernate) + * + * @param learningDesignId + * @throws Exception + */ + public Vector validateLearningDesign(Long learningDesignId); - /** - * Get a unique name for a learning design, based on the names of the learning designs in the folder. - * If the learning design has duplicated name in same folder, then the new name will have a timestamp. - * The new name format will be oldname_ddMMYYYY_idx. The idx will be auto incremental index number, start from 1. - * Warning - this may be quite intensive as it gets all the learning designs in a folder. - * @param originalLearningDesign - * @param workspaceFolder - * @param copyType - * @return - */ - public String getUniqueNameForLearningDesign(String originalTitle, Integer workspaceFolderId); + /** + * + * @param learningDesignId + * @return + */ + public Vector getToolActivities(Long learningDesignId, String languageCode); + /** + * This method returns a output definitions of the Tool in WDDX format. + * + * @return String The required definitions in WDDX format + * @throws IOException + */ + public String getToolOutputDefinitions(Long toolContentID) throws IOException; + + /** + * This method returns a list of all available Learning Designs in WDDX + * format. + * + * @return String The required list in WDDX format + * @throws IOException + */ + public String getAllLearningDesignDetails() throws IOException; + + /** + * Saves the LearningDesign to the database. Will update if already saved. + * Used when a design is run. + * + * @param learningDesign + * The LearningDesign to be saved + * */ + public void saveLearningDesign(LearningDesign learningDesign); + + /** + * Returns a list of LearningDesign's in WDDX format, belonging to the given + * user + * + * @param user + * The user_id of the User for whom the designs are to be fetched + * @return The requested list of LearningDesign's in WDDX format + * @throws IOException + */ + public String getLearningDesignsForUser(Long userID) throws IOException; + + /** + * This method returns a list of all available system libraries in WDDX + * format. + * + * @return String The required information in WDDX format + * @throws IOException + */ + public String getAllLearningLibraryDetails(String languageCode) throws IOException; + + /** + * Returns a string representing the new tool content id in WDDX format. + * + * Typically, when a user clicks on an activity to edit the tool contnet, it + * must have a tool content id passed to it. This method uses the + * ToolContentIDGenerator to generate the new tool content id and passes + * this value back to flash in WDDX format. + * + * @param toolID + * The toolID in which to generate the new tool content id for + * @return String The new tool content id in WDDX Format + */ + public String getToolContentID(Long toolID) throws IOException; + + /** + * Calls an appropriate tool to copy the content indicated by toolContentId. + * Returns a string representing the new tool content id in WDDX format. + * + * The is called when the user copies and pastes a tool activity icon in + * authoring. It should only be called on a ToolActivity - never a Gate or + * Grouping or Complex activity. + * + * @param toolContentID + * The toolContentID indicating the content to copy + * @param customCSV + * The customCSV if this is a tool adapter tool. + * @return String The new tool content id in WDDX Format + */ + public String copyToolContent(Long toolContentID, String customCSV) throws IOException; + + /** + * Calls an appropriate tools to copy the content indicated by + * toolContentIds. Batch version of String copyToolContent(Long + * toolContentID). Returns a map containing the old and new ids, and this is + * converted to a WDDX format in the calling servlet. + * + * The is called when the user copies and pastes a complex activity icon in + * authoring. Authoring calls this method to copy all the contained tool + * activities' content in one go. + * + * It should only be called on a ToolActivity - never a Gate or Grouping or + * Complex activity. + * + * @param userId + * Id of the user requesting the copy + * @param customCSV + * the customCSV required to copy tool adapter tools + * @param toolContentIDs + * The toolContentIDs indicating the content to copy + * @return New Id map in format oldId1=newId1,oldId2=newId2,oldId3=newId3 + */ + public String copyMultipleToolContent(Integer userId, List toolContentIds, String customCSV); + + /** + * Get the available licenses. This will include our supported Creative + * Common licenses and an "OTHER" license which may be used for user entered + * license details. The picture url supplied should be a full URL i.e. if it + * was a relative URL in the database, it should have been converted to a + * complete server URL (starting http://) before sending to the client. + * + * @return Vector of LicenseDTO objects. It is a Vector to ensure + * compatibility with WDDX + */ + public Vector getAvailableLicenses(); + + /** + * Delete a learning design from the database. Does not remove any content + * stored in tools - that is done by the LamsCoreToolService + */ + public void deleteLearningDesign(LearningDesign design); + + /** + * Generates a unique content folder for the newly created design to store + * + * @return String The unique content folder id in WDDX Format + */ + public String generateUniqueContentFolder() throws FileUtilException, IOException; + + /** + * Prepares a LearningDesign to be ready for Edit-On-The-Fly (Editing). + * Return a string representing the updated learning design in WDDX format. + * + * @param design + * The learning design whose WDDX packet is requested + * @param userID + * user_id of the User who will be editing the design. + * @throws UserException + * @throws LearningDesignException + * @throws IOException + */ + public String setupEditOnFlyGate(Long learningDesignID, Integer userID) throws UserException, + LearningDesignException, IOException; + + public boolean setupEditOnFlyLock(Long learningDesignID, Integer userID) throws LearningDesignException, + UserException, IOException; + + /** + * + * + * @param learningDesignID + * The learning_design_id of the design for which editing has + * finished. + * @param userID + * user_id of the User who has finished editing the design. + * @param cancelled + * flag specifying whether user cancelled or saved the edit + * @return wddx packet. + * @throws IOException + */ + public String finishEditOnFly(Long learningDesignID, Integer userID, boolean cancelled) throws IOException; + + /** + * + * @param gate + */ + public LearningDesign removeTempSystemGate(GateActivity gate, LearningDesign design); + + /** + * + * @param design + * @return + * @throws LearningDesignException + */ + public Activity getFirstUnattemptedActivity(LearningDesign design) throws LearningDesignException; + + /** + * + * @param design + * @param userID + * @return + * @throws LearningDesignException + * @throws IOException + */ + public boolean isLearningDesignAvailable(LearningDesign design, Integer userID) throws LearningDesignException, + IOException; + + /** + * Returns the generic help url from configuration + * + * @return String Generic help url + * @throws Exception + */ + public String getHelpURL() throws Exception; + + /** Get the message service, which gives access to the I18N text */ + public MessageService getMessageService(); + + /** + * Get a unique name for a learning design, based on the names of the + * learning designs in the folder. If the learning design has duplicated + * name in same folder, then the new name will have a timestamp. The new + * name format will be oldname_ddMMYYYY_idx. The idx will be auto + * incremental index number, start from 1. Warning - this may be quite + * intensive as it gets all the learning designs in a folder. + * + * @param originalLearningDesign + * @param workspaceFolder + * @param copyType + * @return + */ + public String getUniqueNameForLearningDesign(String originalTitle, Integer workspaceFolderId); + } Index: lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java =================================================================== diff -u -rc82a07c323413bc81bf2c072b7dbeafa6d9e3776 -rdd2804fae0fea44b5b713a8024f75e2a45aceada --- lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java (.../AuthoringAction.java) (revision c82a07c323413bc81bf2c072b7dbeafa6d9e3776) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java (.../AuthoringAction.java) (revision dd2804fae0fea44b5b713a8024f75e2a45aceada) @@ -37,9 +37,6 @@ import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.lamsfoundation.lams.authoring.service.IAuthoringService; -import org.lamsfoundation.lams.learningdesign.LearningDesign; -import org.lamsfoundation.lams.usermanagement.User; -import org.lamsfoundation.lams.usermanagement.WorkspaceFolder; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.FileUtilException; import org.lamsfoundation.lams.util.WebUtil; @@ -54,294 +51,286 @@ /** * @author Manpreet Minhas * - * @struts.action path = "/authoring/author" - * parameter = "method" - * validate = "false" - * + * @struts.action path = "/authoring/author" parameter = "method" validate = + * "false" + * */ -public class AuthoringAction extends LamsDispatchAction{ - - private static Logger log = Logger.getLogger(AuthoringAction.class); +public class AuthoringAction extends LamsDispatchAction { - private static IAuditService auditService; - - public IAuthoringService getAuthoringService(){ - WebApplicationContext webContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServlet().getServletContext()); - return (IAuthoringService) webContext.getBean(AuthoringConstants.AUTHORING_SERVICE_BEAN_NAME); + private static Logger log = Logger.getLogger(AuthoringAction.class); + + private static IAuditService auditService; + + public IAuthoringService getAuthoringService() { + WebApplicationContext webContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this + .getServlet().getServletContext()); + return (IAuthoringService) webContext.getBean(AuthoringConstants.AUTHORING_SERVICE_BEAN_NAME); + } + + private Integer getUserId() { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + return user != null ? user.getUserID() : null; + } + + private String getUserLanguage() { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + return user != null ? user.getLocaleLanguage() : ""; + } + + /** + * Output the supplied WDDX packet. If the request parameter USE_JSP_OUTPUT + * is set, then it sets the session attribute "parameterName" to the wddx + * packet string. If USE_JSP_OUTPUT is not set, then the packet is written + * out to the request's PrintWriter. + * + * @param mapping + * action mapping (for the forward to the success jsp) + * @param request + * needed to check the USE_JSP_OUTPUT parameter + * @param response + * to write out the wddx packet if not using the jsp + * @param wddxPacket + * wddxPacket or message to be sent/displayed + * @param parameterName + * session attribute to set if USE_JSP_OUTPUT is set + * @throws IOException + */ + private ActionForward outputPacket(ActionMapping mapping, HttpServletRequest request, HttpServletResponse response, + String wddxPacket, String parameterName) throws IOException { + PrintWriter writer = response.getWriter(); + writer.println(wddxPacket); + return null; + } + + public ActionForward getToolOutputDefinitions(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + Long toolContentID = WebUtil.readLongParam(request, "toolContentID", false); + + wddxPacket = authoringService.getToolOutputDefinitions(toolContentID); + + } catch (Exception e) { + wddxPacket = handleException(e, "getToolOutputDefinitions", authoringService, true).serializeMessage(); } - - private Integer getUserId() { - HttpSession ss = SessionManager.getSession(); - UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); - return user != null ? user.getUserID() : null; + return outputPacket(mapping, request, response, wddxPacket, "definitions"); + } + + public ActionForward getLearningDesignDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + Long learningDesignID = WebUtil.readLongParam(request, "learningDesignID", false); + wddxPacket = authoringService.getLearningDesignDetails(learningDesignID, getUserLanguage()); + log.debug("LD wddx packet: " + wddxPacket); + } catch (Exception e) { + wddxPacket = handleException(e, "getLearningDesignDetails", authoringService, true).serializeMessage(); } - - private String getUserLanguage() { - HttpSession ss = SessionManager.getSession(); - UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); - return user != null ? user.getLocaleLanguage() : ""; + return outputPacket(mapping, request, response, wddxPacket, "details"); + } + + public ActionForward finishLearningDesignEdit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + Long learningDesignID = WebUtil.readLongParam(request, "learningDesignID", false); + boolean cancelled = WebUtil.readBooleanParam(request, "cancelled", false); + + wddxPacket = authoringService.finishEditOnFly(learningDesignID, getUserId(), cancelled); + + } catch (Exception e) { + wddxPacket = handleException(e, "getLearningDesignDetails", authoringService, true).serializeMessage(); + return outputPacket(mapping, request, response, wddxPacket, "details"); } - /** Output the supplied WDDX packet. If the request parameter USE_JSP_OUTPUT - * is set, then it sets the session attribute "parameterName" to the wddx packet string. - * If USE_JSP_OUTPUT is not set, then the packet is written out to the - * request's PrintWriter. - * - * @param mapping action mapping (for the forward to the success jsp) - * @param request needed to check the USE_JSP_OUTPUT parameter - * @param response to write out the wddx packet if not using the jsp - * @param wddxPacket wddxPacket or message to be sent/displayed - * @param parameterName session attribute to set if USE_JSP_OUTPUT is set - * @throws IOException - */ - private ActionForward outputPacket(ActionMapping mapping, HttpServletRequest request, HttpServletResponse response, - String wddxPacket, String parameterName) throws IOException { - PrintWriter writer = response.getWriter(); - writer.println(wddxPacket); - return null; + return outputPacket(mapping, request, response, wddxPacket, "details"); + + } + + public ActionForward getLearningDesignsForUser(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + Long userID = new Long(getUserId()); + + wddxPacket = authoringService.getLearningDesignsForUser(userID); + } catch (Exception e) { + wddxPacket = handleException(e, "getLearningDesignsForUser", authoringService, true).serializeMessage(); } - - public ActionForward getToolOutputDefinitions(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - Long toolContentID = WebUtil.readLongParam(request,"toolContentID",false); - - wddxPacket = authoringService.getToolOutputDefinitions(toolContentID); - - } catch (Exception e) { - wddxPacket = handleException(e, "getToolOutputDefinitions", authoringService, true).serializeMessage(); - } - return outputPacket(mapping, request, response, wddxPacket, "definitions"); + return outputPacket(mapping, request, response, wddxPacket, "details"); + } + + public ActionForward getAllLearningDesignDetails(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + wddxPacket = authoringService.getAllLearningDesignDetails(); + } catch (Exception e) { + wddxPacket = handleException(e, "getAllLearningDesignDetails", authoringService, true).serializeMessage(); } - - public ActionForward getLearningDesignDetails(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, IOException{ - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - Long learningDesignID = WebUtil.readLongParam(request,"learningDesignID",false); - wddxPacket = authoringService.getLearningDesignDetails(learningDesignID, getUserLanguage()); - log.debug("LD wddx packet: " + wddxPacket); - } catch (Exception e) { - wddxPacket = handleException(e, "getLearningDesignDetails", authoringService, true).serializeMessage(); - } - return outputPacket(mapping, request, response, wddxPacket, "details"); + log.debug("getAllLearningDesignDetails: returning " + wddxPacket); + return outputPacket(mapping, request, response, wddxPacket, "details"); + } + + public ActionForward getAllLearningLibraryDetails(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + wddxPacket = authoringService.getAllLearningLibraryDetails(getUserLanguage()); + } catch (Exception e) { + wddxPacket = handleException(e, "getAllLearningLibraryDetails", authoringService, true).serializeMessage(); } - - public ActionForward finishLearningDesignEdit(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException{ - - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - Long learningDesignID = WebUtil.readLongParam(request,"learningDesignID",false); - boolean cancelled = WebUtil.readBooleanParam(request, "cancelled", false); - - wddxPacket = authoringService.finishEditOnFly(learningDesignID, getUserId(), cancelled); - - } catch (Exception e) { - wddxPacket = handleException(e, "getLearningDesignDetails", authoringService, true).serializeMessage(); - return outputPacket(mapping, request, response, wddxPacket, "details"); - } - - return outputPacket(mapping, request, response, wddxPacket, "details"); - + log.debug("getAllLearningLibraryDetails: returning " + wddxPacket); + return outputPacket(mapping, request, response, wddxPacket, "details"); + } + + public ActionForward getToolContentID(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + Long toolID = WebUtil.readLongParam(request, "toolID", false); + wddxPacket = authoringService.getToolContentID(toolID); + } catch (Exception e) { + wddxPacket = handleException(e, "getAllLearningLibraryDetails", authoringService, true).serializeMessage(); } - - public ActionForward getLearningDesignsForUser(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, IOException{ - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - Long userID = new Long(getUserId()); - - wddxPacket = authoringService.getLearningDesignsForUser(userID); - } catch (Exception e) { - wddxPacket = handleException(e, "getLearningDesignsForUser", authoringService, true).serializeMessage(); - } - return outputPacket(mapping, request, response, wddxPacket, "details"); + return outputPacket(mapping, request, response, wddxPacket, "details"); + + } + + /** + * Copy some existing content. Used when the user copies an activity in + * authoring. Expects one parameters - toolContentId (the content to be + * copied) + */ + public ActionForward copyToolContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + String customCSV = WebUtil.readStrParam(request, AttributeNames.PARAM_CUSTOM_CSV, true); + try { + long toolContentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID, false); + wddxPacket = authoringService.copyToolContent(toolContentID, customCSV); + } catch (Exception e) { + wddxPacket = handleException(e, "copyToolContent", authoringService, true).serializeMessage(); } - public ActionForward getAllLearningDesignDetails(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, IOException{ - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - wddxPacket = authoringService.getAllLearningDesignDetails(); - } catch (Exception e) { - wddxPacket = handleException(e, "getAllLearningDesignDetails", authoringService, true).serializeMessage(); - } - log.debug("getAllLearningDesignDetails: returning "+wddxPacket); - return outputPacket(mapping, request, response, wddxPacket, "details"); + return outputPacket(mapping, request, response, wddxPacket, "details"); + + } + + /** + * This method returns a list of all available license in WDDX format. + * + * This will include our supported Creative Common licenses and an "OTHER" + * license which may be used for user entered license details. The picture + * url supplied should be a full URL i.e. if it was a relative URL in the + * database, it should have been converted to a complete server URL + * (starting http://) before sending to the client. + * + * @return String The required information in WDDX format + * @throws IOException + */ + public ActionForward getAvailableLicenses(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, Exception { + + FlashMessage flashMessage = null; + try { + IAuthoringService authoringService = getAuthoringService(); + Vector licenses = authoringService.getAvailableLicenses(); + flashMessage = new FlashMessage("getAvailableLicenses", licenses); + } catch (Exception e) { + log.error("getAvailableLicenses: License details unavailable due to system error.", e); + flashMessage = new FlashMessage("getAvailableLicenses", "License details unavailable due to system error :" + + e.getMessage(), FlashMessage.ERROR); + + getAuditService().log(AuthoringAction.class.getName(), e.toString()); } - public ActionForward getAllLearningLibraryDetails(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, IOException{ - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - wddxPacket = authoringService.getAllLearningLibraryDetails(getUserLanguage()); - } catch (Exception e) { - wddxPacket = handleException(e, "getAllLearningLibraryDetails", authoringService, true).serializeMessage(); - } - log.debug("getAllLearningLibraryDetails: returning "+wddxPacket); - return outputPacket(mapping, request, response, wddxPacket, "details"); + PrintWriter writer = response.getWriter(); + writer.println(flashMessage.serializeMessage()); + return null; + } + + public ActionForward createUniqueContentFolder(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, Exception { + + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + + try { + wddxPacket = authoringService.generateUniqueContentFolder(); + } catch (FileUtilException fue) { + // return a normal error, not a critical error as a critical error + // interrupts the display + // of the toolkit in the Flash client. + wddxPacket = handleException(fue, "createUniqueContentFolder", authoringService, false).serializeMessage(); + } catch (Exception e) { + wddxPacket = handleException(e, "createUniqueContentFolder", authoringService, false).serializeMessage(); } - - public ActionForward getToolContentID(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - Long toolID = WebUtil.readLongParam(request,"toolID",false); - wddxPacket = authoringService.getToolContentID(toolID); - } catch (Exception e) { - wddxPacket = handleException(e, "getAllLearningLibraryDetails", authoringService, true).serializeMessage(); - } - return outputPacket(mapping, request, response, wddxPacket, "details"); - - } - - /** Copy some existing content. Used when the user copies an activity in authoring. - * Expects one parameters - toolContentId (the content to be copied) */ - public ActionForward copyToolContent(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - String customCSV = WebUtil.readStrParam(request, AttributeNames.PARAM_CUSTOM_CSV, true); - try { - long toolContentID = WebUtil.readLongParam(request,AttributeNames.PARAM_TOOL_CONTENT_ID,false); - wddxPacket = authoringService.copyToolContent(toolContentID, customCSV); - } catch (Exception e) { - wddxPacket = handleException(e, "copyToolContent", authoringService, true).serializeMessage(); - } - return outputPacket(mapping, request, response, wddxPacket, "details"); - - } - /** - * This method returns a list of all available license in - * WDDX format. - * - * This will include our supported Creative Common - * licenses and an "OTHER" license which may be used for user entered license details. - * The picture url supplied should be a full URL i.e. if it was a relative URL in the - * database, it should have been converted to a complete server URL (starting http://) - * before sending to the client. - * - * @return String The required information in WDDX format - * @throws IOException - */ - public ActionForward getAvailableLicenses(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, Exception{ - FlashMessage flashMessage = null; - try { - IAuthoringService authoringService = getAuthoringService(); - Vector licenses = authoringService.getAvailableLicenses(); - flashMessage = new FlashMessage("getAvailableLicenses",licenses); - } catch (Exception e) { - log.error("getAvailableLicenses: License details unavailable due to system error.",e); - flashMessage = new FlashMessage("getAvailableLicenses", - "License details unavailable due to system error :" + e.getMessage(), - FlashMessage.ERROR); - - getAuditService().log(AuthoringAction.class.getName(), e.toString()); - } - - PrintWriter writer = response.getWriter(); - writer.println(flashMessage.serializeMessage()); - return null; - } - - public ActionForward createUniqueContentFolder(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, Exception{ + PrintWriter writer = response.getWriter(); + writer.println(wddxPacket); + return null; + } - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - - try { - wddxPacket = authoringService.generateUniqueContentFolder(); - } catch (FileUtilException fue) { - // return a normal error, not a critical error as a critical error interrupts the display - // of the toolkit in the Flash client. - wddxPacket = handleException(fue, "createUniqueContentFolder", authoringService, false).serializeMessage(); - } catch (Exception e) { - wddxPacket = handleException(e, "createUniqueContentFolder", authoringService, false).serializeMessage(); - } - - PrintWriter writer = response.getWriter(); - writer.println(wddxPacket); - return null; - } - - public ActionForward getHelpURL(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response)throws ServletException, Exception{ + public ActionForward getHelpURL(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ServletException, Exception { - String wddxPacket; - IAuthoringService authoringService = getAuthoringService(); - try { - wddxPacket = authoringService.getHelpURL(); - } catch (Exception e) { - wddxPacket = handleException(e, "getHelpURL", authoringService, true).serializeMessage(); - } - - PrintWriter writer = response.getWriter(); - writer.println(wddxPacket); - return null; + String wddxPacket; + IAuthoringService authoringService = getAuthoringService(); + try { + wddxPacket = authoringService.getHelpURL(); + } catch (Exception e) { + wddxPacket = handleException(e, "getHelpURL", authoringService, true).serializeMessage(); } - /** - * Handle flash error. - * @param e - * @param methodKey - * @param monitoringService - * @return - */ - private FlashMessage handleException(Exception e, String methodKey, IAuthoringService authoringService, boolean useCriticalError) { - log.error("Exception thrown "+methodKey,e); - getAuditService().log(AuthoringAction.class.getName()+":"+methodKey, e.toString()); - String[] msg = new String[1]; - msg[0] = e.getMessage(); - return new FlashMessage(methodKey, - authoringService.getMessageService().getMessage("error.system.error", msg), - useCriticalError ? FlashMessage.CRITICAL_ERROR : FlashMessage.ERROR); + PrintWriter writer = response.getWriter(); + writer.println(wddxPacket); + return null; } - - /** - * Get AuditService bean. - * @return - */ - private IAuditService getAuditService(){ - if(auditService==null){ - WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet().getServletContext()); - auditService = (IAuditService) ctx.getBean("auditService"); - } - return auditService; + + /** + * Handle flash error. + * + * @param e + * @param methodKey + * @param monitoringService + * @return + */ + private FlashMessage handleException(Exception e, String methodKey, IAuthoringService authoringService, + boolean useCriticalError) { + log.error("Exception thrown " + methodKey, e); + getAuditService().log(AuthoringAction.class.getName() + ":" + methodKey, e.toString()); + + String[] msg = new String[1]; + msg[0] = e.getMessage(); + return new FlashMessage(methodKey, authoringService.getMessageService().getMessage("error.system.error", msg), + useCriticalError ? FlashMessage.CRITICAL_ERROR : FlashMessage.ERROR); + } + + /** + * Get AuditService bean. + * + * @return + */ + private IAuditService getAuditService() { + if (auditService == null) { + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() + .getServletContext()); + auditService = (IAuditService) ctx.getBean("auditService"); } + return auditService; + } }