Merge "Merge branch 'master' of ssh://korap.ids-mannheim.de:29418/KorAP/Koral"
diff --git a/README.md b/README.md
index db6206e..e9ab53e 100644
--- a/README.md
+++ b/README.md
@@ -97,13 +97,20 @@
git clone https://github.com/korap/Koral [install-dir]
cd [install-dir]
- mvn test
+ mvn test -Dhttps.protocols=TLSv1.2
mvn install
There is also a command line version. After installation, simply run
java -jar target/Koral-0.2.jar [query] [queryLanguage]
-
+
+## Prerequisites
+
+* Java 7 (OpenJDK or Oracle JDK with [JCE] (http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html))
+* [Git](http://git-scm.com/)
+* At least [Maven 3.2.1](https://maven.apache.org/)
+* Further dependencies are resolved by Maven.
+
## Authorship
Koral and KoralQuery were developed by Joachim Bingel,
diff --git a/pom.xml b/pom.xml
index e59fd5c..17b0666 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,271 +1,318 @@
<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>
+ 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.ids_mannheim.korap</groupId>
- <artifactId>Koral</artifactId>
- <version>0.22</version>
- <packaging>jar</packaging>
- <name>Koral</name>
- <url>http://maven.apache.org</url>
+ <groupId>de.ids_mannheim.korap</groupId>
+ <artifactId>Koral</artifactId>
+ <version>0.22</version>
+ <packaging>jar</packaging>
+ <name>Koral</name>
+ <url>http://maven.apache.org</url>
- <organization>
- <name>IDS Mannheim</name>
- <url>http://www.ids-mannheim.de/</url>
- </organization>
+ <organization>
+ <name>IDS Mannheim</name>
+ <url>http://www.ids-mannheim.de/</url>
+ </organization>
- <developers>
- <developer>
- <name>Joachim Bingel</name>
- <email>bingel@ids-mannheim.de</email>
- </developer>
- <developer>
- <name>Nils Diewald</name>
- <email>diewald@ids-mannheim.de</email>
- <url>http://nils-diewald.de</url>
- </developer>
- <developer>
- <name>Michael Hanl</name>
- <email>hanl@ids-mannheim.de</email>
- </developer>
- <developer>
- <name>Eliza Margaretha</name>
- <email>margaretha@ids-mannheim.de</email>
- </developer>
- </developers>
+ <developers>
+ <developer>
+ <name>Joachim Bingel</name>
+ <email>bingel@ids-mannheim.de</email>
+ </developer>
+ <developer>
+ <name>Nils Diewald</name>
+ <email>diewald@ids-mannheim.de</email>
+ <url>http://nils-diewald.de</url>
+ </developer>
+ <developer>
+ <name>Michael Hanl</name>
+ <email>hanl@ids-mannheim.de</email>
+ </developer>
+ <developer>
+ <name>Eliza Margaretha</name>
+ <email>margaretha@ids-mannheim.de</email>
+ </developer>
+ </developers>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <repositories>
- <repository>
- <id>id-maven-repo</id>
- <url>http://maven.indexdata.com</url>
- </repository>
- </repositories>
- <dependencies>
- <dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- <version>4.2</version>
- </dependency>
- <dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- <version>4.5.1</version>
- </dependency>
- <dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-maven-plugin</artifactId>
- <version>4.2</version>
- </dependency>
- <dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr-runtime</artifactId>
- <version>3.5</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>15.0</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.3.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.3.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.3.3</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.11</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- <dependency>
- <groupId>org.z3950.zing</groupId>
- <artifactId>cql-java</artifactId>
- <version>1.12</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.17</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>apache-log4j-extras</artifactId>
- <version>1.2.17</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.5</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.7.5</version>
- </dependency>
- <dependency>
- <groupId>eu.clarin.sru.fcs</groupId>
- <artifactId>fcs-simple-endpoint</artifactId>
- <version>1.3.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.lucene</groupId>
- <artifactId>lucene-core</artifactId>
- <version>5.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.lucene</groupId>
- <artifactId>lucene-analyzers-common</artifactId>
- <version>5.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.lucene</groupId>
- <artifactId>lucene-queryparser</artifactId>
- <version>5.2.1</version>
- </dependency>
- </dependencies>
- <build>
- <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
- <outputDirectory>${basedir}/target/classes</outputDirectory>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.3</version>
- <configuration>
- <compilerVersion>1.7</compilerVersion>
- <source>1.7</source>
- <target>1.7</target>
- </configuration>
- </plugin>
- <!--
- Formatter plugin for Eclipse based coding conventions
- http://maven-java-formatter-plugin.googlecode.com/svn/site/0.4/usage.html
- -->
- <plugin>
- <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
- <artifactId>maven-java-formatter-plugin</artifactId>
- <version>0.4</version>
- <configuration>
- <configFile>${project.basedir}/Format.xml</configFile>
- <overrideConfigCompilerVersion>true</overrideConfigCompilerVersion>
- <compilerSource>1.7</compilerSource>
- <compilerCompliance>1.7</compilerCompliance>
- <compilerTargetPlatform>1.7</compilerTargetPlatform>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <phase>install</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/../lib</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.5</version>
- <configuration>
- <archive>
- <manifest>
- <addClasspath>true</addClasspath>
- <classpathPrefix>../lib/</classpathPrefix>
- <mainClass>de.ids_mannheim.korap.query.serialize.QuerySerializer</mainClass>
- </manifest>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <!-- This plugin will help to build the ANTLR4 grammar on the fly. The
- recipe is based on http://stackoverflow.com/questions/15310628/ customize-maven-to-automatically-create-antlr4-grammar-java-files-on-build -->
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-maven-plugin</artifactId>
- <version>4.2</version>
- <executions>
- <execution>
- <id>poliqarpplus</id>
- <goals>
- <goal>antlr4</goal>
- </goals>
- <configuration>
- <sourceDirectory>${basedir}/src/main/antlr/poliqarpplus</sourceDirectory>
- <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/poliqarpplus</outputDirectory>
- <libDirectory>${basedir}/src/main/antlr/poliqarpplus</libDirectory>
- </configuration>
- <phase>generate-sources</phase>
- </execution>
- <execution>
- <id>annis</id>
- <goals>
- <goal>antlr4</goal>
- </goals>
- <configuration>
- <sourceDirectory>${basedir}/src/main/antlr/annis</sourceDirectory>
- <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/annis</outputDirectory>
- <libDirectory>${basedir}/src/main/antlr/annis</libDirectory>
- </configuration>
- <phase>generate-sources</phase>
- </execution>
- <execution>
- <id>collection</id>
- <goals>
- <goal>antlr4</goal>
- </goals>
- <configuration>
- <sourceDirectory>${basedir}/src/main/antlr/collection</sourceDirectory>
- <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/collection</outputDirectory>
- <libDirectory>${basedir}/src/main/antlr/collection</libDirectory>
- </configuration>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <!-- This plugin will help to build the ANTLR3 grammar on the fly. The
- recipe is based on http://stackoverflow.com/questions/15310628/ customize-maven-to-automatically-create-antlr4-grammar-java-files-on-build -->
- <groupId>org.antlr</groupId>
- <artifactId>antlr3-maven-plugin</artifactId>
- <version>3.5.1</version>
- <configuration>
- <sourceDirectory>${basedir}/src/main/antlr/cosmas</sourceDirectory>
- <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/cosmas</outputDirectory>
- <libDirectory>${basedir}/src/main/antlr</libDirectory>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>antlr</goal>
- </goals>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>id-maven-repo</id>
+ <url>http://maven.indexdata.com</url>
+ </repository>
+ <repository>
+ <id>CLARIN</id>
+ <name>CLARIN Repository</name>
+ <url>https://nexus.clarin.eu/content/repositories/Clarin</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <dependencies>
+ <!-- <dependency> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId>
+ <version>4.2</version> </dependency> -->
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>4.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>4.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr-runtime</artifactId>
+ <version>3.5</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>15.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.z3950.zing</groupId>
+ <artifactId>cql-java</artifactId>
+ <version>1.12</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>apache-log4j-extras</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ <dependency>
+ <groupId>eu.clarin.sru.fcs</groupId>
+ <artifactId>fcs-simple-endpoint</artifactId>
+ <version>1.3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-core</artifactId>
+ <version>5.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-analyzers-common</artifactId>
+ <version>5.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-queryparser</artifactId>
+ <version>5.2.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+ <outputDirectory>${basedir}/target/classes</outputDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <compilerVersion>1.7</compilerVersion>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <!-- <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>properties-maven-plugin</artifactId>
+ <version>1.0.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>set-system-properties</goal>
+ </goals>
+ <configuration>
+ <properties>
+ <property>
+ <name>https.protocols</name>
+ <value>TLSv1.2</value>
+ </property>
+ </properties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin> -->
+ <!-- <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>https.protocols</name>
+ <value>TLSv1.2</value>
+ </property>
+ </systemProperties>
+ <argLine>-Djava.https.protocols=TLSv1.2</argLine>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <systemPropertyVariables>
+ <https.protocols>TLSv1.2</https.protocols>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin> -->
+ <!-- Formatter plugin for Eclipse based coding conventions http://maven-java-formatter-plugin.googlecode.com/svn/site/0.4/usage.html -->
+ <plugin>
+ <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
+ <artifactId>maven-java-formatter-plugin</artifactId>
+ <version>0.4</version>
+ <configuration>
+ <configFile>${project.basedir}/Format.xml</configFile>
+ <overrideConfigCompilerVersion>true</overrideConfigCompilerVersion>
+ <compilerSource>1.7</compilerSource>
+ <compilerCompliance>1.7</compilerCompliance>
+ <compilerTargetPlatform>1.7</compilerTargetPlatform>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>install</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/../lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>../lib/</classpathPrefix>
+ <mainClass>de.ids_mannheim.korap.query.serialize.QuerySerializer</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <!-- This plugin will help to build the ANTLR4 grammar on the fly. The
+ recipe is based on http://stackoverflow.com/questions/15310628/ customize-maven-to-automatically-create-antlr4-grammar-java-files-on-build -->
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>4.2</version>
+ <executions>
+ <execution>
+ <id>poliqarpplus</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/antlr/poliqarpplus</sourceDirectory>
+ <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/poliqarpplus</outputDirectory>
+ <libDirectory>${basedir}/src/main/antlr/poliqarpplus</libDirectory>
+ </configuration>
+ <phase>generate-sources</phase>
+ </execution>
+ <execution>
+ <id>annis</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/antlr/annis</sourceDirectory>
+ <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/annis</outputDirectory>
+ <libDirectory>${basedir}/src/main/antlr/annis</libDirectory>
+ </configuration>
+ <phase>generate-sources</phase>
+ </execution>
+ <execution>
+ <id>collection</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/antlr/collection</sourceDirectory>
+ <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/collection</outputDirectory>
+ <libDirectory>${basedir}/src/main/antlr/collection</libDirectory>
+ </configuration>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!-- This plugin will help to build the ANTLR3 grammar on the fly. The
+ recipe is based on http://stackoverflow.com/questions/15310628/ customize-maven-to-automatically-create-antlr4-grammar-java-files-on-build -->
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr3-maven-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/antlr/cosmas</sourceDirectory>
+ <outputDirectory>${basedir}/src/main/java/de/ids_mannheim/korap/query/parse/cosmas</outputDirectory>
+ <libDirectory>${basedir}/src/main/antlr</libDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>antlr</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralBoundary.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralBoundary.java
new file mode 100644
index 0000000..0faee0e
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralBoundary.java
@@ -0,0 +1,46 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class KoralBoundary implements KoralObject {
+
+ private static final KoralType type = KoralType.BOUNDARY;
+
+ private int min;
+ private int max;
+
+ public KoralBoundary (int min, int max) {
+ this.min = min;
+ this.max = max;
+ }
+
+ public int getMin() {
+ return min;
+ }
+
+ public void setMin(int min) {
+ this.min = min;
+ }
+
+ public int getMax() {
+ return max;
+ }
+
+ public void setMax(int max) {
+ this.max = max;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", type.toString());
+ if (min > -1) {
+ map.put("min", getMin());
+ }
+ if (max > -1) {
+ map.put("max", getMax());
+ }
+ return map;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralDistance.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralDistance.java
new file mode 100644
index 0000000..eb88f58
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralDistance.java
@@ -0,0 +1,69 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class KoralDistance implements KoralObject {
+
+ private final KoralType type = KoralType.DISTANCE;
+ private String key = "w";
+ private String foundry;
+ private String layer;
+ private KoralBoundary boundary;
+
+ public KoralDistance (KoralBoundary boundary) {
+ this.boundary = boundary;
+ }
+
+ public KoralDistance (String key, KoralBoundary boundary) {
+ this(boundary);
+ this.key = key;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getFoundry() {
+ return foundry;
+ }
+
+ public void setFoundry(String foundry) {
+ this.foundry = foundry;
+ }
+
+ public String getLayer() {
+ return layer;
+ }
+
+ public void setLayer(String layer) {
+ this.layer = layer;
+ }
+
+ public KoralBoundary getBoundary() {
+ return boundary;
+ }
+
+ public void setBoundary(KoralBoundary boundary) {
+ this.boundary = boundary;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> distanceMap = new LinkedHashMap<String, Object>();
+ distanceMap.put("@type", type.toString());
+ distanceMap.put("key", key);
+ if (foundry != null){
+ distanceMap.put("foundry", foundry);
+ }
+ if (layer!=null){
+ distanceMap.put("layer", layer);
+ }
+ distanceMap.put("boundary", boundary.buildMap());
+ return distanceMap;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
index 090ecbc..b304f72 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
@@ -22,8 +22,9 @@
private boolean inOrder = false;
private List<KoralObject> operands;
- private List<Distance> distances;
+ private List<KoralDistance> distances;
private List<Frame> frames;
+ private KoralBoundary boundary;
public KoralGroup (KoralOperation operation) {
this.operation = operation;
@@ -45,11 +46,19 @@
this.operands = operands;
}
- public List<Distance> getDistances() {
+ public KoralOperation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(KoralOperation operation) {
+ this.operation = operation;
+ }
+
+ public List<KoralDistance> getDistances() {
return distances;
}
- public void setDistances(List<Distance> distances) {
+ public void setDistances(List<KoralDistance> distances) {
this.distances = distances;
}
@@ -61,6 +70,14 @@
this.frames = frames;
}
+ public KoralBoundary getBoundary() {
+ return boundary;
+ }
+
+ public void setBoundary(KoralBoundary boundary) {
+ this.boundary = boundary;
+ }
+
@Override
public Map<String, Object> buildMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
@@ -70,17 +87,21 @@
if (getDistances() != null) {
map.put("inOrder", isInOrder());
List<Map<String, Object>> distanceList = new ArrayList<Map<String, Object>>();
- for (Distance d : getDistances()) {
+ for (KoralDistance d : distances) {
distanceList.add(d.buildMap());
}
map.put("distances", distanceList);
}
List<Map<String, Object>> operandList = new ArrayList<Map<String, Object>>();
- for (Object o : getOperands()) {
+ for (Object o : operands) {
operandList.add(MapBuilder.buildQueryMap(o));
}
map.put("operands", operandList);
+
+ if (boundary != null) {
+ map.put("boundary", boundary.buildMap());
+ }
return map;
}
@@ -100,54 +121,4 @@
return "frame:"+value;
}
}
-
- public class Distance implements KoralObject {
-
- private final KoralType type = KoralType.DISTANCE;
- private String key;
- private String min;
- private String max;
-
- public Distance (String key, int min, int max) {
- this.key = key;
- this.min = String.valueOf(min);
- this.max = String.valueOf(max);
- }
-
- public String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
-
- public String getMin() {
- return min;
- }
-
- public void setMin(String min) {
- this.min = min;
- }
-
- public String getMax() {
- return max;
- }
-
- public void setMax(String max) {
- this.max = max;
- }
-
- @Override
- public Map<String, Object> buildMap() {
- Map<String, Object> distanceMap = new LinkedHashMap<String, Object>();
- distanceMap.put("@type", type.toString());
- distanceMap.put("key", getKey());
- distanceMap.put("min", getMin());
- distanceMap.put("max", getMax());
- return distanceMap;
-
- }
-
- }
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
index 06a39ce..7798566 100644
--- a/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
@@ -15,6 +15,8 @@
private final static KoralType type = KoralType.TOKEN;
private KoralObject wrappedObject;
+ public KoralToken () {}
+
public KoralToken (KoralObject wrappedObject) {
this.wrappedObject = wrappedObject;
}
@@ -30,7 +32,9 @@
public Map<String, Object> buildMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("@type", type.toString());
- map.put("wrap", wrappedObject.buildMap());
+ if (wrappedObject != null){
+ map.put("wrap", wrappedObject.buildMap());
+ }
return map;
}
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
index 488b4c8..42f5f83 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
@@ -20,6 +20,7 @@
import eu.clarin.sru.server.fcs.parser.ExpressionGroup;
import eu.clarin.sru.server.fcs.parser.ExpressionNot;
import eu.clarin.sru.server.fcs.parser.ExpressionOr;
+import eu.clarin.sru.server.fcs.parser.ExpressionWildcard;
import eu.clarin.sru.server.fcs.parser.Operator;
import eu.clarin.sru.server.fcs.parser.QueryNode;
import eu.clarin.sru.server.fcs.parser.RegexFlag;
@@ -76,9 +77,9 @@
return parseBooleanExpression(operands, KoralRelation.OR);
}
}
- // else if (queryNode instanceof ExpressionWildcard) {
- // for distance query, using empty token
- // }
+ else if (queryNode instanceof ExpressionWildcard) {
+ return new KoralToken();
+ }
else {
throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
"FCS diagnostic 11: Query is too complex.");
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
index 85be144..df1590f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
@@ -7,12 +7,15 @@
import de.ids_mannheim.korap.query.object.KoralContext;
import de.ids_mannheim.korap.query.serialize.util.KoralException;
import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import de.ids_mannheim.korap.query.object.KoralBoundary;
import de.ids_mannheim.korap.query.object.KoralGroup;
+import de.ids_mannheim.korap.query.object.KoralDistance;
import de.ids_mannheim.korap.query.object.KoralObject;
import de.ids_mannheim.korap.query.object.KoralOperation;
import de.ids_mannheim.korap.query.object.KoralSpan;
import de.ids_mannheim.korap.query.object.KoralTerm;
import de.ids_mannheim.korap.query.object.KoralGroup.Frame;
+import eu.clarin.sru.server.fcs.parser.ExpressionWildcard;
import eu.clarin.sru.server.fcs.parser.QueryDisjunction;
import eu.clarin.sru.server.fcs.parser.QueryGroup;
import eu.clarin.sru.server.fcs.parser.QueryNode;
@@ -34,7 +37,8 @@
this.expressionParser = new ExpressionParser();
}
- public KoralObject parseQueryNode(QueryNode queryNode) throws KoralException {
+ public KoralObject parseQueryNode(QueryNode queryNode)
+ throws KoralException {
if (queryNode instanceof QuerySegment) {
return parseQuerySegment((QuerySegment) queryNode);
@@ -43,63 +47,85 @@
return parseQueryNode(queryNode.getChild(0));
}
else if (queryNode instanceof QuerySequence) {
- return parseGroupQuery(queryNode.getChildren(),
- KoralOperation.SEQUENCE);
+ return parseSequenceQuery(queryNode.getChildren());
}
else if (queryNode instanceof QueryDisjunction) {
return parseGroupQuery(queryNode.getChildren(),
KoralOperation.DISJUNCTION);
}
else if (queryNode instanceof QueryWithWithin) {
- return parseWithinQuery((QueryWithWithin)queryNode);
+ return parseWithinQuery((QueryWithWithin) queryNode);
}
else if (queryNode instanceof SimpleWithin) {
- SimpleWithin withinNode = (SimpleWithin) queryNode;
- return parseWithinScope(withinNode.getScope());
- }
+ SimpleWithin withinNode = (SimpleWithin) queryNode;
+ return parseWithinScope(withinNode.getScope());
+ }
else {
throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
"FCS diagnostic 11:" + queryNode.getNodeType().name()
+ " is currently unsupported.");
}
}
- private KoralObject parseWithinQuery(QueryWithWithin queryNode) throws KoralException {
- KoralGroup koralGroup = new KoralGroup(KoralOperation.POSITION);
- koralGroup.setFrames(Arrays.asList(Frame.IS_AROUND));
-
- List<KoralObject> operands = new ArrayList<KoralObject>();
- operands.add(parseQueryNode(queryNode.getWithin()));
- operands.add(parseQueryNode(queryNode.getQuery()));
- koralGroup.setOperands(operands);
- return koralGroup;
- }
+
+ private KoralObject parseQuerySegment(QuerySegment segment)
+ throws KoralException {
+ int minOccurs = segment.getMinOccurs();
+ int maxOccurs = segment.getMaxOccurs();
- private KoralSpan parseWithinScope(Scope scope) throws KoralException{
- if (scope == null){
- throw new KoralException(StatusCodes.MALFORMED_QUERY,
- "FCS diagnostic 11: Within context is missing.");
- }
+ if ((minOccurs == 1) && (maxOccurs == 1)) {
+ return expressionParser.parseExpression(segment.getExpression());
+ }
+ else {
+ KoralBoundary boundary = new KoralBoundary(minOccurs, maxOccurs);
+ List<KoralObject> operand = new ArrayList<KoralObject>(1);
+ operand.add(expressionParser.parseExpression(segment
+ .getExpression()));
- KoralContext contextSpan;
- if (scope == Scope.SENTENCE) {
- contextSpan = KoralContext.SENTENCE;
- }
- else if (scope == Scope.PARAGRAPH){
- contextSpan = KoralContext.PARAGRAPH;
- }
- else if (scope == Scope.TEXT){
- contextSpan = KoralContext.TEXT;
- }
- else{
- throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
- "FCS diagnostic 11: Within scope " + scope.toString()
- + " is currently unsupported.");
- }
-
- return new KoralSpan(new KoralTerm(contextSpan));
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.REPETITION);
+ koralGroup.setBoundary(boundary);
+ koralGroup.setOperands(operand);
+ return koralGroup;
+ }
}
- private KoralGroup parseGroupQuery(List<QueryNode> children,
+ private KoralObject parseWithinQuery(QueryWithWithin queryNode)
+ throws KoralException {
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.POSITION);
+ koralGroup.setFrames(Arrays.asList(Frame.IS_AROUND));
+
+ List<KoralObject> operands = new ArrayList<KoralObject>();
+ operands.add(parseQueryNode(queryNode.getWithin()));
+ operands.add(parseQueryNode(queryNode.getQuery()));
+ koralGroup.setOperands(operands);
+ return koralGroup;
+ }
+
+ private KoralSpan parseWithinScope(Scope scope) throws KoralException {
+ if (scope == null) {
+ throw new KoralException(StatusCodes.MALFORMED_QUERY,
+ "FCS diagnostic 11: Within context is missing.");
+ }
+
+ KoralContext contextSpan;
+ if (scope == Scope.SENTENCE) {
+ contextSpan = KoralContext.SENTENCE;
+ }
+ else if (scope == Scope.PARAGRAPH) {
+ contextSpan = KoralContext.PARAGRAPH;
+ }
+ else if (scope == Scope.TEXT) {
+ contextSpan = KoralContext.TEXT;
+ }
+ else {
+ throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
+ "FCS diagnostic 11: Within scope " + scope.toString()
+ + " is currently unsupported.");
+ }
+
+ return new KoralSpan(new KoralTerm(contextSpan));
+ }
+
+ private KoralGroup parseGroupQuery(List<QueryNode> children,
KoralOperation operation) throws KoralException {
KoralGroup koralGroup = new KoralGroup(operation);
List<KoralObject> operands = new ArrayList<KoralObject>();
@@ -110,13 +136,104 @@
return koralGroup;
}
- private KoralObject parseQuerySegment(QuerySegment segment) throws KoralException {
- if ((segment.getMinOccurs() == 1) && (segment.getMaxOccurs() == 1)) {
- return expressionParser.parseExpression(segment.getExpression());
+ private KoralGroup parseSequenceQuery(List<QueryNode> children)
+ throws KoralException {
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.SEQUENCE);
+ List<KoralObject> operands = new ArrayList<KoralObject>();
+ KoralObject operand;
+
+ boolean isEmptyTokenFound = false;
+ boolean isLastTokenEmpty = false;
+ int size = children.size();
+
+ for (int i = 0; i < size; i++) {
+ QueryNode child = children.get(i);
+ if (i > 0 && i < size - 1 && findEmptyToken(child)) {
+ QuerySegment qs = (QuerySegment) child;
+ if (isLastTokenEmpty) {
+ updateBoundary(operands.get(operands.size() - 1), qs);
+ }
+ else {
+ operands.add(new KoralBoundary(qs.getMinOccurs(), qs
+ .getMaxOccurs()));
+ isLastTokenEmpty = true;
+ }
+ isEmptyTokenFound = true;
+ continue;
+ }
+ operand = parseQueryNode(child);
+ operands.add(operand);
+ isLastTokenEmpty = false;
}
- else {
- throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
- "FCS diagnostic 11: Query is too complex.");
+
+ if (isEmptyTokenFound) {
+ operands = createDistance(koralGroup,operands);
}
+
+ koralGroup.setOperands(operands);
+ return koralGroup;
+ }
+
+ private boolean findEmptyToken(QueryNode child) {
+ if (child instanceof QuerySegment
+ && ((QuerySegment) child).getExpression() instanceof ExpressionWildcard) {
+ return true;
+ }
+ return false;
+ }
+
+ private void updateBoundary(KoralObject koralObject, QuerySegment qs) {
+ KoralBoundary boundary = (KoralBoundary) koralObject;
+ boundary.setMin(boundary.getMin() + qs.getMinOccurs());
+ boundary.setMax(boundary.getMax() + qs.getMaxOccurs());
+ }
+
+ private List<KoralObject> createDistance(KoralGroup koralGroup, List<KoralObject> operands){
+ boolean isSubGroupAdded = false;
+ List<KoralObject> newOperands = new ArrayList<KoralObject>(
+ operands.size());
+ newOperands.add(operands.get(0));
+ int operandSize = operands.size();
+ for (int i = 1; i < operandSize - 1; i++) {
+ KoralObject operand = operands.get(i);
+ if (operand instanceof KoralBoundary) {
+ List<KoralDistance> distances = new ArrayList<KoralDistance>();
+ distances.add(new KoralDistance ((KoralBoundary) operand));
+
+ if (koralGroup.getDistances() != null){
+ KoralObject lastOperand = newOperands.get(newOperands.size()-1);
+ KoralGroup subGroup = createSubGroup(distances, lastOperand, operands.get(i+1));
+ newOperands.remove(lastOperand);
+ newOperands.add(subGroup);
+ isSubGroupAdded = true;
+ continue;
+ }
+ else{
+ koralGroup.setDistances(distances);
+ koralGroup.setInOrder(true);
+ }
+ }
+ else{
+ newOperands.add(operand);
+ }
+ isSubGroupAdded = false;
+ }
+
+ if (!isSubGroupAdded){
+ newOperands.add(operands.get(operandSize-1));
+ }
+ return newOperands;
+ }
+
+ private KoralGroup createSubGroup(List<KoralDistance> distances,
+ KoralObject operand, KoralObject operand2) {
+ KoralGroup subGroup = new KoralGroup(KoralOperation.SEQUENCE);
+ subGroup.setDistances(distances);
+ subGroup.setInOrder(true);
+ List<KoralObject> operands = new ArrayList<KoralObject>();
+ operands.add(operand);
+ operands.add(operand2);
+ subGroup.setOperands(operands);
+ return subGroup;
}
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
index d4cb27e..28d371f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
@@ -180,19 +180,29 @@
return raw();
}
- private Map raw() {
+ private Map raw () {
if (ast != null) {
- Map<String, Object> requestMap = ast.getRequestMap();
+ Map<String, Object> requestMap = new HashMap<>(ast.getRequestMap());
Map meta = (Map) requestMap.get("meta");
Map collection = (Map) requestMap.get("collection");
List errors = (List) requestMap.get("errors");
List warnings = (List) requestMap.get("warnings");
List messages = (List) requestMap.get("messages");
- this.collection = mergeCollection(collection, this.collection);
- requestMap.put("collection", this.collection);
+ collection = mergeCollection(collection, this.collection);
+ requestMap.put("collection", collection);
+
+ if (meta == null)
+ meta = new HashMap();
+ if (errors == null)
+ errors = new LinkedList();
+ if (warnings == null)
+ warnings = new LinkedList();
+ if (messages == null)
+ messages = new LinkedList();
+
if (this.meta != null) {
- this.meta.putAll(meta);
- requestMap.put("meta", this.meta);
+ meta.putAll(this.meta);
+ requestMap.put("meta", meta);
}
if (this.errors != null && !this.errors.isEmpty()) {
errors.addAll(this.errors);
@@ -206,37 +216,41 @@
messages.addAll(this.messages);
requestMap.put("messages", messages);
}
-
return cleanup(requestMap);
}
return new HashMap<>();
}
- private Map<String, Object> cleanup(Map<String, Object> requestMap) {
+ private Map<String, Object> cleanup (Map<String, Object> requestMap) {
Iterator<Map.Entry<String, Object>> set = requestMap.entrySet()
.iterator();
while (set.hasNext()) {
Map.Entry<String, Object> entry = set.next();
- if (entry.getValue() instanceof List
- && ((List) entry.getValue()).isEmpty())
+ if (entry.getValue() instanceof List
+ && ((List) entry.getValue()).isEmpty())
set.remove();
- else if (entry.getValue() instanceof Map
- && ((Map) entry.getValue()).isEmpty())
+ else if (entry.getValue() instanceof Map
+ && ((Map) entry.getValue()).isEmpty())
set.remove();
- else if (entry.getValue() instanceof String
- && ((String) entry.getValue()).isEmpty())
+ else if (entry.getValue() instanceof String
+ && ((String) entry.getValue()).isEmpty())
set.remove();
}
return requestMap;
}
- private Map<String, Object> mergeCollection(
- Map<String, Object> collection1, Map<String, Object> collection2) {
+ private Map<String, Object> mergeCollection (
+ Map<String, Object> collection1, Map<String, Object> collection2) {
if (collection1 == null || collection1.isEmpty()) {
return collection2;
- } else if (collection2 == null || collection2.isEmpty()) {
+ }
+ else if (collection2 == null || collection2.isEmpty()) {
return collection1;
- } else {
+ }
+ else if (collection1.equals(collection2)) {
+ return collection1;
+ }
+ else {
LinkedHashMap<String, Object> docGroup = KoralObjectGenerator
.makeDocGroup("and");
ArrayList<Object> operands = (ArrayList<Object>) docGroup
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
index 3973aea..47a174e 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
@@ -7,12 +7,18 @@
import org.junit.Test;
+import com.fasterxml.jackson.core.JsonProcessingException;
+
/**
* @author margaretha
*
*/
public class FCSQLComplexTest {
+ String query;
+ String jsonLd;
+ List<Object> error;
+
// -------------------------------------------------------------------------
// simple-query ::= '(' main_query ')' /* grouping */
// | implicit-query
@@ -24,8 +30,8 @@
// simple-query ::= '(' main_query ')' /* grouping */
@Test
public void testGroupQuery() throws IOException {
- String query = "(\"blaue\"|\"grüne\")";
- String jsonLd = "{@type:koral:group,"
+ query = "(\"blaue\"|\"grüne\")";
+ jsonLd = "{@type:koral:group,"
+ "operation:operation:disjunction,"
+ "operands:["
+ "{@type:koral:token, wrap:{@type:koral:term,key:blaue,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
@@ -38,20 +44,6 @@
FCSQLQueryProcessorTest
.validateNode(query, "/query/operands/1", jsonLd);
- // sequence and disjunction
- query = "([pos=\"NN\"]|[cnx:pos=\"N\"])[text=\"Mann\"]";
- jsonLd = "{@type:koral:group,"
- + "operation:operation:sequence,"
- + "operands:["
- + "{@type:koral:group,"
- + "operation:operation:disjunction,"
- + "operands:[{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}},"
- + "{@type:koral:token,wrap:{@type:koral:term,key:N,foundry:cnx,layer:p,type:type:regex,match:match:eq}}"
- + "]},"
- + "{@type:koral:token,wrap:{@type:koral:term,key:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}"
- + "]}";
- FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
-
// group and sequence
query = "([text=\"blaue\"][pos=\"NN\"])";
jsonLd = "{@type:koral:group,"
@@ -73,8 +65,8 @@
// | simple-query "|" main-query /* or */
@Test
public void testOrQuery() throws IOException {
- String query = "\"man\"|\"Mann\"";
- String jsonLd = "{@type:koral:group,"
+ query = "\"man\"|\"Mann\"";
+ jsonLd = "{@type:koral:group,"
+ "operation:operation:disjunction,"
+ "operands:["
+ "{@type:koral:token,wrap:{@type:koral:term,key:man,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
@@ -94,20 +86,13 @@
+ "{@type:koral:token, wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term,key:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
-
- query = "[pos=\"NN\"]&[text=\"Mann\"]";
- List<Object> error = FCSQLQueryProcessorTest
- .getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(399, error.get(0));
- String msg = (String) error.get(1);
- assertEquals(true, msg.startsWith("FCS diagnostic 10"));
}
// | simple-query main-query /* sequence */
@Test
public void testSequenceQuery() throws IOException {
- String query = "\"blaue|grüne\" [pos = \"NN\"]";
- String jsonLd = "{@type:koral:group, "
+ query = "\"blaue|grüne\" [pos = \"NN\"]";
+ jsonLd = "{@type:koral:group, "
+ "operation:operation:sequence, "
+ "operands:["
+ "{@type:koral:token, wrap:{@type:koral:term, key:blaue|grüne, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}},"
@@ -123,12 +108,148 @@
FCSQLQueryProcessorTest
.validateNode(query, "/query/operands/1", jsonLd);
+ // sequence and disjunction
+ query = "([pos=\"NN\"]|[cnx:pos=\"N\"])[text=\"Mann\"]";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "operands:["
+ + "{@type:koral:group,"
+ + "operation:operation:disjunction,"
+ + "operands:[{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:N,foundry:cnx,layer:p,type:type:regex,match:match:eq}}"
+ + "]},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
}
// | simple-query quantifier /* quatification */
@Test
public void testQueryWithQuantifier() throws IOException {
+ // repetition
+ query = "\"die\"{2}";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:die,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}],"
+ + "boundary:{@type:koral:boundary,min:2,max:2}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ query = "\"die\"{1,2}";
+ jsonLd = "{@type:koral:boundary,min:1,max:2}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"{,2}";
+ jsonLd = "{@type:koral:boundary,min:0,max:2}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"{2,}";
+ jsonLd = "{@type:koral:boundary,min:2}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"+";
+ jsonLd = "{@type:koral:boundary,min:1}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"?";
+ jsonLd = "{@type:koral:boundary,min:0, max:1}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"*";
+ jsonLd = "{@type:koral:boundary,min:0}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ query = "\"die\"{0}";
+ jsonLd = "{@type:koral:boundary,min:0, max:0}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+ }
+
+ // wildcards
+ @Test
+ public void testQueryWithEmptyToken() throws IOException {
+ // expansion query
+ query = "[]{2}\"Hund\"";
+ jsonLd = "{@type:koral:group, "
+ + "operation:operation:sequence, "
+ + "operands:["
+ + "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@type:koral:token}],"
+ + "boundary:{@type:koral:boundary,min:2,max:2}},"
+ + "{@type:koral:token, "
+ + "wrap:{@type:koral:term, key:Hund, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "\"Hund\"[]{2}";
+ jsonLd = "{@type:koral:group," + "operation:operation:repetition,"
+ + "operands:[" + "{@type:koral:token}],"
+ + "boundary:{@type:koral:boundary,min:2,max:2}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", jsonLd);
+
+ // arbitrary tokens
+ query = "[]{2}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ // sequence with extension
+ query = "[cnx:pos=\"A\"] \"Hund\"[]{2}";
+ jsonLd = "["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:A,foundry:cnx,layer:p,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:group,operation:operation:repetition,operands:["
+ + "{@type:koral:token}],boundary:{@type:koral:boundary,min:2,max:2}}"
+ + "]";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/operands", jsonLd);
+ }
+
+ @Test
+ public void testQueryWithDistance() throws IOException {
+ // distance query
+ query = "\"Katze\" []{3} \"Hund\"";
+ jsonLd = "{@type:koral:group,operation:operation:sequence,inOrder:true,"
+ + "distances:["
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:3}}"
+ + "],"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Katze,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ // sequences of wildcards
+ query = "\"Katze\" []{3}[] \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:4,max:4}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []{2}[]{3}[] \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:6,max:6}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ // multiple occurrences of wildcards
+ query = "\"Katze\" []{3} \"Hund\" []{1,2} [cnx:pos=\"V\"]";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "inOrder:true,"
+ + "distances:["
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:3}}"
+ + "],"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Katze,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "inOrder:true,"
+ + "distances:["
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1,max:2}}"
+ + "],"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:V,foundry:cnx,layer:p,type:type:regex,match:match:eq}}]}"
+ +"]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
// -------------------------------------------------------------------------
@@ -139,8 +260,8 @@
@Test
public void testWithinQuery() throws IOException {
- String query = "[cnx:pos=\"VVFIN\"] within s";
- String jsonLd = "{@type:koral:group,"
+ query = "[cnx:pos=\"VVFIN\"] within s";
+ jsonLd = "{@type:koral:group,"
+ "operation:operation:position,"
+ "operands:["
+ "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}},"
@@ -162,12 +283,52 @@
.validateNode(query, "/query/operands/0", jsonLd);
query = "[cnx:pos=\"VVFIN\"] within u";
- List<Object> error = FCSQLQueryProcessorTest
- .getError(new FCSQLQueryProcessor(query, "2.0"));
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
assertEquals(310, error.get(0));
assertEquals(
"FCS diagnostic 11: Within scope UTTERANCE is currently unsupported.",
(String) error.get(1));
}
+ @Test
+ public void testWithinQueryWithEmptyTokens() throws IOException {
+ query = "[] within s";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:position,"
+ + "operands:["
+ + "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}},"
+ + "{@type:koral:token}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ @Test
+ public void testWrongQuery() throws IOException {
+ query = "!(mate:lemma=\"sein\" | mate:pos=\"PPOSS\")";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(399, error.get(0));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+
+ query = "![mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+
+ query = "(\"blaue\"&\"grüne\")";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+
+ query = "[pos=\"NN\"]&[text=\"Mann\"]";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(399, error.get(0));
+ String msg = (String) error.get(1);
+ assertEquals(true, msg.startsWith("FCS diagnostic 10"));
+ }
}
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
index 7fa90d0..9c030de 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
@@ -20,13 +20,16 @@
static QuerySerializer qs = new QuerySerializer();
static ObjectMapper mapper = new ObjectMapper();
static JsonNode node;
+ String query;
+ String jsonLd;
+ List<Object> error;
- public static void runAndValidate(String query, String jsonLD)
+ public static void runAndValidate(String query, String jsonLd)
throws JsonProcessingException {
FCSQLQueryProcessor processor = new FCSQLQueryProcessor(query, "2.0");
String serializedQuery = mapper.writeValueAsString(processor
.getRequestMap().get("query"));
- assertEquals(jsonLD.replace(" ", ""), serializedQuery.replace("\"", ""));
+ assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
}
public static void validateNode(String query, String path, String jsonLd)
@@ -44,7 +47,7 @@
@Test
public void testVersion() throws JsonProcessingException {
- List<Object> error = getError(new FCSQLQueryProcessor("\"Sonne\"",
+ error = getError(new FCSQLQueryProcessor("\"Sonne\"",
"1.0"));
assertEquals(309, error.get(0));
assertEquals("SRU diagnostic 5: Only supports SRU version 2.0.",
@@ -59,16 +62,16 @@
// regexp ::= quoted-string
@Test
public void testTermQuery() throws JsonProcessingException {
- String query = "\"Sonne\"";
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, "
+ query = "\"Sonne\"";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, "
+ "foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
runAndValidate(query, jsonLd);
}
@Test
public void testRegex() throws JsonProcessingException {
- String query = "[text=\"M(a|ä)nn(er)?\"]";
- String jsonLd = "{@type:koral:token,wrap:{@type:koral:term,"
+ query = "[text=\"M(a|ä)nn(er)?\"]";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,"
+ "key:M(a|ä)nn(er)?,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}";
runAndValidate(query, jsonLd);
@@ -95,8 +98,8 @@
// | regexp "/" regexp-flag+
@Test
public void testTermQueryWithRegexFlag() throws IOException {
- String query = "\"Fliegen\" /c";
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, caseInsensitive:true, "
+ query = "\"Fliegen\" /c";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, caseInsensitive:true, "
+ "key:Fliegen, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
@@ -111,7 +114,7 @@
FCSQLQueryProcessorTest.validateNode(query, "/query/wrap", jsonLd);
query = "\"Fliegen\" /l";
- List<Object> error = FCSQLQueryProcessorTest
+ error = FCSQLQueryProcessorTest
.getError(new FCSQLQueryProcessor(query, "2.0"));
assertEquals(306, error.get(0));
String msg = (String) error.get(1);
@@ -130,8 +133,8 @@
// | "!=" /* non-equals */
@Test
public void testOperator() throws IOException {
- String query = "[cnx:pos != \"N\"]";
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:N, "
+ query = "[cnx:pos != \"N\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:N, "
+ "foundry:cnx, layer:p, type:type:regex, match:match:ne}}";
runAndValidate(query, jsonLd);
}
@@ -145,8 +148,8 @@
// simple-attribute ::= identifier
@Test
public void testTermQueryWithSpecificLayer() throws JsonProcessingException {
- String query = "[text = \"Sonne\"]";
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, "
+ query = "[text = \"Sonne\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, "
+ "foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
@@ -164,8 +167,8 @@
// qualified-attribute ::= identifier ":" identifier
@Test
public void testTermQueryWithQualifier() throws JsonProcessingException {
- String query = "[mate:lemma = \"sein\"]";
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:sein, "
+ query = "[mate:lemma = \"sein\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:sein, "
+ "foundry:mate, layer:l, type:type:regex, match:match:eq}}";
runAndValidate(query, jsonLd);
@@ -175,28 +178,6 @@
runAndValidate(query, jsonLd);
}
- @Test
- public void testTermQueryException() throws JsonProcessingException {
- String query = "[opennlp:lemma = \"sein\"]";
- List<Object> error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(306, error.get(0));
- assertEquals(
- "SRU diagnostic 48: Layer lemma with qualifier opennlp is unsupported.",
- error.get(1));
-
- query = "[malt:lemma = \"sein\"]";
- error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(306, error.get(0));
- assertEquals("SRU diagnostic 48: Qualifier malt is unsupported.",
- error.get(1));
-
- query = "[cnx:morph = \"heit\"]";
- error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(306, error.get(0));
- assertEquals("SRU diagnostic 48: Layer morph is unsupported.",
- error.get(1));
-
- }
// segment-query ::= "[" expression? "]"
// -------------------------------------------------------------------------
@@ -208,8 +189,8 @@
// | expression "|" expression /* or */
@Test
public void testExpressionOr() throws IOException {
- String query = "[mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
- String jsonLd = "{@type: koral:token,"
+ query = "[mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ " wrap: { @type: koral:termGroup,"
+ "relation: relation:or,"
+ " operands:["
@@ -227,8 +208,8 @@
// | expression "&" expression /* and */
@Test
public void testExpressionAnd() throws IOException {
- String query = "[mate:lemma=\"sein\" & mate:pos=\"PPOSS\"]";
- String jsonLd = "{@type: koral:token,"
+ query = "[mate:lemma=\"sein\" & mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ " wrap: { @type: koral:termGroup,"
+ "relation: relation:and,"
+ " operands:["
@@ -247,8 +228,8 @@
@Test
public void testExpressionGroup() throws JsonProcessingException {
- String query = "[(text=\"blau\"|pos=\"ADJ\")]";
- String jsonLd = "{@type: koral:token,"
+ query = "[(text=\"blau\"|pos=\"ADJ\")]";
+ jsonLd = "{@type: koral:token,"
+ "wrap: {@type: koral:termGroup,"
+ "relation: relation:or,"
+ "operands: ["
@@ -260,9 +241,9 @@
// "!" expression /* not */
@Test
public void testExpressionNot() throws IOException {
- String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:NN, "
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:NN, "
+ "foundry:tt, layer:p, type:type:regex, match:match:eq}}";
- String query = "[!pos != \"NN\"]";
+ query = "[!pos != \"NN\"]";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
query = "[!!pos = \"NN\"]";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
@@ -280,24 +261,42 @@
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
-
@Test
- public void testWrongQuery() throws IOException {
- String query = "!(mate:lemma=\"sein\" | mate:pos=\"PPOSS\")";
- List<Object> error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(399, error.get(0));
- assertEquals(true,
- error.get(1).toString().startsWith("FCS diagnostic 10"));
-
- query = "![mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ public void testExceptions() throws JsonProcessingException {
+ // unsupported lemma und qualifier
+ query = "[opennlp:lemma = \"sein\"]";
error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(true,
- error.get(1).toString().startsWith("FCS diagnostic 10"));
+ assertEquals(306, error.get(0));
+ assertEquals(
+ "SRU diagnostic 48: Layer lemma with qualifier opennlp is unsupported.",
+ error.get(1));
- query = "(\"blaue\"&\"grüne\")";
+ query = "[tt:morph = \"sein\"]";
error = getError(new FCSQLQueryProcessor(query, "2.0"));
- assertEquals(true,
- error.get(1).toString().startsWith("FCS diagnostic 10"));
+ assertEquals(306, error.get(0));
+ assertEquals(
+ "SRU diagnostic 48: Layer morph is unsupported.",
+ error.get(1));
+
+ // unsupported qualifier
+ query = "[malt:lemma = \"sein\"]";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(306, error.get(0));
+ assertEquals("SRU diagnostic 48: Qualifier malt is unsupported.",
+ error.get(1));
+
+ // unsupported layer
+ query = "[cnx:morph = \"heit\"]";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(306, error.get(0));
+ assertEquals("SRU diagnostic 48: Layer morph is unsupported.",
+ error.get(1));
+
+ // missing layer
+ query = "[cnx=\"V\"]";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(306, error.get(0));
+ assertEquals("SRU diagnostic 48: Layer cnx is unsupported.",
+ error.get(1));
}
-
}
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
index 095cc59..2cb60e3 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
@@ -658,7 +658,13 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:token", res.at("/query/@type").asText());
assertEquals(true, res.at("/query/key").isMissingNode());
-
+
+ query = "[]{3}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("{@type:koral:boundary,min:3,max:3}",
+ res.at("/query/boundary").asText());
+
query = "contains(<s>, [])";
qs.setQuery(query, "poliqarpplus");
res = mapper.readTree(qs.toJSON());
@@ -726,6 +732,24 @@
assertEquals("koral:token", operands.get(0).at("/@type").asText());
assertEquals(true, operands.get(0).at("/key").isMissingNode());
+ query = "[base=Mann][]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ operands = Lists.newArrayList(res.at("/query/operands").elements());
+ assertEquals("koral:token", operands.get(1).at("/@type").asText());
+ assertEquals(true, operands.get(1).at("/key").isMissingNode());
+
+ query = "[base=Mann][]{3}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ operands = Lists.newArrayList(res.at("/query/operands").elements());
+ res = operands.get(1);
+ assertEquals("koral:group", res.at("/@type").asText());
+ assertEquals(true, res.at("/key").isMissingNode());
+ assertEquals("operation:repetition", res.at("/operation").asText());
+ assertEquals(3, res.at("/boundary/min").asInt());
+ assertEquals(3, res.at("/boundary/max").asInt());
+
query = "startswith(<s>, [][base=Mann])";
qs.setQuery(query, "poliqarpplus");
res = mapper.readTree(qs.toJSON());