/*******************************************************************************
* LastCalc - The last calculator you'll ever need
* Copyright (C) 2011, 2012 Uprizer Labs LLC
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Affero General Public License for more
* details.
******************************************************************************/
package com.lastcalc.servlets;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.Objectify;
import com.lastcalc.Misc;
import com.lastcalc.Renderers;
import com.lastcalc.SequentialParser;
import com.lastcalc.TokenList;
import com.lastcalc.db.DAO;
import com.lastcalc.db.Line;
import com.lastcalc.db.Worksheet;
import com.lastcalc.lessons.Help;
import com.lastcalc.servlets.WorksheetServlet.AnswerType;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import javax.servlet.http.HttpServlet;
import java.net.URL;
public class MainPageServlet extends HttpServlet {
private static final long serialVersionUID = -797244922688131805L;
@Override
protected void doGet(final javax.servlet.http.HttpServletRequest req,
final javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException,
java.io.IOException {
final boolean skipUACheck = req.getParameterMap().containsKey("skipuacheck");
if (!skipUACheck && req.getHeader("User-Agent").contains("MSIE")) {
resp.sendRedirect("/noie.html");
return;
}
final URL requestURL = new URL(req.getRequestURL().toString());
final String path = requestURL.getPath();
final Objectify obj = DAO.begin();
if (path.equals("/favicon.ico")) {
resp.sendError(404);
return;
}
if (path.equals("/")) {
// Create a new worksheet and redirect to it
final Worksheet worksheet = new Worksheet();
obj.save().entity(worksheet).now();
resp.sendRedirect("/" + worksheet.id + (skipUACheck ? "?skipuacheck=1" : ""));
} else {
final String worksheetId = path.substring(1);
if (worksheetId.length() == 8) {
// This is readonly, duplicate it and redirect to
// a new id
final Worksheet worksheet = new Worksheet();
final Worksheet template = obj.load().type(Worksheet.class).filter("readOnlyId", worksheetId).first().get();
if (template == null) {
resp.sendError(404);
return;
}
worksheet.parentId = worksheet.id;
worksheet.qaPairs = template.qaPairs;
obj.save().entity(worksheet);
resp.sendRedirect("/" + worksheet.id);
} else {
final Worksheet worksheet;
try {
worksheet = obj.load().type(Worksheet.class).id(worksheetId).get();
} catch (final NotFoundException e) {
resp.sendError(404, "Worksheet not found");
return;
}
final Document doc = createDocument(requestURL, worksheet);
// doc.body().appendElement("iframe").attr("id",
// "helpframe").attr("src", "/help")
// .attr("frameBorder", "0");
final Element helpDiv = doc.body().appendElement("div").attr("id", "helpframe")
.attr("style", "display: none;");
for (final Node n : Help.getHelpDoc().body().childNodes()) {
helpDiv.appendChild(n.clone());
}
int lineNo = 1;
final SequentialParser sp = SequentialParser.create();
Element worksheetElement = doc.body().select("#worksheet").first();
for (final Line qa : worksheet.qaPairs) {
sp.processNextAnswer(qa.answer);
final Element lineEl = worksheetElement.appendElement("div").addClass("line")
.attr("id", "line" + lineNo);
if (lineNo == 1) {
lineEl.addClass("firstLine");
}
final Element lineNumber=lineEl.appendElement("div").attr("class","lineNumberMarker");
lineNumber.text(lineNo+".");
final Element question = lineEl.appendElement("div").attr("class", "question")
.attr("contentEditable", "true");
question.text(qa.question);
final TokenList strippedAnswer = sp.stripUDF(qa.answer);
final AnswerType aType = WorksheetServlet.getAnswerType(strippedAnswer);
if (aType.equals(AnswerType.NORMAL)) {
lineEl.appendElement("div").attr("class", "equals").text("=");
lineEl.appendElement("div").attr("class", "answer")
.html(Renderers.toHtml("/", strippedAnswer).toString());
} else {
lineEl.appendElement("div").attr("class", "equals")
.html("<span style=\"font-size:10pt;\">✓</span>");
lineEl.appendElement("div").attr("class", "answer");
}
lineNo++;
}
doc.body().attr("data-variables", Misc.gson.toJson(sp.getUserDefinedKeywordMap()));
final Element lineEl = worksheetElement.appendElement("div").addClass("line").attr("id", "line" + lineNo);
if (lineNo == 1) {
lineEl.addClass("firstLine");
}
final Element lineNumber=lineEl.appendElement("div").attr("class","lineNumberMarker");
lineNumber.text(lineNo+".");
final Element question = lineEl.appendElement("div").attr("class", "question")
.attr("contentEditable", "true");
final Element equals = lineEl.appendElement("div").attr("class", "equals").text("=")
.attr("style", "display:none;");
lineEl.appendElement("div").attr("class", "answer").attr("style", "display:none;");
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().append(doc.toString());
}
}
}
private Document createDocument(final URL requestURL, final Worksheet worksheet) {
final Document doc = Document.createShell(requestURL.toString());
doc.head().appendElement("title").text("LastCalc");
doc.head().appendElement("link").attr("rel", "stylesheet").attr("href", "/css/highlighting.css")
.attr("type", "text/css");
doc.head().appendElement("link").attr("rel", "stylesheet").attr("href", "/css/locutus.css")
.attr("type", "text/css");
doc.head().appendElement("link").attr("rel", "stylesheet")
.attr("href", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/themes/base/jquery-ui.css")
.attr("type", "text/css");
doc.head().appendElement("script").attr("src", "/js/json2.js");
doc.head().appendElement("script")
.attr("src", "https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js");
// doc.head().appendElement("script").attr("src",
// "/js/jquery.tools.min.js");
doc.head().appendElement("script")
.attr("src", "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.min.js");
doc.head().appendElement("script").attr("src", "/js/jquery.cookie.js");
doc.head().appendElement("script").attr("src", "/js/rangy-core.js");
doc.head().appendElement("script").attr("src", "/js/rangy-selectionsaverestore.js");
doc.head().appendElement("script").attr("src", "/js/locutus.js");
doc.head()
.appendElement("script")
.attr("type", "text/javascript")
.text("function woopraReady(tracker) {tracker.setDomain('lastcalc.com');tracker.setIdleTimeout(300000);tracker.track();return false;}(function(){var wsc = document.createElement('script');wsc.src = document.location.protocol+'//static.woopra.com/js/woopra.js';wsc.type = 'text/javascript';wsc.async = true;var ssc = document.getElementsByTagName('script')[0];ssc.parentNode.insertBefore(wsc, ssc);})();");
doc.head().append("<script type=\"text/javascript\"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-354970-27']); _gaq.push(['_trackPageview']);(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);})();</script>");
doc.body().attr("data-worksheet-id", worksheet.id);
doc.body().attr("data-worksheet-ro-id", worksheet.readOnlyId);
final Element header = doc.body().appendElement("div").attr("id", "header");
header.appendElement("div").attr("id", "logo").text("LastCalc");
header.appendElement("div").attr("id", "help-button").text("Show Help");
final Element ws = doc.body().appendElement("div").attr("id", "worksheet");
ws.appendElement("div").attr("class", "groups").appendElement("a")
.attr("href", "https://github.com/sanity/LastCalc/wiki")
.attr("target", "_blank").html("LastCalc is open source! Read more...");
return doc;
}
}