working poc

This commit is contained in:
Matthew Slowe 2020-05-31 10:06:14 +01:00
commit 7965c41516
9 changed files with 368 additions and 0 deletions

33
README.md Normal file
View File

@ -0,0 +1,33 @@
Self-defined checker
====================
Proof-of-concept language checker using the [Self-defined project](https://www.selfdefined.app/).
Requirements
------------
* J2EE compatible web server (eg. Tomcat)
Preparation
-----------
1. Clone the repository
2. Get the dependencies and ensure they're either in `WEB-INF/lib` or the webserver's shared `lib`:
* SQLite JDBC driver (eg. https://bitbucket.org/xerial/sqlite-jdbc/downloads/sqlite-jdbc-3.30.1.jar)
* JSON library (eg. http://stleary.github.io/JSON-java/index.html)
3. Compile the code (YMMV)
```shell
cd WEB-INF
export LIBPATH=/path/to/shared/java/libraries
javac -d classes -classpath src:classes:lib/json-20200518.jar:$LIBPATH/el-api.jar:$LIBPATH/servlet-api.jar:$LIBPATH/sqlite-jdbc.jar src/uk/org/mafoo/selfdefined/Checker.java
```
4. Build a war file
```shell
jar -cvf self-defined.war .
```
5. Deploy! (move the war file to your webservers `/webapps` folder and wait for it to deploy)
Notes
-----
The included database is build using the data from https://github.com/tatianamac/selfdefined.

0
WEB-INF/classes/.keep Normal file
View File

BIN
WEB-INF/files/defs.db Normal file

Binary file not shown.

0
WEB-INF/lib/.keep Normal file
View File

View File

@ -0,0 +1,176 @@
package uk.org.mafoo.selfdefined;
import javax.servlet.annotation.WebServlet;
import javax.management.RuntimeErrorException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import org.sqlite.*;
@WebServlet("/Checker")
public class Checker extends HttpServlet {
Connection db;
PreparedStatement p_checkWord, p_getWord;
String urlBase = "https://www.selfdefined.app/definitions/";
public void init() throws ServletException {
// Do required initialization
try {
db = DriverManager.getConnection(
"jdbc:sqlite:" + getServletContext().getRealPath("/WEB-INF/files/defs.db"));
p_checkWord = db.prepareStatement("SELECT word, ref FROM words WHERE word LIKE ?");
p_getWord = db.prepareStatement("SELECT title, slug, flag_level, flag_text, flag_for FROM definitions WHERE title LIKE ?");
} catch (SQLException e) {
throw new RuntimeException("Failed to load database: " + e.toString());
}
}
private HashMap<String,String> getWord(String word) {
try {
p_getWord.setString(1, word);
ResultSet rs = p_getWord.executeQuery();
if(rs.next()) {
HashMap<String,String> _return = new HashMap<String,String>();
_return.put("word", rs.getString(1));
_return.put("slug", rs.getString(2));
_return.put("flagLevel", rs.getString(3));
_return.put("flagText", rs.getString(4));
_return.put("flagFor", rs.getString(5));
return _return;
} else {
return null;
}
} catch (SQLException e) {
return null;
}
}
private void checkWord(String word, HashMap<String,String> wordMap, HashMap<String,Integer> wordCounts) {
assert(p_checkWord != null);
assert(word != null);
wordCounts.put(word, wordCounts.getOrDefault(word, 0) + 1);
// Do we already know the answer?
if(wordMap.containsKey(word)) {
// If so, just increment the wordcount and return
return;
}
try {
p_checkWord.setString(1, word);
ResultSet rs = p_checkWord.executeQuery();
while(rs.next()) {
if(rs.getString(1).equalsIgnoreCase(rs.getString(2))) {
wordMap.put(rs.getString(1), null);
} else {
wordMap.put(rs.getString(1), rs.getString(2));
}
}
} catch (SQLException e) {
// FIXME
}
}
private Report process(String[] input) {
HashMap<String,String> wordMap = new HashMap<String,String>();
HashMap<String,Integer> wordCounts = new HashMap<String,Integer>();
for(String line : input) {
for(String word : line.split("\\s+")) {
checkWord(word, wordMap, wordCounts);
}
}
Report report = new Report();
for (String word : wordMap.keySet()) {
String ref = wordMap.get(word);
if(ref == null) ref = word;
HashMap<String,String> canonicalWord = getWord(ref);
report.add(
canonicalWord.get("word"),
wordCounts.get(word),
canonicalWord.get("flagLevel"),
canonicalWord.get("flagText"),
canonicalWord.get("flagFor"),
urlBase.concat(canonicalWord.get("slug"))
);
}
return report;
}
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String[] vals = req.getParameterValues("input");
if(vals != null) {
Report r = process(vals);
PrintWriter out = resp.getWriter();
ArrayList<String> acceptHeaders = new ArrayList<String>();
for(Enumeration<String> acceptHeaders_e = req.getHeaders("Accept"); acceptHeaders_e.hasMoreElements(); ) {
acceptHeaders.add(acceptHeaders_e.nextElement());
}
if(acceptHeaders.contains("text/json")) {
resp.setContentType("text/json");
out.println(r.toJSONObject());
} else {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println(" <title>Language Checker</title>");
out.println(" <link rel=\"stylesheet\" type=\"text/css\" href=\"base.css\" />");
out.println(" <link href=\"https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap\" rel=\"stylesheet\">");
out.println("</head>");
out.println("<body>");
out.println(" <h1>Language checker results</h1>");
out.println(r.toHTML());
out.println("</body></html>");
}
} else {
throw new RuntimeException("No data");
}
}
// public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ArrayList<String> arr = new ArrayList<String>();
// try {
// BufferedReader inputData = req.getReader();
// String line;
// while((line = inputData.readLine()) != null) {
// arr.add(line);
// }
// } catch (IOException e) {
// // FIXME
// }
// if(arr.size() > 0) {
// Report r = process((String[]) arr.toArray(new String[0]));
// PrintWriter out = resp.getWriter();
// out.println(r.toJSONObject());
// } else {
// throw new RuntimeException("No data");
// }
// }
public void destroy() {
// Close the database
}
}

View File

@ -0,0 +1,62 @@
package uk.org.mafoo.selfdefined;
import java.util.ArrayList;
import org.json.*;
class Report {
ArrayList<ReportWord> data;
public Report() {
data = new ArrayList<ReportWord>();
}
public void add(String word, Integer count, String flagLevel, String flagText, String flagFor, String url) {
data.add(new ReportWord(word, count, flagLevel, flagText, flagFor, url));
}
public String toString() {
StringBuilder s = new StringBuilder();
s.append("[");
int n = 0;
for (ReportWord w : data) {
if(n++ > 0) { s.append(","); }
s.append(w);
}
s.append("]");
return s.toString();
}
public JSONObject toJSONObject() {
JSONArray arr = new JSONArray();
for(ReportWord w : data) {
arr.put(w.toJSONObject());
}
JSONObject obj = new JSONObject();
obj.put("results", arr);
return obj;
}
public String toHTML() {
StringBuilder str = new StringBuilder();
str.append("<table border='1'>\n");
str.append(" <thead>\n");
str.append(" <th>Word</th>\n");
str.append(" <th>Count</th>\n");
str.append(" <th>Flag Level</th>\n");
str.append(" <th>Flag Text</th>\n");
str.append(" <th>See-Also</th>\n");
str.append(" <th>URL</th>\n");
str.append(" </thead>\n");
str.append(" <tbody>\n");
for(ReportWord w : data) {
str.append(w.toHTML());
}
str.append(" </tbody>\n");
str.append("</table>\n");
return str.toString();
}
}

View File

@ -0,0 +1,54 @@
package uk.org.mafoo.selfdefined;
import org.json.JSONObject;
class ReportWord {
String word;
Integer count;
String flagLevel;
String flagText;
String flagFor;
String url;
public ReportWord(String word, Integer count, String flagLevel, String flagText, String flagFor, String url) {
this.word = word;
this.count = count;
this.flagLevel = flagLevel;
this.flagText = flagText;
this.flagFor = flagFor;
this.url = url;
}
public String toString() {
return String.format(
"{word=%s,count=%d,flagLevel=%s,flagText=%s,flagFor=%s,url=%s}",
word, count, flagLevel, flagText, flagFor, url
);
}
public JSONObject toJSONObject() {
JSONObject jo = new JSONObject();
jo.put("word", word);
jo.put("count", count);
jo.put("flagLevel", flagLevel);
jo.put("flagText", flagText);
jo.put("flagFor", flagFor);
jo.put("url", url);
return jo;
}
public String toHTML() {
StringBuilder str = new StringBuilder();
str.append("<tr>\n");
str.append(" <td>"); str.append(word); str.append("</td>\n");
str.append(" <td>"); str.append(count); str.append("</td>\n");
str.append(" <td>"); str.append(flagLevel); str.append("</td>\n");
str.append(" <td>"); str.append(flagText); str.append("</td>\n");
str.append(" <td>"); str.append(flagFor); str.append("</td>\n");
str.append(" <td><a href='"); str.append(url); str.append("'>ref</a></td>\n");
str.append("</tr>\n");
return str.toString();
}
}

21
WEB-INF/web.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>S</display-name>
<description>S</description>
<servlet>
<servlet-name>CheckerServlet</servlet-name>
<servlet-class>uk.org.mafoo.selfdefined.Checker</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckerServlet</servlet-name>
<url-pattern>/c</url-pattern>
</servlet-mapping>
</web-app>

22
index.jsp Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Language Checker</title>
<link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<body>
<h1>Language checker</h1>
<p>Language checker based on the <a href="https://www.selfdefined.app/">Self Defined</a> project</p>
<blockquote>
Self-Defined seeks to provide more inclusive, holistic, and fluid definitions to reflect the diverse perspectives of the modern world.
With the foundation of vocabulary, we can begin to understand lived experiences of people different than us. Words can provide us with a sense of identify and allow us to find kinship through common experiences.
</blockquote>
<form action="Checker" method="post">
<!--<label for="input">Text to be checked</label>-->
<textarea id="input" size="25" name="input" rows="20" cols="120" value=""></textarea>
<input type="submit" value="Check" />
</form>
<p>You can also POST to the <tt>/Checker</tt> endpoint specifying <tt>Accept: text/json</tt>.</p>
</body>