Index: lams_tool_forum/conf/hibernate/mappings/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.hbm.xml =================================================================== diff -u --- lams_tool_forum/conf/hibernate/mappings/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.hbm.xml (revision 0) +++ lams_tool_forum/conf/hibernate/mappings/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.hbm.xml (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_tool_forum/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r51408ee6d48b84e64c4acbbf4d6e95ddb7ea3ddc -rd71c8a085fb0ea3c341f2cf46df958c356d88ec7 --- lams_tool_forum/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 51408ee6d48b84e64c4acbbf4d6e95ddb7ea3ddc) +++ lams_tool_forum/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -1,249 +1,253 @@ -appName = forum -#language code: en -#locale code: AU - - # Exported from the LAMS Community by Ernie Ghiglione on Mon Mar 27 23:48:33 CST 2017 - -#=================== labels for Forum =================# - -activity.title =Forum -activity.description =Online threaded discussion tool (asynchronous). -activity.helptext =Discussion tool useful for long running collaborations and situations where learners are not all on line at the same time. -tool.display.name =Forum Tool -tool.description =Tool for forums, also known as message boards. -label.authoring.heading.basic =Forum -label.authoring.create.new.topic =Create topic -label.authoring.basic.title =Title -label.authoring.basic.instruction =Instructions -label.authoring.advance.lock.on.finished =Lock when finished -label.authoring.save.button =Save -label.authoring.cancel.button =Cancel -label.authoring.advance.allow.edit =Allow learners to change their own postings -label.authoring.advance.use.richeditor =Allow learners to use rich text editor -label.authoring.advance.limited.input =Maximum number of characters per posting -lable.topic.title.subject =Subject -lable.topic.title.body =Body -lable.topic.title.update =Last post -lable.topic.title.author =Author -lable.topic.title.startedby =Started by -lable.topic.title.replies =Replies -lable.topic.title.mark =Mark -lable.topic.subject.by =By -label.back.to.forum =Back to topics -lable.topic.title.message.number =# of Msg -lable.topic.title.average.mark =Aver mark -page.title.monitoring.content.userlist =Summary -page.title.monitoring.view.user.mark =View user mark -page.title.monitoring.edit.user.mark =Edit user mark -page.title.monitoring.view.activity =View Activity -page.title.monitoring.edit.activity =Edit Activity -page.title.monitoring.view.instructions =View instructions -page.title.monitoring.view.topic =View topic -page.title.monitoring.statistic =Statistic -page.title.monitoring.definelater =Forum Tool Define -label.monitoring.edit.activity.cancel =Cancel -label.monitoring.edit.activity.update =Update -label.monitoring.edit.activity.edit =Edit -label.monitoring.statistic.average.mark =Average message mark -lable.monitoring.statistic.total.message =# of total message -error.valueReqd =Value Required -error.mark.needNumber =Mark must be a number -error.mark.invalid.number =Mark is invalid number format -error.title.empty =Title can not be blank -title.messageTopic.open =Topic Details -title.message.add =Add Message -title.message.open =View Message -title.message.reply =Reply Message -title.message.edit =Edit Message -title.message.view =Message Board -title.message.view.topic =View Message -title.message.delete =Delete Message -message.label.subject =Subject -message.label.body =Body -message.label.attachment =Attachment -message.label.postedOn =Posted on: -message.label.threadReplies =Thread replies -message.link.reply =Reply -label.open =Open -label.delete =Delete -label.view =View -label.edit =Edit -label.reply =Reply -label.done =Done -label.finish =Next Activity -label.newtopic =New Topic -label.refresh =Refresh -lable.char.left =Characters left -label.basic =Basic -label.advanced =Advanced -label.instructions =Instructions -button.upload =Upload -button.done =Done -button.submit =Submit -button.on =On -button.off =Off -button.add =Add -button.cancel =Cancel -js.error.invalid.number =The input is invalid number format -js.error.min.number =The input must be greater than 0 -js.error.title =The following error(s) occurred: -monitoring.tab.summary =Summary -monitoring.tab.edit.activity =Edit Activity -monitoring.user.post.topic =provides following posts: -lable.topic.title.comment =Comment -message.not.avaliable =Not Available -lable.update.mark =Update mark -message.assign.mark =Please assign a mark and a comment for the report by -message.session.name =Session Name -message.monitoring.summary.no.users =No users available -message.view.all.marks =View all marks -message.download.marks =Download marks -label.monitoring.summary.view.forum =View forum -message.monitoring.summary.no.session =No Session Available -topic.message.subject.hidden =Message subject hidden -topic.message.body.hidden =Message body hidden -label.show =Show -label.hide =Hide -page.title.monitoring.init =Forum Monitoring -monitoring.tab.statistics =Statistics -label.save =Save -label.cancel =Cancel -authoring.tab.basic =Basic -authoring.tab.advanced =Advanced -page.title.authoring.init =Forum Authoring -authoring.msg.cancel.save =Do you want to close this window without saving? -define.later.message =Please wait for the instructor to complete the contents of this activity. -button.try.again =Try again -button.close =Close -button.release.mark =Release marks -msg.mark.released =Marks in {0} have been released. -label.authoring.advance.allow.upload =Allow learners to add attachments -label.authoring.advance.allow.new.topics =Allow learners to create new topics -label.authoring.advance.number.reply =Number of posts per learner per thread. -label.authoring.advance.minimum.reply =Minimum: -label.authoring.advance.maximum.reply =Maximum: -label.authoring.advance.no.minimum =No minimum -label.authoring.advance.no.maximum =No maximum -error.min.less.max =The maximum number of posts must be greater than or equal to the minimum number of posts. -error.limit.char.less.zero =Limitation of input characters must be greater zero. -error.less.mini.post =You must contribute at least {0} posts in each topic before finish. -error.must.have.topic =Please add at least 1 topic when "allow learners to create new topics" option is off. -topic.message.attachment.hidden =Message attachment hidden -message.posting.limiting =Posting limits -advanced.reflectOnActivity =Add a notebook at end of forum with the following instructions: -error.reflection.emtpy =Please input notebook entry -title.reflection =Notebook Entry -label.continue =Continue -monitoring.user.fullname =Name -monitoring.user.loginname =Login -monitoring.user.reflection =Notebook entry -page.title.monitoring.view.reflection =View Notebook entries -label.default.user.name =Instructor -error.subject.required =Subject can not be blank. -error.body.required =Body can not be blank. -title.original.message.reply =Original message -output.desc.learner.number.of.posts =Learner's number of postings in the forum -label.download.marks.heading.date =Date -label.download.marks.heading.marks =Marks -label.download.marks.heading.comments =Comments -label.responses.locked =Note: After you click on "Next Activity" and you come back to this Forum, you won't be able to continue posting. -label.responses.locked.reminder =The instructor has set this activity not to allow postings after you have finished it. As you are returning to this Forum again, you are able to see all threads but not allow to post anymore. -monitoring.marked.question =Marked? -label.postingLimits.forum.reminder =Posting limitations for this forum: Minimum {0} and Maximum {1} per thread. -label.postingLimits.topic.reminder =Posting for this thread: Minimum {0} and Maximum {1}. You have posted {2} message(s). -label.export.reflection =Notebook Entries -label.yes =Yes -label.no =No -label.on =On -label.off =Off -monitor.summary.th.advancedSettings =Advanced settings -monitor.summary.td.addNotebook =Add a notebook at the end of Forum -monitor.summary.td.notebookInstructions =Notebook instructions -label.authoring.advanced.notify.mark.release =Notify learners when marks are released. -event.mark.release.subject =LAMS: Marks were released -event.mark.release.body =An instructor released marks in a Forum activity in LAMS.\nYour marks are:\n\n{0}\nThis message was sent automatically, please do not reply to it. -event.mark.release.mark =For the message titled "{0}" posted on {1} the mark is {2}. \n -authoring.tab.conditions =Conditions -label.authoring.heading.conditions.desc =Please enter conditions for Forum -label.authoring.heading.conditions =Conditions -label.authoring.conditions.add.condition =Add condition -label.authoring.conditions.list.title =Conditions -label.authoring.conditions.order =Order -label.authoring.conditions.empty.condition.list =There are no conditions -label.authoring.conditions.condition.name =Name -label.authoring.up =Up -label.authoring.down =Down -error.condition.name.blank =Condition name can not be blank. -error.condition.duplicated.name =Duplicated name. Please choose unique one. -error.condition.no.questions.selected =There are no questions selected. Please select at least one. -error.condition =Error creating condition. -output.desc.topic.name.to.answers.output.definition.forum =Posts contain certain words -topic.name.to.answers.output.definition.forum.default.condition =Posts to the first topic contain word "LAMS" -textsearch.heading =Posts that... -textsearch.all.words =have all these words: -textsearch.phrase =have this exact wording or phrase: -textsearch.any.words =have one or more of these words: -textsearch.excluded.words =have none of these unwanted words: -textsearch.topics =Search in these topics: -lable.topic.title.repliesnew =New -label.postingLimits.forum.reminder.max =Maximum posting limitations for this forum is {0} per thread. -label.postingLimits.forum.reminder.min =Minimum posting limitations for this forum is {0} per thread. -label.postingLimits.topic.reminder.max =Maximum posting for this thread is {0}. You have posted {1} message(s). -label.postingLimits.topic.reminder.min =Minimum posting for this thread is {0}. You have posted {1} message(s). -label.authoring.advanced.send.emails.to =On new postings send email to: -label.authoring.advanced.learners =learners -label.authoring.advanced.teachers =instructors -event.newposting.subject =Forum: {0} -event.newposting.body ={0}:\n{1}\n\n-- email sent automatically by LAMS -label.authoring.basic.do.you.want.to.delete =Do you really want to delete this topic? -label.learning.number.of.votes ={0} / {1} votes -label.authoring.advance.allow.rate.postings =Allow learners to rate each other's postings -monitor.summary.date.restriction =Deadline -monitor.summary.when.date.restriction.is.set =Learners will not be able to post messages after the set date and time. -monitor.summary.after.date =Date/time: -monitor.summary.set.restriction =Set restriction -monitor.summary.unset.restriction =Remove restriction -authoring.info.teacher.set.restriction =For this activity, the instructor fixed a deadline until {0}. After this time this activity will not be available. -monitor.summary.notification =Notification -monitor.summary.date.restriction.set =Deadline has been set -monitor.summary.date.restriction.removed =Deadline has been removed -errors.maxfilesize =Uploaded file exceeded maximum size: {0} -error.attachment.executable =Uploaded file is executable -label.upload.info =Uploaded file must not be executable and not exceed size of {0} -output.desc.all.users.answers.definition.forum =Each learner's posts sent in the Forum -label.submit =Finish -label.rateLimits.forum.reminder =Rating limitation: minimum {0} and maximum {1}. -label.rateLimits.forum.reminder.min =You must rate at least {0} postings. -label.rateLimits.forum.reminder.max =You can only rate up to {0} postings. -js.error.validate.number =There is an error with the minimum and/or maximum set for ratings. Please check and try again. -label.rateLimits.topic.reminder =You have rated {0} postings already. -info.minimum.number.characters =The minimum number of characters for your response is {0}. -warn.minimum.number.characters =You need to enter {0} characters more to proceed. -label.authoring.advance.min.limited.input =Minimum number of characters per posting -label.char.required =Characters required -label.number.of.posts =Posts -label.latest.posting.date =Latest post on -label.number.of.replies =Replies -message.no.reflection.available =No notebook entry was added. -label.show.more.messages =More posts -label.loading.messages =Loading more posts -label.search =Search... -label.show.replies =Show replies -label.hide.replies =Hide replies -label.showhide.prompt =Show/Hide replies -message.complete.or.cancel.reply =Please complete or cancel the current reply before starting a new reply. -message.complete.or.cancel.edit =Please complete or cancel the current edit before starting a new edit. -error.cannot.redisplay.please.refresh =Your changes have been saved but cannot be redisplayed. Please select refresh to reload the forum messages. -label.posting.options =Posting options -label.activity.completion =Activity completion -label.notifications =Notifications -error.min.post.char.less =The maximum number of characters per posting must be greater than minimum. -error.min.rate.less.max =The maximum number of ratings must be greater than its minimum. -js.error.validate.posting.number =There is an error with the minimum and/or maximum set for postings. Please check and try again. -js.error.validate.reply.number =There is an error with the minimum and/or maximum number of posts per thread. -label.topics =Topics -label.authoring.basic.resource.file.input =File -message.monitoring.edit.activity.not.editable =Activity cannot longer be editted - - -#======= End labels: Exported 238 labels for en AU ===== +appName = forum +#language code: en +#locale code: AU + + # Exported from the LAMS Community by Ernie Ghiglione on Mon Mar 27 23:48:33 CST 2017 + +#=================== labels for Forum =================# + +activity.title =Forum +activity.description =Online threaded discussion tool (asynchronous). +activity.helptext =Discussion tool useful for long running collaborations and situations where learners are not all on line at the same time. +tool.display.name =Forum Tool +tool.description =Tool for forums, also known as message boards. +label.authoring.heading.basic =Forum +label.authoring.create.new.topic =Create topic +label.authoring.basic.title =Title +label.authoring.basic.instruction =Instructions +label.authoring.advance.lock.on.finished =Lock when finished +label.authoring.save.button =Save +label.authoring.cancel.button =Cancel +label.authoring.advance.allow.edit =Allow learners to change their own postings +label.authoring.advance.use.richeditor =Allow learners to use rich text editor +label.authoring.advance.limited.input =Maximum number of characters per posting +lable.topic.title.subject =Subject +lable.topic.title.body =Body +lable.topic.title.update =Last post +lable.topic.title.author =Author +lable.topic.title.startedby =Started by +lable.topic.title.replies =Replies +lable.topic.title.mark =Mark +lable.topic.subject.by =By +label.back.to.forum =Back to topics +lable.topic.title.message.number =# of Msg +lable.topic.title.average.mark =Aver mark +page.title.monitoring.content.userlist =Summary +page.title.monitoring.view.user.mark =View user mark +page.title.monitoring.edit.user.mark =Edit user mark +page.title.monitoring.view.activity =View Activity +page.title.monitoring.edit.activity =Edit Activity +page.title.monitoring.view.instructions =View instructions +page.title.monitoring.view.topic =View topic +page.title.monitoring.statistic =Statistic +page.title.monitoring.definelater =Forum Tool Define +label.monitoring.edit.activity.cancel =Cancel +label.monitoring.edit.activity.update =Update +label.monitoring.edit.activity.edit =Edit +label.monitoring.statistic.average.mark =Average message mark +lable.monitoring.statistic.total.message =# of total message +error.valueReqd =Value Required +error.mark.needNumber =Mark must be a number +error.mark.invalid.number =Mark is invalid number format +error.title.empty =Title can not be blank +title.messageTopic.open =Topic Details +title.message.add =Add Message +title.message.open =View Message +title.message.reply =Reply Message +title.message.edit =Edit Message +title.message.view =Message Board +title.message.view.topic =View Message +title.message.delete =Delete Message +message.label.subject =Subject +message.label.body =Body +message.label.attachment =Attachment +message.label.postedOn =Posted on: +message.label.threadReplies =Thread replies +message.link.reply =Reply +label.open =Open +label.delete =Delete +label.view =View +label.edit =Edit +label.reply =Reply +label.done =Done +label.finish =Next Activity +label.newtopic =New Topic +label.refresh =Refresh +lable.char.left =Characters left +label.basic =Basic +label.advanced =Advanced +label.instructions =Instructions +button.upload =Upload +button.done =Done +button.submit =Submit +button.on =On +button.off =Off +button.add =Add +button.cancel =Cancel +js.error.invalid.number =The input is invalid number format +js.error.min.number =The input must be greater than 0 +js.error.title =The following error(s) occurred: +monitoring.tab.summary =Summary +monitoring.tab.edit.activity =Edit Activity +monitoring.user.post.topic =provides following posts: +lable.topic.title.comment =Comment +message.not.avaliable =Not Available +lable.update.mark =Update mark +message.assign.mark =Please assign a mark and a comment for the report by +message.session.name =Session Name +message.monitoring.summary.no.users =No users available +message.view.all.marks =View all marks +message.download.marks =Download marks +label.monitoring.summary.view.forum =View forum +message.monitoring.summary.no.session =No Session Available +topic.message.subject.hidden =Message subject hidden +topic.message.body.hidden =Message body hidden +label.show =Show +label.hide =Hide +page.title.monitoring.init =Forum Monitoring +monitoring.tab.statistics =Statistics +label.save =Save +label.cancel =Cancel +authoring.tab.basic =Basic +authoring.tab.advanced =Advanced +page.title.authoring.init =Forum Authoring +authoring.msg.cancel.save =Do you want to close this window without saving? +define.later.message =Please wait for the instructor to complete the contents of this activity. +button.try.again =Try again +button.close =Close +button.release.mark =Release marks +msg.mark.released =Marks in {0} have been released. +label.authoring.advance.allow.upload =Allow learners to add attachments +label.authoring.advance.allow.new.topics =Allow learners to create new topics +label.authoring.advance.number.reply =Number of posts per learner per thread. +label.authoring.advance.minimum.reply =Minimum: +label.authoring.advance.maximum.reply =Maximum: +label.authoring.advance.no.minimum =No minimum +label.authoring.advance.no.maximum =No maximum +error.min.less.max =The maximum number of posts must be greater than or equal to the minimum number of posts. +error.limit.char.less.zero =Limitation of input characters must be greater zero. +error.less.mini.post =You must contribute at least {0} posts in each topic before finish. +error.must.have.topic =Please add at least 1 topic when "allow learners to create new topics" option is off. +topic.message.attachment.hidden =Message attachment hidden +message.posting.limiting =Posting limits +advanced.reflectOnActivity =Add a notebook at end of forum with the following instructions: +error.reflection.emtpy =Please input notebook entry +title.reflection =Notebook Entry +label.continue =Continue +monitoring.user.fullname =Name +monitoring.user.loginname =Login +monitoring.user.reflection =Notebook entry +page.title.monitoring.view.reflection =View Notebook entries +label.default.user.name =Instructor +error.subject.required =Subject can not be blank. +error.body.required =Body can not be blank. +title.original.message.reply =Original message +output.desc.learner.number.of.posts =Learner's number of postings in the forum +label.download.marks.heading.date =Date +label.download.marks.heading.marks =Marks +label.download.marks.heading.comments =Comments +label.responses.locked =Note: After you click on "Next Activity" and you come back to this Forum, you won't be able to continue posting. +label.responses.locked.reminder =The instructor has set this activity not to allow postings after you have finished it. As you are returning to this Forum again, you are able to see all threads but not allow to post anymore. +monitoring.marked.question =Marked? +label.postingLimits.forum.reminder =Posting limitations for this forum: Minimum {0} and Maximum {1} per thread. +label.postingLimits.topic.reminder =Posting for this thread: Minimum {0} and Maximum {1}. You have posted {2} message(s). +label.export.reflection =Notebook Entries +label.yes =Yes +label.no =No +label.on =On +label.off =Off +monitor.summary.th.advancedSettings =Advanced settings +monitor.summary.td.addNotebook =Add a notebook at the end of Forum +monitor.summary.td.notebookInstructions =Notebook instructions +label.authoring.advanced.notify.mark.release =Notify learners when marks are released. +event.mark.release.subject =LAMS: Marks were released +event.mark.release.body =An instructor released marks in a Forum activity in LAMS.\nYour marks are:\n\n{0}\nThis message was sent automatically, please do not reply to it. +event.mark.release.mark =For the message titled "{0}" posted on {1} the mark is {2}. \n +authoring.tab.conditions =Conditions +label.authoring.heading.conditions.desc =Please enter conditions for Forum +label.authoring.heading.conditions =Conditions +label.authoring.conditions.add.condition =Add condition +label.authoring.conditions.list.title =Conditions +label.authoring.conditions.order =Order +label.authoring.conditions.empty.condition.list =There are no conditions +label.authoring.conditions.condition.name =Name +label.authoring.up =Up +label.authoring.down =Down +error.condition.name.blank =Condition name can not be blank. +error.condition.duplicated.name =Duplicated name. Please choose unique one. +error.condition.no.questions.selected =There are no questions selected. Please select at least one. +error.condition =Error creating condition. +output.desc.topic.name.to.answers.output.definition.forum =Posts contain certain words +topic.name.to.answers.output.definition.forum.default.condition =Posts to the first topic contain word "LAMS" +textsearch.heading =Posts that... +textsearch.all.words =have all these words: +textsearch.phrase =have this exact wording or phrase: +textsearch.any.words =have one or more of these words: +textsearch.excluded.words =have none of these unwanted words: +textsearch.topics =Search in these topics: +lable.topic.title.repliesnew =New +label.postingLimits.forum.reminder.max =Maximum posting limitations for this forum is {0} per thread. +label.postingLimits.forum.reminder.min =Minimum posting limitations for this forum is {0} per thread. +label.postingLimits.topic.reminder.max =Maximum posting for this thread is {0}. You have posted {1} message(s). +label.postingLimits.topic.reminder.min =Minimum posting for this thread is {0}. You have posted {1} message(s). +label.authoring.advanced.send.emails.to =On new postings send email to: +label.authoring.advanced.learners =learners +label.authoring.advanced.teachers =instructors +event.newposting.subject =Forum: {0} +event.newposting.body ={0}:\n{1}\n\n-- email sent automatically by LAMS +label.authoring.basic.do.you.want.to.delete =Do you really want to delete this topic? +label.learning.number.of.votes ={0} / {1} votes +label.authoring.advance.allow.rate.postings =Allow learners to rate each other's postings +monitor.summary.date.restriction =Deadline +monitor.summary.when.date.restriction.is.set =Learners will not be able to post messages after the set date and time. +monitor.summary.after.date =Date/time: +monitor.summary.set.restriction =Set restriction +monitor.summary.unset.restriction =Remove restriction +authoring.info.teacher.set.restriction =For this activity, the instructor fixed a deadline until {0}. After this time this activity will not be available. +monitor.summary.notification =Notification +monitor.summary.date.restriction.set =Deadline has been set +monitor.summary.date.restriction.removed =Deadline has been removed +errors.maxfilesize =Uploaded file exceeded maximum size: {0} +error.attachment.executable =Uploaded file is executable +label.upload.info =Uploaded file must not be executable and not exceed size of {0} +output.desc.all.users.answers.definition.forum =Each learner's posts sent in the Forum +label.submit =Finish +label.rateLimits.forum.reminder =Rating limitation: minimum {0} and maximum {1}. +label.rateLimits.forum.reminder.min =You must rate at least {0} postings. +label.rateLimits.forum.reminder.max =You can only rate up to {0} postings. +js.error.validate.number =There is an error with the minimum and/or maximum set for ratings. Please check and try again. +label.rateLimits.topic.reminder =You have rated {0} postings already. +info.minimum.number.characters =The minimum number of characters for your response is {0}. +warn.minimum.number.characters =You need to enter {0} characters more to proceed. +label.authoring.advance.min.limited.input =Minimum number of characters per posting +label.char.required =Characters required +label.number.of.posts =Posts +label.latest.posting.date =Latest post on +label.number.of.replies =Replies +message.no.reflection.available =No notebook entry was added. +label.show.more.messages =More posts +label.loading.messages =Loading more posts +label.search =Search... +label.show.replies =Show replies +label.hide.replies =Hide replies +label.showhide.prompt =Show/Hide replies +message.complete.or.cancel.reply =Please complete or cancel the current reply before starting a new reply. +message.complete.or.cancel.edit =Please complete or cancel the current edit before starting a new edit. +error.cannot.redisplay.please.refresh =Your changes have been saved but cannot be redisplayed. Please select refresh to reload the forum messages. +label.posting.options =Posting options +label.activity.completion =Activity completion +label.notifications =Notifications +error.min.post.char.less =The maximum number of characters per posting must be greater than minimum. +error.min.rate.less.max =The maximum number of ratings must be greater than its minimum. +js.error.validate.posting.number =There is an error with the minimum and/or maximum set for postings. Please check and try again. +js.error.validate.reply.number =There is an error with the minimum and/or maximum number of posts per thread. +label.topics =Topics +label.authoring.basic.resource.file.input =File +message.monitoring.edit.activity.not.editable =Activity cannot longer be editted +admin.page.title =Forum Settings +admin.success =Configuration successfully saved. +admin.return =Return to maintain LAMS +admin.button.save =Save +admin.keep.learner.content =Never delete learner added posts + +#======= End labels: Exported 238 labels for en AU ===== Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/dbupdates/patch20170707.sql =================================================================== diff -u --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/dbupdates/patch20170707.sql (revision 0) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/dbupdates/patch20170707.sql (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,24 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +----------------------Put all sql statements below here------------------------- + +-- LDEV-4371 Add Forum admin page +CREATE TABLE tl_lafrum11_configuration ( + uid bigint(20) NOT NULL AUTO_INCREMENT, + config_key VARCHAR(30), + config_value VARCHAR(255), + PRIMARY KEY (uid), + UNIQUE KEY config_key (config_key) +); + +INSERT INTO tl_lafrum11_configuration (config_key, config_value) VALUES ('keepLearnerContent', 'false'); + +UPDATE lams_tool SET admin_url='tool/lafrum11/admin/start.do' WHERE tool_signature='lafrum11'; + +----------------------Put all sql statements above here------------------------- + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/forumApplicationContext.xml =================================================================== diff -u -ra6641bf9262a01d07740a517643f8fe187ec5b1f -rd71c8a085fb0ea3c341f2cf46df958c356d88ec7 --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/forumApplicationContext.xml (.../forumApplicationContext.xml) (revision a6641bf9262a01d07740a517643f8fe187ec5b1f) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/forumApplicationContext.xml (.../forumApplicationContext.xml) (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -1,201 +1,201 @@ - - - - - - - - org.lamsfoundation.lams.tool.forum.ApplicationResources - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - - - - - - - PROPAGATION_REQUIRED,readOnly,-java.lang.Exception - PROPAGATION_REQUIRED,readOnly,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - PROPAGATION_REQUIRED,-java.lang.Exception - - - - + + + + + + + + org.lamsfoundation.lams.tool.forum.ApplicationResources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + PROPAGATION_REQUIRED,readOnly,-java.lang.Exception + PROPAGATION_REQUIRED,readOnly,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + + + + \ No newline at end of file Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.java =================================================================== diff -u --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.java (revision 0) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/persistence/ForumConfigItem.java (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,58 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.forum.persistence; + +public class ForumConfigItem implements java.io.Serializable { + + private static final long serialVersionUID = 1618184711102211756L; + + public static final String KEY_KEEP_LEARNER_CONTENT = "keepLearnerContent"; + + private Long id; + private String configKey; + private String configValue; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getConfigKey() { + return configKey; + } + + public void setConfigKey(String configKey) { + this.configKey = configKey; + } + + public String getConfigValue() { + return configValue; + } + + public void setConfigValue(String configValue) { + this.configValue = configValue; + } +} \ No newline at end of file Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumService.java =================================================================== diff -u -r2abc3485dc2d24ea02044a64271f3ee0d3b8c11b -rd71c8a085fb0ea3c341f2cf46df958c356d88ec7 --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumService.java (.../ForumService.java) (revision 2abc3485dc2d24ea02044a64271f3ee0d3b8c11b) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumService.java (.../ForumService.java) (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -1,1595 +1,1614 @@ -/**************************************************************** - * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) - * ============================================================= - * License Information: http://lamsfoundation.org/licensing/lams/2.0/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2.0 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - * - * http://www.gnu.org/licenses/gpl.txt - * **************************************************************** - */ - - -package org.lamsfoundation.lams.tool.forum.service; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.apache.struts.upload.FormFile; -import org.apache.tomcat.util.json.JSONArray; -import org.apache.tomcat.util.json.JSONException; -import org.apache.tomcat.util.json.JSONObject; -import org.lamsfoundation.lams.contentrepository.AccessDeniedException; -import org.lamsfoundation.lams.contentrepository.ICredentials; -import org.lamsfoundation.lams.contentrepository.ITicket; -import org.lamsfoundation.lams.contentrepository.InvalidParameterException; -import org.lamsfoundation.lams.contentrepository.LoginException; -import org.lamsfoundation.lams.contentrepository.NodeKey; -import org.lamsfoundation.lams.contentrepository.RepositoryCheckedException; -import org.lamsfoundation.lams.contentrepository.WorkspaceNotFoundException; -import org.lamsfoundation.lams.contentrepository.service.IRepositoryService; -import org.lamsfoundation.lams.contentrepository.service.SimpleCredentials; -import org.lamsfoundation.lams.events.IEventNotificationService; -import org.lamsfoundation.lams.gradebook.service.IGradebookService; -import org.lamsfoundation.lams.learning.service.ILearnerService; -import org.lamsfoundation.lams.learningdesign.ToolActivity; -import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; -import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; -import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; -import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; -import org.lamsfoundation.lams.lesson.service.ILessonService; -import org.lamsfoundation.lams.notebook.model.NotebookEntry; -import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; -import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; -import org.lamsfoundation.lams.rest.RestTags; -import org.lamsfoundation.lams.rest.ToolRestManager; -import org.lamsfoundation.lams.tool.ToolCompletionStatus; -import org.lamsfoundation.lams.tool.ToolContentManager; -import org.lamsfoundation.lams.tool.ToolOutput; -import org.lamsfoundation.lams.tool.ToolOutputDefinition; -import org.lamsfoundation.lams.tool.ToolSession; -import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; -import org.lamsfoundation.lams.tool.ToolSessionManager; -import org.lamsfoundation.lams.tool.exception.DataMissingException; -import org.lamsfoundation.lams.tool.exception.ToolException; -import org.lamsfoundation.lams.tool.forum.dto.AverageRatingDTO; -import org.lamsfoundation.lams.tool.forum.dto.MessageDTO; -import org.lamsfoundation.lams.tool.forum.persistence.Attachment; -import org.lamsfoundation.lams.tool.forum.persistence.Forum; -import org.lamsfoundation.lams.tool.forum.persistence.ForumCondition; -import org.lamsfoundation.lams.tool.forum.persistence.ForumException; -import org.lamsfoundation.lams.tool.forum.persistence.ForumReport; -import org.lamsfoundation.lams.tool.forum.persistence.ForumToolSession; -import org.lamsfoundation.lams.tool.forum.persistence.ForumUser; -import org.lamsfoundation.lams.tool.forum.persistence.IAttachmentDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IForumDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IForumToolSessionDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IForumUserDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IMessageDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IMessageRatingDAO; -import org.lamsfoundation.lams.tool.forum.persistence.IMessageSeqDAO; -import org.lamsfoundation.lams.tool.forum.persistence.ITimestampDAO; -import org.lamsfoundation.lams.tool.forum.persistence.Message; -import org.lamsfoundation.lams.tool.forum.persistence.MessageRating; -import org.lamsfoundation.lams.tool.forum.persistence.MessageSeq; -import org.lamsfoundation.lams.tool.forum.persistence.PersistenceException; -import org.lamsfoundation.lams.tool.forum.persistence.Timestamp; -import org.lamsfoundation.lams.tool.forum.util.DateComparator; -import org.lamsfoundation.lams.tool.forum.util.ForumConstants; -import org.lamsfoundation.lams.tool.forum.util.ForumToolContentHandler; -import org.lamsfoundation.lams.tool.forum.util.MessageDtoComparator; -import org.lamsfoundation.lams.tool.forum.util.TopicComparator; -import org.lamsfoundation.lams.tool.service.ILamsToolService; -import org.lamsfoundation.lams.usermanagement.User; -import org.lamsfoundation.lams.usermanagement.dto.UserDTO; -import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; -import org.lamsfoundation.lams.util.JsonUtil; -import org.lamsfoundation.lams.util.MessageService; -import org.lamsfoundation.lams.util.audit.IAuditService; - -/** - * - * @author Steve.Ni - * - * @version $Revision$ - */ -public class ForumService implements IForumService, ToolContentManager, ToolSessionManager, ToolRestManager { - private static final Logger log = Logger.getLogger(ForumService.class); - - // DAO variables - private IForumDAO forumDao; - - private IAttachmentDAO attachmentDao; - - private IMessageDAO messageDao; - - private ITimestampDAO timestampDao; - - private IMessageSeqDAO messageSeqDao; - - private IMessageRatingDAO messageRatingDao; - - private IForumUserDAO forumUserDao; - - private IForumToolSessionDAO forumToolSessionDao; - - // system level handler and service - private ILamsToolService toolService; - - private ForumToolContentHandler forumToolContentHandler; - - private IRepositoryService repositoryService; - - private ILearnerService learnerService; - - private IAuditService auditService; - - private MessageService messageService; - - private IExportToolContentService exportContentService; - - private IUserManagementService userManagementService; - - private ICoreNotebookService coreNotebookService; - - private ForumOutputFactory forumOutputFactory; - - private IGradebookService gradebookService; - - private IEventNotificationService eventNotificationService; - - private ILessonService lessonService; - - private IActivityDAO activityDAO; - - private Random generator = new Random(); - - // --------------------------------------------------------------------- - // Inversion of Control Methods - Method injection - // --------------------------------------------------------------------- - public void setAuditService(IAuditService auditService) { - this.auditService = auditService; - } - - @Override - public IAuditService getAuditService() { - return auditService; - } - - public void setMessageService(MessageService messageService) { - this.messageService = messageService; - } - - public ForumOutputFactory getForumOutputFactory() { - return forumOutputFactory; - } - - public void setForumOutputFactory(ForumOutputFactory forumOutputFactory) { - this.forumOutputFactory = forumOutputFactory; - } - - @Override - public Forum updateForum(Forum forum) throws PersistenceException { - forumDao.saveOrUpdate(forum); - return forum; - } - - @Override - public Forum getForum(Long forumUid) throws PersistenceException { - return forumDao.getById(forumUid); - } - - @Override - public Forum getForumByContentId(Long contentID) throws PersistenceException { - return forumDao.getByContentId(contentID); - } - - public void deleteForumAttachment(Long attachmentId) throws PersistenceException { - Attachment attachment = attachmentDao.getById(attachmentId); - attachmentDao.delete(attachment); - } - - @Override - public Message createRootTopic(Long forumId, Long sessionId, Message message) throws PersistenceException { - return createRootTopic(forumId, getSessionBySessionId(sessionId), message); - } - - public Message createRootTopic(Long forumId, ForumToolSession session, Message message) - throws PersistenceException { - // get Forum and ForumToolSesion - if (message.getForum() == null) { - Forum forum = forumDao.getById(forumId); - message.setForum(forum); - } - // if topic created by author, session will be null. - if (session != null) { - message.setToolSession(session); - } - - if (message.getUid() == null) { - // update message sequence - MessageSeq msgSeq = new MessageSeq(); - msgSeq.setMessage(message); - msgSeq.setMessageLevel((short) 0); - // set itself as root - msgSeq.setRootMessage(message); - messageSeqDao.save(msgSeq); - } - - // if this message had any cloned objects, they also need to be changed. - // this will only happen if an authored topic is changed via monitoring - if (message.getSessionClones().size() > 0) { - Iterator iter = message.getSessionClones().iterator(); - while (iter.hasNext()) { - Message clone = (Message) iter.next(); - message.updateClone(clone); - clone.updateModificationData(); - messageDao.saveOrUpdate(clone); - } - } - - // create message in database - message.updateModificationData(); - messageDao.saveOrUpdate(message); - - return message; - } - - @Override - public Message updateTopic(Message message) throws PersistenceException { - - // update message - message.updateModificationData(); - messageDao.saveOrUpdate(message); - - // udate root message's lastReplyDate - MessageSeq msgSeq = messageSeqDao.getByTopicId(message.getUid()); - Message root = msgSeq.getRootMessage(); - root.setLastReplyDate(new Date()); - messageDao.saveOrUpdate(root); - - return message; - } - - @Override - public List getMessageAsDTO(Long messageUid) throws PersistenceException { - - MessageSeq msgSeq = messageSeqDao.getByMessageId(messageUid); - List msgDtoList = new ArrayList(); - msgDtoList.add(makeDTOSetRating(msgSeq, msgSeq.getMessage())); - return msgDtoList; - } - - @Override - public void updateContainedReport(Message message) { - messageDao.saveOrUpdate(message); - } - - @Override - public Message updateMessageHideFlag(Long messageId, boolean hideFlag) { - - Message message = getMessage(messageId); - if (message != null) { - Long userId = 0L; - String loginName = "Default"; - if (message.getCreatedBy() != null) { - userId = message.getCreatedBy().getUserId(); - loginName = message.getCreatedBy().getLoginName(); - } - if (hideFlag) { - auditService.logHideEntry(ForumConstants.TOOL_SIGNATURE, userId, loginName, message.toString()); - } else { - auditService.logShowEntry(ForumConstants.TOOL_SIGNATURE, userId, loginName, message.toString()); - } - - message.setHideFlag(hideFlag); - - // update message - messageDao.update(message); - } - return message; - } - - private Message getMessageForUpdate(Long messageUid) throws PersistenceException { - return messageDao.getByIdForUpdate(messageUid); - } - - @Override - public Message getMessage(Long messageUid) throws PersistenceException { - return messageDao.getById(messageUid); - } - - @Override - public void deleteTopic(Long topicUid) throws PersistenceException { - Message topic = messageDao.getById(topicUid); - - // cascade delete children topic by recursive - List children = messageDao.getChildrenTopics(topicUid); - if (children != null) { - Iterator iter = children.iterator(); - while (iter.hasNext()) { - Message msg = (Message) iter.next(); - this.deleteTopic(msg.getUid()); - } - } - - // recursively delete clones - for (Message clone : (Set) topic.getSessionClones()) { - this.deleteTopic(clone.getUid()); - } - - messageSeqDao.deleteByTopicId(topicUid); - messageDao.delete(topicUid); - } - - @Override - public void deleteCondition(ForumCondition condition) throws PersistenceException { - forumDao.deleteCondition(condition); - } - - @Override - public MessageSeq replyTopic(Long parentId, Long sessionId, Message replyMessage) throws PersistenceException { - // set parent - Message parent = this.getMessageForUpdate(parentId); - replyMessage.setParent(parent); - replyMessage.setForum(parent.getForum()); - // parent sessionID maybe empty if created by author role. So given sessionId is exactly value. - ForumToolSession session = getSessionBySessionId(sessionId); - replyMessage.setToolSession(session); - replyMessage.updateModificationData(); - messageDao.saveOrUpdate(replyMessage); - - // get root topic and create record in MessageSeq table - MessageSeq parentSeq = messageSeqDao.getByTopicId(parent.getUid()); - if (parentSeq == null) { - ForumService.log - .error("Message Sequence table is broken becuase topic " + parent + " can not get Sequence Record"); - } - Message root = parentSeq.getRootMessage(); - MessageSeq msgSeq = new MessageSeq(); - msgSeq.setMessage(replyMessage); - msgSeq.setMessageLevel((short) (parentSeq.getMessageLevel() + 1)); - msgSeq.setRootMessage(root); - // look back up through the parents to find the thread top - will be level 1 - if (msgSeq.getMessageLevel() == 1) { - msgSeq.setThreadMessage(replyMessage); - } else { - MessageSeq threadSeq = parentSeq; - while (threadSeq.getMessageLevel() > 1) { - threadSeq = messageSeqDao.getByTopicId(threadSeq.getMessage().getParent().getUid()); - } - msgSeq.setThreadMessage(threadSeq.getMessage()); - } - messageSeqDao.save(msgSeq); - - // update last reply date for root message - root.setLastReplyDate(new Date()); - // update reply message number for root - root.setReplyNumber(root.getReplyNumber() + 1); - messageDao.saveOrUpdate(root); - - return msgSeq; - } - - @Override - public Attachment uploadAttachment(FormFile uploadFile) throws PersistenceException { - if ((uploadFile == null) || StringUtils.isEmpty(uploadFile.getFileName())) { - throw new ForumException("Could not find upload file: " + uploadFile); - } - - NodeKey nodeKey = processFile(uploadFile); - Attachment file = new Attachment(); - file.setFileUuid(nodeKey.getUuid()); - file.setFileVersionId(nodeKey.getVersion()); - file.setFileName(uploadFile.getFileName()); - - return file; - } - - @Override - public List getTopicThread(Long rootTopicId) { - List unsortedThread = messageSeqDao.getCompleteTopic(rootTopicId); - Iterator iter = unsortedThread.iterator(); - MessageSeq msgSeq; - SortedMap map = new TreeMap(new TopicComparator()); - while (iter.hasNext()) { - msgSeq = (MessageSeq) iter.next(); - map.put(msgSeq, msgSeq.getMessage()); - } - return getSortedMessageDTO(map); - - } - - @Override - public List getTopicThread(Long rootTopicId, Long afterSequenceId, Long pagingSize) { - - long lastThreadMessageUid = afterSequenceId != null ? afterSequenceId.longValue() : 0L; - long usePagingSize = pagingSize != null ? pagingSize.longValue() : ForumConstants.DEFAULT_PAGE_SIZE; - SortedMap map = new TreeMap(new TopicComparator()); - - // first time through we need to include the top topic message (level 0) - if (lastThreadMessageUid == 0) { - MessageSeq msgSeq = messageSeqDao.getByTopicId(rootTopicId); - map.put(msgSeq, msgSeq.getMessage()); - } - - long count = 0; - boolean foundEnough = false; - do { - - List msgSeqs = messageSeqDao.getNextThreadByThreadId(rootTopicId, lastThreadMessageUid); - if (msgSeqs.size() == 0) { - // no more to come from db - foundEnough = true; - } else { - - Iterator iter = msgSeqs.iterator(); - while (iter.hasNext()) { - MessageSeq msgSeq = (MessageSeq) iter.next(); - if (msgSeq.getMessageLevel() == 1) { - lastThreadMessageUid = msgSeq.getMessage().getUid().longValue(); - } - map.put(msgSeq, msgSeq.getMessage()); - count++; - } - if ((usePagingSize >= 0) && (count >= usePagingSize)) { - foundEnough = true; - } - } - } while (!foundEnough); - - return getSortedMessageDTO(map); - } - - @Override - public List getThread(Long threadId) { - List msgSeqs = messageSeqDao.getThreadByThreadId(threadId); - SortedMap map = new TreeMap(new TopicComparator()); - Iterator iter = msgSeqs.iterator(); - while (iter.hasNext()) { - MessageSeq msgSeq = (MessageSeq) iter.next(); - map.put(msgSeq, msgSeq.getMessage()); - } - ; - return getSortedMessageDTO(map); - } - - @Override - public List getRootTopics(Long sessionId) { - ForumToolSession session = getSessionBySessionId(sessionId); - if ((session == null) || (session.getForum() == null)) { - ForumService.log.error("Failed on getting session by given sessionID:" + sessionId); - throw new ForumException("Failed on getting session by given sessionID:" + sessionId); - } - - List topicsBySession = messageDao.getRootTopics(sessionId); - List messageDTOs = MessageDTO.getMessageDTO(topicsBySession); - - // sort by sequence id - Set topicSet = new TreeSet(new MessageDtoComparator()); - topicSet.addAll(messageDTOs); - - topicsBySession.clear(); - topicsBySession.addAll(topicSet); - return topicsBySession; - } - - @Override - public int getTopicsNum(Long userID, Long sessionId) { - return messageDao.getTopicsNum(userID, sessionId); - } - - @Override - public int getNumOfPostsByTopic(Long userId, Long topicId) { - return messageSeqDao.getNumOfPostsByTopic(userId, topicId); - } - - @Override - public ForumUser getUserByID(Long userId) { - return forumUserDao.getByUserId(userId); - } - - @Override - public ForumUser getUserByUserAndSession(Long userId, Long sessionId) { - return forumUserDao.getByUserIdAndSessionId(userId, sessionId); - } - - @Override - public List getUsersForTablesorter(final Long sessionId, int page, int size, int sorting, - String searchString, boolean getNotebookEntries) { - return forumUserDao.getUsersForTablesorter(sessionId, page, size, sorting, searchString, getNotebookEntries, - coreNotebookService); - } - - @Override - public int getCountUsersBySession(Long sessionId, String searchString) { - return forumUserDao.getCountUsersBySession(sessionId, searchString); - } - - @Override - public void createUser(ForumUser forumUser) { - forumUserDao.save(forumUser); - } - - @Override - public ForumToolSession getSessionBySessionId(Long sessionId) { - return forumToolSessionDao.getBySessionId(sessionId); - } - - @Override - public Long getRootTopicId(Long topicId) { - MessageSeq seq = messageSeqDao.getByTopicId(topicId); - if ((seq == null) || (seq.getRootMessage() == null)) { - ForumService.log.error("A sequence information can not be found for topic ID:" + topicId); - return null; - } - return seq.getRootMessage().getUid(); - } - - @Override - public List getAuthoredTopics(Long forumUid) { - List list = messageDao.getTopicsFromAuthor(forumUid); - - TreeMap map = new TreeMap(new DateComparator()); - // get all the topics skipping ones with a tool session (we may be editing in monitor) and sort by create date - Iterator iter = list.iterator(); - while (iter.hasNext()) { - Message topic = (Message) iter.next(); - if (topic.getToolSession() == null) { - map.put(topic.getCreated(), topic); - } - } - return MessageDTO.getMessageDTO(new ArrayList(map.values())); - } - - @Override - public List getSessionsByContentId(Long contentID) { - return forumToolSessionDao.getByContentId(contentID); - } - - @Override - public List getUsersBySessionId(Long sessionID) { - return forumUserDao.getBySessionId(sessionID); - } - - @Override - public List getMessagesByUserUid(Long userId, Long sessionId) { - List list = messageDao.getByUserAndSession(userId, sessionId); - - return MessageDTO.getMessageDTO(list); - } - - @Override - public ForumUser getUser(Long userUid) { - return forumUserDao.getByUid(userUid); - } - - @Override - public void releaseMarksForSession(Long sessionID) { - // udate release mark date for each message. - List list = messageDao.getBySession(sessionID); - Iterator iter = list.iterator(); - ForumToolSession session = forumToolSessionDao.getBySessionId(sessionID); - Forum forum = session.getForum(); - boolean notifyLearnersOnMarkRelease = getEventNotificationService().eventExists(ForumConstants.TOOL_SIGNATURE, - ForumConstants.EVENT_NAME_NOTIFY_LEARNERS_ON_MARK_RELEASE, forum.getContentId()); - Map notificationMessages = null; - Object[] notificationMessageParameters = null; - if (notifyLearnersOnMarkRelease) { - notificationMessages = new TreeMap(); - notificationMessageParameters = new Object[3]; - } - - while (iter.hasNext()) { - Message msg = iter.next(); - ForumReport report = msg.getReport(); - if (report != null) { - report.setDateMarksReleased(new Date()); - if (notifyLearnersOnMarkRelease) { - ForumUser user = msg.getCreatedBy(); - StringBuilder notificationMessage = notificationMessages.get(user.getUserId().intValue()); - if (notificationMessage == null) { - notificationMessage = new StringBuilder(); - } - notificationMessageParameters[0] = msg.getSubject(); - notificationMessageParameters[1] = msg.getUpdated(); - notificationMessageParameters[2] = report.getMark(); - notificationMessage - .append(getLocalisedMessage("event.mark.release.mark", notificationMessageParameters)); - notificationMessages.put(user.getUserId().intValue(), notificationMessage); - } - } - messageDao.saveOrUpdate(msg); - - } - if (notifyLearnersOnMarkRelease) { - notificationMessageParameters = new Object[1]; - for (Integer userID : notificationMessages.keySet()) { - notificationMessageParameters[0] = notificationMessages.get(userID).toString(); - getEventNotificationService().triggerForSingleUser(ForumConstants.TOOL_SIGNATURE, - ForumConstants.EVENT_NAME_NOTIFY_LEARNERS_ON_MARK_RELEASE, forum.getContentId(), userID, - notificationMessageParameters); - - } - } - - List users = getUsersBySessionId(sessionID); - if (users != null) { - for (ForumUser user : users) { - // send marks to gradebook where applicable - sendMarksToGradebook(user, sessionID); - } - } - - // update session to set MarkRelease flag. - session.setMarkReleased(true); - forumToolSessionDao.saveOrUpdate(session); - - } - - @Override - public void finishUserSession(ForumUser currentUser) { - currentUser.setSessionFinished(true); - forumUserDao.save(currentUser); - } - - @Override - public AverageRatingDTO rateMessage(Long messageId, Long userId, Long toolSessionID, float rating) { - ForumUser imageGalleryUser = getUserByUserAndSession(userId, toolSessionID); - MessageRating messageRating = messageRatingDao.getRatingByMessageAndUser(messageId, userId); - Message message = messageDao.getById(messageId); - - //persist MessageRating changes in DB - if (messageRating == null) { // add - messageRating = new MessageRating(); - messageRating.setUser(imageGalleryUser); - messageRating.setMessage(message); - } - messageRating.setRating(rating); - messageRatingDao.saveObject(messageRating); - //to make available new changes be visible in jsp page - return messageRatingDao.getAverageRatingDTOByMessage(messageId); - } - - @Override - public AverageRatingDTO getAverageRatingDTOByMessage(Long messageId) { - return messageRatingDao.getAverageRatingDTOByMessage(messageId); - } - - @Override - public int getNumOfRatingsByUserAndForum(Long userUid, Long forumUid) { - return messageRatingDao.getNumOfRatingsByUserAndForum(userUid, forumUid); - } - - // *************************************************************************************************************** - // Private methods - // *************************************************************************************************************** - /** - * @param map - * @return - */ - private List getSortedMessageDTO(SortedMap map) { - Iterator iter; - MessageSeq msgSeq; - Message message; - List msgDtoList = new ArrayList(); - iter = map.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Entry) iter.next(); - msgSeq = (MessageSeq) entry.getKey(); - message = (Message) entry.getValue(); - msgDtoList.add(makeDTOSetRating(msgSeq, message)); - } - return msgDtoList; - } - - private MessageDTO makeDTOSetRating(MessageSeq msgSeq, Message message) { - MessageDTO dto = MessageDTO.getMessageDTO(message); - dto.setLevel(msgSeq.getMessageLevel()); - //set averageRating - if (message.getForum().isAllowRateMessages()) { - AverageRatingDTO averageRating = getAverageRatingDTOByMessage(message.getUid()); - dto.setAverageRating(averageRating.getRating()); - dto.setNumberOfVotes(averageRating.getNumberOfVotes()); - } - return dto; - } - - /** - * Process an uploaded file. - * - * @param forumForm - * @throws FileNotFoundException - * @throws IOException - * @throws RepositoryCheckedException - * @throws InvalidParameterException - */ - private NodeKey processFile(FormFile file) { - NodeKey node = null; - if ((file != null) && !StringUtils.isEmpty(file.getFileName())) { - String fileName = file.getFileName(); - try { - node = getForumToolContentHandler().uploadFile(file.getInputStream(), fileName, file.getContentType()); - } catch (InvalidParameterException e) { - throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); - } catch (FileNotFoundException e) { - throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); - } catch (RepositoryCheckedException e) { - throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); - } catch (IOException e) { - throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); - } - } - return node; - } - - /** - * This method verifies the credentials of the SubmitFiles Tool and gives it the Ticket to login and - * access the Content Repository. - * - * A valid ticket is needed in order to access the content from the repository. This method would be called evertime - * the tool needs to upload/download files from the content repository. - * - * @return ITicket The ticket for repostory access - * @throws SubmitFilesException - */ - private ITicket getRepositoryLoginTicket() throws ForumException { - ICredentials credentials = new SimpleCredentials(forumToolContentHandler.getRepositoryUser(), - forumToolContentHandler.getRepositoryId()); - try { - ITicket ticket = repositoryService.login(credentials, forumToolContentHandler.getRepositoryWorkspaceName()); - return ticket; - } catch (AccessDeniedException ae) { - throw new ForumException("Access Denied to repository." + ae.getMessage()); - } catch (WorkspaceNotFoundException we) { - throw new ForumException("Workspace not found." + we.getMessage()); - } catch (LoginException e) { - throw new ForumException("Login failed." + e.getMessage()); - } - } - - private Forum getDefaultForum() { - Long defaultForumId = new Long(toolService.getToolDefaultContentIdBySignature(ForumConstants.TOOL_SIGNATURE)); - if (defaultForumId.equals(0L)) { - String error = "Could not retrieve default content id for this tool"; - ForumService.log.error(error); - throw new ForumException(error); - } - Forum defaultForum = getForumByContentId(defaultForumId); - if (defaultForum == null) { - String error = "Could not retrieve default content record for this tool"; - ForumService.log.error(error); - throw new ForumException(error); - } - - return defaultForum; - - } - - @Override - public Long createNotebookEntry(Long sessionId, Integer notebookToolType, String toolSignature, Integer userId, - String entryText) { - return coreNotebookService.createNotebookEntry(sessionId, notebookToolType, toolSignature, userId, "", - entryText); - } - - @Override - public NotebookEntry getEntry(Long sessionId, Integer idType, String signature, Integer userID) { - List list = coreNotebookService.getEntry(sessionId, idType, signature, userID); - if ((list == null) || list.isEmpty()) { - return null; - } else { - return list.get(0); - } - } - - @Override - public void updateEntry(NotebookEntry notebookEntry) { - coreNotebookService.updateEntry(notebookEntry); - } - - @Override - public boolean isGroupedActivity(long toolContentID) { - return toolService.isGroupedActivity(toolContentID); - } - - @Override - public void auditLogStartEditingActivityInMonitor(long toolContentID) { - toolService.auditLogStartEditingActivityInMonitor(toolContentID); - } - - @Override - public String getLearnerContentFolder(Long toolSessionId, Long userId) { - return toolService.getLearnerContentFolder(toolSessionId, userId); - } - - // *************************************************************************************************************** - // ToolContentManager and ToolSessionManager methods - // *************************************************************************************************************** - @Override - public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { - if (toContentId == null) { - throw new ToolException("Failed to create the ForumFiles tool seession"); - } - - Forum fromContent = null; - if (fromContentId != null) { - fromContent = forumDao.getByContentId(fromContentId); - } - if (fromContent == null) { - fromContent = getDefaultForum(); - } - - Forum toContent = Forum.newInstance(fromContent, toContentId); - - // remove session Messages from topics - for (ForumCondition condition : toContent.getConditions()) { - Iterator conditionMessageIter = condition.getTopics().iterator(); - while (conditionMessageIter.hasNext()) { - Message conditionMessage = conditionMessageIter.next(); - if (conditionMessage.getToolSession() != null) { - conditionMessageIter.remove(); - } - } - } - - // save topics in this forum, only save the author created topic!!! and reset its reply number to zero. - Set topics = toContent.getMessages(); - if (topics != null) { - Iterator iter = topics.iterator(); - while (iter.hasNext()) { - Message msg = (Message) iter.next(); - // set this message forum Uid as toContent - if (!msg.getIsAuthored() || (msg.getToolSession() != null)) { - iter.remove(); - continue; - } - msg.setReplyNumber(0); - // msg.setCreated(new Date()); // need to keep the original create date to maintain correct order - msg.setUpdated(new Date()); - msg.setLastReplyDate(new Date()); - msg.setHideFlag(false); - msg.setForum(toContent); - createRootTopic(toContent.getUid(), (ForumToolSession) null, msg); - } - } - forumDao.saveOrUpdate(toContent); - - } - - @Override - public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { - Forum forum = forumDao.getByContentId(toolContentId); - if (forum == null) { - throw new ToolException("No found tool content by given content ID:" + toolContentId); - } - forum.setDefineLater(false); - forum.setContentInUse(false); - } - - @SuppressWarnings("unchecked") - @Override - public void removeToolContent(Long toolContentId) throws ToolException { - Forum forum = forumDao.getByContentId(toolContentId); - if (forum == null) { - ForumService.log.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); - return; - } - - for (ForumToolSession session : (List) forumToolSessionDao.getByContentId(toolContentId)) { - List entries = coreNotebookService.getEntry(session.getSessionId(), - CoreNotebookConstants.NOTEBOOK_TOOL, ForumConstants.TOOL_SIGNATURE); - for (NotebookEntry entry : entries) { - coreNotebookService.deleteEntry(entry); - } - } - forumDao.delete(forum); - } - - @Override - public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { - if (ForumService.log.isDebugEnabled()) { - ForumService.log.debug( - "Hiding or removing Forum messages for user ID " + userId + " and toolContentId " + toolContentId); - } - List sessionList = forumToolSessionDao.getByContentId(toolContentId); - - for (ForumToolSession session : sessionList) { - Long sessionId = session.getSessionId(); - ForumUser user = forumUserDao.getByUserIdAndSessionId(userId.longValue(), sessionId); - if (user != null) { - List messages = messageDao.getByUserAndSession(user.getUid(), sessionId); - Iterator messageIterator = messages.iterator(); - while (messageIterator.hasNext()) { - Message message = messageIterator.next(); - - if (userOwnMessageTree(message, user.getUid())) { - messageSeqDao.deleteByTopicId(message.getUid()); - Timestamp timestamp = timestampDao.getTimestamp(message.getUid(), user.getUid()); - if (timestamp != null) { - timestampDao.delete(timestamp); - } - messageDao.delete(message.getUid()); - messageIterator.remove(); - } else { - message.setHideFlag(true); - messageDao.update(message); - } - } - - NotebookEntry entry = getEntry(session.getSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, - ForumConstants.TOOL_SIGNATURE, userId); - if (entry != null) { - // hopefully it understands NotebookEntries - activityDAO.delete(entry); - } - - user.setSessionFinished(false); - forumUserDao.save(user); - - gradebookService.updateActivityMark(null, null, userId, session.getSessionId(), false); - } - } - } - - @SuppressWarnings("unchecked") - private boolean userOwnMessageTree(Message message, Long userUid) { - if (!message.getCreatedBy().getUid().equals(userUid)) { - return false; - } - List children = messageDao.getChildrenTopics(message.getUid()); - for (Message child : children) { - if (!userOwnMessageTree(child, userUid)) { - return false; - } - } - - return true; - } - - @Override - public void exportToolContent(Long toolContentId, String rootPath) throws DataMissingException, ToolException { - Forum toolContentObj = forumDao.getByContentId(toolContentId); - if (toolContentObj == null) { - toolContentObj = getDefaultForum(); - } - if (toolContentObj == null) { - throw new DataMissingException("Unable to find default content for the forum tool"); - } - - // set ResourceToolContentHandler as null to avoid copy file node in repository again. - toolContentObj = Forum.newInstance(toolContentObj, toolContentId); - toolContentObj.setCreatedBy(null); - Set items = toolContentObj.getMessages(); - Set authorItems = new HashSet(); - for (Message item : items) { - if (item.getIsAuthored() && (item.getToolSession() == null)) { - authorItems.add(item); - item.setCreatedBy(null); - item.setModifiedBy(null); - item.setForum(null); - item.setReport(null); - item.setReplyNumber(0); - item.setParent(null); - item.setSessionClones(null); - } - } - toolContentObj.setMessages(authorItems); - try { - exportContentService.registerFileClassForExport(Attachment.class.getName(), "fileUuid", "fileVersionId"); - exportContentService.exportToolContent(toolContentId, toolContentObj, forumToolContentHandler, rootPath); - } catch (ExportToolContentException e) { - throw new ToolException(e); - } - } - - @Override - public void importToolContent(Long toolContentId, Integer newUserUid, String toolContentPath, String fromVersion, - String toVersion) throws ToolException { - - try { - // register version filter class - exportContentService.registerImportVersionFilterClass(ForumImportContentVersionFilter.class); - - exportContentService.registerFileClassForImport(Attachment.class.getName(), "fileUuid", "fileVersionId", - "fileName", "fileType", null); - - Object toolPOJO = exportContentService.importToolContent(toolContentPath, forumToolContentHandler, - fromVersion, toVersion); - if (!(toolPOJO instanceof Forum)) { - throw new ImportToolContentException( - "Import Forum tool content failed. Deserialized object is " + toolPOJO); - } - Forum toolContentObj = (Forum) toolPOJO; - - // reset it to new toolContentId - toolContentObj.setContentId(toolContentId); - ForumUser user = forumUserDao.getByUserId(new Long(newUserUid.longValue())); - if (user == null) { - user = new ForumUser(); - UserDTO sysUser = ((User) userManagementService.findById(User.class, newUserUid)).getUserDTO(); - user.setFirstName(sysUser.getFirstName()); - user.setLastName(sysUser.getLastName()); - user.setLoginName(sysUser.getLogin()); - user.setUserId(new Long(newUserUid.longValue())); - this.createUser(user); - } - toolContentObj.setCreatedBy(user); - // save forum first - forumDao.saveOrUpdate(toolContentObj); - - // save all authoring message one by one. - // reset all resourceItem createBy user - Set items = toolContentObj.getMessages(); - int sequenceId = 1; - for (Message item : items) { - item.setCreatedBy(user); - item.setIsAuthored(true); - item.setForum(toolContentObj); - item.setSessionClones(new HashSet()); - // very old LDs did not have sequence IDs in Message and the default value is 0 - if (item.getSequenceId() == 0) { - item.setSequenceId(sequenceId++); - } - createRootTopic(toolContentObj.getUid(), (ForumToolSession) null, item); - } - } catch (ImportToolContentException e) { - throw new ToolException(e); - } - } - - @Override - public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) - throws ToolException { - Forum forum = getForumByContentId(toolContentId); - if (forum == null) { - forum = getDefaultForum(); - } - return getForumOutputFactory().getToolOutputDefinitions(forum, definitionType); - } - - @Override - public String getToolContentTitle(Long toolContentId) { - return getForumByContentId(toolContentId).getTitle(); - } - - @Override - public boolean isContentEdited(Long toolContentId) { - return getForumByContentId(toolContentId).isDefineLater(); - } - - @Override - public boolean isReadOnly(Long toolContentId) { - for (ForumToolSession session : (List) forumToolSessionDao.getByContentId(toolContentId)) { - for (ForumUser user : (List) forumUserDao.getBySessionId(session.getSessionId())) { - // we don't remove users in removeLearnerContent() - // we just remove or hide messages - if (!messageDao.getByUserAndSession(user.getUid(), session.getSessionId()).isEmpty()) { - return true; - } - } - } - - return false; - } - - @Override - public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentId) throws ToolException { - ForumToolSession session = new ForumToolSession(); - session.setSessionId(toolSessionId); - session.setSessionName(toolSessionName); - Forum forum = forumDao.getByContentId(toolContentId); - session.setForum(forum); - - // also clone author created topic from this forum tool content!!! - // this can avoid topic record information conflict when multiple sessions are against same tool content - // for example, the reply number maybe various for different sessions. - ForumService.log.debug("Clone tool content [" + forum.getContentId() + "] topics for session [" - + session.getSessionId() + "]"); - Set contentTopics = forum.getMessages(); - if ((contentTopics != null) && (contentTopics.size() > 0)) { - for (Message msg : contentTopics) { - if (msg.getIsAuthored() && (msg.getToolSession() == null)) { - Message newMsg = Message.newInstance(msg); - msg.getSessionClones().add(newMsg); - createRootTopic(forum.getContentId(), session, newMsg); - } - } - } - session.setStatus(ForumConstants.STATUS_CONTENT_COPYED); - - forumToolSessionDao.saveOrUpdate(session); - if (ForumService.log.isDebugEnabled()) { - ForumService.log.debug("tool session [" + session.getSessionId() + "] created."); - } - } - - @Override - public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { - if (toolSessionId == null) { - ForumService.log.error("Fail to leave tool Session based on null tool session id."); - throw new ToolException("Fail to remove tool Session based on null tool session id."); - } - if (learnerId == null) { - ForumService.log.error("Fail to leave tool Session based on null learner."); - throw new ToolException("Fail to remove tool Session based on null learner."); - } - - ForumToolSession session = forumToolSessionDao.getBySessionId(toolSessionId); - if (session != null) { - forumToolSessionDao.saveOrUpdate(session); - } else { - ForumService.log.error("Fail to leave tool Session.Could not find submit file " - + "session by given session id: " + toolSessionId); - throw new DataMissingException("Fail to leave tool Session." - + "Could not find submit file session by given session id: " + toolSessionId); - } - return learnerService.completeToolSession(toolSessionId, learnerId); - } - - @Override - public ToolSessionExportOutputData exportToolSession(Long toolSessionId) - throws DataMissingException, ToolException { - return null; - } - - @Override - public ToolSessionExportOutputData exportToolSession(List toolSessionIds) - throws DataMissingException, ToolException { - return null; - } - - @Override - public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { - forumToolSessionDao.delete(toolSessionId); - } - - @Override - public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { - - return forumOutputFactory.getToolOutput(names, this, toolSessionId, learnerId); - - } - - @Override - public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { - return forumOutputFactory.getToolOutput(name, this, toolSessionId, learnerId); - } - - @Override - public List getToolOutputs(String name, Long toolContentId) { - return new ArrayList(); - } - - @Override - public void forceCompleteUser(Long toolSessionId, User user) { - //no actions required - } - - @Override - public Forum getDefaultContent(Long contentID) { - if (contentID == null) { - String error = "Could not retrieve default content id for Forum tool"; - ForumService.log.error(error); - throw new ForumException(error); - } - - Forum defaultContent = getDefaultForum(); - // get default content by given ID. - Forum content = Forum.newInstance(defaultContent, contentID); - - return content; - } - - @Override - public List getAllTopicsFromSession(Long sessionID) { - return MessageDTO.getMessageDTO(messageDao.getBySession(sessionID)); - } - - /** - * Sends marks straight to gradebook from a forum report - * - * @param user - * @param toolSessionID - */ - public void sendMarksToGradebook(ForumUser user, Long toolSessionID) { - - List messages = getMessagesByUserUid(user.getUid(), toolSessionID); - if (messages != null) { - Float totalMark = null; - for (MessageDTO message : messages) { - if (totalMark == null) { - totalMark = message.getMark(); - } else if (message.getMark() != null) { - totalMark += message.getMark(); - } - } - if (totalMark != null) { - Double mark = new Double(totalMark); - gradebookService.updateActivityMark(mark, null, user.getUserId().intValue(), toolSessionID, false); - } - } - - } - - // *************************************************************************************************************** - // Get / Set methods - // *************************************************************************************************************** - public ILamsToolService getToolService() { - return toolService; - } - - public void setToolService(ILamsToolService toolService) { - this.toolService = toolService; - } - - public IAttachmentDAO getAttachmentDao() { - return attachmentDao; - } - - public void setAttachmentDao(IAttachmentDAO attachmentDao) { - this.attachmentDao = attachmentDao; - } - - public IForumDAO getForumDao() { - return forumDao; - } - - public void setForumDao(IForumDAO forumDao) { - this.forumDao = forumDao; - } - - public ITimestampDAO getTimestampDao() { - return timestampDao; - } - - public void setTimestampDao(ITimestampDAO timestampDao) { - this.timestampDao = timestampDao; - } - - public IMessageDAO getMessageDao() { - return messageDao; - } - - public void setMessageDao(IMessageDAO messageDao) { - this.messageDao = messageDao; - } - - public IMessageSeqDAO getMessageSeqDao() { - return messageSeqDao; - } - - public void setMessageSeqDao(IMessageSeqDAO messageSeqDao) { - this.messageSeqDao = messageSeqDao; - } - - public IMessageRatingDAO getMessageRatingDao() { - return messageRatingDao; - } - - public void setMessageRatingDao(IMessageRatingDAO messageRatingDao) { - this.messageRatingDao = messageRatingDao; - } - - public IForumToolSessionDAO getForumToolSessionDao() { - return forumToolSessionDao; - } - - public void setForumToolSessionDao(IForumToolSessionDAO forumToolSessionDao) { - this.forumToolSessionDao = forumToolSessionDao; - } - - public IForumUserDAO getForumUserDao() { - return forumUserDao; - } - - public void setForumUserDao(IForumUserDAO forumUserDao) { - this.forumUserDao = forumUserDao; - } - - public IRepositoryService getRepositoryService() { - return repositoryService; - } - - public void setRepositoryService(IRepositoryService repositoryService) { - this.repositoryService = repositoryService; - } - - public ForumToolContentHandler getForumToolContentHandler() { - return forumToolContentHandler; - } - - public void setForumToolContentHandler(ForumToolContentHandler toolContentHandler) { - forumToolContentHandler = toolContentHandler; - } - - public ILearnerService getLearnerService() { - return learnerService; - } - - public void setLearnerService(ILearnerService learnerService) { - this.learnerService = learnerService; - } - - public IExportToolContentService getExportContentService() { - return exportContentService; - } - - public void setExportContentService(IExportToolContentService exportContentService) { - this.exportContentService = exportContentService; - } - - public IUserManagementService getUserManagementService() { - return userManagementService; - } - - public void setUserManagementService(IUserManagementService userManagementService) { - this.userManagementService = userManagementService; - } - - public ICoreNotebookService getCoreNotebookService() { - return coreNotebookService; - } - - public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { - this.coreNotebookService = coreNotebookService; - } - - @Override - public IEventNotificationService getEventNotificationService() { - return eventNotificationService; - } - - public void setEventNotificationService(IEventNotificationService eventNotificationService) { - this.eventNotificationService = eventNotificationService; - } - - @Override - public String getLocalisedMessage(String key, Object[] args) { - return messageService.getMessage(key, args); - } - - public void setGradebookService(IGradebookService gradebookService) { - this.gradebookService = gradebookService; - } - - public void setLessonService(ILessonService lessonService) { - this.lessonService = lessonService; - } - - public void setActivityDAO(IActivityDAO activityDAO) { - this.activityDAO = activityDAO; - } - - /** - * {@inheritDoc} - */ - @Override - public String createTextSearchConditionName(Collection existingConditions) { - String uniqueNumber = null; - do { - uniqueNumber = String.valueOf(Math.abs(generator.nextInt())); - for (ForumCondition condition : existingConditions) { - String[] splittedName = getForumOutputFactory().splitConditionName(condition.getName()); - if (uniqueNumber.equals(splittedName[1])) { - uniqueNumber = null; - } - } - } while (uniqueNumber == null); - return getForumOutputFactory().buildTopicDatesToAnswersConditionName(uniqueNumber); - } - - /** - * Get number of new postings. - * - * @param messageId - * @param userId - * @return - */ - @Override - public int getNewMessagesNum(Message message, Long userId) { - Timestamp timestamp = timestampDao.getTimestamp(message.getUid(), userId); - if (timestamp == null) { - // if first time - show all postings as new, including root message - return message.getReplyNumber() + 1; - } else { - return messageSeqDao.getNumOfPostsNewerThan(message.getUid(), timestamp.getTimestamp()); - } - } - - @Override - public void saveTimestamp(Long rootTopicId, ForumUser forumUser) { - Timestamp timestamp = timestampDao.getTimestamp(rootTopicId, forumUser.getUid()); - if (timestamp != null) { - timestamp.setTimestamp(new Date()); - } else { - timestamp = new Timestamp(); - timestamp.setMessage(getMessage(rootTopicId)); - timestamp.setTimestamp(new Date()); - timestamp.setForumUser(forumUser); - } - timestampDao.saveOrUpdate(timestamp); - } - - @Override - public void sendNotificationsOnNewPosting(Long forumId, Long sessionId, Message message) { - Forum forum = getForum(forumId); - ForumUser postAuthor = message.getCreatedBy(); - String fullName = postAuthor.getLastName() + " " + postAuthor.getFirstName(); - ToolSession toolSession = toolService.getToolSession(sessionId); - Long activityId = toolSession.getToolActivity().getActivityId(); - ToolActivity activity = (ToolActivity) activityDAO.getActivityByActivityId(activityId, ToolActivity.class); - boolean isHtmlFormat = forum.isAllowRichEditor(); - - if (forum.isNotifyLearnersOnForumPosting()) { - List learners = lessonService.getLearnersAttemptedOrCompletedActivity(activity); - if ((learners != null) && !learners.isEmpty()) { - ArrayList learnerIds = new ArrayList(); - for (User learner : learners) { - learnerIds.add(learner.getUserId()); - } - - getEventNotificationService().sendMessage(null, learnerIds.toArray(new Integer[0]), - IEventNotificationService.DELIVERY_METHOD_MAIL, - getLocalisedMessage("event.newposting.subject", new Object[] { forum.getTitle() }), - getLocalisedMessage("event.newposting.body", new Object[] { fullName, message.getBody() }), - isHtmlFormat); - } - } - - if (forum.isNotifyTeachersOnForumPosting()) { - String emailMessage = getLocalisedMessage("event.newposting.body", - new Object[] { fullName, message.getBody() }); - getEventNotificationService().notifyLessonMonitors(sessionId, emailMessage, isHtmlFormat); - } - } - - @Override - public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { - return getForumOutputFactory().getSupportedDefinitionClasses(definitionType); - } - - @Override - public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { - ForumUser learner = getUserByUserAndSession(learnerId, toolSessionId); - if (learner == null) { - return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); - } - - Object[] dates = messageDao.getDateRangeOfMessages(learner.getUid()); - if (learner.isSessionFinished()) - return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, (Date)dates[0], (Date)dates[1]); - else - return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED,(Date) dates[0], null); - } - - - // ****************** REST methods ************************* - - /** - * Used by the Rest calls to create content. Mandatory fields in toolContentJSON: title, instructions, topics. - * Topics must contain a JSONArray of JSONObject objects, which have the following mandatory fields: subject, body - * There will usually be at least one topic object in the Topics array but the array may be of zero length. - */ - @Override - public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) - throws JSONException { - - Forum forum = new Forum(); - Date updateDate = new Date(); - forum.setCreated(updateDate); - forum.setUpdated(updateDate); - - forum.setContentId(toolContentID); - forum.setTitle(toolContentJSON.getString(RestTags.TITLE)); - forum.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); - - forum.setAllowAnonym(JsonUtil.opt(toolContentJSON, "allowAnonym", Boolean.FALSE)); - forum.setAllowEdit(JsonUtil.opt(toolContentJSON, "allowEdit", Boolean.TRUE)); // defaults to true in the default - // entry in the db - forum.setAllowNewTopic(JsonUtil.opt(toolContentJSON, "allowNewTopic", Boolean.TRUE)); // defaults to true in the - // default entry in the db - forum.setAllowRateMessages(JsonUtil.opt(toolContentJSON, "allowRateMessages", Boolean.FALSE)); - forum.setAllowRichEditor(JsonUtil.opt(toolContentJSON, RestTags.ALLOW_RICH_TEXT_EDITOR, Boolean.FALSE)); - forum.setAllowUpload(JsonUtil.opt(toolContentJSON, "allowUpload", Boolean.FALSE)); - forum.setContentInUse(false); - forum.setDefineLater(false); - forum.setLimitedMaxCharacters(JsonUtil.opt(toolContentJSON, "limitedMaxCharacters", Boolean.TRUE)); - forum.setLimitedMinCharacters(JsonUtil.opt(toolContentJSON, "limitedMinCharacters", Boolean.FALSE)); - forum.setLockWhenFinished(JsonUtil.opt(toolContentJSON, "lockWhenFinished", Boolean.FALSE)); - forum.setMaxCharacters(JsonUtil.opt(toolContentJSON, "maxCharacters", 5000)); // defaults to 5000 chars in the - // default entry in the db. - forum.setMaximumRate(JsonUtil.opt(toolContentJSON, "maximumRate", 0)); - forum.setMaximumReply(JsonUtil.opt(toolContentJSON, "maximumReply", 0)); - forum.setMinCharacters(JsonUtil.opt(toolContentJSON, "minCharacters", 0)); - forum.setMinimumRate(JsonUtil.opt(toolContentJSON, "minimumRate", 0)); - forum.setMinimumReply(JsonUtil.opt(toolContentJSON, "minimumReply", 0)); - forum.setNotifyLearnersOnForumPosting( - JsonUtil.opt(toolContentJSON, "notifyLearnersOnForumPosting", Boolean.FALSE)); - forum.setNotifyLearnersOnMarkRelease( - JsonUtil.opt(toolContentJSON, "notifyLearnersOnMarkRelease", Boolean.FALSE)); - forum.setNotifyTeachersOnForumPosting( - JsonUtil.opt(toolContentJSON, "notifyTeachersOnForumPosting", Boolean.FALSE)); - forum.setReflectInstructions((String) JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, null)); - forum.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); - // submissionDeadline is set in monitoring - - // *******************************Handle user******************* - // Code taken from AuthoringAction TODO - // String contentFolderID = (String) sessionMap.get(AttributeNames.PARAM_CONTENT_FOLDER_ID); - // check whether it is sysadmin:LDEV-906 - // if (!StringUtils.equals(contentFolderID, "-1")) { - // try to get form system session - // HttpSession ss = SessionManager.getSession(); - // get back login user DTO - // UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); - ForumUser forumUser = getUserByID(userID.longValue()); - if (forumUser == null) { - forumUser = new ForumUser(userID.longValue(), toolContentJSON.getString("firstName"), - toolContentJSON.getString("lastName"), toolContentJSON.getString("loginName")); - getForumUserDao().save(forumUser); - } - forum.setCreatedBy(forumUser); - - updateForum(forum); - - // **************************** Handle topic ********************* - JSONArray topics = toolContentJSON.getJSONArray("topics"); - for (int i = 0; i < topics.length(); i++) { - JSONObject msgData = (JSONObject) topics.get(i); - Message newMsg = new Message(); - // newMsg.setAttachments(attachments); TODO - newMsg.setCreatedBy(forumUser); - newMsg.setCreated(updateDate); - newMsg.setModifiedBy(null); - newMsg.setUpdated(updateDate); - - newMsg.setSubject(msgData.getString("subject")); - newMsg.setBody(msgData.getString("body")); - newMsg.setForum(forum); - newMsg.setHideFlag(false); - // newMsg.setIsAnonymous(false); Does not appear on authoring interface - newMsg.setIsAuthored(true); - newMsg.setLastReplyDate(updateDate); - newMsg.setParent(null); - newMsg.setReplyNumber(0); - newMsg.setReport(null); - newMsg.setSequenceId(i); - // newMsg.setSessionClones(sessionClones); Used for updating in monitoring - newMsg.setToolSession(null); - createRootTopic(forum.getUid(), (ForumToolSession) null, newMsg); - } - - // ******************************* - // TODO - investigate - //forum.setConditions(conditions); - // message attachments - } +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.forum.service; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.upload.FormFile; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.contentrepository.AccessDeniedException; +import org.lamsfoundation.lams.contentrepository.ICredentials; +import org.lamsfoundation.lams.contentrepository.ITicket; +import org.lamsfoundation.lams.contentrepository.InvalidParameterException; +import org.lamsfoundation.lams.contentrepository.LoginException; +import org.lamsfoundation.lams.contentrepository.NodeKey; +import org.lamsfoundation.lams.contentrepository.RepositoryCheckedException; +import org.lamsfoundation.lams.contentrepository.WorkspaceNotFoundException; +import org.lamsfoundation.lams.contentrepository.service.IRepositoryService; +import org.lamsfoundation.lams.contentrepository.service.SimpleCredentials; +import org.lamsfoundation.lams.events.IEventNotificationService; +import org.lamsfoundation.lams.gradebook.service.IGradebookService; +import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; +import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; +import org.lamsfoundation.lams.tool.ToolCompletionStatus; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.ToolOutput; +import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSession; +import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; +import org.lamsfoundation.lams.tool.ToolSessionManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.forum.dto.AverageRatingDTO; +import org.lamsfoundation.lams.tool.forum.dto.MessageDTO; +import org.lamsfoundation.lams.tool.forum.persistence.Attachment; +import org.lamsfoundation.lams.tool.forum.persistence.Forum; +import org.lamsfoundation.lams.tool.forum.persistence.ForumCondition; +import org.lamsfoundation.lams.tool.forum.persistence.ForumConfigItem; +import org.lamsfoundation.lams.tool.forum.persistence.ForumException; +import org.lamsfoundation.lams.tool.forum.persistence.ForumReport; +import org.lamsfoundation.lams.tool.forum.persistence.ForumToolSession; +import org.lamsfoundation.lams.tool.forum.persistence.ForumUser; +import org.lamsfoundation.lams.tool.forum.persistence.IAttachmentDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IForumDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IForumToolSessionDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IForumUserDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IMessageDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IMessageRatingDAO; +import org.lamsfoundation.lams.tool.forum.persistence.IMessageSeqDAO; +import org.lamsfoundation.lams.tool.forum.persistence.ITimestampDAO; +import org.lamsfoundation.lams.tool.forum.persistence.Message; +import org.lamsfoundation.lams.tool.forum.persistence.MessageRating; +import org.lamsfoundation.lams.tool.forum.persistence.MessageSeq; +import org.lamsfoundation.lams.tool.forum.persistence.PersistenceException; +import org.lamsfoundation.lams.tool.forum.persistence.Timestamp; +import org.lamsfoundation.lams.tool.forum.util.DateComparator; +import org.lamsfoundation.lams.tool.forum.util.ForumConstants; +import org.lamsfoundation.lams.tool.forum.util.ForumToolContentHandler; +import org.lamsfoundation.lams.tool.forum.util.MessageDtoComparator; +import org.lamsfoundation.lams.tool.forum.util.TopicComparator; +import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.JsonUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.audit.IAuditService; + +/** + * + * @author Steve.Ni + * + * @version $Revision$ + */ +public class ForumService implements IForumService, ToolContentManager, ToolSessionManager, ToolRestManager { + private static final Logger log = Logger.getLogger(ForumService.class); + + // DAO variables + private IForumDAO forumDao; + + private IAttachmentDAO attachmentDao; + + private IMessageDAO messageDao; + + private ITimestampDAO timestampDao; + + private IMessageSeqDAO messageSeqDao; + + private IMessageRatingDAO messageRatingDao; + + private IForumUserDAO forumUserDao; + + private IForumToolSessionDAO forumToolSessionDao; + + // system level handler and service + private ILamsToolService toolService; + + private ForumToolContentHandler forumToolContentHandler; + + private IRepositoryService repositoryService; + + private ILearnerService learnerService; + + private IAuditService auditService; + + private MessageService messageService; + + private IExportToolContentService exportContentService; + + private IUserManagementService userManagementService; + + private ICoreNotebookService coreNotebookService; + + private ForumOutputFactory forumOutputFactory; + + private IGradebookService gradebookService; + + private IEventNotificationService eventNotificationService; + + private ILessonService lessonService; + + private IActivityDAO activityDAO; + + private Random generator = new Random(); + + // --------------------------------------------------------------------- + // Inversion of Control Methods - Method injection + // --------------------------------------------------------------------- + public void setAuditService(IAuditService auditService) { + this.auditService = auditService; + } + + @Override + public IAuditService getAuditService() { + return auditService; + } + + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + + public ForumOutputFactory getForumOutputFactory() { + return forumOutputFactory; + } + + public void setForumOutputFactory(ForumOutputFactory forumOutputFactory) { + this.forumOutputFactory = forumOutputFactory; + } + + @Override + public Forum updateForum(Forum forum) throws PersistenceException { + forumDao.saveOrUpdate(forum); + return forum; + } + + @Override + public Forum getForum(Long forumUid) throws PersistenceException { + return forumDao.getById(forumUid); + } + + @Override + public Forum getForumByContentId(Long contentID) throws PersistenceException { + return forumDao.getByContentId(contentID); + } + + public void deleteForumAttachment(Long attachmentId) throws PersistenceException { + Attachment attachment = attachmentDao.getById(attachmentId); + attachmentDao.delete(attachment); + } + + @Override + public Message createRootTopic(Long forumId, Long sessionId, Message message) throws PersistenceException { + return createRootTopic(forumId, getSessionBySessionId(sessionId), message); + } + + public Message createRootTopic(Long forumId, ForumToolSession session, Message message) + throws PersistenceException { + // get Forum and ForumToolSesion + if (message.getForum() == null) { + Forum forum = forumDao.getById(forumId); + message.setForum(forum); + } + // if topic created by author, session will be null. + if (session != null) { + message.setToolSession(session); + } + + if (message.getUid() == null) { + // update message sequence + MessageSeq msgSeq = new MessageSeq(); + msgSeq.setMessage(message); + msgSeq.setMessageLevel((short) 0); + // set itself as root + msgSeq.setRootMessage(message); + messageSeqDao.save(msgSeq); + } + + // if this message had any cloned objects, they also need to be changed. + // this will only happen if an authored topic is changed via monitoring + if (message.getSessionClones().size() > 0) { + Iterator iter = message.getSessionClones().iterator(); + while (iter.hasNext()) { + Message clone = (Message) iter.next(); + message.updateClone(clone); + clone.updateModificationData(); + messageDao.saveOrUpdate(clone); + } + } + + // create message in database + message.updateModificationData(); + messageDao.saveOrUpdate(message); + + return message; + } + + @Override + public Message updateTopic(Message message) throws PersistenceException { + + // update message + message.updateModificationData(); + messageDao.saveOrUpdate(message); + + // udate root message's lastReplyDate + MessageSeq msgSeq = messageSeqDao.getByTopicId(message.getUid()); + Message root = msgSeq.getRootMessage(); + root.setLastReplyDate(new Date()); + messageDao.saveOrUpdate(root); + + return message; + } + + @Override + public List getMessageAsDTO(Long messageUid) throws PersistenceException { + + MessageSeq msgSeq = messageSeqDao.getByMessageId(messageUid); + List msgDtoList = new ArrayList<>(); + msgDtoList.add(makeDTOSetRating(msgSeq, msgSeq.getMessage())); + return msgDtoList; + } + + @Override + public void updateContainedReport(Message message) { + messageDao.saveOrUpdate(message); + } + + @Override + public Message updateMessageHideFlag(Long messageId, boolean hideFlag) { + + Message message = getMessage(messageId); + if (message != null) { + Long userId = 0L; + String loginName = "Default"; + if (message.getCreatedBy() != null) { + userId = message.getCreatedBy().getUserId(); + loginName = message.getCreatedBy().getLoginName(); + } + if (hideFlag) { + auditService.logHideEntry(ForumConstants.TOOL_SIGNATURE, userId, loginName, message.toString()); + } else { + auditService.logShowEntry(ForumConstants.TOOL_SIGNATURE, userId, loginName, message.toString()); + } + + message.setHideFlag(hideFlag); + + // update message + messageDao.update(message); + } + return message; + } + + private Message getMessageForUpdate(Long messageUid) throws PersistenceException { + return messageDao.getByIdForUpdate(messageUid); + } + + @Override + public Message getMessage(Long messageUid) throws PersistenceException { + return messageDao.getById(messageUid); + } + + @Override + public void deleteTopic(Long topicUid) throws PersistenceException { + Message topic = messageDao.getById(topicUid); + + // cascade delete children topic by recursive + List children = messageDao.getChildrenTopics(topicUid); + if (children != null) { + Iterator iter = children.iterator(); + while (iter.hasNext()) { + Message msg = (Message) iter.next(); + this.deleteTopic(msg.getUid()); + } + } + + // recursively delete clones + for (Message clone : (Set) topic.getSessionClones()) { + this.deleteTopic(clone.getUid()); + } + + messageSeqDao.deleteByTopicId(topicUid); + messageDao.delete(topicUid); + } + + @Override + public void deleteCondition(ForumCondition condition) throws PersistenceException { + forumDao.deleteCondition(condition); + } + + @Override + public MessageSeq replyTopic(Long parentId, Long sessionId, Message replyMessage) throws PersistenceException { + // set parent + Message parent = this.getMessageForUpdate(parentId); + replyMessage.setParent(parent); + replyMessage.setForum(parent.getForum()); + // parent sessionID maybe empty if created by author role. So given sessionId is exactly value. + ForumToolSession session = getSessionBySessionId(sessionId); + replyMessage.setToolSession(session); + replyMessage.updateModificationData(); + messageDao.saveOrUpdate(replyMessage); + + // get root topic and create record in MessageSeq table + MessageSeq parentSeq = messageSeqDao.getByTopicId(parent.getUid()); + if (parentSeq == null) { + ForumService.log + .error("Message Sequence table is broken becuase topic " + parent + " can not get Sequence Record"); + } + Message root = parentSeq.getRootMessage(); + MessageSeq msgSeq = new MessageSeq(); + msgSeq.setMessage(replyMessage); + msgSeq.setMessageLevel((short) (parentSeq.getMessageLevel() + 1)); + msgSeq.setRootMessage(root); + // look back up through the parents to find the thread top - will be level 1 + if (msgSeq.getMessageLevel() == 1) { + msgSeq.setThreadMessage(replyMessage); + } else { + MessageSeq threadSeq = parentSeq; + while (threadSeq.getMessageLevel() > 1) { + threadSeq = messageSeqDao.getByTopicId(threadSeq.getMessage().getParent().getUid()); + } + msgSeq.setThreadMessage(threadSeq.getMessage()); + } + messageSeqDao.save(msgSeq); + + // update last reply date for root message + root.setLastReplyDate(new Date()); + // update reply message number for root + root.setReplyNumber(root.getReplyNumber() + 1); + messageDao.saveOrUpdate(root); + + return msgSeq; + } + + @Override + public Attachment uploadAttachment(FormFile uploadFile) throws PersistenceException { + if ((uploadFile == null) || StringUtils.isEmpty(uploadFile.getFileName())) { + throw new ForumException("Could not find upload file: " + uploadFile); + } + + NodeKey nodeKey = processFile(uploadFile); + Attachment file = new Attachment(); + file.setFileUuid(nodeKey.getUuid()); + file.setFileVersionId(nodeKey.getVersion()); + file.setFileName(uploadFile.getFileName()); + + return file; + } + + @Override + public List getTopicThread(Long rootTopicId) { + List unsortedThread = messageSeqDao.getCompleteTopic(rootTopicId); + Iterator iter = unsortedThread.iterator(); + MessageSeq msgSeq; + SortedMap map = new TreeMap<>(new TopicComparator()); + while (iter.hasNext()) { + msgSeq = (MessageSeq) iter.next(); + map.put(msgSeq, msgSeq.getMessage()); + } + return getSortedMessageDTO(map); + + } + + @Override + public List getTopicThread(Long rootTopicId, Long afterSequenceId, Long pagingSize) { + + long lastThreadMessageUid = afterSequenceId != null ? afterSequenceId.longValue() : 0L; + long usePagingSize = pagingSize != null ? pagingSize.longValue() : ForumConstants.DEFAULT_PAGE_SIZE; + SortedMap map = new TreeMap<>(new TopicComparator()); + + // first time through we need to include the top topic message (level 0) + if (lastThreadMessageUid == 0) { + MessageSeq msgSeq = messageSeqDao.getByTopicId(rootTopicId); + map.put(msgSeq, msgSeq.getMessage()); + } + + long count = 0; + boolean foundEnough = false; + do { + + List msgSeqs = messageSeqDao.getNextThreadByThreadId(rootTopicId, lastThreadMessageUid); + if (msgSeqs.size() == 0) { + // no more to come from db + foundEnough = true; + } else { + + Iterator iter = msgSeqs.iterator(); + while (iter.hasNext()) { + MessageSeq msgSeq = (MessageSeq) iter.next(); + if (msgSeq.getMessageLevel() == 1) { + lastThreadMessageUid = msgSeq.getMessage().getUid().longValue(); + } + map.put(msgSeq, msgSeq.getMessage()); + count++; + } + if ((usePagingSize >= 0) && (count >= usePagingSize)) { + foundEnough = true; + } + } + } while (!foundEnough); + + return getSortedMessageDTO(map); + } + + @Override + public List getThread(Long threadId) { + List msgSeqs = messageSeqDao.getThreadByThreadId(threadId); + SortedMap map = new TreeMap<>(new TopicComparator()); + Iterator iter = msgSeqs.iterator(); + while (iter.hasNext()) { + MessageSeq msgSeq = (MessageSeq) iter.next(); + map.put(msgSeq, msgSeq.getMessage()); + } + ; + return getSortedMessageDTO(map); + } + + @Override + public List getRootTopics(Long sessionId) { + ForumToolSession session = getSessionBySessionId(sessionId); + if ((session == null) || (session.getForum() == null)) { + ForumService.log.error("Failed on getting session by given sessionID:" + sessionId); + throw new ForumException("Failed on getting session by given sessionID:" + sessionId); + } + + List topicsBySession = messageDao.getRootTopics(sessionId); + List messageDTOs = MessageDTO.getMessageDTO(topicsBySession); + + // sort by sequence id + Set topicSet = new TreeSet<>(new MessageDtoComparator()); + topicSet.addAll(messageDTOs); + + topicsBySession.clear(); + topicsBySession.addAll(topicSet); + return topicsBySession; + } + + @Override + public int getTopicsNum(Long userID, Long sessionId) { + return messageDao.getTopicsNum(userID, sessionId); + } + + @Override + public int getNumOfPostsByTopic(Long userId, Long topicId) { + return messageSeqDao.getNumOfPostsByTopic(userId, topicId); + } + + @Override + public ForumUser getUserByID(Long userId) { + return forumUserDao.getByUserId(userId); + } + + @Override + public ForumUser getUserByUserAndSession(Long userId, Long sessionId) { + return forumUserDao.getByUserIdAndSessionId(userId, sessionId); + } + + @Override + public List getUsersForTablesorter(final Long sessionId, int page, int size, int sorting, + String searchString, boolean getNotebookEntries) { + return forumUserDao.getUsersForTablesorter(sessionId, page, size, sorting, searchString, getNotebookEntries, + coreNotebookService); + } + + @Override + public int getCountUsersBySession(Long sessionId, String searchString) { + return forumUserDao.getCountUsersBySession(sessionId, searchString); + } + + @Override + public void createUser(ForumUser forumUser) { + forumUserDao.save(forumUser); + } + + @Override + public ForumToolSession getSessionBySessionId(Long sessionId) { + return forumToolSessionDao.getBySessionId(sessionId); + } + + @Override + public Long getRootTopicId(Long topicId) { + MessageSeq seq = messageSeqDao.getByTopicId(topicId); + if ((seq == null) || (seq.getRootMessage() == null)) { + ForumService.log.error("A sequence information can not be found for topic ID:" + topicId); + return null; + } + return seq.getRootMessage().getUid(); + } + + @Override + public List getAuthoredTopics(Long forumUid) { + List list = messageDao.getTopicsFromAuthor(forumUid); + + TreeMap map = new TreeMap<>(new DateComparator()); + // get all the topics skipping ones with a tool session (we may be editing in monitor) and sort by create date + Iterator iter = list.iterator(); + while (iter.hasNext()) { + Message topic = (Message) iter.next(); + if (topic.getToolSession() == null) { + map.put(topic.getCreated(), topic); + } + } + return MessageDTO.getMessageDTO(new ArrayList<>(map.values())); + } + + @Override + public List getSessionsByContentId(Long contentID) { + return forumToolSessionDao.getByContentId(contentID); + } + + @Override + public List getUsersBySessionId(Long sessionID) { + return forumUserDao.getBySessionId(sessionID); + } + + @Override + public List getMessagesByUserUid(Long userId, Long sessionId) { + List list = messageDao.getByUserAndSession(userId, sessionId); + + return MessageDTO.getMessageDTO(list); + } + + @Override + public ForumUser getUser(Long userUid) { + return forumUserDao.getByUid(userUid); + } + + @Override + public void releaseMarksForSession(Long sessionID) { + // udate release mark date for each message. + List list = messageDao.getBySession(sessionID); + Iterator iter = list.iterator(); + ForumToolSession session = forumToolSessionDao.getBySessionId(sessionID); + Forum forum = session.getForum(); + boolean notifyLearnersOnMarkRelease = getEventNotificationService().eventExists(ForumConstants.TOOL_SIGNATURE, + ForumConstants.EVENT_NAME_NOTIFY_LEARNERS_ON_MARK_RELEASE, forum.getContentId()); + Map notificationMessages = null; + Object[] notificationMessageParameters = null; + if (notifyLearnersOnMarkRelease) { + notificationMessages = new TreeMap<>(); + notificationMessageParameters = new Object[3]; + } + + while (iter.hasNext()) { + Message msg = iter.next(); + ForumReport report = msg.getReport(); + if (report != null) { + report.setDateMarksReleased(new Date()); + if (notifyLearnersOnMarkRelease) { + ForumUser user = msg.getCreatedBy(); + StringBuilder notificationMessage = notificationMessages.get(user.getUserId().intValue()); + if (notificationMessage == null) { + notificationMessage = new StringBuilder(); + } + notificationMessageParameters[0] = msg.getSubject(); + notificationMessageParameters[1] = msg.getUpdated(); + notificationMessageParameters[2] = report.getMark(); + notificationMessage + .append(getLocalisedMessage("event.mark.release.mark", notificationMessageParameters)); + notificationMessages.put(user.getUserId().intValue(), notificationMessage); + } + } + messageDao.saveOrUpdate(msg); + + } + if (notifyLearnersOnMarkRelease) { + notificationMessageParameters = new Object[1]; + for (Integer userID : notificationMessages.keySet()) { + notificationMessageParameters[0] = notificationMessages.get(userID).toString(); + getEventNotificationService().triggerForSingleUser(ForumConstants.TOOL_SIGNATURE, + ForumConstants.EVENT_NAME_NOTIFY_LEARNERS_ON_MARK_RELEASE, forum.getContentId(), userID, + notificationMessageParameters); + + } + } + + List users = getUsersBySessionId(sessionID); + if (users != null) { + for (ForumUser user : users) { + // send marks to gradebook where applicable + sendMarksToGradebook(user, sessionID); + } + } + + // update session to set MarkRelease flag. + session.setMarkReleased(true); + forumToolSessionDao.saveOrUpdate(session); + + } + + @Override + public void finishUserSession(ForumUser currentUser) { + currentUser.setSessionFinished(true); + forumUserDao.save(currentUser); + } + + @Override + public AverageRatingDTO rateMessage(Long messageId, Long userId, Long toolSessionID, float rating) { + ForumUser imageGalleryUser = getUserByUserAndSession(userId, toolSessionID); + MessageRating messageRating = messageRatingDao.getRatingByMessageAndUser(messageId, userId); + Message message = messageDao.getById(messageId); + + //persist MessageRating changes in DB + if (messageRating == null) { // add + messageRating = new MessageRating(); + messageRating.setUser(imageGalleryUser); + messageRating.setMessage(message); + } + messageRating.setRating(rating); + messageRatingDao.saveObject(messageRating); + //to make available new changes be visible in jsp page + return messageRatingDao.getAverageRatingDTOByMessage(messageId); + } + + @Override + public AverageRatingDTO getAverageRatingDTOByMessage(Long messageId) { + return messageRatingDao.getAverageRatingDTOByMessage(messageId); + } + + @Override + public int getNumOfRatingsByUserAndForum(Long userUid, Long forumUid) { + return messageRatingDao.getNumOfRatingsByUserAndForum(userUid, forumUid); + } + + // *************************************************************************************************************** + // Private methods + // *************************************************************************************************************** + /** + * @param map + * @return + */ + private List getSortedMessageDTO(SortedMap map) { + Iterator iter; + MessageSeq msgSeq; + Message message; + List msgDtoList = new ArrayList<>(); + iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Entry) iter.next(); + msgSeq = (MessageSeq) entry.getKey(); + message = (Message) entry.getValue(); + msgDtoList.add(makeDTOSetRating(msgSeq, message)); + } + return msgDtoList; + } + + private MessageDTO makeDTOSetRating(MessageSeq msgSeq, Message message) { + MessageDTO dto = MessageDTO.getMessageDTO(message); + dto.setLevel(msgSeq.getMessageLevel()); + //set averageRating + if (message.getForum().isAllowRateMessages()) { + AverageRatingDTO averageRating = getAverageRatingDTOByMessage(message.getUid()); + dto.setAverageRating(averageRating.getRating()); + dto.setNumberOfVotes(averageRating.getNumberOfVotes()); + } + return dto; + } + + /** + * Process an uploaded file. + * + * @param forumForm + * @throws FileNotFoundException + * @throws IOException + * @throws RepositoryCheckedException + * @throws InvalidParameterException + */ + private NodeKey processFile(FormFile file) { + NodeKey node = null; + if ((file != null) && !StringUtils.isEmpty(file.getFileName())) { + String fileName = file.getFileName(); + try { + node = getForumToolContentHandler().uploadFile(file.getInputStream(), fileName, file.getContentType()); + } catch (InvalidParameterException e) { + throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); + } catch (FileNotFoundException e) { + throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); + } catch (RepositoryCheckedException e) { + throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); + } catch (IOException e) { + throw new ForumException("FileNotFoundException occured while trying to upload File" + e.getMessage()); + } + } + return node; + } + + /** + * This method verifies the credentials of the SubmitFiles Tool and gives it the Ticket to login and + * access the Content Repository. + * + * A valid ticket is needed in order to access the content from the repository. This method would be called evertime + * the tool needs to upload/download files from the content repository. + * + * @return ITicket The ticket for repostory access + * @throws SubmitFilesException + */ + private ITicket getRepositoryLoginTicket() throws ForumException { + ICredentials credentials = new SimpleCredentials(forumToolContentHandler.getRepositoryUser(), + forumToolContentHandler.getRepositoryId()); + try { + ITicket ticket = repositoryService.login(credentials, forumToolContentHandler.getRepositoryWorkspaceName()); + return ticket; + } catch (AccessDeniedException ae) { + throw new ForumException("Access Denied to repository." + ae.getMessage()); + } catch (WorkspaceNotFoundException we) { + throw new ForumException("Workspace not found." + we.getMessage()); + } catch (LoginException e) { + throw new ForumException("Login failed." + e.getMessage()); + } + } + + private Forum getDefaultForum() { + Long defaultForumId = new Long(toolService.getToolDefaultContentIdBySignature(ForumConstants.TOOL_SIGNATURE)); + if (defaultForumId.equals(0L)) { + String error = "Could not retrieve default content id for this tool"; + ForumService.log.error(error); + throw new ForumException(error); + } + Forum defaultForum = getForumByContentId(defaultForumId); + if (defaultForum == null) { + String error = "Could not retrieve default content record for this tool"; + ForumService.log.error(error); + throw new ForumException(error); + } + + return defaultForum; + + } + + @Override + public Long createNotebookEntry(Long sessionId, Integer notebookToolType, String toolSignature, Integer userId, + String entryText) { + return coreNotebookService.createNotebookEntry(sessionId, notebookToolType, toolSignature, userId, "", + entryText); + } + + @Override + public NotebookEntry getEntry(Long sessionId, Integer idType, String signature, Integer userID) { + List list = coreNotebookService.getEntry(sessionId, idType, signature, userID); + if ((list == null) || list.isEmpty()) { + return null; + } else { + return list.get(0); + } + } + + @Override + public void updateEntry(NotebookEntry notebookEntry) { + coreNotebookService.updateEntry(notebookEntry); + } + + @Override + public boolean isGroupedActivity(long toolContentID) { + return toolService.isGroupedActivity(toolContentID); + } + + @Override + public void auditLogStartEditingActivityInMonitor(long toolContentID) { + toolService.auditLogStartEditingActivityInMonitor(toolContentID); + } + + @Override + public String getLearnerContentFolder(Long toolSessionId, Long userId) { + return toolService.getLearnerContentFolder(toolSessionId, userId); + } + + // *************************************************************************************************************** + // ToolContentManager and ToolSessionManager methods + // *************************************************************************************************************** + @Override + public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { + if (toContentId == null) { + throw new ToolException("Failed to create the ForumFiles tool seession"); + } + + Forum fromContent = null; + if (fromContentId != null) { + fromContent = forumDao.getByContentId(fromContentId); + } + if (fromContent == null) { + fromContent = getDefaultForum(); + } + + Forum toContent = Forum.newInstance(fromContent, toContentId); + + // remove session Messages from topics + for (ForumCondition condition : toContent.getConditions()) { + Iterator conditionMessageIter = condition.getTopics().iterator(); + while (conditionMessageIter.hasNext()) { + Message conditionMessage = conditionMessageIter.next(); + if (conditionMessage.getToolSession() != null) { + conditionMessageIter.remove(); + } + } + } + + // save topics in this forum, only save the author created topic!!! and reset its reply number to zero. + Set topics = toContent.getMessages(); + if (topics != null) { + Iterator iter = topics.iterator(); + while (iter.hasNext()) { + Message msg = (Message) iter.next(); + // set this message forum Uid as toContent + if (!msg.getIsAuthored() || (msg.getToolSession() != null)) { + iter.remove(); + continue; + } + msg.setReplyNumber(0); + // msg.setCreated(new Date()); // need to keep the original create date to maintain correct order + msg.setUpdated(new Date()); + msg.setLastReplyDate(new Date()); + msg.setHideFlag(false); + msg.setForum(toContent); + createRootTopic(toContent.getUid(), (ForumToolSession) null, msg); + } + } + forumDao.saveOrUpdate(toContent); + + } + + @Override + public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { + Forum forum = forumDao.getByContentId(toolContentId); + if (forum == null) { + throw new ToolException("No found tool content by given content ID:" + toolContentId); + } + forum.setDefineLater(false); + forum.setContentInUse(false); + } + + @SuppressWarnings("unchecked") + @Override + public void removeToolContent(Long toolContentId) throws ToolException { + Forum forum = forumDao.getByContentId(toolContentId); + if (forum == null) { + ForumService.log.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); + return; + } + + for (ForumToolSession session : (List) forumToolSessionDao.getByContentId(toolContentId)) { + List entries = coreNotebookService.getEntry(session.getSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, ForumConstants.TOOL_SIGNATURE); + for (NotebookEntry entry : entries) { + coreNotebookService.deleteEntry(entry); + } + } + forumDao.delete(forum); + } + + @Override + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { + // do not remove learner content if it was set up so in sysadmin tool management + ForumConfigItem keepLearnerContent = getConfigItem(ForumConfigItem.KEY_KEEP_LEARNER_CONTENT); + if (Boolean.valueOf(keepLearnerContent.getConfigValue())) { + return; + } + + if (ForumService.log.isDebugEnabled()) { + ForumService.log.debug( + "Hiding or removing Forum messages for user ID " + userId + " and toolContentId " + toolContentId); + } + List sessionList = forumToolSessionDao.getByContentId(toolContentId); + + for (ForumToolSession session : sessionList) { + Long sessionId = session.getSessionId(); + ForumUser user = forumUserDao.getByUserIdAndSessionId(userId.longValue(), sessionId); + if (user != null) { + List messages = messageDao.getByUserAndSession(user.getUid(), sessionId); + Iterator messageIterator = messages.iterator(); + while (messageIterator.hasNext()) { + Message message = messageIterator.next(); + + if (userOwnMessageTree(message, user.getUid())) { + messageSeqDao.deleteByTopicId(message.getUid()); + Timestamp timestamp = timestampDao.getTimestamp(message.getUid(), user.getUid()); + if (timestamp != null) { + timestampDao.delete(timestamp); + } + messageDao.delete(message.getUid()); + messageIterator.remove(); + } else { + message.setHideFlag(true); + messageDao.update(message); + } + } + + NotebookEntry entry = getEntry(session.getSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, + ForumConstants.TOOL_SIGNATURE, userId); + if (entry != null) { + // hopefully it understands NotebookEntries + activityDAO.delete(entry); + } + + user.setSessionFinished(false); + forumUserDao.save(user); + + gradebookService.updateActivityMark(null, null, userId, session.getSessionId(), false); + } + } + } + + @SuppressWarnings("unchecked") + private boolean userOwnMessageTree(Message message, Long userUid) { + if (!message.getCreatedBy().getUid().equals(userUid)) { + return false; + } + List children = messageDao.getChildrenTopics(message.getUid()); + for (Message child : children) { + if (!userOwnMessageTree(child, userUid)) { + return false; + } + } + + return true; + } + + @Override + public void exportToolContent(Long toolContentId, String rootPath) throws DataMissingException, ToolException { + Forum toolContentObj = forumDao.getByContentId(toolContentId); + if (toolContentObj == null) { + toolContentObj = getDefaultForum(); + } + if (toolContentObj == null) { + throw new DataMissingException("Unable to find default content for the forum tool"); + } + + // set ResourceToolContentHandler as null to avoid copy file node in repository again. + toolContentObj = Forum.newInstance(toolContentObj, toolContentId); + toolContentObj.setCreatedBy(null); + Set items = toolContentObj.getMessages(); + Set authorItems = new HashSet<>(); + for (Message item : items) { + if (item.getIsAuthored() && (item.getToolSession() == null)) { + authorItems.add(item); + item.setCreatedBy(null); + item.setModifiedBy(null); + item.setForum(null); + item.setReport(null); + item.setReplyNumber(0); + item.setParent(null); + item.setSessionClones(null); + } + } + toolContentObj.setMessages(authorItems); + try { + exportContentService.registerFileClassForExport(Attachment.class.getName(), "fileUuid", "fileVersionId"); + exportContentService.exportToolContent(toolContentId, toolContentObj, forumToolContentHandler, rootPath); + } catch (ExportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public void importToolContent(Long toolContentId, Integer newUserUid, String toolContentPath, String fromVersion, + String toVersion) throws ToolException { + + try { + // register version filter class + exportContentService.registerImportVersionFilterClass(ForumImportContentVersionFilter.class); + + exportContentService.registerFileClassForImport(Attachment.class.getName(), "fileUuid", "fileVersionId", + "fileName", "fileType", null); + + Object toolPOJO = exportContentService.importToolContent(toolContentPath, forumToolContentHandler, + fromVersion, toVersion); + if (!(toolPOJO instanceof Forum)) { + throw new ImportToolContentException( + "Import Forum tool content failed. Deserialized object is " + toolPOJO); + } + Forum toolContentObj = (Forum) toolPOJO; + + // reset it to new toolContentId + toolContentObj.setContentId(toolContentId); + ForumUser user = forumUserDao.getByUserId(new Long(newUserUid.longValue())); + if (user == null) { + user = new ForumUser(); + UserDTO sysUser = ((User) userManagementService.findById(User.class, newUserUid)).getUserDTO(); + user.setFirstName(sysUser.getFirstName()); + user.setLastName(sysUser.getLastName()); + user.setLoginName(sysUser.getLogin()); + user.setUserId(new Long(newUserUid.longValue())); + this.createUser(user); + } + toolContentObj.setCreatedBy(user); + // save forum first + forumDao.saveOrUpdate(toolContentObj); + + // save all authoring message one by one. + // reset all resourceItem createBy user + Set items = toolContentObj.getMessages(); + int sequenceId = 1; + for (Message item : items) { + item.setCreatedBy(user); + item.setIsAuthored(true); + item.setForum(toolContentObj); + item.setSessionClones(new HashSet()); + // very old LDs did not have sequence IDs in Message and the default value is 0 + if (item.getSequenceId() == 0) { + item.setSequenceId(sequenceId++); + } + createRootTopic(toolContentObj.getUid(), (ForumToolSession) null, item); + } + } catch (ImportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { + Forum forum = getForumByContentId(toolContentId); + if (forum == null) { + forum = getDefaultForum(); + } + return getForumOutputFactory().getToolOutputDefinitions(forum, definitionType); + } + + @Override + public String getToolContentTitle(Long toolContentId) { + return getForumByContentId(toolContentId).getTitle(); + } + + @Override + public boolean isContentEdited(Long toolContentId) { + return getForumByContentId(toolContentId).isDefineLater(); + } + + @Override + public boolean isReadOnly(Long toolContentId) { + for (ForumToolSession session : (List) forumToolSessionDao.getByContentId(toolContentId)) { + for (ForumUser user : (List) forumUserDao.getBySessionId(session.getSessionId())) { + // we don't remove users in removeLearnerContent() + // we just remove or hide messages + if (!messageDao.getByUserAndSession(user.getUid(), session.getSessionId()).isEmpty()) { + return true; + } + } + } + + return false; + } + + @Override + public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentId) throws ToolException { + ForumToolSession session = new ForumToolSession(); + session.setSessionId(toolSessionId); + session.setSessionName(toolSessionName); + Forum forum = forumDao.getByContentId(toolContentId); + session.setForum(forum); + + // also clone author created topic from this forum tool content!!! + // this can avoid topic record information conflict when multiple sessions are against same tool content + // for example, the reply number maybe various for different sessions. + ForumService.log.debug("Clone tool content [" + forum.getContentId() + "] topics for session [" + + session.getSessionId() + "]"); + Set contentTopics = forum.getMessages(); + if ((contentTopics != null) && (contentTopics.size() > 0)) { + for (Message msg : contentTopics) { + if (msg.getIsAuthored() && (msg.getToolSession() == null)) { + Message newMsg = Message.newInstance(msg); + msg.getSessionClones().add(newMsg); + createRootTopic(forum.getContentId(), session, newMsg); + } + } + } + session.setStatus(ForumConstants.STATUS_CONTENT_COPYED); + + forumToolSessionDao.saveOrUpdate(session); + if (ForumService.log.isDebugEnabled()) { + ForumService.log.debug("tool session [" + session.getSessionId() + "] created."); + } + } + + @Override + public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { + if (toolSessionId == null) { + ForumService.log.error("Fail to leave tool Session based on null tool session id."); + throw new ToolException("Fail to remove tool Session based on null tool session id."); + } + if (learnerId == null) { + ForumService.log.error("Fail to leave tool Session based on null learner."); + throw new ToolException("Fail to remove tool Session based on null learner."); + } + + ForumToolSession session = forumToolSessionDao.getBySessionId(toolSessionId); + if (session != null) { + forumToolSessionDao.saveOrUpdate(session); + } else { + ForumService.log.error("Fail to leave tool Session.Could not find submit file " + + "session by given session id: " + toolSessionId); + throw new DataMissingException("Fail to leave tool Session." + + "Could not find submit file session by given session id: " + toolSessionId); + } + return learnerService.completeToolSession(toolSessionId, learnerId); + } + + @Override + public ToolSessionExportOutputData exportToolSession(Long toolSessionId) + throws DataMissingException, ToolException { + return null; + } + + @Override + public ToolSessionExportOutputData exportToolSession(List toolSessionIds) + throws DataMissingException, ToolException { + return null; + } + + @Override + public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { + forumToolSessionDao.delete(toolSessionId); + } + + @Override + public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { + + return forumOutputFactory.getToolOutput(names, this, toolSessionId, learnerId); + + } + + @Override + public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { + return forumOutputFactory.getToolOutput(name, this, toolSessionId, learnerId); + } + + @Override + public List getToolOutputs(String name, Long toolContentId) { + return new ArrayList<>(); + } + + @Override + public void forceCompleteUser(Long toolSessionId, User user) { + //no actions required + } + + @Override + public Forum getDefaultContent(Long contentID) { + if (contentID == null) { + String error = "Could not retrieve default content id for Forum tool"; + ForumService.log.error(error); + throw new ForumException(error); + } + + Forum defaultContent = getDefaultForum(); + // get default content by given ID. + Forum content = Forum.newInstance(defaultContent, contentID); + + return content; + } + + @Override + public List getAllTopicsFromSession(Long sessionID) { + return MessageDTO.getMessageDTO(messageDao.getBySession(sessionID)); + } + + /** + * Sends marks straight to gradebook from a forum report + * + * @param user + * @param toolSessionID + */ + public void sendMarksToGradebook(ForumUser user, Long toolSessionID) { + + List messages = getMessagesByUserUid(user.getUid(), toolSessionID); + if (messages != null) { + Float totalMark = null; + for (MessageDTO message : messages) { + if (totalMark == null) { + totalMark = message.getMark(); + } else if (message.getMark() != null) { + totalMark += message.getMark(); + } + } + if (totalMark != null) { + Double mark = new Double(totalMark); + gradebookService.updateActivityMark(mark, null, user.getUserId().intValue(), toolSessionID, false); + } + } + + } + + // *************************************************************************************************************** + // Get / Set methods + // *************************************************************************************************************** + public ILamsToolService getToolService() { + return toolService; + } + + public void setToolService(ILamsToolService toolService) { + this.toolService = toolService; + } + + public IAttachmentDAO getAttachmentDao() { + return attachmentDao; + } + + public void setAttachmentDao(IAttachmentDAO attachmentDao) { + this.attachmentDao = attachmentDao; + } + + public IForumDAO getForumDao() { + return forumDao; + } + + public void setForumDao(IForumDAO forumDao) { + this.forumDao = forumDao; + } + + public ITimestampDAO getTimestampDao() { + return timestampDao; + } + + public void setTimestampDao(ITimestampDAO timestampDao) { + this.timestampDao = timestampDao; + } + + public IMessageDAO getMessageDao() { + return messageDao; + } + + public void setMessageDao(IMessageDAO messageDao) { + this.messageDao = messageDao; + } + + public IMessageSeqDAO getMessageSeqDao() { + return messageSeqDao; + } + + public void setMessageSeqDao(IMessageSeqDAO messageSeqDao) { + this.messageSeqDao = messageSeqDao; + } + + public IMessageRatingDAO getMessageRatingDao() { + return messageRatingDao; + } + + public void setMessageRatingDao(IMessageRatingDAO messageRatingDao) { + this.messageRatingDao = messageRatingDao; + } + + public IForumToolSessionDAO getForumToolSessionDao() { + return forumToolSessionDao; + } + + public void setForumToolSessionDao(IForumToolSessionDAO forumToolSessionDao) { + this.forumToolSessionDao = forumToolSessionDao; + } + + public IForumUserDAO getForumUserDao() { + return forumUserDao; + } + + public void setForumUserDao(IForumUserDAO forumUserDao) { + this.forumUserDao = forumUserDao; + } + + public IRepositoryService getRepositoryService() { + return repositoryService; + } + + public void setRepositoryService(IRepositoryService repositoryService) { + this.repositoryService = repositoryService; + } + + public ForumToolContentHandler getForumToolContentHandler() { + return forumToolContentHandler; + } + + public void setForumToolContentHandler(ForumToolContentHandler toolContentHandler) { + forumToolContentHandler = toolContentHandler; + } + + public ILearnerService getLearnerService() { + return learnerService; + } + + public void setLearnerService(ILearnerService learnerService) { + this.learnerService = learnerService; + } + + public IExportToolContentService getExportContentService() { + return exportContentService; + } + + public void setExportContentService(IExportToolContentService exportContentService) { + this.exportContentService = exportContentService; + } + + public IUserManagementService getUserManagementService() { + return userManagementService; + } + + public void setUserManagementService(IUserManagementService userManagementService) { + this.userManagementService = userManagementService; + } + + public ICoreNotebookService getCoreNotebookService() { + return coreNotebookService; + } + + public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { + this.coreNotebookService = coreNotebookService; + } + + @Override + public IEventNotificationService getEventNotificationService() { + return eventNotificationService; + } + + public void setEventNotificationService(IEventNotificationService eventNotificationService) { + this.eventNotificationService = eventNotificationService; + } + + @Override + public String getLocalisedMessage(String key, Object[] args) { + return messageService.getMessage(key, args); + } + + public void setGradebookService(IGradebookService gradebookService) { + this.gradebookService = gradebookService; + } + + public void setLessonService(ILessonService lessonService) { + this.lessonService = lessonService; + } + + public void setActivityDAO(IActivityDAO activityDAO) { + this.activityDAO = activityDAO; + } + + /** + * {@inheritDoc} + */ + @Override + public String createTextSearchConditionName(Collection existingConditions) { + String uniqueNumber = null; + do { + uniqueNumber = String.valueOf(Math.abs(generator.nextInt())); + for (ForumCondition condition : existingConditions) { + String[] splittedName = getForumOutputFactory().splitConditionName(condition.getName()); + if (uniqueNumber.equals(splittedName[1])) { + uniqueNumber = null; + } + } + } while (uniqueNumber == null); + return getForumOutputFactory().buildTopicDatesToAnswersConditionName(uniqueNumber); + } + + /** + * Get number of new postings. + * + * @param messageId + * @param userId + * @return + */ + @Override + public int getNewMessagesNum(Message message, Long userId) { + Timestamp timestamp = timestampDao.getTimestamp(message.getUid(), userId); + if (timestamp == null) { + // if first time - show all postings as new, including root message + return message.getReplyNumber() + 1; + } else { + return messageSeqDao.getNumOfPostsNewerThan(message.getUid(), timestamp.getTimestamp()); + } + } + + @Override + public void saveTimestamp(Long rootTopicId, ForumUser forumUser) { + Timestamp timestamp = timestampDao.getTimestamp(rootTopicId, forumUser.getUid()); + if (timestamp != null) { + timestamp.setTimestamp(new Date()); + } else { + timestamp = new Timestamp(); + timestamp.setMessage(getMessage(rootTopicId)); + timestamp.setTimestamp(new Date()); + timestamp.setForumUser(forumUser); + } + timestampDao.saveOrUpdate(timestamp); + } + + @Override + public void sendNotificationsOnNewPosting(Long forumId, Long sessionId, Message message) { + Forum forum = getForum(forumId); + ForumUser postAuthor = message.getCreatedBy(); + String fullName = postAuthor.getLastName() + " " + postAuthor.getFirstName(); + ToolSession toolSession = toolService.getToolSession(sessionId); + Long activityId = toolSession.getToolActivity().getActivityId(); + ToolActivity activity = (ToolActivity) activityDAO.getActivityByActivityId(activityId, ToolActivity.class); + boolean isHtmlFormat = forum.isAllowRichEditor(); + + if (forum.isNotifyLearnersOnForumPosting()) { + List learners = lessonService.getLearnersAttemptedOrCompletedActivity(activity); + if ((learners != null) && !learners.isEmpty()) { + ArrayList learnerIds = new ArrayList<>(); + for (User learner : learners) { + learnerIds.add(learner.getUserId()); + } + + getEventNotificationService().sendMessage(null, learnerIds.toArray(new Integer[0]), + IEventNotificationService.DELIVERY_METHOD_MAIL, + getLocalisedMessage("event.newposting.subject", new Object[] { forum.getTitle() }), + getLocalisedMessage("event.newposting.body", new Object[] { fullName, message.getBody() }), + isHtmlFormat); + } + } + + if (forum.isNotifyTeachersOnForumPosting()) { + String emailMessage = getLocalisedMessage("event.newposting.body", + new Object[] { fullName, message.getBody() }); + getEventNotificationService().notifyLessonMonitors(sessionId, emailMessage, isHtmlFormat); + } + } + + @Override + public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { + return getForumOutputFactory().getSupportedDefinitionClasses(definitionType); + } + + @Override + public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { + ForumUser learner = getUserByUserAndSession(learnerId, toolSessionId); + if (learner == null) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); + } + + Object[] dates = messageDao.getDateRangeOfMessages(learner.getUid()); + if (learner.isSessionFinished()) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, (Date) dates[0], (Date) dates[1]); + } else { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED, (Date) dates[0], null); + } + } + + @SuppressWarnings("unchecked") + @Override + public ForumConfigItem getConfigItem(String key) { + List result = forumDao.findByProperty(ForumConfigItem.class, "configKey", + ForumConfigItem.KEY_KEEP_LEARNER_CONTENT); + return result.isEmpty() ? null : result.get(0); + } + + @Override + public void saveForumConfigItem(ForumConfigItem item) { + forumDao.insertOrUpdate(item); + } + + // ****************** REST methods ************************* + + /** + * Used by the Rest calls to create content. Mandatory fields in toolContentJSON: title, instructions, topics. + * Topics must contain a JSONArray of JSONObject objects, which have the following mandatory fields: subject, body + * There will usually be at least one topic object in the Topics array but the array may be of zero length. + */ + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + + Forum forum = new Forum(); + Date updateDate = new Date(); + forum.setCreated(updateDate); + forum.setUpdated(updateDate); + + forum.setContentId(toolContentID); + forum.setTitle(toolContentJSON.getString(RestTags.TITLE)); + forum.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + + forum.setAllowAnonym(JsonUtil.opt(toolContentJSON, "allowAnonym", Boolean.FALSE)); + forum.setAllowEdit(JsonUtil.opt(toolContentJSON, "allowEdit", Boolean.TRUE)); // defaults to true in the default + // entry in the db + forum.setAllowNewTopic(JsonUtil.opt(toolContentJSON, "allowNewTopic", Boolean.TRUE)); // defaults to true in the + // default entry in the db + forum.setAllowRateMessages(JsonUtil.opt(toolContentJSON, "allowRateMessages", Boolean.FALSE)); + forum.setAllowRichEditor(JsonUtil.opt(toolContentJSON, RestTags.ALLOW_RICH_TEXT_EDITOR, Boolean.FALSE)); + forum.setAllowUpload(JsonUtil.opt(toolContentJSON, "allowUpload", Boolean.FALSE)); + forum.setContentInUse(false); + forum.setDefineLater(false); + forum.setLimitedMaxCharacters(JsonUtil.opt(toolContentJSON, "limitedMaxCharacters", Boolean.TRUE)); + forum.setLimitedMinCharacters(JsonUtil.opt(toolContentJSON, "limitedMinCharacters", Boolean.FALSE)); + forum.setLockWhenFinished(JsonUtil.opt(toolContentJSON, "lockWhenFinished", Boolean.FALSE)); + forum.setMaxCharacters(JsonUtil.opt(toolContentJSON, "maxCharacters", 5000)); // defaults to 5000 chars in the + // default entry in the db. + forum.setMaximumRate(JsonUtil.opt(toolContentJSON, "maximumRate", 0)); + forum.setMaximumReply(JsonUtil.opt(toolContentJSON, "maximumReply", 0)); + forum.setMinCharacters(JsonUtil.opt(toolContentJSON, "minCharacters", 0)); + forum.setMinimumRate(JsonUtil.opt(toolContentJSON, "minimumRate", 0)); + forum.setMinimumReply(JsonUtil.opt(toolContentJSON, "minimumReply", 0)); + forum.setNotifyLearnersOnForumPosting( + JsonUtil.opt(toolContentJSON, "notifyLearnersOnForumPosting", Boolean.FALSE)); + forum.setNotifyLearnersOnMarkRelease( + JsonUtil.opt(toolContentJSON, "notifyLearnersOnMarkRelease", Boolean.FALSE)); + forum.setNotifyTeachersOnForumPosting( + JsonUtil.opt(toolContentJSON, "notifyTeachersOnForumPosting", Boolean.FALSE)); + forum.setReflectInstructions((String) JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, null)); + forum.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + // submissionDeadline is set in monitoring + + // *******************************Handle user******************* + // Code taken from AuthoringAction TODO + // String contentFolderID = (String) sessionMap.get(AttributeNames.PARAM_CONTENT_FOLDER_ID); + // check whether it is sysadmin:LDEV-906 + // if (!StringUtils.equals(contentFolderID, "-1")) { + // try to get form system session + // HttpSession ss = SessionManager.getSession(); + // get back login user DTO + // UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + ForumUser forumUser = getUserByID(userID.longValue()); + if (forumUser == null) { + forumUser = new ForumUser(userID.longValue(), toolContentJSON.getString("firstName"), + toolContentJSON.getString("lastName"), toolContentJSON.getString("loginName")); + getForumUserDao().save(forumUser); + } + forum.setCreatedBy(forumUser); + + updateForum(forum); + + // **************************** Handle topic ********************* + JSONArray topics = toolContentJSON.getJSONArray("topics"); + for (int i = 0; i < topics.length(); i++) { + JSONObject msgData = (JSONObject) topics.get(i); + Message newMsg = new Message(); + // newMsg.setAttachments(attachments); TODO + newMsg.setCreatedBy(forumUser); + newMsg.setCreated(updateDate); + newMsg.setModifiedBy(null); + newMsg.setUpdated(updateDate); + + newMsg.setSubject(msgData.getString("subject")); + newMsg.setBody(msgData.getString("body")); + newMsg.setForum(forum); + newMsg.setHideFlag(false); + // newMsg.setIsAnonymous(false); Does not appear on authoring interface + newMsg.setIsAuthored(true); + newMsg.setLastReplyDate(updateDate); + newMsg.setParent(null); + newMsg.setReplyNumber(0); + newMsg.setReport(null); + newMsg.setSequenceId(i); + // newMsg.setSessionClones(sessionClones); Used for updating in monitoring + newMsg.setToolSession(null); + createRootTopic(forum.getUid(), (ForumToolSession) null, newMsg); + } + + // ******************************* + // TODO - investigate + //forum.setConditions(conditions); + // message attachments + } } \ No newline at end of file Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/IForumService.java =================================================================== diff -u -r2abc3485dc2d24ea02044a64271f3ee0d3b8c11b -rd71c8a085fb0ea3c341f2cf46df958c356d88ec7 --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/IForumService.java (.../IForumService.java) (revision 2abc3485dc2d24ea02044a64271f3ee0d3b8c11b) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/IForumService.java (.../IForumService.java) (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -1,464 +1,467 @@ -/**************************************************************** - * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) - * ============================================================= - * License Information: http://lamsfoundation.org/licensing/lams/2.0/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2.0 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - * - * http://www.gnu.org/licenses/gpl.txt - * **************************************************************** - */ - - -package org.lamsfoundation.lams.tool.forum.service; - -import java.util.Collection; -import java.util.List; - -import org.apache.struts.upload.FormFile; -import org.lamsfoundation.lams.events.IEventNotificationService; -import org.lamsfoundation.lams.notebook.model.NotebookEntry; -import org.lamsfoundation.lams.tool.forum.dto.AverageRatingDTO; -import org.lamsfoundation.lams.tool.forum.dto.MessageDTO; -import org.lamsfoundation.lams.tool.forum.persistence.Attachment; -import org.lamsfoundation.lams.tool.forum.persistence.Forum; -import org.lamsfoundation.lams.tool.forum.persistence.ForumCondition; -import org.lamsfoundation.lams.tool.forum.persistence.ForumToolSession; -import org.lamsfoundation.lams.tool.forum.persistence.ForumUser; -import org.lamsfoundation.lams.tool.forum.persistence.Message; -import org.lamsfoundation.lams.tool.forum.persistence.MessageSeq; -import org.lamsfoundation.lams.tool.forum.persistence.PersistenceException; -import org.lamsfoundation.lams.util.audit.IAuditService; - -/** - * User: conradb Date: 8/06/2005 Time: 14:49:59 - */ -public interface IForumService { - // ************************************************************************************ - // Forum Method - // ************************************************************************************ - /** - * Create a Forum instance according to the default content.
- * Note, this new instance won't save into database until called persist method. - * - * @param contentID - * @return - */ - Forum getDefaultContent(Long contentID); - - /** - * Update forum by given Forum. If forum does not exist, the create a new forum. - * - * @param forum - * @return - * @throws PersistenceException - */ - Forum updateForum(Forum forum) throws PersistenceException; - - /** - * Get forum by forum UID - * - * @param forumUid - * @return - * @throws PersistenceException - */ - Forum getForum(Long forumUid) throws PersistenceException; - - /** - * Get forum by forum ID(not record UID) - * - * @param contentID - * @return - * @throws PersistenceException - */ - Forum getForumByContentId(Long contentID) throws PersistenceException; - - List getUsersForTablesorter(final Long sessionId, int page, int size, int sorting, String searchString, - boolean getNotebookEntries); - - int getCountUsersBySession(Long sessionId, String searchString); - - // ************************************************************************************ - // Topic Method - // ************************************************************************************ - - /** - * Get number of new postings. - * - * @param messageId - * @param userId - * @return - */ - int getNewMessagesNum(Message message, Long userId); - - /** - * Saves timestamp - * - * @param rootTopicId - * @param forumUser - */ - void saveTimestamp(Long rootTopicId, ForumUser forumUser); - - /** - * Create a root topic. - * - * @param forumId - * @param sessionId - * @param message - * @return - * @throws PersistenceException - */ - Message createRootTopic(Long forumId, Long sessionId, Message message) throws PersistenceException; - - /** - * Update a topic by give Message instance. - * - * @param message - * @return - * @throws PersistenceException - */ - Message updateTopic(Message message) throws PersistenceException; - - /** - * Hide a message by given Message instance - * - * @param message - * @return - * @throws PersistenceException - */ - Message updateMessageHideFlag(Long messageId, boolean hideFlag) throws PersistenceException; - - /** - * Reply a topic. - * - * @param parentId - * @param sessionId - * ToolSessionID - * @param message - * @return - * @throws PersistenceException - */ - MessageSeq replyTopic(Long parentId, Long sessionId, Message message) throws PersistenceException; - - /** - * Delete the topic by given topic ID. The function will delete all children topics under this topic. - * - * @param topicId - * @throws PersistenceException - */ - void deleteTopic(Long topicId) throws PersistenceException; - - /** - * Upload message attachment file into repository. This method only upload the given file into system repository. It - * does not execute any database operation. - * - * @param file - * @return Attachment A new instance of attachment has uploaded file VersionID and UUID information. - * @throws PersistenceException - */ - Attachment uploadAttachment(FormFile file) throws PersistenceException; - - // ************************************************************************************ - // *********************Get topic methods ********************** - // ************************************************************************************ - /** - * Get a complete topic and its children list by given root topic ID. Note that the return type is DTO. - * - * @param rootTopicId - * @return List of MessageDTO - */ - List getTopicThread(Long rootTopicId); - - /** - * Get topic and its children list by given root topic ID, starting from after the sequence number specified. - * Return the number of entries indicated by the paging number. Note that the return type is DTO. - * - * @param rootTopicId - * @param afterSequenceId - * @param pagingSize - * @return List of MessageDTO - */ - public List getTopicThread(Long rootTopicId, Long afterSequenceId, Long pagingSize); - - /** - * Get one complete thread within a topic Note that the return type is DTO. - * - * @param threadId - * @return List of MessageDTO - */ - public List getThread(Long threadId); - - /** - * Get root topics by a given sessionID value. Simultanousely, it gets back topics, which author posted in authoring - * page for this forum, which is related with the given sessionID value. - * - * This method will used by user to display initial topic page for a forum. - * - * Note that the return type is DTO. - * - * @param sessionId - * @return List of MessageDTO - */ - List getRootTopics(Long sessionId); - - /** - * Get topics posted by author role. Note that the return type is DTO. - * - * @return List of MessageDTO - */ - List getAuthoredTopics(Long forumId); - - /** - * This method will look up root topic ID by any level topicID. - * - * @param topicId - * @return - */ - Long getRootTopicId(Long topicId); - - /** - * Get message by given message UID - * - * @param messageUid - * @return Message - * @throws PersistenceException - */ - Message getMessage(Long messageUid) throws PersistenceException; - - /** - * Get message by given message UID, wrapped up in the usual DTO list that is used for the view code in learner. - * - * @param messageUid - * @return Message - * @throws PersistenceException - */ - List getMessageAsDTO(Long messageUid) throws PersistenceException; - - /** - * Get message list posted by given user. Note that the return type is DTO. - * - * @param userId - * @return - */ - List getMessagesByUserUid(Long userId, Long sessionId); - - /** - * Get how many post of this user post in a special session. DOES NOT include posts from author. - * - * @param userID - * @param sessionId - * @return - */ - int getTopicsNum(Long userID, Long sessionId); - - /** - * Returns the number of posts this user has made in this topic. - * - * @param userId - * @param topicId - * @return - */ - int getNumOfPostsByTopic(Long userId, Long topicId); - - // ************************************************************************************ - // Session Method - // ************************************************************************************ - /** - * Get Forum tool session by Session ID (not record UID). - * - * @param sessionId - * @return - */ - ForumToolSession getSessionBySessionId(Long sessionId); - - /** - * Get session list according to content ID. - * - * @param contentID - * @return List - */ - List getSessionsByContentId(Long contentID); - - /** - * Get all message according to the given session ID. - * - * @param sessionID - * @return - */ - List getAllTopicsFromSession(Long sessionID); - - // ************************************************************************************ - // User Method - // ************************************************************************************ - /** - * Create a new user in database. - * - * @param forumUser - */ - void createUser(ForumUser forumUser); - - /** - * Get user by user ID (not record UID). - * - * @param userId - * @return - */ - ForumUser getUserByUserAndSession(Long userId, Long sessionId); - - /** - * Get user list by given session ID. - * - * @param sessionID - * @return - */ - List getUsersBySessionId(Long sessionID); - - /** - * Get user by uid - * - * @param userUid - * @return - */ - ForumUser getUser(Long userUid); - - /** - * Get user by user ID - * - * @param userId - * @return - */ - ForumUser getUserByID(Long userId); - - /** - * Update report contained inside specified message. - * - * @param message - * specified message - */ - void updateContainedReport(Message message); - - // ************************************************************************************ - // Report Method - // ************************************************************************************ - - // ************************************************************************************ - // Miscellaneous Method - // ************************************************************************************ - void releaseMarksForSession(Long sessionID); - - /** The topic updates (for monitoring) are done in the web layer, so need the audit service to log the updates */ - IAuditService getAuditService(); - - /** - * Mark user completing a session. - * - * @param currentUser - */ - void finishUserSession(ForumUser currentUser); - - /** - * Create refection entry into notebook tool. - * - * @param sessionId - * @param notebook_tool - * @param tool_signature - * @param userId - * @param entryText - */ - Long createNotebookEntry(Long sessionId, Integer notebookToolType, String toolSignature, Integer userId, - String entryText); - - /** - * Get reflection entry from notebook tool. - * - * @param sessionId - * @param idType - * @param signature - * @param userID - * @return - */ - NotebookEntry getEntry(Long sessionId, Integer idType, String signature, Integer userID); - - /** - * @param notebookEntry - */ - void updateEntry(NotebookEntry notebookEntry); - - IEventNotificationService getEventNotificationService(); - - /** - * Gets a message from resource bundle. Same as in JSP pages. - * - * @param key - * key of the message - * @param args - * arguments for the message - * @return message content - */ - String getLocalisedMessage(String key, Object[] args); - - /** - * Creates an unique name for a ForumCondition. It consists of the tool output definition name and a unique positive - * integer number. - * - * @param existingConditions - * existing conditions; required to check if a condition with the same name does not exist. - * @return unique ForumCondition name - */ - String createTextSearchConditionName(Collection existingConditions); - - void deleteCondition(ForumCondition condition) throws PersistenceException; - - void sendNotificationsOnNewPosting(Long forumId, Long sessionId, Message message); - - /** - * Returns whether activity is grouped and therefore it is expected more than one tool session. - * - * @param toolContentID - * @return - */ - boolean isGroupedActivity(long toolContentID); - - /** - * Audit log the teacher has started editing activity in monitor. - * - * @param toolContentID - */ - void auditLogStartEditingActivityInMonitor(long toolContentID); - - /** - * Return content folder (unique to each learner and lesson) which is used for storing user generated content. - * It's been used by CKEditor. - * - * @param toolSessionId - * @param userId - * @return - */ - String getLearnerContentFolder(Long toolSessionId, Long userId); - - AverageRatingDTO rateMessage(Long messageId, Long userId, Long toolSessionID, float rating); - - AverageRatingDTO getAverageRatingDTOByMessage(Long responseId); - - /** - * Return total number of posts done by current user in this forum activity - * - * @param userUid - * @param forumUid - * @return - */ - int getNumOfRatingsByUserAndForum(Long userUid, Long forumUid); - -} +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.forum.service; + +import java.util.Collection; +import java.util.List; + +import org.apache.struts.upload.FormFile; +import org.lamsfoundation.lams.events.IEventNotificationService; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.tool.forum.dto.AverageRatingDTO; +import org.lamsfoundation.lams.tool.forum.dto.MessageDTO; +import org.lamsfoundation.lams.tool.forum.persistence.Attachment; +import org.lamsfoundation.lams.tool.forum.persistence.Forum; +import org.lamsfoundation.lams.tool.forum.persistence.ForumCondition; +import org.lamsfoundation.lams.tool.forum.persistence.ForumConfigItem; +import org.lamsfoundation.lams.tool.forum.persistence.ForumToolSession; +import org.lamsfoundation.lams.tool.forum.persistence.ForumUser; +import org.lamsfoundation.lams.tool.forum.persistence.Message; +import org.lamsfoundation.lams.tool.forum.persistence.MessageSeq; +import org.lamsfoundation.lams.tool.forum.persistence.PersistenceException; +import org.lamsfoundation.lams.util.audit.IAuditService; + +/** + * User: conradb Date: 8/06/2005 Time: 14:49:59 + */ +public interface IForumService { + // ************************************************************************************ + // Forum Method + // ************************************************************************************ + /** + * Create a Forum instance according to the default content.
+ * Note, this new instance won't save into database until called persist method. + * + * @param contentID + * @return + */ + Forum getDefaultContent(Long contentID); + + /** + * Update forum by given Forum. If forum does not exist, the create a new forum. + * + * @param forum + * @return + * @throws PersistenceException + */ + Forum updateForum(Forum forum) throws PersistenceException; + + /** + * Get forum by forum UID + * + * @param forumUid + * @return + * @throws PersistenceException + */ + Forum getForum(Long forumUid) throws PersistenceException; + + /** + * Get forum by forum ID(not record UID) + * + * @param contentID + * @return + * @throws PersistenceException + */ + Forum getForumByContentId(Long contentID) throws PersistenceException; + + List getUsersForTablesorter(final Long sessionId, int page, int size, int sorting, String searchString, + boolean getNotebookEntries); + + int getCountUsersBySession(Long sessionId, String searchString); + + // ************************************************************************************ + // Topic Method + // ************************************************************************************ + + /** + * Get number of new postings. + * + * @param messageId + * @param userId + * @return + */ + int getNewMessagesNum(Message message, Long userId); + + /** + * Saves timestamp + * + * @param rootTopicId + * @param forumUser + */ + void saveTimestamp(Long rootTopicId, ForumUser forumUser); + + /** + * Create a root topic. + * + * @param forumId + * @param sessionId + * @param message + * @return + * @throws PersistenceException + */ + Message createRootTopic(Long forumId, Long sessionId, Message message) throws PersistenceException; + + /** + * Update a topic by give Message instance. + * + * @param message + * @return + * @throws PersistenceException + */ + Message updateTopic(Message message) throws PersistenceException; + + /** + * Hide a message by given Message instance + * + * @param message + * @return + * @throws PersistenceException + */ + Message updateMessageHideFlag(Long messageId, boolean hideFlag) throws PersistenceException; + + /** + * Reply a topic. + * + * @param parentId + * @param sessionId + * ToolSessionID + * @param message + * @return + * @throws PersistenceException + */ + MessageSeq replyTopic(Long parentId, Long sessionId, Message message) throws PersistenceException; + + /** + * Delete the topic by given topic ID. The function will delete all children topics under this topic. + * + * @param topicId + * @throws PersistenceException + */ + void deleteTopic(Long topicId) throws PersistenceException; + + /** + * Upload message attachment file into repository. This method only upload the given file into system repository. It + * does not execute any database operation. + * + * @param file + * @return Attachment A new instance of attachment has uploaded file VersionID and UUID information. + * @throws PersistenceException + */ + Attachment uploadAttachment(FormFile file) throws PersistenceException; + + // ************************************************************************************ + // *********************Get topic methods ********************** + // ************************************************************************************ + /** + * Get a complete topic and its children list by given root topic ID. Note that the return type is DTO. + * + * @param rootTopicId + * @return List of MessageDTO + */ + List getTopicThread(Long rootTopicId); + + /** + * Get topic and its children list by given root topic ID, starting from after the sequence number specified. + * Return the number of entries indicated by the paging number. Note that the return type is DTO. + * + * @param rootTopicId + * @param afterSequenceId + * @param pagingSize + * @return List of MessageDTO + */ + public List getTopicThread(Long rootTopicId, Long afterSequenceId, Long pagingSize); + + /** + * Get one complete thread within a topic Note that the return type is DTO. + * + * @param threadId + * @return List of MessageDTO + */ + public List getThread(Long threadId); + + /** + * Get root topics by a given sessionID value. Simultanousely, it gets back topics, which author posted in authoring + * page for this forum, which is related with the given sessionID value. + * + * This method will used by user to display initial topic page for a forum. + * + * Note that the return type is DTO. + * + * @param sessionId + * @return List of MessageDTO + */ + List getRootTopics(Long sessionId); + + /** + * Get topics posted by author role. Note that the return type is DTO. + * + * @return List of MessageDTO + */ + List getAuthoredTopics(Long forumId); + + /** + * This method will look up root topic ID by any level topicID. + * + * @param topicId + * @return + */ + Long getRootTopicId(Long topicId); + + /** + * Get message by given message UID + * + * @param messageUid + * @return Message + * @throws PersistenceException + */ + Message getMessage(Long messageUid) throws PersistenceException; + + /** + * Get message by given message UID, wrapped up in the usual DTO list that is used for the view code in learner. + * + * @param messageUid + * @return Message + * @throws PersistenceException + */ + List getMessageAsDTO(Long messageUid) throws PersistenceException; + + /** + * Get message list posted by given user. Note that the return type is DTO. + * + * @param userId + * @return + */ + List getMessagesByUserUid(Long userId, Long sessionId); + + /** + * Get how many post of this user post in a special session. DOES NOT include posts from author. + * + * @param userID + * @param sessionId + * @return + */ + int getTopicsNum(Long userID, Long sessionId); + + /** + * Returns the number of posts this user has made in this topic. + * + * @param userId + * @param topicId + * @return + */ + int getNumOfPostsByTopic(Long userId, Long topicId); + + // ************************************************************************************ + // Session Method + // ************************************************************************************ + /** + * Get Forum tool session by Session ID (not record UID). + * + * @param sessionId + * @return + */ + ForumToolSession getSessionBySessionId(Long sessionId); + + /** + * Get session list according to content ID. + * + * @param contentID + * @return List + */ + List getSessionsByContentId(Long contentID); + + /** + * Get all message according to the given session ID. + * + * @param sessionID + * @return + */ + List getAllTopicsFromSession(Long sessionID); + + // ************************************************************************************ + // User Method + // ************************************************************************************ + /** + * Create a new user in database. + * + * @param forumUser + */ + void createUser(ForumUser forumUser); + + /** + * Get user by user ID (not record UID). + * + * @param userId + * @return + */ + ForumUser getUserByUserAndSession(Long userId, Long sessionId); + + /** + * Get user list by given session ID. + * + * @param sessionID + * @return + */ + List getUsersBySessionId(Long sessionID); + + /** + * Get user by uid + * + * @param userUid + * @return + */ + ForumUser getUser(Long userUid); + + /** + * Get user by user ID + * + * @param userId + * @return + */ + ForumUser getUserByID(Long userId); + + /** + * Update report contained inside specified message. + * + * @param message + * specified message + */ + void updateContainedReport(Message message); + + // ************************************************************************************ + // Report Method + // ************************************************************************************ + + // ************************************************************************************ + // Miscellaneous Method + // ************************************************************************************ + void releaseMarksForSession(Long sessionID); + + /** The topic updates (for monitoring) are done in the web layer, so need the audit service to log the updates */ + IAuditService getAuditService(); + + /** + * Mark user completing a session. + * + * @param currentUser + */ + void finishUserSession(ForumUser currentUser); + + /** + * Create refection entry into notebook tool. + * + * @param sessionId + * @param notebook_tool + * @param tool_signature + * @param userId + * @param entryText + */ + Long createNotebookEntry(Long sessionId, Integer notebookToolType, String toolSignature, Integer userId, + String entryText); + + /** + * Get reflection entry from notebook tool. + * + * @param sessionId + * @param idType + * @param signature + * @param userID + * @return + */ + NotebookEntry getEntry(Long sessionId, Integer idType, String signature, Integer userID); + + /** + * @param notebookEntry + */ + void updateEntry(NotebookEntry notebookEntry); + + IEventNotificationService getEventNotificationService(); + + /** + * Gets a message from resource bundle. Same as in JSP pages. + * + * @param key + * key of the message + * @param args + * arguments for the message + * @return message content + */ + String getLocalisedMessage(String key, Object[] args); + + /** + * Creates an unique name for a ForumCondition. It consists of the tool output definition name and a unique positive + * integer number. + * + * @param existingConditions + * existing conditions; required to check if a condition with the same name does not exist. + * @return unique ForumCondition name + */ + String createTextSearchConditionName(Collection existingConditions); + + void deleteCondition(ForumCondition condition) throws PersistenceException; + + void sendNotificationsOnNewPosting(Long forumId, Long sessionId, Message message); + + /** + * Returns whether activity is grouped and therefore it is expected more than one tool session. + * + * @param toolContentID + * @return + */ + boolean isGroupedActivity(long toolContentID); + + /** + * Audit log the teacher has started editing activity in monitor. + * + * @param toolContentID + */ + void auditLogStartEditingActivityInMonitor(long toolContentID); + + /** + * Return content folder (unique to each learner and lesson) which is used for storing user generated content. + * It's been used by CKEditor. + * + * @param toolSessionId + * @param userId + * @return + */ + String getLearnerContentFolder(Long toolSessionId, Long userId); + + AverageRatingDTO rateMessage(Long messageId, Long userId, Long toolSessionID, float rating); + + AverageRatingDTO getAverageRatingDTOByMessage(Long responseId); + + /** + * Return total number of posts done by current user in this forum activity + * + * @param userUid + * @param forumUid + * @return + */ + int getNumOfRatingsByUserAndForum(Long userUid, Long forumUid); + + ForumConfigItem getConfigItem(String key); + + void saveForumConfigItem(ForumConfigItem item); +} \ No newline at end of file Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/actions/AdminAction.java =================================================================== diff -u --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/actions/AdminAction.java (revision 0) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/actions/AdminAction.java (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,90 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.forum.web.actions; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.tool.forum.persistence.ForumConfigItem; +import org.lamsfoundation.lams.tool.forum.service.ForumServiceProxy; +import org.lamsfoundation.lams.tool.forum.service.IForumService; +import org.lamsfoundation.lams.tool.forum.web.forms.AdminForm; + +/** + * @author Marcin Cieslak + */ +public class AdminAction extends Action { + private IForumService forumService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + String param = mapping.getParameter(); + if (param.equals("start")) { + return start(mapping, form, request, response); + } + if (param.equals("saveContent")) { + return saveContent(mapping, form, request, response); + } + + return start(mapping, form, request, response); + } + + public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + if (forumService == null) { + forumService = ForumServiceProxy.getForumService(this.getServlet().getServletContext()); + } + + AdminForm adminForm = (AdminForm) form; + + ForumConfigItem keepLearnerContent = forumService.getConfigItem(ForumConfigItem.KEY_KEEP_LEARNER_CONTENT); + if (keepLearnerContent != null) { + adminForm.setKeepLearnerContent(Boolean.valueOf(keepLearnerContent.getConfigValue())); + } + + request.setAttribute("error", false); + return mapping.findForward("config"); + } + + public ActionForward saveContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + AdminForm adminForm = (AdminForm) form; + + if (forumService == null) { + forumService = ForumServiceProxy.getForumService(this.getServlet().getServletContext()); + } + + ForumConfigItem keepLearnerContent = forumService.getConfigItem(ForumConfigItem.KEY_KEEP_LEARNER_CONTENT); + keepLearnerContent.setConfigValue(String.valueOf(adminForm.getKeepLearnerContent())); + forumService.saveForumConfigItem(keepLearnerContent); + + request.setAttribute("savedSuccess", true); + return mapping.findForward("config"); + } +} \ No newline at end of file Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/forms/AdminForm.java =================================================================== diff -u --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/forms/AdminForm.java (revision 0) +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/web/forms/AdminForm.java (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,39 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.forum.web.forms; + +import org.apache.struts.action.ActionForm; + +public class AdminForm extends ActionForm { + private static final long serialVersionUID = -9080785256404216422L; + + private boolean keepLearnerContent; + + public boolean getKeepLearnerContent() { + return keepLearnerContent; + } + + public void setKeepLearnerContent(boolean keepContent) { + this.keepLearnerContent = keepContent; + } +} \ No newline at end of file Index: lams_tool_forum/web/WEB-INF/struts-config.xml =================================================================== diff -u -rb47369533cc464d433b2a4306e8cc0bd3f8ecaa1 -rd71c8a085fb0ea3c341f2cf46df958c356d88ec7 --- lams_tool_forum/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision b47369533cc464d433b2a4306e8cc0bd3f8ecaa1) +++ lams_tool_forum/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -1,458 +1,487 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_tool_forum/web/jsps/admin/config.jsp =================================================================== diff -u --- lams_tool_forum/web/jsps/admin/config.jsp (revision 0) +++ lams_tool_forum/web/jsps/admin/config.jsp (revision d71c8a085fb0ea3c341f2cf46df958c356d88ec7) @@ -0,0 +1,38 @@ + + +<%@ include file="/common/taglibs.jsp"%> + + + + <fmt:message key="admin.page.title" /> + + + + + + + + + + + <%@ include file="/common/messages.jsp"%> + + + + + + + + +
+ +
+ +
+ + +
+ + \ No newline at end of file