Importing WformServices and GlemmServices
Change-Id: Ifa95576d69e0d3863f63d3fdedb48c2c21cf64bc
diff --git a/GlemmClient/.classpath b/GlemmClient/.classpath
new file mode 100644
index 0000000..0915405
--- /dev/null
+++ b/GlemmClient/.classpath
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ <attribute name="org.eclipse.jst.component.nondependency" value=""/>
+ </attributes>
+ </classpathentry>
+ <classpathentry combineaccessrules="false" kind="src" path="/GlemmServices"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/JsonTraverse"/>
+ <classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v9.0">
+ <attributes>
+ <attribute name="owner.project.facets" value="jst.utility"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_231">
+ <attributes>
+ <attribute name="owner.project.facets" value="java"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/GlemmClient/.project b/GlemmClient/.project
new file mode 100644
index 0000000..23dcb98
--- /dev/null
+++ b/GlemmClient/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>GlemmClient</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/GlemmClient/.settings/org.eclipse.jdt.core.prefs b/GlemmClient/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..4e4a3ad
--- /dev/null
+++ b/GlemmClient/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/GlemmClient/.settings/org.eclipse.m2e.core.prefs b/GlemmClient/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/GlemmClient/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/GlemmClient/.settings/org.eclipse.wst.common.component b/GlemmClient/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..96f1e14
--- /dev/null
+++ b/GlemmClient/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="GlemmClient">
+ <wb-resource deploy-path="/" source-path="/src"/>
+ </wb-module>
+</project-modules>
diff --git a/GlemmClient/.settings/org.eclipse.wst.common.project.facet.core.xml b/GlemmClient/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..3eca3e1
--- /dev/null
+++ b/GlemmClient/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <runtime name="Apache Tomcat v9.0"/>
+ <installed facet="java" version="1.8"/>
+ <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/GlemmClient/.settings/org.eclipse.wst.validation.prefs b/GlemmClient/.settings/org.eclipse.wst.validation.prefs
new file mode 100644
index 0000000..04cad8c
--- /dev/null
+++ b/GlemmClient/.settings/org.eclipse.wst.validation.prefs
@@ -0,0 +1,2 @@
+disabled=06target
+eclipse.preferences.version=1
diff --git a/GlemmClient/pom.xml b/GlemmClient/pom.xml
new file mode 100644
index 0000000..c5030f9
--- /dev/null
+++ b/GlemmClient/pom.xml
@@ -0,0 +1,53 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>de.korap.services.glemm.client</groupId>
+ <artifactId>GlemmClient</artifactId>
+ <version>0.2-Test</version>
+ <name>Glemm Client library</name>
+ <description>Client for communication with Glemm Services</description>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.7.0</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.9.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.9.6</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.9.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>de.korap.json</groupId>
+ <artifactId>JsonTraverse</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>de.korap.services</groupId>
+ <artifactId>utils</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/GlemmClient/src/de/korap/services/glemm/client/GlemmClient.java b/GlemmClient/src/de/korap/services/glemm/client/GlemmClient.java
new file mode 100644
index 0000000..2befa42
--- /dev/null
+++ b/GlemmClient/src/de/korap/services/glemm/client/GlemmClient.java
@@ -0,0 +1,343 @@
+package de.korap.services.glemm.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.net.*;
+import java.util.Properties;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.korap.services.LemmaResponse;
+import de.korap.services.utils.Utils;
+
+/*
+ * Notes on encoding URLs:
+ *
+ * -> http://server:port/GlemmServices-0.2-test/lemma/info/Haus?opts=comp+other
+ * - in this URL, 'Haus' is not part of the query but part of the path.
+ * - the query starts behind the '?'.
+ * -> http://server:port/GlemmServices-0.2-test/lemma/info?lemma=Haus&opts=comp+other
+ * - that would be correct: now lemma=Haus is part of the query.
+ * - But fortunatly, URI.toASCIIString() will also urlencode lemma 'Haus' as part
+ * of the path in the 1st URL above.
+ */
+
+public class GlemmClient {
+
+ /* constants that may be rewritten by properties */
+ String URLGlemmServer = "http://c0r4ft";
+ int GlemmPort = 40913;
+ String URLGlemmServices = "GlemmServices-0.1-SNAPSHOT";
+ String LemmaRequestPath = "index/info/lemma";
+
+ public PrintStream fout = null;
+ public PrintStream ferr = null;
+
+ public GlemmClient(PrintStream fout, PrintStream ferr)
+
+ {
+ this.fout = fout;
+ this.ferr = ferr;
+
+ fout.printf("Debug: GlemmClient: constructor called.\n");
+ }
+
+ /* GlemmClient constructor:
+ *
+ * init constants from properties.
+ *
+ * 22.10.21/FB
+ */
+
+ public GlemmClient(Properties props, PrintStream fout, PrintStream ferr)
+
+ {
+ String
+ tmp;
+
+ this.fout = fout;
+ this.ferr = ferr;
+
+ URLGlemmServer = Utils.getConstantFromProperties(props, "URLGlemmServer", "http://c0r4ft");
+ tmp = Utils.getConstantFromProperties(props, "GlemmPort", "40913");
+ GlemmPort = Integer.parseInt(tmp);
+ URLGlemmServices= Utils.getConstantFromProperties(props, "URLGlemmServices", "GlemmServices-0.1-SNAPSHOT");
+ LemmaRequestPath= Utils.getConstantFromProperties(props, "LemmaRequestPath", "index/info/lemma");
+ }
+
+ public int GlemmConnect()
+
+ {
+ final String func = "GlemmConnect";
+
+ fout.printf("Debug: %s: starting to connect to GLEMM Services...\n", func);
+
+ return 0;
+ } // GlemmConnect
+
+ /*
+ * sendQuery:
+ * - sends a lemma query over the network to the Glemm Services.
+ * Notes:
+ * - classical use of URLs, HttpURLConnections, etc. out of the box of
+ * the java library; no other library is needed.
+ *
+ * Arguments:
+ * lemmaQuery: e.g. Schuh or Schuh?opts=flex+comp+other
+ *
+ * Returns:
+ * - list of wordforms (= lemma expansions).
+ *
+ * 27.04.20/FB
+ * 10.05.21/FB :
+ * - converting lemmaQuery using urlencoding.
+ * note: - JVM on COSMAS II-lunix is using ISO-8859-1 per default.
+ * - currently, modifying default character encoding (at JVM start) is discouraged.
+ * - sendQuery() get JSON [UTF-8] back from the GlemmServices.
+ * - list of wfs returned [UTF-8] have to be converted to [ISO8859-1] before being converted
+ * by transform_JSON2Obj() to JSON [UTF-8]. Otherwise UTF-8 chars will be wrongly
+ * converted to UTF-8 (convert UTF-8 to UTF-8 = carbage).
+ * - lemmaQuery: using URI + uri.toASCIIString() for "lemma?opts=flex+comp":
+ * this urlencodes the lemma part but not the query parameters behind the '?'.
+ * 28.10.21/FB
+ */
+
+ public LemmaResponse sendQuery(String lemmaQuery)
+
+ {
+ final String func = "sendQuery";
+ String
+ URLasString;
+ URL
+ url = null;
+ URI
+ uri = null;
+ HttpURLConnection
+ con;
+ int
+ status;
+ String
+ responseContent;
+ LemmaResponse
+ lemResp = null;
+ final boolean
+ bURLencode = true; // if true: urlencode query.
+ final boolean
+ bLat1 = true; // if true: convert from UTF-8 to ISO8859-1
+
+ this.fout.printf("Debug: %s: requested lemma = '%s'.\n", func, lemmaQuery);
+
+ if( bURLencode )
+ {
+ URLasString = String.format("%s:%d/%s/%s/%s",
+ URLGlemmServer,
+ GlemmPort,
+ URLGlemmServices,
+ LemmaRequestPath, // = path without lemma which is part of the path.
+ lemmaQuery); // not urlencoded yet!
+ try {
+ uri = new URI(URLasString);
+ // uri.toASCIIString: urlencodes only the lemma (OK).
+ this.fout.printf("Debug: %s: uri als ASCII string = '%s'.\n", func, uri.toASCIIString());
+ }
+ catch (URISyntaxException e1) {
+ this.ferr.printf("Error: %s: cannot convert to URI: '%s'!\n", func, URLasString);
+ e1.printStackTrace();
+ return null;
+ }
+
+ try {
+ url = new URL(uri.toASCIIString()); // which translates the lemma, but not the query part behind the '?' to urlencoding.
+ this.fout.printf("Debug: %s: creating URL='%s'.\n", func, url.toString());
+ }
+ catch (MalformedURLException e) {
+ this.ferr.printf("Error: %s: cannot build URL from '%s'!\n", func, uri.toASCIIString());
+ e.printStackTrace();
+ return null;
+ }
+ }
+ else
+ {
+ // formulate request as URL:
+ URLasString = String.format("%s:%d/%s/%s/%s",
+ URLGlemmServer,
+ GlemmPort,
+ URLGlemmServices,
+ LemmaRequestPath,
+ lemmaQuery);
+
+ try {
+ url = new URL(URLasString);
+ this.fout.printf("Debug: %s: creating URL='%s'.\n", func, url.toString());
+ }
+ catch (MalformedURLException e) {
+ this.ferr.printf("Error: %s: cannot build URL from '%s'!\n", func, URLasString);
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ // build the connection:
+
+ try {
+ con = (HttpURLConnection) url.openConnection();
+ }
+ catch (IOException e) {
+ this.ferr.printf("Error: %s: cannot connect to URL='%s'!\n", func, URLasString);
+ e.printStackTrace();
+ return null;
+ }
+
+ try {
+ con.setRequestMethod("GET");
+ con.setRequestProperty("Content-Type", "application/json");
+ con.setRequestProperty("Accept", "application/json");
+ con.setUseCaches(false);
+ }
+ catch (ProtocolException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ // sending the request & waiting for the response with the wf lists:
+
+ try {
+ if( (status = con.getResponseCode()) == HttpURLConnection.HTTP_OK )
+ {
+ this.fout.printf("Debug: %s: HTTP return status = OK.\n", func);
+ responseContent = getResponseContent(con);
+ if( responseContent == null )
+ return null;
+ this.fout.printf("Debug: %s: HTTP Response Content = '%s'.\n", func, responseContent);
+ // 28.10.21/FB
+ if( bLat1 )
+ {
+ String
+ responseContentLat1 = new String(responseContent.getBytes("ISO-8859-1"), "utf-8");
+ this.fout.printf("Debug: %s: Response Content = '%s' [Lat1].\n", func, responseContentLat1);
+ responseContent = responseContentLat1;
+ }
+ }
+ else
+ {
+ this.fout.printf("Debug: %s: HTTP return status = %d (%s)!\n", func, status, con.getResponseMessage());
+ con.disconnect();
+ return null;
+ }
+ }
+ catch (IOException e) {
+ this.ferr.printf("Error: %s: while sending request to GlemmServices!\n", func);
+ e.printStackTrace();
+ con.disconnect();
+ return null;
+ }
+
+ // converting JSON Response Content to object:
+ lemResp = transform_JSON2Obj(responseContent);
+
+ this.fout.printf("Debug: %s: lemResp='%s'.\n", func, lemResp.toString());
+
+ // disconnecting:
+ con.disconnect();
+
+ // returning lemma Response Object:
+ return lemResp; // ok.
+
+ } // sendQuery
+
+
+ /* getResponseContent:
+ *
+ * - returns the HTTP Response Content on con.
+ * Returns:
+ * - either the Content as String.
+ * - or null if an error occures.
+ * 29.04.20/FB
+ */
+
+ private String getResponseContent(HttpURLConnection con)
+
+ {
+ final String func = "getResponseContent";
+ BufferedReader
+ in;
+ String
+ inputLine;
+ StringBuffer
+ content;
+
+ try {
+ in = new BufferedReader(
+ new InputStreamReader(con.getInputStream()));
+ }
+ catch (IOException e) {
+ this.ferr.printf("Error: %s: cannot read returned HTTP Content!\n", func);
+ e.printStackTrace();
+ return null;
+ }
+
+ content = new StringBuffer();
+
+ try {
+ while ((inputLine = in.readLine()) != null)
+ {
+ content.append(inputLine);
+ }
+ }
+ catch (IOException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ in.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ // return Response Content:
+ return content.toString();
+
+ } // getResponseContent
+
+ /* transform_JSON2Obj
+ * - transforms the JSON formated Glemm Response content to an
+ * object.
+ * 29.04.20/FB
+ */
+
+ private LemmaResponse transform_JSON2Obj(String jsonString)
+
+ {
+ ObjectMapper
+ objMapper = null;
+ LemmaResponse
+ lemResp;
+
+ objMapper = new ObjectMapper();
+
+ try {
+ lemResp = objMapper.readValue(jsonString, LemmaResponse.class);
+ }
+ catch (JsonParseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ catch (JsonMappingException e) {
+ e.printStackTrace();
+ return null;
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return lemResp;
+ } // transform_JSON2Obj
+
+} // class GlemmClient