package http;
import graphexpr.ExprResolver;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import latex.TikzGraphExpr;
import latex.TikzReduction;
import org.apache.commons.lang3.tuple.Pair;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.simpleframework.http.core.Container;
import org.simpleframework.http.core.ContainerServer;
import org.simpleframework.transport.Server;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;
import app.SimpleTokenizer;
import com.hp.hpl.jena.rdf.model.Statement;
import pregroup.Parser;
import pregroup.SimpleType;
import rdf.GraphCompiler;
import rdf.GraphString;
import rdf.ModelViewer;
import rdf.TypeException;
import tagging.StanfordTagger;
import util.FileUtils;
import util.InternalException;
import util.UnknownTagException;
import xmllexicon.SemanticLexicon;
class UserInputError extends Exception
{
private static final long serialVersionUID = 1L;
public String what;
public UserInputError(String w) { what = w; }
}
public class WebApp implements Container
{
private String homePage;
private String resultPage;
private String thatsMyFault;
private String notSupported;
private String tokenError;
private String seemsIncorrect;
private PrintWriter logWriter;
private final static Integer port = 4040;
//private String errorPage;
private SemanticLexicon sem;
private StanfordTagger tagger;
public void handle(Request request, Response response)
{
try
{
PrintStream body = response.getPrintStream();
long time = System.currentTimeMillis();
logWriter.println((new Date()).toString()+": request from "+request.getClientAddress().toString());
String pageName = request.getPath().getPath();
response.setValue("Content-Type", "text/html");
response.setValue("Server", "PregroupSPARQL/1.0 (Simple)");
response.setDate("Date", time);
response.setDate("Last-Modified", time);
if(pageName.equals("/reload"))
sem.load("semantics.xml");
System.out.println("Requested \""+pageName+"\"");
if(pageName.equals("/index.html") || pageName.equals("/") || pageName.equals("/reload"))
body.println(homePage);
else if(pageName.equals("/process.html"))
body.println(processSentence(request.getQuery().get("sentence")));
else if(pageName.startsWith("/tmp/img/"))
{
//! TODO THIS IS A BACKDOOOOOOOOR
response.setValue("Content-Type", "image/png");
body.write(readBinary("."+pageName));
}
else
body.println("404 Page Not Found\n");
body.close();
}
catch (Exception e)
{
System.out.println("Exception caught in handle():");
e.printStackTrace();
}
}
private String escapeHtml(String input)
{
String output = new String(input);
output = output.replace("&", "&");
output = output.replace(">", ">");
return output.replace("<", "<");
}
private String processSentence(String input)
{
String resPage = new String(resultPage);
logWriter.println((new Date()).toString()+": Input sentence: "+input);
logWriter.flush();
String messages = "";
try
{
if(input == null)
{
resPage = resPage.replace("$SENTENCE", "");
throw new UserInputError("No input sentence.");
}
resPage = resPage.replace("$SENTENCE", escapeHtml(input));
try
{
List<String> sentence;
try
{ sentence = new SimpleTokenizer(input).toList(); }
catch(Exception e)
{
throw new UserInputError("Unable to tokenize the input sentence."+tokenError);
}
SimpleType target =
new SimpleType("s", 0);
List<Pair<String,String>> tags = tagger.tagSentence(sentence);
messages += "<h5>Tagging</h5>\n"+
"<table>\n"+
"<tr>\n";
for(String word : sentence)
messages += "<td>"+escapeHtml(word)+"</td>";
messages += "\n</tr>\n"+
"<tr>\n";
for(Pair<String,String> tag : tags)
messages += "<td>"+tag.getRight()+"</td>";
messages += "\n</tr>\n"+
"</table>\n\n";
GraphString phrase;
try
{ phrase = new GraphString(sem, tags, target);
} catch(TypeException e)
{
throw new UserInputError(e.what+thatsMyFault);
}
Parser p = new Parser(phrase, sem.getComparator());
System.out.println(phrase.toString());
if(p.run())
{
ExprResolver resolver = new ExprResolver(phrase, p.getReduction());
TikzGraphExpr drawer = new TikzGraphExpr();
genImage(drawer.draw(phrase, sentence, p.getReduction(),resolver,false));
messages += "<h5>Type reduction</h5>\n"+
"<img alt=\"Type reduction\" src=\"tmp/img/output.png\" />\n\n";
GraphCompiler compiler = new GraphCompiler(resolver);
try {
Statement res = compiler.compileStmt(phrase.getPattern(resolver.getEntryPoint()));
compiler.assume(res);
String graph = compiler.dumpTriples();
messages += "<h5>Triples</h5>\n"+
"<pre>\n"+
escapeHtml(graph)+
"\n</pre>\n\n";
ModelViewer mv = new ModelViewer(compiler.getModel());
genGraph(mv.toDot());
messages += "<h5>Graph</h5>\n" +
"<img alt=\"RDF graph\" src=\"tmp/img/graph.png\" />\n\n";
} catch (TypeException e) {
throw new UserInputError("Type exception in the grammar:<br/>"+e.what+thatsMyFault);
}
}
else
throw new UserInputError("Incorrect sentence."+seemsIncorrect);
}
catch(UnknownTagException e)
{
throw new UserInputError("Unknown tag: "+e.what+notSupported);
}
}
catch(UserInputError e)
{
messages += "<h5>Error</h5>\n"+e.what+"\n\n";
}
catch(Exception e)
{
System.out.println("Exception caught in processSentence():");
e.printStackTrace();
}
resPage = resPage.replace("$OUTPUT", messages);
return resPage;
}
private String genImage(String tikzCode)
{
try
{
PrintWriter out = new PrintWriter("tmp/output.tex");
out.println(tikzCode);
out.close();
List<String> pdflatex = new ArrayList<String>();
pdflatex.add("pdflatex");
pdflatex.add("-halt-on-error");
pdflatex.add("standalone.tex");
ProcessBuilder builder = new ProcessBuilder(pdflatex);
builder.directory(new File("tmp"));
Process p = builder.start();
p.waitFor();
List<String> convert = new ArrayList<String>();
convert.add("convert");
convert.add("-density");
convert.add("150");
convert.add("standalone.pdf");
convert.add("img/output.png");
builder = new ProcessBuilder(convert);
builder.directory(new File("tmp"));
p = builder.start();
p.waitFor();
//Runtime.getRuntime().exec("convert -density 300 tmp/standalone.pdf tmp/standalone.png");
}
catch(IOException e)
{
e.printStackTrace();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
return "";
}
private String genGraph(String dotCode)
{
try
{
PrintWriter out = new PrintWriter("tmp/output.dot");
out.println(dotCode);
out.close();
List<String> dot = new ArrayList<String>();
dot.add("dot");
dot.add("-Tpng");
dot.add("output.dot");
dot.add("-o");
dot.add("img/graph.png");
ProcessBuilder builder = new ProcessBuilder(dot);
builder.directory(new File("tmp"));
Process p = builder.start();
p.waitFor();
}
catch(IOException e)
{
e.printStackTrace();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
return "";
}
public WebApp() throws InternalException
{
super();
try
{
homePage = FileUtils.readFile("www/index.html");
thatsMyFault = FileUtils.readFile("www/thatsMyFault.html");
notSupported = FileUtils.readFile("www/notSupported.html");
tokenError = FileUtils.readFile("www/tokenError.html");
resultPage = FileUtils.readFile("www/process.html");
seemsIncorrect = FileUtils.readFile("www/seemsIncorrect.html");
logWriter = new PrintWriter("requests.log");
}
catch(IOException e)
{
homePage = "Error while loading the web pages.";
}
org.apache.jena.atlas.logging.Log.setLog4j();
sem = new SemanticLexicon();
sem.load("semantics.xml");
tagger = new StanfordTagger();
tagger.load("taggers/english-left3words-distsim.tagger");
}
public static void main(String[] list) throws Exception
{
try {
Container container = new WebApp();
Server server = new ContainerServer(container);
Connection connection = new SocketConnection(server);
SocketAddress address = new InetSocketAddress(port);
connection.connect(address);
} catch(InternalException e)
{
System.err.println(e.what);
}
}
private byte[] readBinary(String fileName) throws IOException
{
File file = new File(fileName);
byte[] result = new byte[(int)file.length()];
InputStream input = null;
try
{
int totalBytesRead = 0;
input = new BufferedInputStream(new FileInputStream(file));
while(totalBytesRead < result.length)
{
int bytesRemaining = result.length - totalBytesRead;
int bytesRead = input.read(result, totalBytesRead, bytesRemaining);
if (bytesRead > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
}
}
}
finally
{
input.close();
}
return result;
}
}