/********************************************************************************** * $URL: $ * $Id: $ *********************************************************************************** * * Copyright (c) 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.poll.tool.params; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.poll.logic.ExternalLogic; import org.sakaiproject.poll.logic.PollListManager; import org.sakaiproject.poll.logic.PollVoteManager; import org.sakaiproject.poll.model.Option; import org.sakaiproject.poll.model.Poll; import org.sakaiproject.poll.model.Vote; import org.sakaiproject.poll.model.VoteCollection; import org.sakaiproject.poll.util.PollUtils; import org.sakaiproject.util.FormattedText; import uk.org.ponder.localeutil.LocaleGetter; import uk.org.ponder.messageutil.MessageLocator; import uk.org.ponder.messageutil.TargettedMessage; import uk.org.ponder.messageutil.TargettedMessageList; public class PollToolBean { private static final Log LOG = LogFactory.getLog(PollToolBean.class); public static final String HANDLE_DELETE_OPTION_DO_NOTHING = "do-nothing", HANDLE_DELETE_OPTION_RETURN_VOTES = "return-votes"; //public Poll newPoll = new Poll(); public String siteID; public Option option; private VoteCollection voteCollection; //values to hold the parts of the date public String openDay; public String openMonth; public String openYear; public String openHour; public String openMinutes; public String openAmPm; public String closeDay; public String closeMonth; public String closeYear; public String closeHour; public String closeMinutes; public String closeAmPm; private VoteBean voteBean; public Long[] deleteids; public String submissionStatus; private PollVoteManager pollVoteManager; //how to handle orphaned votes when deleting an option private String handleOrphanVotes; public Map perms = null; public void setRoleperms(Map perms) { this.perms = perms; } private PollListManager manager; public void setPollListManager(PollListManager manager) { this.manager = manager; } public void setPollVoteManager(PollVoteManager pvm){ this.pollVoteManager = pvm; } public void setVoteBean(VoteBean vb){ this.voteBean = vb; } public void setVoteCollection(VoteCollection vc) { this.voteCollection = vc; } private ExternalLogic externalLogic; public void setExternalLogic(ExternalLogic externalLogic) { this.externalLogic = externalLogic; } public void setOption (Option o) { this.option = o; } private Poll poll; public void setPoll(Poll p) { poll = p; } private LocaleGetter localegetter; public void setLocaleGetter(LocaleGetter localegetter) { this.localegetter = localegetter; } private TargettedMessageList messages; public void setMessages(TargettedMessageList messages) { this.messages = messages; } private MessageLocator messageLocator; public void setMessageLocator(MessageLocator messageLocator) { this.messageLocator = messageLocator; } public Poll processActionAdd() { boolean isNew = true; if (poll.getPollId()!=null) { LOG.debug("Actualy updating poll " + poll.getPollId()); isNew = false; //check for possible unchanged values LOG.debug(" newPoll is " + poll.getText()+ " while poll text is " + poll.getText()); if (poll.getText().equals("") && poll.getText()!=null) poll.setText(poll.getText()); if (poll.getDetails().equals("") && poll.getDetails() != null) poll.setDetails(poll.getDetails()); } LOG.debug("Poll opens: " + poll.getVoteOpen() + " and closes: " + poll.getVoteClose()); if (poll.getVoteOpen().after(poll.getVoteClose())) { LOG.debug("Poll closes before it opens"); messages.addMessage(new TargettedMessage("close_before_open")); throw new IllegalArgumentException("close_before_open"); } if (poll.getMinOptions() > poll.getMaxOptions()) { LOG.debug("Min options greater than max options"); messages.addMessage(new TargettedMessage("min_greater_than_max"," min greater than max")); throw new IllegalArgumentException("min_greater_than_max"); } if (poll.getText().trim() == null || poll.getText().length() == 0 ) { LOG.debug("Poll question is Empty!"); messages.addMessage(new TargettedMessage("error_no_text","no text")); throw new IllegalArgumentException("error_no_text"); } poll.setDetails(PollUtils.cleanupHtmlPtags(FormattedText.processFormattedText(poll.getDetails(), new StringBuilder()))); LOG.debug("about to save poll " + poll); manager.savePoll(poll); LOG.info("Poll saved with id of " + poll.getPollId()); //if this is not a new poll populate the options list if (!isNew) poll.setOptions(manager.getOptionsForPoll(poll)); voteBean.poll = poll; return poll; } public void processActionDelete() { for (int i = 0; i < deleteids.length; i ++) { Poll todelete = (Poll) manager.getPollById(Long.valueOf(deleteids[i].longValue())); try { manager.deletePoll(todelete); } catch(SecurityException e){ LOG.error(" Permission Error" + e); } } } public VoteCollection processActionVote() { //m_log.info("got a vote! with " + optionsSelected.length + "options"); LOG.debug("vote is on poll " + voteCollection.getPollId()); Poll poll = manager.getPollById(voteCollection.getPollId()); //need to check if the user hasn't already voted on this poll //pollvoteManger.userHasVoted(poll.getPollId(); VoteCollection votes = voteCollection; LOG.info("got vote collection with id " + votes.getId()); List options = new ArrayList(); if (votes.getOptionsSelected() == null && votes.getOption() != null) { options.add(votes.getOption()); } else if (votes.getOptionsSelected() != null){ for (int i = 0;i < votes.getOptionsSelected().length;i++){ options.add(votes.getOptionsSelected()[i]); } } //if options list is empty this may be a spoiled vote if (options.size()==0 && poll.getMinOptions()==0) { //to do we need to map to somthing special LOG.warn("this is a spoiled vote"); options.add("0"); } List<Vote> votesToSave = new ArrayList<Vote>(); for (int i = 0; i < options.size(); i++){ //create a new vote LOG.debug("this vote is for option " + options.get(i)); Option opt = new Option(Long.valueOf((String)options.get(i))); Vote vote = new Vote(poll,opt,votes.getId()); if (vote.getIp() == null) { LOG.warn("IP is null"); vote.setIp("Nothing"); } votesToSave.add(vote); } pollVoteManager.saveVoteList(votesToSave); voteBean.voteCollection = votes; LOG.debug("Votes saved about to return"); return votes; } public String proccessActionAddOption() { if ("cancel".equals(submissionStatus)) return "cancel"; LOG.debug("adding option with text " + option.getOptionText()); if (option.getOptionText() == null || option.getOptionText().trim().length()==0) { //errors.reject("vote_closed","vote closed"); // return null; } StringBuilder sb = new StringBuilder(); option.setOptionText(FormattedText.processFormattedText(option.getOptionText(), sb, true, true)); String text = option.getOptionText(); text = PollUtils.cleanupHtmlPtags(text); option.setOptionText(text); manager.saveOption(option); LOG.debug("Succesuly save option with id" + option.getId()); //voteBean.poll = manager.getPollById(option.getPollId()); if ("option".equals(submissionStatus)) return "option"; else return "Saved"; } public Poll proccessActionDeleteOption() { LOG.info("about to delete option " + option.getId()); Long pollId = option.getPollId(); List<Vote> votes = (List<Vote>) pollVoteManager.getAllVotesForOption(option); if (votes != null && votes.size() > 0) { //if the option had votes, we need some special handling if (HANDLE_DELETE_OPTION_RETURN_VOTES.equals(getHandleOrphanVotes())) { Set<String> userEids = new HashSet<String>(); //hard-delete the option. It will no longer have any votes manager.deleteOption(option); for (Vote vote : votes) { String userId = vote.getUserId(); if (userId != null) { String userEid = externalLogic.getUserEidFromId(userId); userEids.add(userEid); } pollVoteManager.deleteVote(vote); } //send the notification to affected users sendOptionDeletedNotification(userEids.toArray(new String[0])); } else { //soft delete the option. we still want it to show up in the results /* * The option in this bean is mapped by parameters * given to the form by the producer. This seems a bit * shakey. 'persistentOption' will be a fresh and full * copy of the option from the DB. This should be a safer * "save" operation. -bv */ Option persistentOption = manager.getOptionById(option.getOptionId()); manager.deleteOption(persistentOption, true); } } else { //if the option didn't have any votes, just blow it away manager.deleteOption(option); } //we now need to update the poll object in memory Poll poll = manager.getPollById(pollId); voteBean.setPoll(poll); return poll; } public String cancel() { return "cancel"; } public void setHandleOrphanVotes(String handleOrphanVotes) { this.handleOrphanVotes = handleOrphanVotes; } public String getHandleOrphanVotes() { return this.handleOrphanVotes; } private void sendOptionDeletedNotification(String[] userEids) { Poll poll = manager.getPollById(option.getPollId()); String siteTitle = externalLogic.getSiteTile(poll.getSiteId()); externalLogic.notifyDeletedOption(Arrays.asList(userEids), siteTitle, poll.getPollText()); } }