view src/nabble/modules/poll/NodeNamespaceExt.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 fschmidt.db.DbDatabase;
import fschmidt.util.java.DateUtils;
import nabble.model.Node;
import nabble.model.Person;
import nabble.model.User;
import nabble.naml.compiler.Command;
import nabble.naml.compiler.CommandSpec;
import nabble.naml.compiler.IPrintWriter;
import nabble.naml.compiler.Interpreter;
import nabble.naml.compiler.Namespace;
import nabble.naml.compiler.NamespaceExtension;
import nabble.naml.compiler.ScopedInterpreter;
import nabble.naml.namespaces.StringList;
import nabble.view.web.template.DateNamespace;
import nabble.view.web.template.NodeNamespace;
import nabble.view.web.template.RequestNamespace;
import nabble.view.web.template.ServletNamespace;
import nabble.view.web.template.ServletNamespaceUtils;

import javax.servlet.ServletException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@NamespaceExtension(
	name = "node_poll",
	target = NodeNamespace.class
)
public class NodeNamespaceExt {

	private final Node node;
	private final ServletNamespaceUtils servletNsUtils;

	public NodeNamespaceExt(NodeNamespace ns) {
		this.node = ns.node();
		this.servletNsUtils = ns.servletNsUtils;
	}

	private Poll getPoll() {
		return Poll.of(node);
	}

	public static final CommandSpec set_poll = CommandSpec.DO()
		.parameters("poll_question", "poll_options")
		.optionalParameters("poll_max_choices","poll_days_left",
				"poll_allow_vote_change","poll_show_results_before_vote",
				"poll_show_results_before_end")
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void set_poll(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp)
		throws ServletException, Poll.PollEditException, Poll.PollFormatException
	{
		User user = servletNsUtils.visitorUser(interp);
		if (!node.getOwner().equals(user))
			throw new Poll.PollEditException();
		String pollQuestion = interp.getArgString("poll_question");
		RequestNamespace.ParameterValueList pollOptionsList = interp.getArgAsNamespace(RequestNamespace.ParameterValueList.class, "poll_options");
		String[] pollOptions = pollOptionsList.values().toArray(new String[0]);
		int maxChoices = interp.getArgAsInt("poll_max_choices",1);
		int daysLeft = interp.getArgAsInt("poll_days_left", 0);
		boolean allowVoteChange = interp.getArgAsBoolean("poll_allow_vote_change",false);
		boolean showResultsBeforeVote = interp.getArgAsBoolean("poll_show_results_before_vote",false);
		boolean showResultsBeforeEnd = interp.getArgAsBoolean("poll_show_results_before_end",false);
		setPoll(
			pollQuestion,
			pollOptions,
			maxChoices,
			daysLeft,
			allowVoteChange,
			showResultsBeforeVote,
			showResultsBeforeEnd
		);
	}

	private void setPoll(String pollQuestion, String[] pollOptions, int maxChoices, int daysLeft, boolean allowVoteChange, boolean showResultsBeforeVote, boolean showResultsBeforeEnd)
		throws Poll.PollFormatException
	{
		DbDatabase db = node.getSite().getDb();
		if( !db.isInTransaction() ) {
			db.beginTransaction();
			try {
				setPoll(
					pollQuestion,
					pollOptions,
					maxChoices,
					daysLeft,
					allowVoteChange,
					showResultsBeforeVote,
					showResultsBeforeEnd
				);
				db.commitTransaction();
			} finally {
				db.endTransaction();
			}
			return;
		}
		Poll poll = new Poll( node.getGoodCopy(), pollOptions.length );
		poll.set(pollQuestion, pollOptions);
		poll.setMaxChoices(maxChoices);
		if (daysLeft > 0) poll.setEndDate(DateUtils.addDays(new Date(), daysLeft));
		poll.setAllowVoteChange(allowVoteChange);
		poll.setShowResultsBeforeVote(showResultsBeforeVote);
		poll.setShowResultsBeforeEnd(showResultsBeforeEnd);
	}

	public static final CommandSpec edit_poll = CommandSpec.DO()
			.optionalParameters("poll_max_choices","poll_days_left",
					"poll_allow_vote_change","poll_show_results_before_vote",
					"poll_show_results_before_end")
			.requiredInStack(ServletNamespace.class)
			.build()
	;

	@Command public void edit_poll(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp)
		throws ServletException, Poll.PollEditException, Poll.PollFormatException
	{
		User user = servletNsUtils.visitorUser(interp);
		if (!node.getOwner().equals(user))
			throw new Poll.PollEditException();
		Poll poll = getPoll();
		poll.setMaxChoices(interp.getArgAsInt("poll_max_choices",1));
		String daysLeftS = interp.getArgString("poll_days_left");
		if (daysLeftS != null) {
			int daysLeft;
			try {
				daysLeft = Integer.parseInt(daysLeftS);
			} catch (NumberFormatException e) {
				throw new Poll.PollFormatException();
			}
			Date endDate = poll.endDate();
			Date now = new Date();
			if (endDate==null) {
				poll.setEndDate(DateUtils.addDays(now, daysLeft));
			} else {
				int daysLeftOrig = DateUtils.datesBetween(now, endDate);
				if (daysLeftOrig != daysLeft) {
					poll.setEndDate(DateUtils.addDays(endDate, daysLeft-daysLeftOrig));
				}
			}
		} else {
			poll.setEndDate(null);
		}
		poll.setAllowVoteChange(interp.getArgAsBoolean("poll_allow_vote_change",false));
		poll.setShowResultsBeforeVote(interp.getArgAsBoolean("poll_show_results_before_vote",false));
		poll.setShowResultsBeforeEnd(interp.getArgAsBoolean("poll_show_results_before_end",false));
	}

	public static final CommandSpec delete_poll = CommandSpec.DO()
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void delete_poll(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp)
		throws ServletException, Poll.PollEditException
	{
		User user = servletNsUtils.visitorUser(interp);
		if (!node.getOwner().equals(user))
			throw new Poll.PollEditException();
		DbDatabase db = node.getSite().getDb();
		db.beginTransaction();
		try {
			Poll poll = Poll.of( node.getGoodCopy() );
			if( poll != null )
				poll.delete();
			db.commitTransaction();
		} finally {
			db.endTransaction();
		}
	}

	public static final CommandSpec has_poll = CommandSpec.DO;

	@Command public void has_poll(IPrintWriter out, Interpreter interp) {
		out.print(getPoll()!=null);
	}

	public static final CommandSpec poll_question = CommandSpec.DO;

	@Command public void poll_question(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().getQuestion());
	}

	public static final CommandSpec poll_option_list = CommandSpec.DO;

	@Command public void poll_option_list(IPrintWriter out,ScopedInterpreter<PollOptionList> interp) {
		List<String> options = Arrays.asList(getPoll().getOptions());
		Object block = interp.getArg(new PollOptionList(options, getPoll().getNode().getId()),"do");
		out.print(block);
	}

	public static final CommandSpec poll_max_choices = CommandSpec.DO;

	@Command public void poll_max_choices(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().maxChoices());
	}

	public static final CommandSpec poll_has_end_date = CommandSpec.DO;

	@Command public void poll_has_end_date(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().endDate()!=null);
	}

	public static final CommandSpec poll_end_date = CommandSpec.DO;

	@Command public void poll_end_date(IPrintWriter out,ScopedInterpreter<DateNamespace> interp) {
		out.print(interp.getArg( new DateNamespace(getPoll().endDate()), "do" ));
	}

	public static final CommandSpec poll_days_left = CommandSpec.DO;

	@Command public void poll_days_left(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		Date endDate = getPoll().endDate();
		if (endDate!=null) {
			out.print(DateUtils.datesBetween(new Date(), endDate));
		}
	}

	public static final CommandSpec poll_allow_vote_change = CommandSpec.DO;

	@Command public void poll_allow_vote_change(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().allowVoteChange());
	}

	public static final CommandSpec poll_show_results_before_vote = CommandSpec.DO;

	@Command public void poll_show_results_before_vote(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().showResultsBeforeVote());
	}

	public static final CommandSpec poll_show_results_before_end = CommandSpec.DO;

	@Command public void poll_show_results_before_end(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print(getPoll().showResultsBeforeEnd());
	}

	public static final CommandSpec poll_vote_counts = CommandSpec.DO()
			.build()
	;

	@Command public void poll_vote_counts(IPrintWriter out,ScopedInterpreter<PollOptionList> interp) {
		int[] v = getPoll().getVoteCounts();
		List<String> voteCounts = new ArrayList<String>();
		for (int n : v) {
			voteCounts.add(String.valueOf(n));
		}
		Object block = interp.getArg(new PollOptionList(voteCounts, getPoll().getNode().getId()),"do");
		out.print(block);
	}

	public static final CommandSpec poll_visitor_has_voted = CommandSpec.DO()
			.dotParameter("index")
			.requiredInStack(ServletNamespace.class)
			.build()
	;

	@Command public void poll_visitor_has_voted(IPrintWriter out,ScopedInterpreter<StringList> interp)
		throws ServletException
	{
		int index = interp.getArgAsInt("index");
		User viewer = servletNsUtils.visitorUser(interp);
		int[] v = getPoll().getVotes(viewer);
		for (int i : v) {
			if (i==index) {
				out.print(true);
				return;
			}
		}
		out.print(false);
	}

	public static final CommandSpec poll_visitor_can_see_votes = CommandSpec.DO()
			.requiredInStack(ServletNamespace.class)
			.build()
	;

	@Command public void poll_visitor_can_see_votes(IPrintWriter out,Interpreter interp)
			throws ServletException
	{
		Poll poll = getPoll();
		User viewer = servletNsUtils.visitorUser(interp);
		Person owner = node.getOwner();
		if (viewer!=null && viewer.equals(owner)) {
			out.print(true);
			return;
		}
		if (poll.endDate()!=null) {
			Date now = new Date();
			if (!poll.showResultsBeforeEnd() && poll.endDate().after(now)) {
				out.print(false);
				return;
			}
			if (poll.endDate().before(now)) {
				out.print(true);
				return;
			}
		}
		if (!poll.showResultsBeforeVote() && (viewer==null || poll.getVotes(viewer).length==0)) {
			out.print(false);
			return;
		}
		out.print(true);
	}

	public static final CommandSpec poll_has_ended = CommandSpec.DO;

	@Command public void poll_has_ended(IPrintWriter out,Interpreter interp)
		throws ServletException
	{
		Poll poll = getPoll();
		boolean hasEnded = poll.endDate() != null && poll.endDate().before(new Date());
		out.print(hasEnded);
	}

	public static final CommandSpec poll_visitor_can_vote = CommandSpec.DO()
			.requiredInStack(ServletNamespace.class)
			.build()
	;

	@Command public void poll_visitor_can_vote(IPrintWriter out,Interpreter interp)
		throws ServletException
	{
		Poll poll = getPoll();
		User viewer = servletNsUtils.visitorUser(interp);
		if (poll.endDate()!=null && poll.endDate().before(new Date())) {
			out.print(false);
			return;
		}
		if (!poll.allowVoteChange() && (viewer==null || poll.getVotes(viewer).length>0)) {
			out.print(false);
			return;
		}
		out.print(true);
	}

	public static final CommandSpec poll_vote = CommandSpec.DO()
			.parameters("votes")
			.requiredInStack(ServletNamespace.class)
			.build()
	;

	@Command public void poll_vote(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp)
		throws ServletException, Poll.PollVoteException {
		Poll poll = getPoll();
		User voter = servletNsUtils.visitorUser(interp);
		RequestNamespace.ParameterValueList vlist = interp.getArgAsNamespace(RequestNamespace.ParameterValueList.class, "votes");
		if (vlist==null) return;
		List<String> votes = vlist.values();
		int[] v = new int[votes.size()];
		for (int i=0; i<v.length; i++)
			v[i] = Integer.parseInt(votes.get(i));
		poll.vote(voter, v);
	}

	@Namespace(
		name = "poll_option_list",
		global = true
	)
	public static final class PollOptionList extends StringList {

		private final long nodeId;

		PollOptionList(List<String> list, long nodeId) {
			super(list);
			this.nodeId = nodeId;
		}

		@Command public void option_id(IPrintWriter out,Interpreter interp) {
			out.print(nodeId + "-" + index);
		}
	}
}