Mercurial Hosting > nabble
view src/nabble/modules/poll/Poll.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
line wrap: on
line source
package nabble.modules.poll; import java.io.Serializable; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import fschmidt.db.DbNull; import fschmidt.db.DbRecord; import fschmidt.db.LongKey; import nabble.model.ModelException; import nabble.model.Node; import nabble.model.User; import nabble.model.ExtensionFactory; import nabble.model.ModelHome; final class Poll { private static final ExtensionFactory<Node,Poll> FACTORY = new ExtensionFactory<Node,Poll>() { public String getName() { return PollModule.INSTANCE.getName(); } public Class<Poll> extensionClass() { return Poll.class; } public Poll construct(Node node) { return null; } public Poll construct(Node node,ResultSet rs) throws SQLException { int pollOptionCount = rs.getInt("poll_option_count"); if( pollOptionCount==0 ) return null; return new Poll(node,pollOptionCount); } public Serializable getExportData(Node node) { return null; //throw new UnsupportedOperationException(); } public void saveExportData(Node node,Serializable s) { //throw new UnsupportedOperationException(); } }; static { ModelHome.addNodeExtensionFactory(FACTORY); } static void init() {} public static Poll of(Node node) { return node.getExtension(FACTORY); } private final Node node; private int pollOptionCount; private String question; private String[] options; private int maxChoices = 1; private Date endDate = null; private boolean allowVoteChange = true; private boolean showResultsBeforeVote = true; private boolean showResultsBeforeEnd = true; Poll(Node node,int pollOptionCount) { this.node = node; this.pollOptionCount = pollOptionCount; this.question = node.getProperty("poll_question"); this.options = new String[pollOptionCount]; for (int i=0; i<options.length; i++) this.options[i] = node.getProperty("poll_option_"+i); String maxChoicesS = node.getProperty("poll_max_choices"); maxChoices = maxChoicesS!=null ? Integer.parseInt(maxChoicesS) : 1; String endtime = node.getProperty("poll_end_date"); endDate = endtime == null ? null : new Date(Long.parseLong(endtime)); allowVoteChange = !"false".equals(node.getProperty("poll_allow_vote_change")); showResultsBeforeVote = !"false".equals(node.getProperty("poll_show_results_before_vote")); showResultsBeforeEnd = !"false".equals(node.getProperty("poll_show_results_before_end")); } void set(String question, String[] options) throws PollFormatException { if( !node.getSite().getDb().isInTransaction() ) throw new RuntimeException("not in transaction"); if (question.trim().length()==0 || options.length < 2) throw new PollFormatException(); this.pollOptionCount = options.length; DbRecord<LongKey,?> record = node.getDbRecord(); record.fields().put("poll_option_count", pollOptionCount); record.update(); this.question = question.trim(); node.setProperty("poll_question", question.trim()); this.options = new String[options.length]; for (int i=0; i<options.length; i++) { String option = options[i].trim(); if (option.length()==0) throw new PollFormatException(); this.options[i] = option; node.setProperty("poll_option_"+i, option); } clearVotes(); } Node getNode() { return node; } String getQuestion() { return question; } String[] getOptions() { return options; } int[] getVoteCounts() { int[] votes = new int[options.length]; for (int i=0; i<options.length; i++) { votes[i] = node.getSite().countTags("node_id="+node.getId()+"and label='"+VOTE_LABEL_PREFIX+i+"'"); } return votes; } private static final String VOTE_LABEL_PREFIX="poll_vote:"; int[] getVotes(User user) { List<Integer> v = new ArrayList<Integer>(); for (int i=0; i<options.length; i++) { boolean vote = node.getSite().hasTags(node, user, "label='"+VOTE_LABEL_PREFIX+i+"'"); if (vote) v.add(i); // duplicates aren't possible because the index is unique } int[] votes = new int[v.size()]; for (int i=0; i<votes.length; i++) votes[i] = v.get(i); return votes; /* List<String> labels = node.getSite().findTagLabels( "node_id="+node.getId()+" and user_id="+user.getId()+" and label like '"+VOTE_LABEL_PREFIX+"%'" ); int[] votes = new int[labels.size()]; for (int i=0; i<votes.length; i++) { votes[i] = Integer.parseInt(labels.get(i).substring(VOTE_LABEL_PREFIX.length())); } return votes; */ } void vote(User user, int[] votes) throws PollVoteException { if (votes.length > maxChoices) throw new PollVoteException(); if (!allowVoteChange && getVotes(user).length>0) throw new PollVoteException(); if (endDate!=null && endDate.before(new Date())) throw new PollVoteException(); node.getSite().deleteTags(node, user, "label like '"+VOTE_LABEL_PREFIX+"%'"); for (int vote : votes) { node.getSite().addTag(node, user, VOTE_LABEL_PREFIX+vote); } } private void clearVotes() { node.getSite().deleteTags( "node_id="+node.getId()+" and label like '"+VOTE_LABEL_PREFIX+"%'" ); } void delete() { if( !node.getSite().getDb().isInTransaction() ) throw new RuntimeException("not in transaction"); node.setProperty("poll_question", null); for (int i=0; i<pollOptionCount; i++) { node.setProperty("poll_option_"+i, null); } node.setProperty("poll_max_choices", null); node.setProperty("poll_end_date", null); node.setProperty("poll_allow_vote_change", null); node.setProperty("poll_show_results_before_vote", null); node.setProperty("poll_show_results_before_end", null); clearVotes(); DbRecord<LongKey,?> record = node.getDbRecord(); record.fields().put("poll_option_count", DbNull.INTEGER); record.update(); } int maxChoices() { return maxChoices; } Date endDate() { return endDate; } boolean allowVoteChange() { return allowVoteChange; } boolean showResultsBeforeVote() { return showResultsBeforeVote; } boolean showResultsBeforeEnd() { return showResultsBeforeEnd; } void setMaxChoices(int maxChoices) throws PollFormatException { if (maxChoices < 1 || maxChoices > options.length) throw new PollFormatException(); this.maxChoices = maxChoices; node.setProperty("poll_max_choices", maxChoices > 1 ? String.valueOf(maxChoices) : null); } void setEndDate(Date endDate) { this.endDate = endDate; node.setProperty("poll_end_date", endDate!=null ? String.valueOf(endDate.getTime()) : null); } void setAllowVoteChange(boolean allowVoteChange) { node.setProperty("poll_allow_vote_change", allowVoteChange ? null : "false"); this.allowVoteChange = allowVoteChange; } void setShowResultsBeforeVote(boolean showResultsBeforeVote) { node.setProperty("poll_show_results_before_vote", showResultsBeforeVote ? null : "false"); this.showResultsBeforeVote = showResultsBeforeVote; } void setShowResultsBeforeEnd(boolean showResultsBeforeEnd) { node.setProperty("poll_show_results_before_end", showResultsBeforeEnd ? null : "false"); this.showResultsBeforeEnd = showResultsBeforeEnd; } public static class PollFormatException extends ModelException { public PollFormatException() { super(name("invalid_poll_format"), "Invalid poll parameters."); } } public static class PollEditException extends ModelException { public PollEditException() { super(name("poll_edit_disallowed"), "You cannot modify this poll."); } } public static class PollVoteException extends ModelException { public PollVoteException() { super(name("invalid_vote_attempt"), "Invalid voting attempt."); } } }