package edu.stanford.nlp.patterns;
import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.patterns.TextAnnotationPatterns;
import edu.stanford.nlp.util.StringUtils;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.stream.JsonParser;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
/**
* A simple web frontend to the SPIED System.
*
* Shamelessly copied from Gabor's Naturali
* @author Sonal
*/
public class SPIEDServlet extends HttpServlet {
Logger logger = Logger.getAnonymousLogger();
String testPropertiesFile;
Map<String, String> modelNametoDirName;
/**
* Set the properties to the paths they appear at on the servlet.
* See build.xml for where these paths get copied.
* @throws javax.servlet.ServletException Thrown by the implementation
*/
public void init() throws ServletException {
testPropertiesFile = getServletContext().getRealPath("/WEB-INF/data/test.properties");
modelNametoDirName = new HashMap<>();
modelNametoDirName.put("food","food");
}
/**
* Originally extracted from Jettison; copied from http://stackoverflow.com/questions/3020094/how-should-i-escape-strings-in-json
* @param string The string to quote.
* @return A quoted version of the string, safe to send over the wire.
*/
public static String quote(String string) {
if (string == null || string.length() == 0) {
return "\"\"";
}
char c = 0;
int i;
int len = string.length();
StringBuilder sb = new StringBuilder(len + 4);
String t;
sb.append('"');
for (i = 0; i < len; i += 1) {
c = string.charAt(i);
switch (c) {
case '\\':
case '"':
sb.append('\\');
sb.append(c);
break;
case '/':
// if (b == '<') {
sb.append('\\');
// }
sb.append(c);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (c < ' ') {
t = "000" + Integer.toHexString(c);
sb.append("\\u" + t.substring(t.length() - 4));
} else {
sb.append(c);
}
}
}
sb.append('"');
return sb.toString();
}
/**
* Actually perform the GET request, given all the relevant information (already sanity checked).
* This is the meat of the servlet code.
* @param out The writer to write the output to.
* @param q The query string.
*/
private void run(PrintWriter out, String q, String seedWords, String model) throws Exception{
// Clean the string a bit
q = q.trim();
if (q.length() == 0) {
return;
}
char lastChar = q.charAt(q.length() - 1);
if (lastChar != '.' && lastChar != '!' && lastChar != '?') {
q = q + ".";
}
TextAnnotationPatterns annotate = new TextAnnotationPatterns();
String quotedString = quote(q);
String jsonObject = "{\"input\":"+quotedString+",\"seedWords\":{\"NAME\":[\""+ StringUtils.join(seedWords.split("[,;]"), "\",\"")+"\"]}}";
boolean testmode = true;
if(model.equalsIgnoreCase("new"))
testmode = false;
logger.info("Testmode is " + testmode);
logger.info("model is " + model);
String suggestions;
// Collect results
if(testmode){
Properties testProps= new Properties();
if(testPropertiesFile != null && new File(testPropertiesFile).exists()){
try {
String props = IOUtils.stringFromFile(testPropertiesFile);
testProps.load(new StringReader(props));
} catch (IOException e) {
writeError(e, out, "Cannot read test properties file");
return;
}
} else{
writeError(new RuntimeException("test prop file not found"), out, "Test properties file not found");
return;
}
String modelDir = getServletContext().getRealPath("/WEB-INF/data/"+modelNametoDirName.get(model));
testProps.setProperty("patternsWordsDir", modelDir);
logger.info("Reading saved model from " + modelDir);
String seedWordsFiles="NAME,"+modelDir+"/NAME/seedwords.txt,"+modelDir+"/NAME/phrases.txt";
String modelPropertiesFile = modelDir+"/model.properties";
logger.info("Loading model properties from " + modelPropertiesFile);
String stopWordsFile = modelDir+"/stopwords.txt";
boolean writeOutputFile = false;
annotate.setUpProperties(jsonObject, false, writeOutputFile, seedWordsFiles);
suggestions = annotate.suggestPhrasesTest(testProps, modelPropertiesFile, stopWordsFile);
}
else{
boolean writeOutputFile = false;
annotate.setUpProperties(jsonObject, false, writeOutputFile, null);
annotate.processText(writeOutputFile);
suggestions = annotate.suggestPhrases();
}
out.print(suggestions);
}
/**
* {@inheritDoc}
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("GET SPIED query from " + request.getRemoteAddr());
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding("utf-8");
}
response.setContentType("text/json; charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String raw = request.getParameter("q");
String seedwords = request.getParameter("seedwords");
String model = request.getParameter("model");
if (raw == null || "".equals(raw)) {
out.print("{\"okay\":false,\"reason\":\"No data provided\"}");
} else {
run(out, raw, seedwords, model);
}
} catch (Exception t) {
writeError(t, out, request.toString());
}
out.close();
}
void writeError(Throwable t, PrintWriter out, String input){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
logger.info("input is " + input);
logger.info(sw.toString());
out.print("{\"okay\":false, \"reason\":\"Something bad happened. Contact the author.\"}");
}
/**
* {@inheritDoc}
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("Responding to the request for SPIED");
getServletContext().log("Responding through SPIED through servlet context!!");
doGet(request, response);
// logger.info("POST SPIED query from " + request.getRemoteAddr());
//
// //StringBuffer jb = new StringBuffer();
// String line = "";
// response.setContentType("text/json; charset=UTF-8");
// PrintWriter out = response.getWriter();
// try {
// String raw = StringUtils.toAscii(request.getParameter("q"));
// String seedwords = request.getParameter("seedwords");
//// BufferedReader reader = request.getReader();
//// while ((line = reader.readLine()) != null)
//// jb.append(line);
//// JsonReader jsonReader = Json.createReader(new StringReader(jb.toString()));
//// JsonObject obj = jsonReader.readObject();
//// String raw = obj.get("q").toString();
//// String seedwords = obj.get("seedwords").toString();
// line = request.toString();
// if (raw == null || "".equals(raw)) {
// out.print("{\"okay\":false,\"reason\":\"No data provided\"}");
// } else {
// run(out, raw, seedwords);
// }
// } catch (Throwable t) {
// writeError(t, out, line);
// }
//
// out.close();
}
/**
* A helper so that we can see how the servlet sees the world, modulo model paths, at least.
*/
public static void main(String[] args) throws ServletException, IOException {
SPIEDServlet servlet = new SPIEDServlet();
servlet.init();
// IOUtils.console(line -> {
// StringWriter str = new StringWriter();
// PrintWriter out = new PrintWriter(str);
// servlet.doGet(new PrintWriter(out), line,"obama");
// out.close();
// System.out.println(str.toString());
// });
}
}