diff --git a/build.gradle.kts b/build.gradle.kts
index dd7970e..cc2cec8 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -100,10 +100,13 @@ dependencies {
implementation("io.github.eb4j:mdict4j:0.2.0")
implementation("org.jsoup:jsoup:1.14.3")
+ // for oxford-api
+ implementation("tokyo.northside:java-oxford-dictionaries:0.3.1")
+
// for video replay
implementation("uk.co.caprica:vlcj:4.7.1")
- implementation("com.formdev:flatlaf:1.6.4")
+ implementation("com.formdev:flatlaf:1.6.5")
// for projector support
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
diff --git a/src/main/java/io/github/eb4j/ebview/dictionary/DictionariesManager.java b/src/main/java/io/github/eb4j/ebview/dictionary/DictionariesManager.java
index e124c25..48ad7a0 100644
--- a/src/main/java/io/github/eb4j/ebview/dictionary/DictionariesManager.java
+++ b/src/main/java/io/github/eb4j/ebview/dictionary/DictionariesManager.java
@@ -20,6 +20,7 @@
import io.github.eb4j.ebview.data.DictionaryEntry;
import io.github.eb4j.ebview.data.IDictionary;
+import io.github.eb4j.ebview.dictionary.oxford.OxfordDriver;
import io.github.eb4j.ebview.utils.Stemmer;
import io.github.eb4j.ebview.utils.FileUtils;
import org.slf4j.Logger;
@@ -55,6 +56,7 @@ public DictionariesManager() {
factories.add(new StarDict());
factories.add(new PDic());
factories.add(new MDict());
+ dictionaries.add(new OxfordDriver());
stemmer = new Stemmer();
}
diff --git a/src/main/java/io/github/eb4j/ebview/dictionary/oxford/HTMLFormatter.java b/src/main/java/io/github/eb4j/ebview/dictionary/oxford/HTMLFormatter.java
new file mode 100644
index 0000000..e39942d
--- /dev/null
+++ b/src/main/java/io/github/eb4j/ebview/dictionary/oxford/HTMLFormatter.java
@@ -0,0 +1,84 @@
+package io.github.eb4j.ebview.dictionary.oxford;
+
+import io.github.eb4j.ebview.data.DictionaryEntry;
+import tokyo.northside.oxfordapi.dtd.Entry;
+import tokyo.northside.oxfordapi.dtd.Example;
+import tokyo.northside.oxfordapi.dtd.LexicalEntry;
+import tokyo.northside.oxfordapi.dtd.Pronunciation;
+import tokyo.northside.oxfordapi.dtd.Sense;
+import tokyo.northside.oxfordapi.dtd.Translation;
+
+import java.util.List;
+
+public final class HTMLFormatter {
+
+ private HTMLFormatter() {
+ }
+
+ public static DictionaryEntry formatTranslations(final LexicalEntry lexicalEntry) {
+ String title = lexicalEntry.getText();
+ StringBuilder sb = new StringBuilder("
");
+ for (Entry entry : lexicalEntry.getEntries()) {
+ for (Sense sense : entry.getSenses()) {
+ if (sense.getTranslations() == null) {
+ continue;
+ }
+ for (Translation translation : sense.getTranslations()) {
+ sb.append("- ").append(translation.getText()).append("
");
+ }
+ }
+ }
+ sb.append("
");
+ return new DictionaryEntry(title, sb.toString(), "oxford");
+ }
+
+ public static DictionaryEntry formatDefinitions(final LexicalEntry lexicalEntry) {
+ String title = lexicalEntry.getText();
+ String category = lexicalEntry.getLexicalCategory().getText();
+ StringBuilder sb = new StringBuilder("[").append(category).append("] ");
+ for (Entry entry : lexicalEntry.getEntries()) {
+ List pronunciations = entry.getPronunciations();
+ if (pronunciations != null) {
+ sb.append("");
+ for (Pronunciation pron: pronunciations) {
+ if (pron.getAudioFile() != null) {
+ sb.append("");
+ }
+ sb.append("[").append(pron.getPhoneticSpelling()).append("]");
+ if (pron.getAudioFile() != null) {
+ sb.append("");
+ }
+ }
+ sb.append(" ");
+ }
+ List etymologies = entry.getEtymologies();
+ if (etymologies != null) {
+ sb.append("");
+ for (String etymology : etymologies) {
+ sb.append(etymology);
+ }
+ sb.append("");
+ }
+ sb.append("");
+ for (Sense sense : entry.getSenses()) {
+ if (sense.getDefinitions() == null) {
+ continue;
+ }
+ for (String text : sense.getDefinitions()) {
+ sb.append("- ").append(text).append("
");
+ }
+
+ List examples = sense.getExamples();
+ if (examples != null) {
+ sb.append("");
+ for (Example ex : examples) {
+ sb.append("- ").append(ex.getText()).append("
");
+ }
+ sb.append("
");
+ }
+ }
+ sb.append("
");
+ }
+ return new DictionaryEntry(title, sb.toString(), "oxford");
+ }
+}
diff --git a/src/main/java/io/github/eb4j/ebview/dictionary/oxford/OxfordDriver.java b/src/main/java/io/github/eb4j/ebview/dictionary/oxford/OxfordDriver.java
new file mode 100644
index 0000000..8de8669
--- /dev/null
+++ b/src/main/java/io/github/eb4j/ebview/dictionary/oxford/OxfordDriver.java
@@ -0,0 +1,79 @@
+package io.github.eb4j.ebview.dictionary.oxford;
+
+import io.github.eb4j.ebview.data.DictionaryEntry;
+import io.github.eb4j.ebview.data.IDictionary;
+import tokyo.northside.oxfordapi.OxfordClient;
+import tokyo.northside.oxfordapi.OxfordClientException;
+import tokyo.northside.oxfordapi.dtd.LexicalEntry;
+import tokyo.northside.oxfordapi.dtd.Result;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class OxfordDriver implements IDictionary {
+
+ private final OxfordClient client;
+ private final String source;
+ private static final String APPID = ""; // FIXME
+ private static final String APPKEY = ""; // FIXME: add GUI to set and store encrypted
+ private final Map> cache = new HashMap<>();
+
+ public OxfordDriver() {
+ source = "en-gb";
+ client = new OxfordClient(APPID, APPKEY);
+ }
+
+ @Override
+ public String getDictionaryName() {
+ return "Oxford Dictionaries";
+ }
+
+ /**
+ * Read article's text.
+ *
+ * @param word The word to look up in the dictionary
+ * @return List of entries. May be empty, but cannot be null.
+ */
+ @Override
+ public List readArticles(final String word) {
+ return queryArticle(word, true);
+ }
+
+ /**
+ * Read article's text. Matching is predictive, so e.g. supplying "term"
+ * will return articles for "term", "terminology", "termite", etc.
+ *
+ * @param word The word to look up in the dictionary
+ * @return List of entries. May be empty, but cannot be null.
+ */
+ @Override
+ public List readArticlesPredictive(final String word) {
+ return queryArticle(word, false);
+ }
+
+ private List queryArticle(final String word, final boolean strict) {
+ if (!cache.containsKey(word)) {
+ List dictionaryEntries = new ArrayList<>();
+ try {
+ for (Result result: client.queryEntry(word, source, strict)) {
+ for (LexicalEntry lexicalEntry : result.getLexicalEntries()) {
+ dictionaryEntries.add(HTMLFormatter.formatDefinitions(lexicalEntry));
+ }
+ }
+ } catch (OxfordClientException oce) {
+ // when got connection/query error, return without any content.
+ return Collections.emptyList();
+ }
+ cache.put(word, dictionaryEntries);
+ }
+ return cache.get(word);
+ }
+
+
+ @Override
+ public void close() {
+ }
+}