Importing WformServices and GlemmServices
Change-Id: Ifa95576d69e0d3863f63d3fdedb48c2c21cf64bc
diff --git a/JsonTraverse/.classpath b/JsonTraverse/.classpath
new file mode 100644
index 0000000..1ff5a38
--- /dev/null
+++ b/JsonTraverse/.classpath
@@ -0,0 +1,26 @@
+<?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 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 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/JsonTraverse/.project b/JsonTraverse/.project
new file mode 100644
index 0000000..2313174
--- /dev/null
+++ b/JsonTraverse/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>JsonTraverse</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/JsonTraverse/.settings/org.eclipse.jdt.core.prefs b/JsonTraverse/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..4e4a3ad
--- /dev/null
+++ b/JsonTraverse/.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/JsonTraverse/.settings/org.eclipse.m2e.core.prefs b/JsonTraverse/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/JsonTraverse/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/JsonTraverse/.settings/org.eclipse.wst.common.component b/JsonTraverse/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..049ec8b
--- /dev/null
+++ b/JsonTraverse/.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="JsonTraverse">
+ <wb-resource deploy-path="/" source-path="/src"/>
+ </wb-module>
+</project-modules>
diff --git a/JsonTraverse/.settings/org.eclipse.wst.common.project.facet.core.xml b/JsonTraverse/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..3eca3e1
--- /dev/null
+++ b/JsonTraverse/.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/JsonTraverse/.settings/org.eclipse.wst.validation.prefs b/JsonTraverse/.settings/org.eclipse.wst.validation.prefs
new file mode 100644
index 0000000..04cad8c
--- /dev/null
+++ b/JsonTraverse/.settings/org.eclipse.wst.validation.prefs
@@ -0,0 +1,2 @@
+disabled=06target
+eclipse.preferences.version=1
diff --git a/JsonTraverse/pom.xml b/JsonTraverse/pom.xml
new file mode 100644
index 0000000..caf90bf
--- /dev/null
+++ b/JsonTraverse/pom.xml
@@ -0,0 +1,44 @@
+<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.json</groupId>
+ <artifactId>JsonTraverse</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>JsonTraverse</name>
+ <description>Methods for traversing a Json Tree (KorallQuery) and extracting/rewriting data</description>
+
+ <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>provided</scope>
+ </dependency>
+ </dependencies>
+
+
+ <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>
+</project>
\ No newline at end of file
diff --git a/JsonTraverse/src/de/korap/json/JsonTraverse.java b/JsonTraverse/src/de/korap/json/JsonTraverse.java
new file mode 100644
index 0000000..60e87fa
--- /dev/null
+++ b/JsonTraverse/src/de/korap/json/JsonTraverse.java
@@ -0,0 +1,158 @@
+package de.korap.json;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+public class JsonTraverse
+
+{
+ // kind of operations during JsonTree Traversal:
+
+ public final static int COLLECT = 1;
+ public final static int REWRITE = 2; // replace lemmata by refs on expansion list.
+ public final static int REWRITE_EXP = 3; // replace lemmata by expansion list [wf,wf,...].
+
+ PrintStream
+ fout, // to be set by caller, replaces stdout.
+ ferr; // to be set by caller, replaces stderr.
+
+ /*
+ * traverseJsonTree
+ *
+ * - traverses JsonTree starting at node.
+ * - tPath: collects lemmata and contains references to rewrite.
+ * - mode: operation mode COLLECT, REWRITE, REWRITE_EXP.
+ * 31.03.20/FB
+ */
+
+ static final public void traverseJsonTree(
+ JsonNode node,
+ TraversedPath tPath,
+ final int mode,
+ final PrintStream fout,
+ final PrintStream ferr )
+
+ {
+ final String func = "traverseJsonTree";
+ boolean
+ isFound = false;
+ boolean
+ bDebug = false;
+
+ if( node.isObject())
+ {
+ Iterator<String> fieldNames = node.fieldNames();
+ if( bDebug )
+ fout.printf("Debug:%s: object: { \n", func);
+
+ while(fieldNames.hasNext())
+ {
+ String fieldName = fieldNames.next();
+
+ // path search under 'query':
+ if( tPath.checkPath(fieldName, node.get(fieldName), mode, fout) )
+ isFound = true;
+
+ JsonNode fieldValue = node.get(fieldName);
+ if( bDebug )
+ fout.printf("Debug:%s: key='%s':\n", func, fieldName);
+ traverseJsonTree(fieldValue, tPath, mode, fout, ferr);
+ }
+
+ if( bDebug )
+ fout.printf("Debug:%s: } : end of object.\n", func);
+
+ if( (mode == REWRITE || mode == REWRITE_EXP) && isFound )
+ {
+ tPath.rewriteObjNode(node, mode, fout);
+ fout.printf("Debug:%s: after rewrite: node='%s'.\n", func, node.toString());
+ }
+ }
+ else if(node.isArray())
+ {
+ if( bDebug )
+ fout.printf("Debug:%s: array: [\n", func);
+
+ ArrayNode arrayNode = (ArrayNode) node;
+ for(int i = 0; i < arrayNode.size(); i++)
+ {
+ JsonNode arrayElement = arrayNode.get(i);
+ traverseJsonTree(arrayElement, tPath, mode, fout, ferr);
+ }
+ if( bDebug )
+ fout.printf("Debug:%s: ] end of array.\n", func);
+ }
+ else {
+ // JsonNode node represents a single value field - do something with it.
+ if( bDebug )
+ fout.printf("Debug:%s: single value field = '%s'\n", func, node.asText());
+ }
+
+ } // traverseJsonTree
+
+ /*
+ * isPathLemmaQuery
+ *
+ * returns: lemma as a String, if path & lemma were found.
+ * else: null.
+ * 04.04.20/FB
+ */
+
+ static private String isPathLemmaQuery(JsonNode node, PrintStream fout, PrintStream ferr)
+
+ {
+ final String func = "isPathLemmaQuery";
+ int
+ nMatches = 0;
+ String
+ lemma = null;
+ boolean
+ bDebug = false;
+
+ if( node.isObject() == false )
+ return null;
+
+ Iterator<String> fieldNames = node.fieldNames();
+
+ while(fieldNames.hasNext())
+ {
+ String fieldName = fieldNames.next();
+ String fieldValue = node.get(fieldName).asText();
+
+ if( fieldName.equals("@type") && fieldValue.equals("koral:token") )
+ nMatches++;
+ else if( fieldName.equals("wrap") && node.get(fieldName).isObject() == true )
+ {
+ Iterator<String>fieldNames2 = node.get(fieldName).fieldNames();
+ while( fieldNames2.hasNext())
+ {
+ String fn = fieldNames2.next();
+ if( fn.equals("@type") && node.get(fn).asText().equals("koral:term") )
+ nMatches++;
+ else if( fn.equals("key") )
+ {
+ lemma = node.get(fn).asText();
+ }
+ else if( fn.equals("layer") && node.get(fn).asText().equals("lemma") )
+ nMatches++;
+ } // while
+ }
+ } // while
+
+ if( bDebug )
+ fout.printf("Debug: %s: nMatches=%d.\n", func, nMatches);
+
+ if( nMatches == 3 && lemma != null )
+ {
+ fout.printf("Debug:%s: path found to lemma '%s'.\n", func, lemma);
+ return lemma;
+ }
+
+ // path of lemma not found:
+ return null;
+ } // isPathLemmaQuery
+
+} // JsonTraverse
diff --git a/JsonTraverse/src/de/korap/json/TraversedPath.java b/JsonTraverse/src/de/korap/json/TraversedPath.java
new file mode 100644
index 0000000..65dc242
--- /dev/null
+++ b/JsonTraverse/src/de/korap/json/TraversedPath.java
@@ -0,0 +1,426 @@
+package de.korap.json;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import de.korap.services.LemmaResponse;
+
+public class TraversedPath {
+
+ boolean
+ insideQuery;
+ int
+ level;
+ boolean
+ okType;
+ int
+ queryType; // LEMMA, etc.
+ List<String>
+ lemmata = null; // the extracted lemmata.
+ String
+ lemma = null; // currently found lemma.
+ List<String>
+ refs = null; // references to expansion lists returned from GLEMM.
+ // same order than lemmata in lemmata[].
+ JsonNode
+ wrapNode = null; // node under 'wrap' where properties of lemma term
+ // are stored, here called level 2.
+ ObjectMapper
+ objMapper = null;
+ int
+ iRewrite = 0; // index of lemma currently rewritten (in lemmata).
+ List<List<String>>
+ expansionLists = null; // each element of this list is an expansion list
+ // i.e. a list of wfs for a lemma.
+ List<LemmaResponse> // list of lemmaResponse corresponding to each
+ lemRespList = null; // lemma of list lemmata.
+ // todo: should replace List expansionLists.
+
+ public static final int NONE = 0; // undefined.
+ public static final int LEMMA = 1; // GLEMM lemma.
+ public static final int REGEXPR = 2; // COSMAS II's regex on word level.
+ public static final int WILDCARD = 3; // COSMAS II's wildcard expression.
+
+ public TraversedPath(ObjectMapper obj)
+
+ {
+ objMapper = obj;
+ insideQuery = false;
+ okType = false;
+ level = 0;
+ queryType = NONE;
+ }
+
+ /*
+ * checkPath
+ *
+ * notes:
+ * - to be called for each property of an object.
+ * - collects all lemma subqueries inside a query tree.
+ * Arguments:
+ * fieldName: currently processed field name.
+ * node : JsonNode that is the value of fieldName.
+ * mode : COLLECT or REWRITE.
+ * Returns:
+ * - List<String>lemmata as a list of lemmata.
+ * - true if wrap-object to be rewritten has been found.
+ * 04.04.20/FB
+ */
+
+ boolean checkPath(final String fieldName, JsonNode node, final int mode, final PrintStream fout)
+
+ {
+ final String func = "checkPath";
+ final boolean
+ bLog = true; // for loging.
+ boolean
+ isFound = false; // true, when wrap-obj to be rewritten has been found.
+
+ if( insideQuery == false )
+ {
+ if( fieldName.equals("query") )
+ {
+ insideQuery = true;
+ level = 1;
+ okType = false;
+ }
+ return false;
+ }
+
+ if( level == 1 )
+ {
+ if( !okType && fieldName.equals("@type") )
+ {
+ if( node.isTextual() && node.asText().equals("koral:token") )
+ {
+ okType = true;
+ }
+ return false;
+ }
+ else if( okType && fieldName.equals("wrap") )
+ {
+ level = 2;
+ okType = false; // reset for next level.
+ queryType = NONE;
+ lemma = null;
+ wrapNode = node;
+ if( bLog && fout != null )
+ fout.printf("Debug: %s: wrap-Obj: '%s'\n", func, node.toString());
+ }
+ return false;
+ } // level 1
+
+ if( level == 2 )
+ {
+ if( fieldName.equals("@type") )
+ {
+ if( node.isTextual() && node.asText().equals("koral:term") )
+ okType = true;
+ else
+ { // reset, this is not the requested @type.
+ level = 1;
+ okType = false;
+ }
+ }
+ else if( fieldName.equals("layer") )
+ {
+ if( node.isTextual() && node.asText().equals("lemma") )
+ queryType = LEMMA;
+ }
+ else if( fieldName.equals("key") )
+ {
+ if( node.isTextual() )
+ lemma = node.asText();
+ }
+
+ if( okType && queryType == LEMMA && lemma != null )
+ {
+ if( mode == JsonTraverse.COLLECT )
+ {
+ if( lemmata == null )
+ lemmata = new ArrayList<String>();
+ lemmata.add(lemma);
+
+ if( bLog && fout != null )
+ fout.printf("Debug: %s: found: lemma='%s' as koral:term.\n", func, lemma);
+ }
+
+ isFound = true;
+
+ // reset before searching the next lemma (i.e. @type); supposing we stay underneath node 'query'.
+ level = 1;
+ okType = false;
+ }
+ return isFound;
+ } // level 2
+
+ return false;
+ } // checkPath
+
+ /* rewriteObjNode
+ * notes: https://mkyong.com/java/jackson-tree-model-example/
+ * 08.04.20/FB
+ */
+
+ public void rewriteObjNode(JsonNode node, final int mode, final PrintStream fout)
+
+ {
+ final String func = "rewriteObjNode";
+
+ if( mode == JsonTraverse.REWRITE )
+ {
+ fout.printf("Debug: %s: rewriting for lemma '%s' ('%s') > '%s'...\n", func,
+ lemma, lemmata.get(iRewrite), refs.get(iRewrite));
+
+ ((ObjectNode)node).put("key", "");
+ ((ObjectNode)node).put("layer", "orth");
+ ((ObjectNode)node).put("desc", "&"+lemma);
+ ((ObjectNode)node).put("hide", "key"); // TODO: must be ["key"] !
+ ((ObjectNode)node).put("ref", refs.get(iRewrite)); // TODO: must be ["key"] !
+ iRewrite++;
+ }
+ else // mode == REWRITE_EXP
+ {
+ fout.printf("Debug: %s: rewriting for lemma '%s'.\n", func, lemmata.get(iRewrite));
+
+ // inserting expansion list from corresponding Lemma Response obj:
+ ArrayNode
+ array = objMapper.createArrayNode();
+ LemmaResponse
+ lemResp = lemRespList.get(iRewrite);
+
+ for(int i=0; i<lemResp.listofWfs.size(); i++)
+ array.add(lemResp.listofWfs.get(i));
+
+ ((ObjectNode)node).set("key", array); // expansion list as Json Node.
+ ((ObjectNode)node).put("layer", "orth");
+ ((ObjectNode)node).put("desc", "&"+lemma);
+ ((ObjectNode)node).put("hide", "key"); // TODO: must be ["key"] !
+ iRewrite++;
+
+ /* old version :
+ ArrayNode
+ array = objMapper.createArrayNode();
+ List<String>
+ curList = expansionLists.get(iRewrite);
+
+ for(int i=0; i<curList.size(); i++)
+ array.add(curList.get(i));
+
+ ((ObjectNode)node).set("key", array); // expansion list.
+ ((ObjectNode)node).put("layer", "orth");
+ ((ObjectNode)node).put("desc", "&"+lemma);
+ ((ObjectNode)node).put("hide", "key"); // TODO: must be ["key"] !
+ iRewrite++;
+ */
+ }
+
+ } // rewriteObjNode
+
+ /*
+ * getLemmata
+ *
+ * returns list of lemmata collected and found in KoralQuery in String format.
+ *
+ * 06.04.20/FB
+ */
+
+ public String getLemmata()
+
+ {
+ return this.lemmata != null ? this.lemmata.toString() : "";
+ } // getLemmata
+
+ /* getLemmataCount
+ *
+ * returns no. of lemmata found in KoralQuery.
+ * 07.04.20/FB
+ */
+
+ public int getLemmaCount()
+
+ {
+ return this.lemmata != null ? this.lemmata.size() : 0;
+ } // getLemmataCount
+
+ /* getLemma:
+ * returns lemma by its index i.
+ * returns null if index out of range.
+ * 07.04.20/FB
+ */
+
+ public String getLemma(int i)
+
+ {
+ if( i < 0 || i > this.lemmata.size() )
+ return null;
+
+ return this.lemmata.get(i);
+ } // getLemma
+
+ /* setRef:
+ * - inserts a reference to a instanciation list into the
+ * list refs by index i.
+ * - index i must correspond to lemma i in list lemmata.
+ * - this method ensures that list refs is allocated with as much positions
+ * than the size of list lemmata.
+ * 07.04.20/FB
+ */
+
+ public void setRef(String ref)
+
+ {
+ if( this.refs == null )
+ {
+ int size = this.lemmata.size();
+ this.refs = new ArrayList<String>(size);
+ }
+
+ this.refs.add(ref);
+ } // setRef
+
+ /* getRefsCount:
+ * returns no. of references stored in list this.refs.
+ * 07.04.20/FB
+ */
+
+ public int getRefsCount()
+
+ {
+ return this.refs != null ? this.refs.size() : 0 ;
+ } // getRefsCount.
+
+ /* getRefsasString:
+ * - returns a printable list of references together with the corresponding
+ * lemmata.
+ * 07.04.20/FB
+ */
+
+ public String getRefsasString()
+
+ {
+ int
+ i, max;
+
+ if( this.lemmata == null || this.refs == null )
+ return "";
+
+ //max = this.lemmata.size() > this.refs.size() ?
+ // this.lemmata.size() : this.refs.size();
+
+ return this.refs.toString();
+ } // getRefsasString
+
+ /* addExpList
+ *
+ * adds an Expansion List for lemma i.
+ * Notes:
+ * - add expList in same order as lemmata stored in list lemmata.
+ * - todo: will be replaced by addLemmaResponse().
+ * 08.04.20/FB
+ */
+
+ public void addExpList(List expList)
+
+ {
+ if( expansionLists == null )
+ {
+ expansionLists = new ArrayList<List<String>>(lemmata.size());
+ }
+
+ expansionLists.add(expList);
+ } // addExpList
+
+ /*
+ * addLemmaResponse:
+ * - adds a LemmaResponse object for the correspondig lemma.
+ * 30.04.20/FB
+ *
+ */
+
+ public void addLemmaResponse(LemmaResponse lemResp)
+
+ {
+ if( this.lemRespList == null )
+ this.lemRespList = new ArrayList<LemmaResponse>(lemmata.size());
+
+ this.lemRespList.add(lemResp);
+ } // addLemmaResponse
+
+ /* rewriteSubQuery
+ *
+ * Rules: Old > New:
+ * "key": "&Haus" "key": "ref", or
+ * "key": "&Haus" "key": [Wf1, Wf2, ...].
+ * "layer": "lemma" "layer": "orth"
+ * "" "desc": "&Lemma" (neu)
+ * "" "hide": "key" (neu)
+ * Arguments:
+ * node : expected to be a "wrap"-object.
+ * 07.04.20/FB
+ */
+
+ protected void rewriteSubQuery(JsonNode node, final String lemma, final PrintStream fout)
+
+ {
+ final String func = "rewriteSubQuery";
+ final boolean
+ bLog = true;
+
+ if( bLog && fout != null)
+ fout.printf("Debug: %s: rewrite '%s'.\n", func, node.toString());
+
+ if( node.isObject() )
+ {
+ Iterator<String>
+ fieldNames = node.fieldNames();
+
+ while(fieldNames.hasNext())
+ {
+ String
+ fieldName = fieldNames.next();
+ JsonNode
+ fieldValue = node.get(fieldName);
+
+ if( fieldValue.isTextual() == false )
+ continue;
+
+ // path search under 'query':
+ if( fieldName.equals("key") )
+ {
+ if( bLog && fout != null )
+ fout.printf("Debug: %s: replacing %s='%s' by %s='%s'.\n",
+ func, fieldName, fieldValue.asText(),
+ fieldName, "[...]");
+
+ //JsonNode newNode = objMapper.createObjectNode();
+ //((ObjectNode)node).put("newkey", val);
+ ((ObjectNode)node).put("key", "[...]");
+
+ if( bLog && fout != null )
+ fout.printf("Debug: %s: %s='%s' (after replacement).\n", func, fieldName, node.get("key"));
+ }
+ else if( fieldName.equals("layer") )
+ {
+
+ }
+
+ } // while
+
+ if( bLog && fout != null )
+ fout.printf("Debug: %s: after rewriting, wrap-Obj='%s'.\n", func, node.toString());
+
+ } // object
+
+ } // rewriteSubQuery
+
+
+} // class TraversedPath
+
diff --git a/JsonTraverse/src/de/korap/services/LemmaResponse.java b/JsonTraverse/src/de/korap/services/LemmaResponse.java
new file mode 100644
index 0000000..bd6fd79
--- /dev/null
+++ b/JsonTraverse/src/de/korap/services/LemmaResponse.java
@@ -0,0 +1,104 @@
+package de.korap.services;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessorType;
+//import javax.xml.bind.annotation.XmlRootElement;
+//import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.*;
+
+/* General infos:
+ * http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
+ */
+
+/*
+ * LemmaResponse:
+ * Object to return by GlemmServices on a Lemma Request.
+ * Will be converted by glassfish to JSON.
+ * Notes:
+ * - header fields are prexided by 'head_' because JSON will be sorted alphabetically by JAXB.
+ *
+ * 24.01.20/FB
+ */
+
+//@XmlRootElement(name="LemmaResponse") - no effect
+@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+//@XmlType (name="abc", propOrder={"query", "options", "nWfs", "listofWfs"}) - no effect
+
+
+public class LemmaResponse
+
+{
+ final int PRINT_LIST_LIMIT = 10; // do not print more than 10 Wfs of listofWfs[].
+
+ public int
+ head_nWfs = 0;
+ public String
+ head_query = null,
+ head_options = null, // e.g. "+flex-sonst",
+ head_errMess = null;
+
+ public List<String>
+ listofWfs = null;
+
+ public LemmaResponse()
+ {
+
+ }
+
+ /* toString
+ * - formats partially a LemmaResponse obj to string.
+ * Returns formated string or null if an error occures.
+ * 29.04.20/FB
+ */
+
+ public String toString()
+
+ {
+ String
+ s = null;
+ //StringBuffer
+ // sb = new StringBuffer();
+
+ s = String.format("head: nWfs=%d, list=%s.", this.head_nWfs, this.listofWfs);
+
+ return s != null ? s : "";
+ } // toString
+
+ /* printPartialList:
+ *
+ * - prints the full list of Wfs or, if the list is longer than
+ * PRINT_LIST_LIMIT, only the beginning and the end of it.
+ *
+ * Returns the formated (partial) list of Wfs as a string or "[]" if
+ * the list is empty.
+ * 27.10.21/FB
+ */
+
+ public String printPartialList()
+
+ {
+ StringBuffer
+ sb = new StringBuffer();
+ final int
+ iMin = PRINT_LIST_LIMIT/2,
+ iMax = this.listofWfs.size()-(PRINT_LIST_LIMIT/2);
+
+ sb.append('[');
+
+ for(int i=0; i<this.listofWfs.size(); i++)
+ {
+ if( i<iMin || i>=iMax )
+ {
+ if(i>0)
+ sb.append(',');
+ sb.append(this.listofWfs.get(i));
+ }
+ }
+ sb.append(']');
+
+ return sb.toString();
+
+ } // printPartialList
+
+}