Merge branch 'master' of ssh://korap.ids-mannheim.de:29418/KorAP/Koral
diff --git a/.gitignore b/.gitignore
index c304b58..f993ee1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,18 @@
# /
+/sandbox
+/Sandbox
+/todo.org
+/target
+/.settings
/.project
/.classpath
-/.settings/org.eclipse.jdt.core.prefs
-/target
+*~
+.*
+!.gitignore
+
+
+/src/main/resources
# /src/main/antlr/cosmas/
/src/main/antlr/cosmas/c2ps_regex.g
diff --git a/Changes b/Changes
index ffea7ec..f58784d 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,13 @@
-0.22 2016-06-03
+0.22 2016-06-15
- Spans now always wrap terms (diewald)
+ - Cosmas-II "und", "oder", and "nicht" operations
+ now serialize to unordered sequences (diewald)
+ - Cleanup POM (diewald)
+ - Fix deserialization of unnecessary brackets
+ around terms and termGroups in Poliqarp (diewald)
+ - Support for FCS 2.0 (margaretha)
+ - Fixed handling of escapes in regex
+ (issue #21; diewald)
0.21 2015-10-27
- Improved meta query builder (hanl)
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 76d29f5..e9df54e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,219 +1,303 @@
<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>
- <!-- <parent> <groupId>KorAP-modules</groupId> <artifactId>KorAP-core-modules</artifactId>
- <version>1.1</version> </parent> -->
+ 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>
- <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-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>
- </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>
+ <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>
+
+ <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>
- <executions>
- <execution>
- <goals>
- <goal>antlr</goal>
- </goals>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <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>
+ </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/antlr/poliqarpplus/PoliqarpPlusLexer.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
index 68c0bef..b3bedb1 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
@@ -86,9 +86,13 @@
EMPTYREL : '@';
/* Regular expressions and Regex queries */
-fragment RE_char : ~('*' | '?' | '+' | '{' | '}' | '[' | ']'
- | '(' | ')' | '|' | '"' | ':' | '\'' | '\\');
+fragment RE_symbol : ~('*' | '?' | '+' | '{' | '}' | '[' | ']'
+ | '(' | ')' | '|' | '\\' | '"' | ':' | '\'');
+fragment RE_esc : '\\' ('.' | '*' | '?' | '+' | '{' | '}' | '[' | ']'
+ | '(' | ')' | '|' | '\\' | '"' | ':' | '\'');
+fragment RE_char : (RE_symbol | RE_esc );
fragment RE_alter : ((RE_char | ('(' RE_expr ')') | RE_chgroup) '|' RE_expr )+;
+
fragment RE_chgroup : '[' RE_char+ ']';
fragment RE_quant : (RE_star | RE_plus | RE_occ) QMARK?;
fragment RE_opt : (RE_char | RE_chgroup | ( '(' RE_expr ')')) '?';
@@ -100,4 +104,4 @@
fragment RE_dquote : '"' (RE_expr | '\'' | ':' )* '"';
fragment RE_squote : '\'' (RE_expr | '\"' | ':' )* '\'';
-REGEX : ( RE_dquote | RE_squote | );
+REGEX : ( RE_dquote | RE_squote );
diff --git a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
index c48a3f9..571cf12 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
@@ -43,9 +43,9 @@
;
key
-: WORD
+: (WORD
| regex
-| NUMBER
+| NUMBER)
;
foundry
@@ -57,14 +57,13 @@
;
value
-: WORD
-| NUMBER
-| regex
+: (WORD | NUMBER) | regex
;
/* Fields */
term
-: NEG* (foundry SLASH)? layer termOp key (COLON value)? flag?
+: NEG* (foundry SLASH)? layer termOp key (COLON value)? flag?
+| LRPAREN term RRPAREN
;
termOp
@@ -103,6 +102,7 @@
termGroup
: (term | LRPAREN termGroup RRPAREN) boolOp (term | LRPAREN termGroup RRPAREN | termGroup)
+| LRPAREN termGroup RRPAREN
;
repetition
@@ -125,8 +125,7 @@
;
span
-: LT ((foundry SLASH)? layer termOp)? key NEG* (LRPAREN term RRPAREN|LRPAREN termGroup RRPAREN)? GT
-| LT ((foundry SLASH)? layer termOp)? key NEG* (term|termGroup)? GT
+: LT ((foundry SLASH)? layer termOp)? key NEG* ((LRPAREN term RRPAREN|LRPAREN termGroup RRPAREN)? | (term|termGroup)?) GT
;
position
@@ -150,7 +149,7 @@
;
alignment
-: segment? (CARET segment)* CARET?
+: segment? ( (CARET segment)+ | CARET)
;
disjunction
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/KoralContext.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralContext.java
new file mode 100644
index 0000000..abdde0b
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralContext.java
@@ -0,0 +1,22 @@
+package de.ids_mannheim.korap.query.object;
+
+/**
+ * @author margaretha
+ *
+ */
+public enum KoralContext {
+ SENTENCE("s"), PARAGRAPH("p"), TEXT("t");
+
+ private final String key;
+ public static final String FOUNDRY ="base";
+ public static final String LAYER="s"; // surface
+
+ KoralContext(String key){
+ this.key = key;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+}
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
new file mode 100644
index 0000000..b304f72
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralGroup.java
@@ -0,0 +1,124 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.serialize.MapBuilder;
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralOperation;
+import de.ids_mannheim.korap.query.object.KoralType;
+
+/**
+ * @author margaretha
+ *
+ */
+public class KoralGroup implements KoralObject {
+
+ private static final KoralType type = KoralType.GROUP;
+
+ private KoralOperation operation;
+
+ private boolean inOrder = false;
+ private List<KoralObject> operands;
+ private List<KoralDistance> distances;
+ private List<Frame> frames;
+ private KoralBoundary boundary;
+
+ public KoralGroup (KoralOperation operation) {
+ this.operation = operation;
+ }
+
+ public boolean isInOrder() {
+ return inOrder;
+ }
+
+ public void setInOrder(boolean inOrder) {
+ this.inOrder = inOrder;
+ }
+
+ public List<KoralObject> getOperands() {
+ return operands;
+ }
+
+ public void setOperands(List<KoralObject> operands) {
+ this.operands = operands;
+ }
+
+ public KoralOperation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(KoralOperation operation) {
+ this.operation = operation;
+ }
+
+ public List<KoralDistance> getDistances() {
+ return distances;
+ }
+
+ public void setDistances(List<KoralDistance> distances) {
+ this.distances = distances;
+ }
+
+ public List<Frame> getFrames() {
+ return frames;
+ }
+
+ public void setFrames(List<Frame> frames) {
+ 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>();
+ map.put("@type", type.toString());
+ map.put("operation", operation.toString());
+
+ if (getDistances() != null) {
+ map.put("inOrder", isInOrder());
+ List<Map<String, Object>> distanceList = new ArrayList<Map<String, Object>>();
+ 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 : operands) {
+ operandList.add(MapBuilder.buildQueryMap(o));
+ }
+ map.put("operands", operandList);
+
+ if (boundary != null) {
+ map.put("boundary", boundary.buildMap());
+ }
+ return map;
+ }
+
+ public enum Frame{
+ SUCCEDS("succeeds"), SUCCEDS_DIRECTLY("succeedsDirectly"), OVERLAPS_RIGHT("overlapsRight"),
+ ALIGNS_RIGHT("alignsRight"), IS_WITHIN("isWithin"), STARTS_WITH("startsWith"),
+ MATCHES("matches"), ALIGNS_LEFT("alignsLeft"), IS_AROUND("isAround"), ENDS_WITH("endsWith"),
+ OVERLAPS_LEFT("overlapsLeft"), PRECEEDS_DIRECTLY("precedesDirectly"), PRECEDES("precedes");
+
+ private String value;
+ Frame(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "frame:"+value;
+ }
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java
new file mode 100644
index 0000000..bd5f6ea
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralMatchOperator.java
@@ -0,0 +1,20 @@
+package de.ids_mannheim.korap.query.object;
+
+/**
+ * @author margaretha
+ *
+ */
+public enum KoralMatchOperator {
+ EQUALS("eq"), NOT_EQUALS("ne");
+
+ String value;
+
+ KoralMatchOperator (String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "match:" + value;
+ };
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java
new file mode 100644
index 0000000..21fcf67
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralObject.java
@@ -0,0 +1,12 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.Map;
+
+/**
+ * @author margaretha
+ *
+ */
+public interface KoralObject {
+
+ public Map<String, Object> buildMap();
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java
new file mode 100644
index 0000000..972bfd3
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralOperation.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.query.object;
+
+/**
+ * @author margaretha
+ *
+ */
+public enum KoralOperation {
+ SEQUENCE, POSITION, DISJUNCTION, REPETITION, CLASS, MERGE, RELATION;
+
+ @Override
+ public String toString() {
+ return "operation:" + super.toString().toLowerCase();
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java
new file mode 100644
index 0000000..84a1ff8
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralRelation.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.query.object;
+
+/**
+ * @author margaretha
+ *
+ */
+public enum KoralRelation {
+
+ AND, OR;
+
+ @Override
+ public String toString() {
+ return "relation:" + super.toString().toLowerCase();
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java
new file mode 100644
index 0000000..4310bb9
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralSpan.java
@@ -0,0 +1,62 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+
+/**
+ * @author margaretha
+ *
+ */
+public class KoralSpan implements KoralObject{
+
+ private static final KoralType type = KoralType.SPAN;
+ private final KoralObject wrappedObject;
+ private KoralObject attribute;
+
+ public KoralSpan(KoralTerm term) throws KoralException {
+ if (term == null){
+ throw new KoralException(StatusCodes.MALFORMED_QUERY, "KoralSpan must not wrap null.");
+ }
+ this.wrappedObject = term;
+ }
+
+ public KoralSpan(KoralTermGroup termGroup) throws KoralException {
+ if (termGroup == null){
+ throw new KoralException(StatusCodes.MALFORMED_QUERY,"KoralSpan must not wrap null.");
+ }
+ this.wrappedObject = termGroup;
+ }
+
+ public KoralObject getWrappedObject() {
+ return wrappedObject;
+ }
+
+ public KoralObject getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(KoralTerm attribute) {
+ this.attribute = attribute;
+ }
+
+ public void setAttribute(KoralTermGroup attributes) {
+ this.attribute = attributes;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", type.toString());
+ if (wrappedObject == null){
+ throw new NullPointerException("KoralSpan does not have a wrapped object.");
+ }
+ map.put("wrap", wrappedObject.buildMap());
+ if(attribute != null){
+ map.put("wrap", attribute.buildMap());
+ }
+ return map;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java
new file mode 100644
index 0000000..f9f60cd
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralTerm.java
@@ -0,0 +1,138 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+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.KoralMatchOperator;
+import de.ids_mannheim.korap.query.object.KoralType;
+
+/**
+ * @author margaretha
+ *
+ */
+public class KoralTerm implements KoralObject {
+
+ private static final KoralType koralType = KoralType.TERM;
+
+ private final String key;
+ private String value;
+ private String layer;
+ private String foundry;
+ private KoralMatchOperator operator; // match
+
+ private KoralTermType type;
+
+ private boolean caseSensitive = true;
+
+ public KoralTerm(String key) throws KoralException {
+ if (key == null){
+ throw new KoralException(StatusCodes.MALFORMED_QUERY,
+ "KoralTerm key cannot be null.");
+ }
+ this.key = key;
+ }
+
+ public KoralTerm(KoralContext context) throws KoralException {
+ if (context.getKey() == null){
+ throw new KoralException(StatusCodes.MALFORMED_QUERY,
+ "KoralTerm key cannot be null.");
+ }
+ this.key = context.getKey();
+ this.foundry = KoralContext.FOUNDRY;
+ this.layer = KoralContext.LAYER;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getLayer() {
+ return layer;
+ }
+
+ public void setLayer(String layer) {
+ this.layer = layer;
+ }
+
+ public String getFoundry() {
+ return foundry;
+ }
+
+ public void setFoundry(String foundry) {
+ this.foundry = foundry;
+ }
+
+ public KoralMatchOperator getOperator() {
+ return operator;
+ }
+
+ public void setOperator(KoralMatchOperator operator) {
+ this.operator = operator;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public KoralTermType getType() {
+ return type;
+ }
+
+ public void setType(KoralTermType regex) {
+ this.type = regex;
+ }
+
+ public boolean isCaseSensitive() {
+ return caseSensitive;
+ }
+
+ public void setCaseSensitive(boolean isCaseSensitive) {
+ this.caseSensitive = isCaseSensitive;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", koralType.toString());
+ if (!isCaseSensitive()) {
+ map.put("caseInsensitive", "true");
+ }
+
+ map.put("key", getKey());
+ if (value != null){
+ map.put("value", getValue());
+ }
+ map.put("foundry", getFoundry());
+ map.put("layer", getLayer());
+ if (type != null){
+ map.put("type", getType().toString());
+ }
+ if (operator !=null){
+ map.put("match", getOperator().toString());
+ }
+ return map;
+ }
+
+ public enum KoralTermType {
+ STRING("type:string"), REGEX("type:regex"), WILDCARD("type:wildcard"), PUNCT(
+ "type:punct");
+
+ String value;
+
+ KoralTermType (String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java
new file mode 100644
index 0000000..eaae803
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralTermGroup.java
@@ -0,0 +1,57 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.serialize.MapBuilder;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+
+/**
+ * @author margaretha
+ *
+ */
+public class KoralTermGroup implements KoralObject {
+
+ private static final KoralType type = KoralType.TERMGROUP;
+
+ private String relation;
+ private List<KoralObject> operands = new ArrayList<KoralObject>();
+
+ public KoralTermGroup (KoralRelation relation, List<KoralObject> operands)
+ throws KoralException {
+ this.relation = relation.toString();
+ this.operands = operands;
+ }
+
+ public String getRelation() {
+ return relation;
+ }
+
+ public void setRelation(String relation) {
+ this.relation = relation;
+ }
+
+ public List<KoralObject> getOperands() {
+ return operands;
+ }
+
+ public void setOperands(List<KoralObject> operands) {
+ this.operands = operands;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", type.toString());
+ map.put("relation", getRelation());
+
+ List<Map<String, Object>> operandList = new ArrayList<Map<String, Object>>();
+ for (Object o : getOperands()) {
+ operandList.add(MapBuilder.buildQueryMap(o));
+ }
+ map.put("operands", operandList);
+ return map;
+ }
+}
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
new file mode 100644
index 0000000..7798566
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralToken.java
@@ -0,0 +1,40 @@
+package de.ids_mannheim.korap.query.object;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralType;
+
+/**
+ * @author margaretha
+ *
+ */
+public class KoralToken implements KoralObject {
+
+ private final static KoralType type = KoralType.TOKEN;
+ private KoralObject wrappedObject;
+
+ public KoralToken () {}
+
+ public KoralToken (KoralObject wrappedObject) {
+ this.wrappedObject = wrappedObject;
+ }
+
+ public KoralObject getWrappedObject() {
+ return wrappedObject;
+ }
+ public void setWrappedObject(KoralObject wrappedObject) {
+ this.wrappedObject = wrappedObject;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", type.toString());
+ if (wrappedObject != null){
+ map.put("wrap", wrappedObject.buildMap());
+ }
+ return map;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java b/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java
new file mode 100644
index 0000000..df7608f
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/object/KoralType.java
@@ -0,0 +1,23 @@
+package de.ids_mannheim.korap.query.object;
+
+/**
+ * @author margaretha
+ *
+ */
+public enum KoralType {
+ TERMGROUP("koral:termGroup"), TERM("koral:term"), TOKEN("koral:token"), SPAN(
+ "koral:span"), GROUP("koral:group"), BOUNDARY("koral:boundary"), RELATION(
+ "koral:relation"), DISTANCE("koral:distance"), REFERENCE(
+ "koral:reference");
+
+ String value;
+
+ KoralType (String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
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
new file mode 100644
index 0000000..42f5f83
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
@@ -0,0 +1,220 @@
+package de.ids_mannheim.korap.query.parse.fcsql;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import de.ids_mannheim.korap.query.object.KoralMatchOperator;
+import de.ids_mannheim.korap.query.object.KoralObject;
+import de.ids_mannheim.korap.query.object.KoralRelation;
+import de.ids_mannheim.korap.query.object.KoralTerm;
+import de.ids_mannheim.korap.query.object.KoralTerm.KoralTermType;
+import de.ids_mannheim.korap.query.object.KoralTermGroup;
+import de.ids_mannheim.korap.query.object.KoralToken;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import eu.clarin.sru.server.fcs.parser.Expression;
+import eu.clarin.sru.server.fcs.parser.ExpressionAnd;
+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;
+
+/**
+ * @author margaretha
+ *
+ */
+public class ExpressionParser {
+
+ private static final String FOUNDRY_CNX = "cnx";
+ private static final String FOUNDRY_OPENNLP = "opennlp";
+ private static final String FOUNDRY_TT = "tt";
+ private static final String FOUNDRY_MATE = "mate";
+ private static final String FOUNDRY_XIP = "xip";
+
+ private List<String> supportedFoundries = Arrays
+ .asList(new String[] { FOUNDRY_CNX, FOUNDRY_OPENNLP, FOUNDRY_TT,
+ FOUNDRY_MATE, FOUNDRY_XIP });
+
+ public KoralObject parseExpression(QueryNode queryNode) throws KoralException {
+ return parseExpression(queryNode, false, true);
+ }
+
+ public KoralObject parseExpression(QueryNode queryNode, boolean isNot,
+ boolean isToken) throws KoralException {
+
+ if (queryNode instanceof Expression) {
+ return parseSimpleExpression((Expression) queryNode, isNot, isToken);
+ }
+ else if (queryNode instanceof ExpressionAnd) {
+ List<QueryNode> operands = queryNode.getChildren();
+ if (isNot) {
+ return parseBooleanExpression(operands, KoralRelation.OR);
+ }
+ else {
+ return parseBooleanExpression(operands, KoralRelation.AND);
+ }
+ }
+ else if (queryNode instanceof ExpressionGroup) {
+ // Ignore the group
+ return parseExpression(queryNode.getFirstChild());
+ }
+ else if (queryNode instanceof ExpressionNot) {
+ boolean negation = isNot ? false : true;
+ return parseExpression(queryNode.getChild(0), negation, isToken);
+ }
+ else if (queryNode instanceof ExpressionOr) {
+ List<QueryNode> operands = queryNode.getChildren();
+ if (isNot) {
+ return parseBooleanExpression(operands, KoralRelation.AND);
+ }
+ else {
+ return parseBooleanExpression(operands, KoralRelation.OR);
+ }
+ }
+ else if (queryNode instanceof ExpressionWildcard) {
+ return new KoralToken();
+ }
+ else {
+ throw new KoralException(StatusCodes.QUERY_TOO_COMPLEX,
+ "FCS diagnostic 11: Query is too complex.");
+ }
+ }
+
+ private KoralToken parseBooleanExpression(List<QueryNode> operands,
+ KoralRelation relation) throws KoralException {
+ List<KoralObject> terms = new ArrayList<>();
+ for (QueryNode node : operands) {
+ terms.add(parseExpression(node, false, false));
+ }
+ KoralTermGroup termGroup = new KoralTermGroup(relation, terms);
+ return new KoralToken(termGroup);
+ }
+
+ private KoralObject parseSimpleExpression(Expression expression, boolean isNot,
+ boolean isToken) throws KoralException {
+ KoralTerm koralTerm = parseTerm(expression, isNot);
+ if (isToken) {
+ return new KoralToken(koralTerm);
+ }
+ else {
+ return koralTerm;
+ }
+ }
+
+ public KoralTerm parseTerm(Expression expression, boolean isNot) throws KoralException {
+ KoralTerm koralTerm = null;
+ koralTerm = new KoralTerm(expression.getRegexValue());
+ koralTerm.setType(KoralTermType.REGEX);
+ parseLayerIdentifier(koralTerm, expression.getLayerIdentifier());
+ parseQualifier(koralTerm, expression.getLayerQualifier());
+ parseOperator(koralTerm, expression.getOperator(), isNot);
+ parseRegexFlags(koralTerm, expression.getRegexFlags());
+ return koralTerm;
+ }
+
+ private void parseLayerIdentifier(KoralTerm koralTerm, String identifier) throws KoralException {
+ String layer = null;
+ if (identifier == null) {
+ throw new KoralException(StatusCodes.MALFORMED_QUERY,
+ "FCS diagnostic 10: Layer identifier is missing.");
+ }
+ else if (identifier.equals("text")) {
+ layer = "orth";
+ }
+ else if (identifier.equals("pos")) {
+ layer = "p";
+ }
+ else if (identifier.equals("lemma")) {
+ layer = "l";
+ }
+ else {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 48: Layer " + identifier
+ + " is unsupported.");
+ }
+
+ koralTerm.setLayer(layer);
+ }
+
+ private void parseQualifier(KoralTerm koralTerm, String qualifier) throws KoralException {
+ String layer = koralTerm.getLayer();
+ if (layer == null) {
+ return;
+ }
+ // Set default foundry
+ if (qualifier == null) {
+ if (layer.equals("orth")) {
+ qualifier = FOUNDRY_OPENNLP;
+ }
+ else {
+ qualifier = FOUNDRY_TT;
+ }
+ }
+ else if (qualifier.equals(FOUNDRY_OPENNLP) && layer.equals("l")) {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 48: Layer lemma with qualifier opennlp is unsupported.");
+ }
+ else if (!supportedFoundries.contains(qualifier)) {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 48: Qualifier " + qualifier
+ + " is unsupported.");
+ }
+
+ koralTerm.setFoundry(qualifier);
+ }
+
+ private void parseOperator(KoralTerm koralTerm, Operator operator,
+ boolean isNot) throws KoralException {
+ KoralMatchOperator matchOperator = null;
+ if (operator == null || operator == Operator.EQUALS) {
+ matchOperator = isNot ? KoralMatchOperator.NOT_EQUALS : KoralMatchOperator.EQUALS;
+ }
+ else if (operator == Operator.NOT_EQUALS) {
+ matchOperator = isNot ? KoralMatchOperator.EQUALS : KoralMatchOperator.NOT_EQUALS;
+ }
+ else {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 37:" + operator.name()
+ + " is unsupported.");
+ }
+ koralTerm.setOperator(matchOperator);
+ }
+
+ private void parseRegexFlags(KoralTerm koralTerm, Set<RegexFlag> set) throws KoralException {
+ // default case sensitive
+ if (set == null) return;
+
+ ArrayList<String> names = new ArrayList<String>();
+ Iterator<RegexFlag> i = set.iterator();
+ while (i.hasNext()) {
+ RegexFlag f = i.next();
+ if (f == RegexFlag.CASE_SENSITVE) {
+ koralTerm.setCaseSensitive(true);
+ }
+ else if (f == RegexFlag.CASE_INSENSITVE) {
+ koralTerm.setCaseSensitive(false);
+ }
+ else {
+ names.add(f.name());
+ }
+ }
+
+ if (names.size() == 1) {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 48: Regexflag: " + names.get(0)
+ + " is unsupported.");
+ }
+ else if (names.size() > 1) {
+ throw new KoralException(StatusCodes.UNKNOWN_QUERY_ELEMENT,
+ "SRU diagnostic 48: Regexflags: " + names.toString()
+ + " are unsupported.");
+ }
+ }
+
+}
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
new file mode 100644
index 0000000..96e12b1
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
@@ -0,0 +1,242 @@
+package de.ids_mannheim.korap.query.parse.fcsql;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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;
+import eu.clarin.sru.server.fcs.parser.QuerySegment;
+import eu.clarin.sru.server.fcs.parser.QuerySequence;
+import eu.clarin.sru.server.fcs.parser.QueryWithWithin;
+import eu.clarin.sru.server.fcs.parser.SimpleWithin;
+import eu.clarin.sru.server.fcs.parser.SimpleWithin.Scope;
+
+/**
+ * @author margaretha
+ *
+ */
+public class FCSSRUQueryParser {
+
+ private ExpressionParser expressionParser;
+
+ public FCSSRUQueryParser () {
+ this.expressionParser = new ExpressionParser();
+ }
+
+ public KoralObject parseQueryNode(QueryNode queryNode)
+ throws KoralException {
+
+ if (queryNode instanceof QuerySegment) {
+ return parseQuerySegment((QuerySegment) queryNode);
+ }
+ else if (queryNode instanceof QueryGroup) {
+ return parseQueryGroup((QueryGroup) queryNode);
+ }
+ else if (queryNode instanceof QuerySequence) {
+ return parseSequenceQuery(queryNode.getChildren());
+ }
+ else if (queryNode instanceof QueryDisjunction) {
+ return parseQueryDisjunction(queryNode.getChildren());
+ }
+ else if (queryNode instanceof QueryWithWithin) {
+ return parseWithinQuery((QueryWithWithin) queryNode);
+ }
+ else if (queryNode instanceof SimpleWithin) {
+ 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 parseQuerySegment(QuerySegment segment)
+ throws KoralException {
+ KoralObject object = expressionParser.parseExpression(segment.getExpression());
+ return handleQuantifier(object, segment.getMinOccurs(), segment.getMaxOccurs());
+ }
+
+ private KoralObject parseQueryGroup(QueryGroup group) throws KoralException {
+ KoralObject object = parseQueryNode(group.getFirstChild());
+ return handleQuantifier(object, group.getMinOccurs(), group.getMaxOccurs());
+ }
+
+ private KoralObject handleQuantifier(KoralObject object, int minOccurs, int maxOccurs){
+ if ((minOccurs == 1) && (maxOccurs == 1)) {
+ return object;
+ }
+
+ KoralBoundary boundary = new KoralBoundary(minOccurs, maxOccurs);
+ List<KoralObject> operand = new ArrayList<KoralObject>(1);
+ operand.add(object);
+
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.REPETITION);
+ koralGroup.setBoundary(boundary);
+ koralGroup.setOperands(operand);
+ return koralGroup;
+ }
+
+ 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 parseQueryDisjunction(List<QueryNode> children) throws KoralException {
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.DISJUNCTION);
+ List<KoralObject> operands = new ArrayList<KoralObject>();
+ for (QueryNode child : children) {
+ operands.add(parseQueryNode(child));
+ }
+ koralGroup.setOperands(operands);
+ return koralGroup;
+ }
+
+ 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;
+ }
+
+ 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/CollectionQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
index 1baa50a..ae544a1 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessor.java
@@ -25,7 +25,7 @@
* of the KoralQuery tree. See the official documentation for VC query
* syntax
* and functionality.
- *
+ *
* @author Michael Hanl (hanl@ids-mannheim.de)
* @author Joachim Bingel (bingel@ids-mannheim.de)
* @version 0.3.0
@@ -36,26 +36,31 @@
private static Logger log = LoggerFactory
.getLogger(CollectionQueryProcessor.class);
- public CollectionQueryProcessor() {
+
+ public CollectionQueryProcessor () {
KoralObjectGenerator.setQueryProcessor(this);
}
- public CollectionQueryProcessor(boolean verbose) {
+
+ public CollectionQueryProcessor (boolean verbose) {
KoralObjectGenerator.setQueryProcessor(this);
CollectionQueryProcessor.verbose = verbose;
}
- public CollectionQueryProcessor(String query) {
+
+ public CollectionQueryProcessor (String query) {
KoralObjectGenerator.setQueryProcessor(this);
process(query);
}
+
@Override
- public void process(String query) {
+ public void process (String query) {
ParseTree tree = parseCollectionQuery(query);
if (this.parser != null) {
super.parser = this.parser;
- }else {
+ }
+ else {
throw new NullPointerException("Parser has not been instantiated!");
}
log.info("Processing virtual collection query: " + query);
@@ -64,13 +69,15 @@
if (tree != null) {
log.debug("ANTLR parse tree: " + tree.toStringTree(parser));
processNode(tree);
- }else {
- addError(StatusCodes.MALFORMED_QUERY,
- "Could not parse query >>> " + query + " <<<.");
+ }
+ else {
+ addError(StatusCodes.MALFORMED_QUERY, "Could not parse query >>> "
+ + query + " <<<.");
}
}
- private void processNode(ParseTree node) {
+
+ private void processNode (ParseTree node) {
// Top-down processing
String nodeCat = getNodeCat(node);
openNodeCats.push(nodeCat);
@@ -90,8 +97,8 @@
*/
if (nodeCat.equals("relation")) {
- String operator = getNodeCat(node.getChild(1).getChild(0))
- .equals("&") ? "and" : "or";
+ String operator = getNodeCat(node.getChild(1).getChild(0)).equals(
+ "&") ? "and" : "or";
LinkedHashMap<String, Object> relationGroup = KoralObjectGenerator
.makeDocGroup(operator);
putIntoSuperObject(relationGroup);
@@ -114,14 +121,14 @@
requestMap = new LinkedHashMap<String, Object>();
return;
}
-// if (QueryUtils.checkDateValidity(valueNode.getText())) {
-// addWarning("The collection query contains a value that looks"
-// + " like a date ('" + valueNode.getText() + "') and an"
-// + " operator that is only defined for strings" + " ('"
-// + match + "'). The value is interpreted as"
-// + " a string. Use a date operator to ensure the value"
-// + " is treated as a date");
-// }
+ // if (QueryUtils.checkDateValidity(valueNode.getText())) {
+ // addWarning("The collection query contains a value that looks"
+ // + " like a date ('" + valueNode.getText() + "') and an"
+ // + " operator that is only defined for strings" + " ('"
+ // + match + "'). The value is interpreted as"
+ // + " a string. Use a date operator to ensure the value"
+ // + " is treated as a date");
+ // }
putIntoSuperObject(term);
}
@@ -192,7 +199,8 @@
}
}
token.put("wrap", term);
- }else {
+ }
+ else {
// child is 'term' or 'termGroup' -> process in extra method
LinkedHashMap<String, Object> termOrTermGroup = parseTermOrTermGroup(
node.getChild(1), negated);
@@ -231,18 +239,19 @@
}
+
/**
* Checks whether the combination of operator and value is legal
* (inequation operators <,>,<=,>= may only be used with dates).
*/
- private boolean checkOperatorValueConformance(
+ private boolean checkOperatorValueConformance (
LinkedHashMap<String, Object> term) {
String match = (String) term.get("match");
String type = (String) term.get("type");
if (type == null || type.equals("type:regex")) {
- if (!(match.equals("match:eq") || match.equals("match:ne") || match
- .equals("match:contains") || match
- .equals("match:containsnot"))) {
+ if (!(match.equals("match:eq") || match.equals("match:ne")
+ || match.equals("match:contains") || match
+ .equals("match:containsnot"))) {
addError(StatusCodes.INCOMPATIBLE_OPERATOR_AND_OPERAND,
"You used an inequation operator with a string value.");
return false;
@@ -251,7 +260,8 @@
return true;
}
- private LinkedHashMap<String, Object> parseValue(ParseTree valueNode) {
+
+ private LinkedHashMap<String, Object> parseValue (ParseTree valueNode) {
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
if (getNodeCat(valueNode).equals("date")) {
map.put("type", "type:date");
@@ -275,15 +285,16 @@
return map;
}
+
/**
* Checks if value is a date
- *
+ *
* @param valueNode
* @return
*/
@Deprecated
- private boolean checkDateValidity(ParseTree valueNode) {
+ private boolean checkDateValidity (ParseTree valueNode) {
Pattern p = Pattern.compile("[0-9]{4}(-([0-9]{2})(-([0-9]{2}))?)?");
Matcher m = p.matcher(valueNode.getText());
@@ -294,7 +305,8 @@
if (month != null) {
if (Integer.parseInt(month) > 12) {
return false;
- }else if (day != null) {
+ }
+ else if (day != null) {
if (Integer.parseInt(day) > 31) {
return false;
}
@@ -303,7 +315,8 @@
return true;
}
- private String interpretMatchOperator(String match) {
+
+ private String interpretMatchOperator (String match) {
String out = null;
switch (match) {
case "<":
@@ -351,8 +364,9 @@
return out;
}
+
@Deprecated
- private String invertInequation(String op) {
+ private String invertInequation (String op) {
String inv = null;
switch (op) {
case "lt":
@@ -371,41 +385,47 @@
return inv;
}
- private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
+
+ private void putIntoSuperObject (LinkedHashMap<String, Object> object) {
putIntoSuperObject(object, 0);
}
+
@SuppressWarnings({ "unchecked" })
- private void putIntoSuperObject(LinkedHashMap<String, Object> object,
+ private void putIntoSuperObject (LinkedHashMap<String, Object> object,
int objStackPosition) {
if (objectStack.size() > objStackPosition) {
ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack
.get(objStackPosition).get("operands");
topObjectOperands.add(object);
- }else {
+ }
+ else {
// requestMap = object;
requestMap.put("collection", object);
}
}
- private LinkedHashMap<String, Object> parseTermOrTermGroup(ParseTree node,
+
+ private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
boolean negated) {
return parseTermOrTermGroup(node, negated, "token");
}
+
/**
* Parses a (term) or (termGroup) node
- *
+ *
* @param node
- * @param negatedGlobal Indicates whether the term/termGroup is globally
- * negated, e.g. through a negation operator preceding
- * the related token
- * like "![base=foo]". Global negation affects the
- * "match" parameter.
+ * @param negatedGlobal
+ * Indicates whether the term/termGroup is globally
+ * negated, e.g. through a negation operator preceding
+ * the related token
+ * like "![base=foo]". Global negation affects the
+ * "match" parameter.
* @return A term or termGroup object, depending on input
*/
@SuppressWarnings("unchecked")
- private LinkedHashMap<String, Object> parseTermOrTermGroup(ParseTree node,
+ private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
boolean negatedGlobal, String mode) {
if (getNodeCat(node).equals("term")) {
String key = null;
@@ -479,7 +499,8 @@
}
}
return term;
- }else {
+ }
+ else {
// For termGroups, establish a boolean relation between operands
// and recursively call this function with the term or termGroup
// operands.
@@ -509,7 +530,8 @@
}
}
- private ParserRuleContext parseCollectionQuery(String query) {
+
+ private ParserRuleContext parseCollectionQuery (String query) {
Lexer lexer = new CollectionQueryLexer((CharStream) null);
ParserRuleContext tree = null;
Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
index 1b22f39..fbf63ac 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
@@ -669,6 +669,7 @@
// Step I: create group
LinkedHashMap<String, Object> disjunction = KoralObjectGenerator
.makeGroup("disjunction");
+ disjunction.put("inOrder", false); // Order is not important
objectStack.push(disjunction);
stackedObjects++;
// Step II: decide where to put
@@ -681,6 +682,7 @@
String nodeCat = getNodeCat(node);
LinkedHashMap<String, Object> distgroup = KoralObjectGenerator
.makeGroup("sequence");
+ distgroup.put("inOrder", false); // Order is not important
ArrayList<Object> distances = new ArrayList<Object>();
LinkedHashMap<String, Object> zerodistance = KoralObjectGenerator
.makeDistance("t", 0, 0);
@@ -1350,4 +1352,4 @@
}
return tree;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
index b06731c..2dd8985 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessor.java
@@ -12,7 +12,7 @@
/**
* @author margaretha
- * @date 09.05.14
+ * @date 30.05.16
*/
public class CqlQueryProcessor extends AbstractQueryProcessor {
@@ -22,51 +22,40 @@
private static final String INDEX_WORDS = "words";
private static final String TERM_RELATION_CQL_1_1 = "scr";
private static final String TERM_RELATION_CQL_1_2 = "=";
- private static final String SUPPORTED_RELATION_EXACT = "exact"; // not
- // in
- // the
- // doc
+ private static final String SUPPORTED_RELATION_EXACT = "exact"; // not in the doc
private static final String OPERATION_OR = "operation:or";
private static final String OPERATION_SEQUENCE = "operation:sequence";
private static final String OPERATION_POSITION = "operation:position";
- private static final String KORAP_CONTEXT = "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld";
- private LinkedHashMap<String, Object> requestMap;
private String version;
private boolean isCaseSensitive; // default true
-
public CqlQueryProcessor (String query) {
this(query, VERSION_1_2, true);
}
-
public CqlQueryProcessor (String query, String version) {
this(query, version, true);
}
-
public CqlQueryProcessor (String query, String version,
- boolean isCaseSensitive) {
+ boolean isCaseSensitive) {
+ super();
this.version = version;
this.isCaseSensitive = isCaseSensitive;
- this.requestMap = new LinkedHashMap<>();
- requestMap.put("@context", KORAP_CONTEXT);
process(query);
}
-
@Override
- public Map<String, Object> getRequestMap () {
+ public Map<String, Object> getRequestMap() {
return this.requestMap;
}
-
@Override
- public void process (String query) {
+ public void process(String query) {
if ((query == null) || query.isEmpty())
- addError(StatusCodes.MALFORMED_QUERY,
- "SRU diagnostic 27: An empty query is unsupported.");
+ addError(StatusCodes.NO_QUERY,
+ "SRU diagnostic 27: Empty query is unsupported.");
CQLNode cqlNode = parseQuerytoCQLNode(query);
Map<String, Object> queryMap = parseCQLNode(cqlNode);
@@ -74,8 +63,7 @@
// requestMap.put("query", sentenceWrapper(queryMap));
}
-
- private Map<String, Object> sentenceWrapper (Map<String, Object> m) {
+ private Map<String, Object> sentenceWrapper(Map<String, Object> m) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("@type", "koral:group");
map.put("operation", OPERATION_POSITION);
@@ -93,8 +81,7 @@
return map;
}
-
- private CQLNode parseQuerytoCQLNode (String query) {
+ private CQLNode parseQuerytoCQLNode(String query) {
try {
int compat = -1;
switch (version) {
@@ -113,8 +100,7 @@
}
}
-
- private Map<String, Object> parseCQLNode (CQLNode node) {
+ private Map<String, Object> parseCQLNode(CQLNode node) {
if (node instanceof CQLTermNode) {
return parseTermNode((CQLTermNode) node);
@@ -134,8 +120,7 @@
}
}
-
- private Map<String, Object> parseTermNode (CQLTermNode node) {
+ private Map<String, Object> parseTermNode(CQLTermNode node) {
checkTermNode(node);
final String term = node.getTerm();
if ((term == null) || term.isEmpty()) {
@@ -151,8 +136,7 @@
}
}
-
- private Map<String, Object> parseAndNode (CQLAndNode node) {
+ private Map<String, Object> parseAndNode(CQLAndNode node) {
checkBooleanModifier(node);
Map<String, Object> map = new LinkedHashMap<String, Object>();
@@ -177,8 +161,7 @@
return map;
}
-
- private Map<String, Object> parseOrNode (CQLOrNode node) {
+ private Map<String, Object> parseOrNode(CQLOrNode node) {
checkBooleanModifier(node);
Map<String, Object> map = new LinkedHashMap<String, Object>();
@@ -193,8 +176,7 @@
return map;
}
-
- private Map<String, Object> writeSequence (String str) {
+ private Map<String, Object> writeSequence(String str) {
Map<String, Object> sequenceMap = new LinkedHashMap<String, Object>();
sequenceMap.put("@type", "koral:group");
sequenceMap.put("operation", OPERATION_SEQUENCE);
@@ -209,8 +191,7 @@
return sequenceMap;
}
-
- private Map<String, Object> writeTerm (String term) {
+ private Map<String, Object> writeTerm(String term) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("@type", "koral:term");
if (!isCaseSensitive) {
@@ -226,8 +207,7 @@
return tokenMap;
}
-
- private void checkBooleanModifier (CQLBooleanNode node) {
+ private void checkBooleanModifier(CQLBooleanNode node) {
List<Modifier> modifiers = node.getModifiers();
if ((modifiers != null) && !modifiers.isEmpty()) {
Modifier modifier = modifiers.get(0);
@@ -237,8 +217,7 @@
}
}
-
- private void checkTermNode (CQLTermNode node) {
+ private void checkTermNode(CQLTermNode node) {
// only allow "cql.serverChoice" and "words" index
if (!(INDEX_CQL_SERVERCHOICE.equals(node.getIndex()) || INDEX_WORDS
.equals(node.getIndex()))) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
new file mode 100644
index 0000000..369e8e3
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
@@ -0,0 +1,109 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.parse.fcsql.FCSSRUQueryParser;
+import de.ids_mannheim.korap.query.serialize.util.KoralException;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
+import eu.clarin.sru.server.SRUQueryBase;
+import eu.clarin.sru.server.fcs.Constants;
+import eu.clarin.sru.server.fcs.parser.QueryNode;
+import eu.clarin.sru.server.fcs.parser.QueryParser;
+import eu.clarin.sru.server.fcs.parser.QueryParserException;
+
+/**
+ * @author margaretha
+ *
+ */
+public class FCSQLQueryProcessor extends AbstractQueryProcessor {
+
+ public static final class FCSSRUQuery extends SRUQueryBase<QueryNode> {
+
+ private FCSSRUQuery (String rawQuery, QueryNode parsedQuery) {
+ super(rawQuery, parsedQuery);
+ }
+
+ @Override
+ public String getQueryType() {
+ return Constants.FCS_QUERY_TYPE_FCS;
+ }
+ }
+
+ private static final String VERSION_2_0 = "2.0";
+
+ private final QueryParser fcsParser = new QueryParser();
+ private String version;
+
+ public FCSQLQueryProcessor (String query, String version) {
+ super();
+ this.version = version;
+ process(query);
+ }
+
+ @Override
+ public Map<String, Object> getRequestMap() {
+ return this.requestMap;
+ }
+
+ @Override
+ public void process(String query) {
+ if (isVersionValid()) {
+ FCSSRUQuery fcsSruQuery = parseQueryStringtoFCSQuery(query);
+ if (fcsSruQuery != null) {
+ QueryNode fcsQueryNode = fcsSruQuery.getParsedQuery();
+ try {
+ parseFCSQueryToKoralQuery(fcsQueryNode);
+ } catch (KoralException e) {
+ addError(e.getStatusCode(), e.getMessage());
+ }
+ }
+ }
+ }
+
+ private boolean isVersionValid() {
+ if (version == null || version.isEmpty()) {
+ addError(StatusCodes.MISSING_VERSION,
+ "SRU diagnostic 7: Version number is missing.");
+ return false;
+ }
+ else if (!version.equals(VERSION_2_0)) {
+ addError(StatusCodes.MISSING_VERSION,
+ "SRU diagnostic 5: Only supports SRU version 2.0.");
+ return false;
+ }
+ return true;
+ }
+
+ private FCSSRUQuery parseQueryStringtoFCSQuery(String query) {
+ if ((query == null) || query.isEmpty())
+ addError(StatusCodes.NO_QUERY,
+ "SRU diagnostic 1: No query has been passed.");
+ FCSSRUQuery fcsQuery = null;
+ try {
+ QueryNode parsedQuery = fcsParser.parse(query);
+ fcsQuery = new FCSSRUQuery(query, parsedQuery);
+ if (fcsQuery == null) {
+ addError(StatusCodes.UNKNOWN_QUERY_ERROR,
+ "FCS diagnostic 10: Unexpected error while parsing query.");
+ }
+ }
+ catch (QueryParserException e) {
+ addError(
+ StatusCodes.UNKNOWN_QUERY_ERROR,
+ "FCS diagnostic 10: Query cannot be parsed, "
+ + e.getMessage());
+ }
+ catch (Exception e) {
+ addError(StatusCodes.UNKNOWN_QUERY_ERROR, "FCS diagnostic 10: "
+ + "Unexpected error while parsing query.");
+ }
+ return fcsQuery;
+ }
+
+ private void parseFCSQueryToKoralQuery(QueryNode queryNode) throws KoralException {
+ FCSSRUQueryParser parser = new FCSSRUQueryParser();
+ Object o = parser.parseQueryNode(queryNode);
+ Map<String, Object> queryMap = MapBuilder.buildQueryMap(o);
+ if (queryMap != null) requestMap.put("query", queryMap);
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
new file mode 100644
index 0000000..9d1c2ee
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
@@ -0,0 +1,42 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import java.util.Map;
+
+import de.ids_mannheim.korap.query.object.KoralGroup;
+import de.ids_mannheim.korap.query.object.KoralSpan;
+import de.ids_mannheim.korap.query.object.KoralTerm;
+import de.ids_mannheim.korap.query.object.KoralTermGroup;
+import de.ids_mannheim.korap.query.object.KoralToken;
+
+/**
+ * @author margaretha
+ *
+ */
+public class MapBuilder {
+
+ public static Map<String, Object> buildQueryMap(Object o) {
+ if (o != null) {
+ if (o instanceof KoralToken) {
+ KoralToken token = (KoralToken) o;
+ return token.buildMap();
+ }
+ else if (o instanceof KoralGroup) {
+ KoralGroup group = (KoralGroup) o;
+ return group.buildMap();
+ }
+ if (o instanceof KoralTerm) {
+ KoralTerm term = (KoralTerm) o;
+ return term.buildMap();
+ }
+ else if (o instanceof KoralTermGroup) {
+ KoralTermGroup termGroup = (KoralTermGroup) o;
+ return termGroup.buildMap();
+ }
+ else if (o instanceof KoralSpan){
+ KoralSpan span = (KoralSpan) o;
+ return span.buildMap();
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
index cc51dd4..cad4319 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
@@ -17,41 +17,45 @@
private Map meta;
private SpanContext spanContext;
- public MetaQueryBuilder() {
+
+ public MetaQueryBuilder () {
this.meta = new LinkedHashMap();
// this.meta.put("fields", new LinkedList<>());
}
+
/**
* context segment if context is either of type char or token.
* size can differ for left and right span
- *
+ *
* @param left
* @param leftType
* @param right
* @param rightType
* @return
*/
- public MetaQueryBuilder setSpanContext(Integer left, String leftType,
+ public MetaQueryBuilder setSpanContext (Integer left, String leftType,
Integer right, String rightType) {
this.spanContext = new SpanContext(left, leftType, right, rightType);
return this;
}
- public SpanContext getSpanContext() {
+
+ public SpanContext getSpanContext () {
return this.spanContext;
}
+
/**
* context if of type paragraph or sentence where left and right
* size delimiters are irrelevant; or 2-token, 2-char p/paragraph,
* s/sentence or token, char.
* Distinguish
- *
+ *
* @param context
* @return
*/
- public MetaQueryBuilder setSpanContext(String context) {
+ public MetaQueryBuilder setSpanContext (String context) {
if (context != null) {
if (!p.matcher(context).find())
this.spanContext = new SpanContext(context);
@@ -66,13 +70,15 @@
return this;
}
- public MetaQueryBuilder addEntry(String name, Object value) {
+
+ public MetaQueryBuilder addEntry (String name, Object value) {
if (value != null)
meta.put(name, value);
return this;
}
- public Map raw() {
+
+ public Map raw () {
if (this.spanContext != null)
meta.putAll(this.spanContext.raw());
return meta;
@@ -85,24 +91,26 @@
private int right_size;
private String context = null;
+
/**
* context segment if context is either of type char or token.
* size can differ for left and right span
- *
+ *
* @param ls
* @param lt
* @param rs
* @param rt
* @return
*/
- public SpanContext(int ls, String lt, int rs, String rt) {
+ public SpanContext (int ls, String lt, int rs, String rt) {
this.left_type = lt;
this.left_size = ls;
this.right_type = rt;
this.right_size = rs;
}
- public SpanContext(String context) {
+
+ public SpanContext (String context) {
this.context = context;
}
@@ -122,9 +130,6 @@
return this.right_size;
}
-
-
-
public Map raw() {
Map meta = new LinkedHashMap();
if (this.context == null) {
@@ -138,7 +143,8 @@
r.add(this.right_size);
map.put("right", r);
meta.put("context", map);
- }else
+ }
+ else
meta.put("context", this.context);
return meta;
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
index 4571efb..c0a88c9 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
@@ -770,8 +770,16 @@
@SuppressWarnings("unchecked")
private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
boolean negatedGlobal, String mode) {
+
String nodeCat = getNodeCat(node);
+
if (nodeCat.equals("term")) {
+
+ // Term is defined recursive with non-necessary brackets
+ if (getNodeCat(node.getChild(0)).equals("(")) {
+ return parseTermOrTermGroup(node.getChild(1), negatedGlobal, mode);
+ };
+
String key = null;
LinkedHashMap<String, Object> term = KoralObjectGenerator
.makeTerm();
@@ -857,6 +865,12 @@
return term;
}
else if (nodeCat.equals("termGroup")) {
+
+ // TermGroup is defined recursive with non-necessary brackets
+ if (getNodeCat(node.getChild(0)).equals("(")) {
+ return parseTermOrTermGroup(node.getChild(1), negatedGlobal, mode);
+ };
+
// For termGroups, establish a boolean relation between
// operands and recursively call this function with
// the term or termGroup operands
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 fa4c029..62422ae 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
@@ -12,11 +12,10 @@
import java.util.*;
/**
- * Main class for Koral, serializes queries from concrete QLs to
- * KoralQuery
- *
- * @author Joachim Bingel (bingel@ids-mannheim.de),
- * Michael Hanl (hanl@ids-mannheim.de)
+ * Main class for Koral, serializes queries from concrete QLs to KoralQuery
+ *
+ * @author Joachim Bingel (bingel@ids-mannheim.de), Michael Hanl
+ * (hanl@ids-mannheim.de), Eliza Margaretha (margaretha@ids-mannheim.de)
* @version 0.3.0
* @since 0.1.0
*/
@@ -31,8 +30,8 @@
static {
qlProcessorAssignment = new HashMap<String, Class<? extends AbstractQueryProcessor>>();
- qlProcessorAssignment
- .put("poliqarpplus", PoliqarpPlusQueryProcessor.class);
+ qlProcessorAssignment.put("poliqarpplus",
+ PoliqarpPlusQueryProcessor.class);
qlProcessorAssignment.put("cosmas2", Cosmas2QueryProcessor.class);
qlProcessorAssignment.put("annis", AnnisQueryProcessor.class);
qlProcessorAssignment.put("cql", CqlQueryProcessor.class);
@@ -51,7 +50,7 @@
private org.slf4j.Logger log = LoggerFactory
.getLogger(QuerySerializer.class);
- public QuerySerializer() {
+ public QuerySerializer() {
this.errors = new LinkedList<>();
this.warnings = new LinkedList<>();
this.messages = new LinkedList<>();
@@ -60,7 +59,7 @@
/**
* @param args
*/
- public static void main(String[] args) {
+ public static void main(String[] args) {
/*
* just for testing...
*/
@@ -73,7 +72,7 @@
System.err
.println("Usage: QuerySerializer \"query\" queryLanguage");
System.exit(1);
- }else {
+ } else {
queries = new String[] { args[0] };
ql = args[1];
}
@@ -82,95 +81,106 @@
try {
jg.run(q, ql);
System.out.println();
- }catch (NullPointerException npe) {
+ } catch (NullPointerException npe) {
npe.printStackTrace();
System.out.println("null\n");
- }catch (IOException e) {
+ } catch (IOException e) {
e.printStackTrace();
}
}
}
/**
- * Runs the QuerySerializer by initializing the relevant
- * AbstractSyntaxTree implementation (depending on specified query
- * language) and transforms and writes the tree's requestMap to
- * the specified output file.
- *
- * @param query The query string
- * @param queryLanguage The query language. As of 17 Dec 2014, this must be
- * one of 'poliqarpplus', 'cosmas2', 'annis' or 'cql'.
- * @throws IOException
- */
- public void run(String query, String queryLanguage) throws IOException {
+ * Runs the QuerySerializer by initializing the relevant AbstractSyntaxTree
+ * implementation (depending on specified query language) and transforms and
+ * writes the tree's requestMap to the specified output file.
+ *
+ * @param query
+ * The query string
+ * @param queryLanguage
+ * The query language. As of 17 Dec 2014, this must be one of
+ * 'poliqarpplus', 'cosmas2', 'annis' or 'cql'.
+ * @throws IOException
+ */
+ public void run(String query, String queryLanguage) throws IOException {
if (queryLanguage.equalsIgnoreCase("poliqarp")) {
ast = new PoliqarpPlusQueryProcessor(query);
- }else if (queryLanguage.equalsIgnoreCase("cosmas2")) {
+ } else if (queryLanguage.equalsIgnoreCase("cosmas2")) {
ast = new Cosmas2QueryProcessor(query);
- }else if (queryLanguage.equalsIgnoreCase("poliqarpplus")) {
+ } else if (queryLanguage.equalsIgnoreCase("poliqarpplus")) {
ast = new PoliqarpPlusQueryProcessor(query);
- }else if (queryLanguage.equalsIgnoreCase("cql")) {
+ } else if (queryLanguage.equalsIgnoreCase("cql")) {
ast = new CqlQueryProcessor(query);
+ } else if (queryLanguage.equalsIgnoreCase("fcsql")) {
+ ast = new FCSQLQueryProcessor(query, "2.0");
}else if (queryLanguage.equalsIgnoreCase("annis")) {
ast = new AnnisQueryProcessor(query);
- }else {
- throw new IllegalArgumentException(
- queryLanguage + " is not a supported query language!");
+ } else {
+ throw new IllegalArgumentException(queryLanguage
+ + " is not a supported query language!");
}
toJSON();
}
- public QuerySerializer setQuery(String query, String ql, String version) {
+ public QuerySerializer setQuery(String query, String ql, String version) {
ast = new DummyQueryProcessor();
if (query == null || query.isEmpty()) {
ast.addError(StatusCodes.NO_QUERY, "You did not specify a query!");
- }else if (ql == null || ql.isEmpty()) {
+ } else if (ql == null || ql.isEmpty()) {
ast.addError(StatusCodes.NO_QUERY,
"You did not specify any query language!");
- }else if (ql.equalsIgnoreCase("poliqarp")) {
+ } else if (ql.equalsIgnoreCase("poliqarp")) {
ast = new PoliqarpPlusQueryProcessor(query);
- }else if (ql.equalsIgnoreCase("cosmas2")) {
+ } else if (ql.equalsIgnoreCase("cosmas2")) {
ast = new Cosmas2QueryProcessor(query);
- }else if (ql.equalsIgnoreCase("poliqarpplus")) {
+ } else if (ql.equalsIgnoreCase("poliqarpplus")) {
ast = new PoliqarpPlusQueryProcessor(query);
}else if (ql.equalsIgnoreCase("cql")) {
- if (version == null)
+ if (version == null) {
ast = new CqlQueryProcessor(query);
- else
+ } else {
ast = new CqlQueryProcessor(query, version);
- }else if (ql.equalsIgnoreCase("annis")) {
+ }
+ } else if (ql.equalsIgnoreCase("fcsql")) {
+ if (version == null) {
+ ast.addError(StatusCodes.MISSING_VERSION,
+ "SRU Version is missing!");
+ } else {
+ ast = new FCSQLQueryProcessor(query, version);
+ }
+ } else if (ql.equalsIgnoreCase("annis")) {
ast = new AnnisQueryProcessor(query);
}else {
- ast.addError(StatusCodes.UNKNOWN_QL,
+ ast.addError(StatusCodes.UNKNOWN_QUERY_LANGUAGE,
ql + " is not a supported query language!");
}
return this;
}
- public QuerySerializer setQuery(String query, String ql) {
+ public QuerySerializer setQuery(String query, String ql) {
return setQuery(query, ql, "");
}
- public void setVerbose(boolean verbose) {
+ public void setVerbose(boolean verbose) {
AbstractQueryProcessor.verbose = verbose;
}
- public final String toJSON() {
+ public final String toJSON() {
String ser;
try {
ser = mapper.writeValueAsString(raw());
qllogger.info("Serialized query: " + ser);
- }catch (JsonProcessingException e) {
+ } catch (JsonProcessingException e) {
return "";
}
return ser;
}
- public final Map build() {
+ public final Map build() {
return raw();
}
- private Map raw() {
+ private Map raw () {
if (ast != null) {
Map<String, Object> requestMap = new HashMap<>(ast.getRequestMap());
Map meta = (Map) requestMap.get("meta");
@@ -211,33 +221,36 @@
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 if (collection1.equals(collection2)) {
+ }
+ else if (collection1.equals(collection2)) {
return collection1;
- }else {
+ }
+ else {
LinkedHashMap<String, Object> docGroup = KoralObjectGenerator
.makeDocGroup("and");
ArrayList<Object> operands = (ArrayList<Object>) docGroup
@@ -249,7 +262,7 @@
}
@Deprecated
- public QuerySerializer addMeta(String cli, String cri, int cls, int crs,
+ public QuerySerializer addMeta(String cli, String cri, int cls, int crs,
int num, int pageIndex) {
MetaQueryBuilder meta = new MetaQueryBuilder();
meta.setSpanContext(cls, cli, crs, cri);
@@ -259,12 +272,17 @@
return this;
}
- public QuerySerializer setMeta(Map<String, Object> meta) {
+ public QuerySerializer setMeta(Map<String, Object> meta) {
this.meta = meta;
return this;
}
- public QuerySerializer setCollection(String collection) {
+ public QuerySerializer setMeta(MetaQueryBuilder meta) {
+ this.meta = meta.raw();
+ return this;
+ }
+
+ public QuerySerializer setCollection(String collection) {
CollectionQueryProcessor tree = new CollectionQueryProcessor();
tree.process(collection);
Map<String, Object> collectionRequest = tree.getRequestMap();
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
index 6980b2e..47b5e09 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QueryUtils.java
@@ -14,7 +14,7 @@
*/
public class QueryUtils {
- public static SimpleEntry<String, Integer> checkUnbalancedPars(String q) {
+ public static SimpleEntry<String, Integer> checkUnbalancedPars (String q) {
Map<Character, Character> brackets = new HashMap<Character, Character>();
brackets.put('[', ']');
brackets.put('{', '}');
@@ -31,8 +31,9 @@
if (brackets.containsKey(q.charAt(i))) {
stack.push(q.charAt(i));
lastOpenBracket = i;
- }else if (stack.empty() || (q.charAt(i) != brackets
- .get(stack.pop()))) {
+ }
+ else if (stack.empty()
+ || (q.charAt(i) != brackets.get(stack.pop()))) {
return new SimpleEntry<String, Integer>(
"Parantheses/brackets unbalanced.", i);
}
@@ -43,13 +44,15 @@
return null;
}
- public static List<String> parseMorph(String stringTree) {
+
+ public static List<String> parseMorph (String stringTree) {
ArrayList<String> morph = new ArrayList<String>();
return morph;
}
- public static String buildCypherQuery(String cypher, String ctypel,
+
+ public static String buildCypherQuery (String cypher, String ctypel,
String ctyper, int cl, int cr, int page, int limit) {
// todo: implies that there is only one type allowed!
String sctypel = "", sctyper = "";
@@ -100,7 +103,8 @@
return buffer.toString();
}
- public static String buildDotQuery(long sid, String graphdb_id) {
+
+ public static String buildDotQuery (long sid, String graphdb_id) {
StringBuffer b = new StringBuffer();
b.append("<query>");
b.append("<sentenceId>");
@@ -122,7 +126,8 @@
return b.toString();
}
- public String buildaggreQuery(String query) {
+
+ public String buildaggreQuery (String query) {
StringBuffer b = new StringBuffer();
b.append("<query><cypher><![CDATA[");
b.append(query);
@@ -151,9 +156,10 @@
return b.toString();
}
+
@Deprecated
- public static Map addParameters(Map request, int page, int num, String cli,
- String cri, int cls, int crs, boolean cutoff) {
+ public static Map addParameters (Map request, int page, int num,
+ String cli, String cri, int cls, int crs, boolean cutoff) {
Map ctx = new LinkedHashMap();
List left = new ArrayList();
left.add(cli);
@@ -172,14 +178,15 @@
return request;
}
+
/**
* Checks if value is a date
- *
+ *
* @param value
* @return
*/
- public static boolean checkDateValidity(String value) {
+ public static boolean checkDateValidity (String value) {
Pattern p = Pattern.compile("^[0-9]{4}(-([0-9]{2})(-([0-9]{2}))?)?$");
Matcher m = p.matcher(value);
@@ -190,7 +197,8 @@
if (month != null) {
if (Integer.parseInt(month) > 12) {
return false;
- }else if (day != null) {
+ }
+ else if (day != null) {
if (Integer.parseInt(day) > 31) {
return false;
}
@@ -199,7 +207,8 @@
return true;
}
- public static String escapeRegexSpecialChars(String key) {
+
+ public static String escapeRegexSpecialChars (String key) {
key.replace("\\", "\\\\");
Pattern p = Pattern
.compile("\\.|\\^|\\$|\\||\\?|\\*|\\+|\\(|\\)|\\[|\\]|\\{|\\}");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java
new file mode 100644
index 0000000..34d4569
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/KoralException.java
@@ -0,0 +1,30 @@
+package de.ids_mannheim.korap.query.serialize.util;
+
+public class KoralException extends Exception{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5463242042200109417L;
+ private int statusCode;
+
+ public KoralException(int code, String message) {
+ super(message);
+ this.statusCode = code;
+ }
+
+ public KoralException(int code, String message, Throwable cause) {
+ super(message, cause);
+ this.statusCode = code;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
index 10614ea..1f896b3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
@@ -7,7 +7,9 @@
public final static int INVALID_CLASS_REFERENCE = 304;
public final static int INCOMPATIBLE_OPERATOR_AND_OPERAND = 305;
public final static int UNKNOWN_QUERY_ELEMENT = 306;
- public final static int UNKNOWN_QL = 307;
+ public final static int UNKNOWN_QUERY_LANGUAGE = 307;
public final static int UNBOUND_ANNIS_RELATION = 308;
- public final static int UNKNOWN_QUERY_ERROR = 399;
-}
+ public final static int MISSING_VERSION = 309;
+ public final static int QUERY_TOO_COMPLEX = 310;
+ public final static int UNKNOWN_QUERY_ERROR = 399;
+}
\ No newline at end of file
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
index ed8e40f..f7c4dd1 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryDuplicateTest.java
@@ -17,16 +17,20 @@
public class CollectionQueryDuplicateTest {
@Test
- public void testCollectionQueryDuplicateThrowsAssertionException() throws IOException {
+ public void testCollectionQueryDuplicateThrowsAssertionException ()
+ throws IOException {
QuerySerializer serializer = new QuerySerializer();
serializer.setQuery("[base=Haus]", "poliqarp");
serializer.setCollection("textClass=politik & corpusID=WPD");
ObjectMapper m = new ObjectMapper();
JsonNode first = m.readTree(serializer.toJSON());
assertNotNull(first);
- assertEquals(first.at("/collection"), m.readTree(serializer.toJSON()).at("/collection"));
- assertEquals(first.at("/collection"), m.readTree(serializer.toJSON()).at("/collection"));
- assertEquals(first.at("/collection"), m.readTree(serializer.toJSON()).at("/collection"));
+ assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+ .at("/collection"));
+ assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+ .at("/collection"));
+ assertEquals(first.at("/collection"), m.readTree(serializer.toJSON())
+ .at("/collection"));
}
}
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
index 1a24352..0e91058 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/CollectionQueryProcessorTest.java
@@ -22,8 +22,9 @@
ObjectMapper mapper = new ObjectMapper();
JsonNode res;
+
@Test
- public void testContext() throws JsonProcessingException, IOException {
+ public void testContext () throws JsonProcessingException, IOException {
collection = "textClass=politik";
String contextString = "http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld";
qs.setQuery(query, ql);
@@ -32,8 +33,9 @@
assertEquals(contextString, res.get("@context").asText());
}
+
@Test
- public void testSimple() throws JsonProcessingException, IOException {
+ public void testSimple () throws JsonProcessingException, IOException {
collection = "textClass=politik";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -53,9 +55,10 @@
assertEquals("match:ne", res.at("/collection/match").asText());
}
+
@Test
- public void testSpecialCharacters()
- throws JsonProcessingException, IOException {
+ public void testSpecialCharacters () throws JsonProcessingException,
+ IOException {
collection = "[base/n=alt]";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -71,8 +74,9 @@
;
+
@Test
- public void testContains() throws JsonProcessingException, IOException {
+ public void testContains () throws JsonProcessingException, IOException {
collection = "title~Mannheim";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -101,8 +105,9 @@
assertEquals("match:contains", res.at("/collection/match").asText());
}
+
@Test
- public void testNotDate() throws JsonProcessingException, IOException {
+ public void testNotDate () throws JsonProcessingException, IOException {
collection = "author=\"firefighter1974\"";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -115,29 +120,29 @@
assertEquals("", res.at("/warnings/0/0").asText());
}
+
@Test
- public void testTwoConjuncts() throws JsonProcessingException, IOException {
+ public void testTwoConjuncts () throws JsonProcessingException, IOException {
collection = "textClass=Sport & pubDate in 2014";
qs.setQuery(query, ql);
qs.setCollection(collection);
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:and", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/1/@type").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+ .asText());
assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
assertEquals("2014", res.at("/collection/operands/1/value").asText());
- assertEquals("type:date",
- res.at("/collection/operands/1/type").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/1/match").asText());
+ assertEquals("type:date", res.at("/collection/operands/1/type")
+ .asText());
+ assertEquals("match:eq", res.at("/collection/operands/1/match")
+ .asText());
collection = "textClass=Sport & pubDate=2014";
qs.setQuery(query, ql);
@@ -146,166 +151,165 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:and", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/1/@type").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+ .asText());
assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
assertEquals("2014", res.at("/collection/operands/1/value").asText());
- assertEquals(true,
- res.at("/collection/operands/1/type").isMissingNode());
- assertEquals("match:eq",
- res.at("/collection/operands/1/match").asText());
+ assertEquals(true, res.at("/collection/operands/1/type")
+ .isMissingNode());
+ assertEquals("match:eq", res.at("/collection/operands/1/match")
+ .asText());
assertTrue(res.at("/warnings/0").isMissingNode());
// assertTrue(res.at("/warnings/0/0").asText().startsWith(
// "The collection query contains a value that looks like a date"));
}
+
@Test
- public void testThreeConjuncts()
- throws JsonProcessingException, IOException {
+ public void testThreeConjuncts () throws JsonProcessingException,
+ IOException {
collection = "textClass=Sport & pubDate in 2014 & corpusId=WPD";
qs.setQuery(query, ql);
qs.setCollection(collection);
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:and", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/1/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("pubDate",
- res.at("/collection/operands/1/operands/0/key").asText());
- assertEquals("2014",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+ .asText());
+ assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("type:date",
res.at("/collection/operands/1/operands/0/type").asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/0/match").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/1/@type").asText());
- assertEquals("corpusId",
- res.at("/collection/operands/1/operands/1/key").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/1/value").asText());
+ assertEquals("corpusId", res
+ .at("/collection/operands/1/operands/1/key").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+ .asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/1/match").asText());
}
+
@Test
- public void testTwoDisjuncts() throws JsonProcessingException, IOException {
+ public void testTwoDisjuncts () throws JsonProcessingException, IOException {
collection = "textClass=Sport | pubDate in 2014";
qs.setQuery(query, ql);
qs.setCollection(collection);
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/1/@type").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+ .asText());
assertEquals("pubDate", res.at("/collection/operands/1/key").asText());
assertEquals("2014", res.at("/collection/operands/1/value").asText());
- assertEquals("type:date",
- res.at("/collection/operands/1/type").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/1/match").asText());
+ assertEquals("type:date", res.at("/collection/operands/1/type")
+ .asText());
+ assertEquals("match:eq", res.at("/collection/operands/1/match")
+ .asText());
}
+
@Test
- public void testThreeDisjuncts()
- throws JsonProcessingException, IOException {
+ public void testThreeDisjuncts () throws JsonProcessingException,
+ IOException {
collection = "textClass=Sport | pubDate in 2014 | corpusId=WPD";
qs.setQuery(query, ql);
qs.setCollection(collection);
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:or",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:or", res.at("/collection/operands/1/operation")
+ .asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("pubDate",
- res.at("/collection/operands/1/operands/0/key").asText());
- assertEquals("2014",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+ .asText());
+ assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("type:date",
res.at("/collection/operands/1/operands/0/type").asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/0/match").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/1/@type").asText());
- assertEquals("corpusId",
- res.at("/collection/operands/1/operands/1/key").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/1/value").asText());
+ assertEquals("corpusId", res
+ .at("/collection/operands/1/operands/1/key").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+ .asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/1/match").asText());
}
+
@Test
- public void testMixed() throws JsonProcessingException, IOException {
+ public void testMixed () throws JsonProcessingException, IOException {
collection = "textClass=Sport | (pubDate in 2014 & corpusId=WPD)";
qs.setQuery(query, ql);
qs.setCollection(collection);
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/1/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("pubDate",
- res.at("/collection/operands/1/operands/0/key").asText());
- assertEquals("2014",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+ .asText());
+ assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("type:date",
res.at("/collection/operands/1/operands/0/type").asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/0/match").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/1/@type").asText());
- assertEquals("corpusId",
- res.at("/collection/operands/1/operands/1/key").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/1/value").asText());
+ assertEquals("corpusId", res
+ .at("/collection/operands/1/operands/1/key").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+ .asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/1/match").asText());
@@ -315,33 +319,32 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("textClass",
- res.at("/collection/operands/0/key").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("textClass", res.at("/collection/operands/0/key").asText());
assertEquals("Sport", res.at("/collection/operands/0/value").asText());
- assertEquals("match:eq",
- res.at("/collection/operands/0/match").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("match:eq", res.at("/collection/operands/0/match")
+ .asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/1/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("pubDate",
- res.at("/collection/operands/1/operands/0/key").asText());
- assertEquals("2014",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("pubDate", res.at("/collection/operands/1/operands/0/key")
+ .asText());
+ assertEquals("2014", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("type:date",
res.at("/collection/operands/1/operands/0/type").asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/0/match").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/1/@type").asText());
- assertEquals("corpusId",
- res.at("/collection/operands/1/operands/1/key").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/1/value").asText());
+ assertEquals("corpusId", res
+ .at("/collection/operands/1/operands/1/key").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/1/value")
+ .asText());
assertEquals("match:eq",
res.at("/collection/operands/1/operands/1/match").asText());
@@ -351,16 +354,16 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:and", res.at("/collection/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("operation:or",
- res.at("/collection/operands/0/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("operation:or", res.at("/collection/operands/0/operation")
+ .asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/0/@type").asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/1/@type").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/1/@type").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+ .asText());
collection = "(textClass=Sport & pubDate in 2014) & corpusId=WPD";
qs.setQuery(query, ql);
@@ -368,16 +371,16 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:and", res.at("/collection/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/0/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/0/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/0/@type").asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/1/@type").asText());
- assertEquals("koral:doc",
- res.at("/collection/operands/1/@type").asText());
+ assertEquals("koral:doc", res.at("/collection/operands/1/@type")
+ .asText());
collection = "(textClass=Sport & textClass=ausland) | (corpusID=WPD & author=White)";
qs.setQuery(query, ql);
@@ -385,30 +388,30 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/0/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/0/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/1/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/0/@type").asText());
- assertEquals("Sport",
- res.at("/collection/operands/0/operands/0/value").asText());
+ assertEquals("Sport", res.at("/collection/operands/0/operands/0/value")
+ .asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/1/@type").asText());
assertEquals("ausland",
res.at("/collection/operands/0/operands/1/value").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/1/@type").asText());
- assertEquals("White",
- res.at("/collection/operands/1/operands/1/value").asText());
+ assertEquals("White", res.at("/collection/operands/1/operands/1/value")
+ .asText());
collection = "(textClass=Sport & textClass=ausland) | (corpusID=WPD & author=White & pubDate in 2000)";
qs.setQuery(query, ql);
@@ -416,26 +419,26 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:docGroup", res.at("/collection/@type").asText());
assertEquals("operation:or", res.at("/collection/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/0/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/0/operation").asText());
- assertEquals("koral:docGroup",
- res.at("/collection/operands/1/@type").asText());
- assertEquals("operation:and",
- res.at("/collection/operands/1/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/0/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/0/operation").asText());
+ assertEquals("koral:docGroup", res.at("/collection/operands/1/@type")
+ .asText());
+ assertEquals("operation:and", res
+ .at("/collection/operands/1/operation").asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/0/@type").asText());
- assertEquals("Sport",
- res.at("/collection/operands/0/operands/0/value").asText());
+ assertEquals("Sport", res.at("/collection/operands/0/operands/0/value")
+ .asText());
assertEquals("koral:doc",
res.at("/collection/operands/0/operands/1/@type").asText());
assertEquals("ausland",
res.at("/collection/operands/0/operands/1/value").asText());
assertEquals("koral:doc",
res.at("/collection/operands/1/operands/0/@type").asText());
- assertEquals("WPD",
- res.at("/collection/operands/1/operands/0/value").asText());
+ assertEquals("WPD", res.at("/collection/operands/1/operands/0/value")
+ .asText());
assertEquals("koral:docGroup",
res.at("/collection/operands/1/operands/1/@type").asText());
assertEquals("operation:and",
@@ -448,8 +451,9 @@
.asText());
}
+
@Test
- public void testDateYear() throws JsonProcessingException, IOException {
+ public void testDateYear () throws JsonProcessingException, IOException {
collection = "pubDate in 2000";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -491,8 +495,9 @@
assertEquals("match:leq", res.at("/collection/match").asText());
}
+
@Test
- public void testDateMonthDay() throws JsonProcessingException, IOException {
+ public void testDateMonthDay () throws JsonProcessingException, IOException {
collection = "pubDate in 2000-02";
qs.setQuery(query, ql);
qs.setCollection(collection);
@@ -534,8 +539,9 @@
assertEquals("match:leq", res.at("/collection/match").asText());
}
+
@Test
- public void testDateValidate() {
+ public void testDateValidate () {
String fake_date = "fireStorm2014";
String fake_date_2 = "2014-12Date";
String date = "2015";
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
index 802ba9e..9db30b9 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessorTest.java
@@ -305,11 +305,17 @@
@Test
public void testOPORAND () throws JsonProcessingException, IOException {
+
+ // Query
query = "(Sonne oder Mond) und scheint";
qs.setQuery(query, "cosmas2");
res = mapper.readTree(qs.toJSON());
assertEquals("koral:group", res.at("/query/@type").asText());
assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+ assertEquals(false, res.at("/query/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/inOrder").asBoolean());
+
assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
.asText());
assertEquals("t", res.at("/query/distances/0/key").asText());
@@ -318,6 +324,10 @@
assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
assertEquals("operation:disjunction",
res.at("/query/operands/0/operation").asText());
+
+ assertEquals(false, res.at("/query/operands/0/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/operands/0/inOrder").asBoolean());
+
assertEquals("Sonne", res.at("/query/operands/0/operands/0/wrap/key")
.asText());
assertEquals("Mond", res.at("/query/operands/0/operands/1/wrap/key")
@@ -325,10 +335,15 @@
assertEquals("koral:token", res.at("/query/operands/1/@type").asText());
assertEquals("scheint", res.at("/query/operands/1/wrap/key").asText());
+ // Query
query = "scheint und (Sonne oder Mond)";
qs.setQuery(query, "cosmas2");
res = mapper.readTree(qs.toJSON());
assertEquals("koral:group", res.at("/query/@type").asText());
+
+ assertEquals(false, res.at("/query/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/inOrder").asBoolean());
+
assertEquals("operation:sequence", res.at("/query/operation").asText());
assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
.asText());
@@ -340,16 +355,25 @@
assertEquals("koral:group", res.at("/query/operands/1/@type").asText());
assertEquals("operation:disjunction",
res.at("/query/operands/1/operation").asText());
+
+ assertEquals(false, res.at("/query/operands/1/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/operands/1/inOrder").asBoolean());
+
assertEquals("Sonne", res.at("/query/operands/1/operands/0/wrap/key")
.asText());
assertEquals("Mond", res.at("/query/operands/1/operands/1/wrap/key")
.asText());
+ // Query
query = "Regen und scheint und (Sonne oder Mond)";
qs.setQuery(query, "cosmas2");
res = mapper.readTree(qs.toJSON());
assertEquals("koral:group", res.at("/query/@type").asText());
assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+ assertEquals(false, res.at("/query/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/inOrder").asBoolean());
+
assertEquals("cosmas:distance", res.at("/query/distances/0/@type")
.asText());
assertEquals("t", res.at("/query/distances/0/key").asText());
@@ -357,8 +381,14 @@
assertEquals(0, res.at("/query/distances/0/max").asInt());
assertEquals("koral:token", res.at("/query/operands/0/@type").asText());
assertEquals("Regen", res.at("/query/operands/0/wrap/key").asText());
- assertEquals("koral:group", res.at("/query/@type").asText());
- assertEquals("operation:sequence", res.at("/query/operation").asText());
+
+ assertEquals("koral:group", res.at("/query/operands/1/@type").asText());
+ assertEquals("operation:sequence", res
+ .at("/query/operands/1/operation").asText());
+
+ assertEquals(false, res.at("/query/operands/1/inOrder").isMissingNode());
+ assertEquals(false, res.at("/query/operands/1/inOrder").asBoolean());
+
assertEquals("cosmas:distance",
res.at("/query/operands/1/distances/0/@type").asText());
assertEquals("t", res.at("/query/operands/1/distances/0/key").asText());
@@ -368,6 +398,12 @@
.asText());
assertEquals("koral:group", res
.at("/query/operands/1/operands/1/@type").asText());
+
+ assertEquals(false, res.at("/query/operands/1/operands/1/inOrder")
+ .isMissingNode());
+ assertEquals(false, res.at("/query/operands/1/operands/1/inOrder")
+ .asBoolean());
+
assertEquals("operation:disjunction",
res.at("/query/operands/1/operands/1/operation").asText());
assertEquals("Sonne",
@@ -728,8 +764,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/wrap/key")
- .asText());
+ assertEquals("s",
+ res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group", res
.at("/query/operands/0/operands/1/@type").asText());
assertEquals("operation:class",
@@ -1401,7 +1438,8 @@
.asText());
assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key").asText());
+ assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+ .asText());
query = "#BED(der Mann , +pe)";
qs.setQuery(query, "cosmas2");
@@ -1425,8 +1463,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/0/operands/0/@type")
.asText());
- assertEquals("p", res.at("/query/operands/0/operands/0/operands/0/wrap/key")
- .asText());
+ assertEquals("p",
+ res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+ .asText());
assertEquals("koral:reference",
res.at("/query/operands/0/operands/1/@type").asText());
assertEquals("operation:focus",
@@ -1478,8 +1517,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/wrap/key")
- .asText());
+ assertEquals("s",
+ res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group",
res.at("/query/operands/0/operands/0/operands/1/@type")
.asText());
@@ -1513,8 +1553,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/1/operands/0/@type")
.asText());
- assertEquals("p", res.at("/query/operands/0/operands/1/operands/0/wrap/key")
- .asText());
+ assertEquals("p",
+ res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group",
res.at("/query/operands/0/operands/1/operands/1/@type")
.asText());
@@ -1567,7 +1608,8 @@
.asText());
assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key").asText());
+ assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+ .asText());
query = "der:sa,-pa";
qs.setQuery(query, "cosmas2");
@@ -1589,8 +1631,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/wrap/key")
- .asText());
+ assertEquals("s",
+ res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group",
res.at("/query/operands/0/operands/0/operands/1/@type")
.asText());
@@ -1615,8 +1658,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/1/operands/0/@type")
.asText());
- assertEquals("p", res.at("/query/operands/0/operands/1/operands/0/wrap/key")
- .asText());
+ assertEquals("p",
+ res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group",
res.at("/query/operands/0/operands/1/operands/1/@type")
.asText());
@@ -1651,8 +1695,9 @@
assertEquals("koral:span",
res.at("/query/operands/0/operands/0/operands/0/@type")
.asText());
- assertEquals("s", res.at("/query/operands/0/operands/0/operands/0/wrap/key")
- .asText());
+ assertEquals("s",
+ res.at("/query/operands/0/operands/0/operands/0/wrap/key")
+ .asText());
assertEquals("koral:group",
res.at("/query/operands/0/operands/0/operands/1/@type")
.asText());
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessorTest.java
index 6f2bdd9..5af4b60 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/CqlQueryProcessorTest.java
@@ -3,81 +3,58 @@
import static org.junit.Assert.assertEquals;
import java.io.IOException;
+import java.util.List;
import org.junit.Test;
import org.z3950.zing.cql.CQLParseException;
-import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import de.ids_mannheim.korap.query.serialize.CqlQueryProcessor;
-import de.ids_mannheim.korap.query.serialize.Cosmas2QueryProcessor;
-
-
public class CqlQueryProcessorTest {
String query;
- String version = "1.2";
+ String VERSION = "1.2";
ObjectMapper mapper = new ObjectMapper();
-
- @Test
- public void testExceptions () throws CQLParseException, IOException {
- query = "(Kuh) prox (Germ) ";
- try {
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
- }
- catch (Exception e) {
- int errorCode = Integer.parseInt(e.getMessage().split(":")[0]
- .replace("SRU diagnostic ", ""));
- assertEquals(48, errorCode);
- }
-
- query = "(Kuh) or/rel.combine=sum (Germ) ";
- try {
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
- }
- catch (Exception e) {
- int errorCode = Integer.parseInt(e.getMessage().split(":")[0]
- .replace("SRU diagnostic ", ""));
- assertEquals(20, errorCode);
- }
-
- query = "dc.title any Germ ";
- try {
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
- }
- catch (Exception e) {
- int errorCode = Integer.parseInt(e.getMessage().split(":")[0]
- .replace("SRU diagnostic ", ""));
- assertEquals(16, errorCode);
- }
-
- query = "cql.serverChoice any Germ ";
- try {
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
- }
- catch (Exception e) {
- int errorCode = Integer.parseInt(e.getMessage().split(":")[0]
- .replace("SRU diagnostic ", ""));
- assertEquals(19, errorCode);
- }
-
- query = "";
- try {
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
- }
- catch (Exception e) {
- int errorCode = Integer.parseInt(e.getMessage().split(":")[0]
- .replace("SRU diagnostic ", ""));
- assertEquals(27, errorCode);
- }
+ private List<Object> getError(CqlQueryProcessor processor) {
+ List<Object> errors = (List<Object>) processor.requestMap.get("errors");
+ return (List<Object>) errors.get(0);
}
+ @Test
+ public void testExceptions() throws CQLParseException, IOException {
+ query = "(Kuh) prox (Germ) ";
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
+ List<Object> error = getError(cqlTree);
+ assertEquals(
+ "SRU diagnostic 48: Only basic search including term-only "
+ + "and boolean (AND,OR) operator queries are currently supported.",
+ error.get(1));
+
+ query = "(Kuh) or/rel.combine=sum (Germ) ";
+ error = getError(new CqlQueryProcessor(query, VERSION));
+ assertEquals(
+ "SRU diagnostic 20: Relation modifier rel.combine = sum is not supported.",
+ error.get(1));
+
+ query = "dc.title any Germ ";
+ error = getError(new CqlQueryProcessor(query, VERSION));
+ assertEquals("SRU diagnostic 16: Index dc.title is not supported.",
+ error.get(1));
+
+ query = "cql.serverChoice any Germ ";
+ error = getError(new CqlQueryProcessor(query, VERSION));
+ assertEquals("SRU diagnostic 19: Relation any is not supported.",
+ error.get(1));
+
+ query = "";
+ error = getError(new CqlQueryProcessor(query, VERSION));
+ assertEquals("SRU diagnostic 27: Empty query is unsupported.",
+ error.get(1));
+ }
@Test
- public void testAndQuery () throws CQLParseException, IOException,
- Exception {
+ public void testAndQuery() throws CQLParseException, IOException, Exception {
query = "(Sonne) and (scheint)";
String jsonLd = "{@type : koral:group, operation : operation:sequence, inOrder : false,"
+ "distances:[ "
@@ -87,19 +64,20 @@
+ "{@type : koral:token,wrap : {@type : koral:term,key : scheint,layer : orth,match : match:eq}"
+ "}]}";
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
String serializedQuery = mapper.writeValueAsString(cqlTree
.getRequestMap().get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
- // /System.out.println(serializedQuery);
- //CosmasTree ct = new CosmasTree("Sonne und scheint");
- //serializedQuery = mapper.writeValueAsString(ct.getRequestMap().get("query"));
- //assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
+ // /System.out.println(serializedQuery);
+ // CosmasTree ct = new CosmasTree("Sonne und scheint");
+ // serializedQuery =
+ // mapper.writeValueAsString(ct.getRequestMap().get("query"));
+ // assertEquals(jsonLd.replace(" ", ""),
+ // serializedQuery.replace("\"", ""));
}
-
@Test
- public void testBooleanQuery () throws CQLParseException, IOException,
+ public void testBooleanQuery() throws CQLParseException, IOException,
Exception {
query = "((Sonne) or (Mond)) and (scheint)";
String jsonLd = "{@type:koral:group, operation:operation:sequence, inOrder : false, distances:["
@@ -111,12 +89,11 @@
+ "]},"
+ "{@type:koral:token, wrap:{@type:koral:term, key:scheint, layer:orth, match:match:eq}}"
+ "]}";
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
String serializedQuery = mapper.writeValueAsString(cqlTree
.getRequestMap().get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
-
query = "(scheint) and ((Sonne) or (Mond))";
jsonLd = "{@type:koral:group, operation:operation:sequence, inOrder : false, distances:["
+ "{@type:koral:distance, key:s, min:0, max:0}"
@@ -126,23 +103,22 @@
+ "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, layer:orth, match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term, key:Mond, layer:orth, match:match:eq}}"
+ "]}" + "]}";
- cqlTree = new CqlQueryProcessor(query, version);
+ cqlTree = new CqlQueryProcessor(query, VERSION);
serializedQuery = mapper.writeValueAsString(cqlTree.getRequestMap()
.get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
}
-
@Test
- public void testOrQuery () throws CQLParseException, IOException, Exception {
+ public void testOrQuery() throws CQLParseException, IOException, Exception {
query = "(Sonne) or (Mond)";
String jsonLd = "{@type:koral:group, operation:operation:or, operands:["
+ "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, layer:orth, match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term, key:Mond, layer:orth, match:match:eq}}"
+ "]}";
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
String serializedQuery = mapper.writeValueAsString(cqlTree
.getRequestMap().get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
@@ -156,7 +132,7 @@
+ "{@type:koral:token, wrap:{@type:koral:term, key:Mond, layer:orth, match:match:eq}}"
+ "]}";
- cqlTree = new CqlQueryProcessor(query, version);
+ cqlTree = new CqlQueryProcessor(query, VERSION);
serializedQuery = mapper.writeValueAsString(cqlTree.getRequestMap()
.get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
@@ -171,27 +147,25 @@
+ "{@type:koral:token, wrap:{@type:koral:term, key:Mond, layer:orth, match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term, key:scheint, layer:orth, match:match:eq}}"
+ "]}" + "]}";
- cqlTree = new CqlQueryProcessor(query, version);
+ cqlTree = new CqlQueryProcessor(query, VERSION);
serializedQuery = mapper.writeValueAsString(cqlTree.getRequestMap()
.get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
}
-
@Test
- public void testTermQuery () throws CQLParseException, IOException,
+ public void testTermQuery() throws CQLParseException, IOException,
Exception {
query = "Sonne";
String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, layer:orth, match:match:eq}}";
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
String serializedQuery = mapper.writeValueAsString(cqlTree
.getRequestMap().get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
}
-
@Test
- public void testPhraseQuery () throws CQLParseException, IOException,
+ public void testPhraseQuery() throws CQLParseException, IOException,
Exception {
query = "\"der Mann\"";
String jsonLd = "{@type:koral:group, operation:operation:sequence, operands:["
@@ -199,12 +173,11 @@
+ "{@type:koral:token, wrap:{@type:koral:term, key:Mann, layer:orth, match:match:eq}}"
+ "]}";
- CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, version);
+ CqlQueryProcessor cqlTree = new CqlQueryProcessor(query, VERSION);
String serializedQuery = mapper.writeValueAsString(cqlTree
.getRequestMap().get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
-
query = "der Mann schläft";
jsonLd = "{@type:koral:group, operation:operation:sequence, operands:["
+ "{@type:koral:token, wrap:{@type:koral:term, key:der, layer:orth, match:match:eq}},"
@@ -212,7 +185,7 @@
+ "{@type:koral:token, wrap:{@type:koral:term, key:schläft, layer:orth, match:match:eq}}"
+ "]}";
- cqlTree = new CqlQueryProcessor(query, version);
+ cqlTree = new CqlQueryProcessor(query, VERSION);
serializedQuery = mapper.writeValueAsString(cqlTree.getRequestMap()
.get("query"));
assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
index 58d775b..264ca67 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/EmptyResultsTest.java
@@ -15,8 +15,9 @@
private static ObjectMapper mapper = new ObjectMapper();
+
@Test
- public void testEmptyQueryObject() {
+ public void testEmptyQueryObject () {
QuerySerializer s = new QuerySerializer();
s.setQuery("prox/unit=word/distance<=5", "cql");
JsonNode node = mapper.valueToTree(s.build());
@@ -24,8 +25,9 @@
assertEquals(node.has("collection"), false);
}
+
@Test
- public void testEmptyCollectionObject() {
+ public void testEmptyCollectionObject () {
QuerySerializer s = new QuerySerializer();
s.setQuery("[base=Wort]", "poliqarp");
@@ -34,8 +36,9 @@
assertEquals(node.has("collection"), false);
}
+
@Test
- public void testEmptyMetaObject() {
+ public void testEmptyMetaObject () {
QuerySerializer s = new QuerySerializer();
s.setQuery("[base=Wort]", "poliqarp");
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
new file mode 100644
index 0000000..093d715
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
@@ -0,0 +1,416 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+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
+ // | segment-query
+ // -------------------------------------------------------------------------
+ // implicit-query ::= flagged-regexp
+ // segment-query ::= "[" expression? "]"
+ // -------------------------------------------------------------------------
+ // simple-query ::= '(' main_query ')' /* grouping */
+ @Test
+ public void testGroupQuery() throws IOException {
+ 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}},"
+ + "{@type:koral:token, wrap:{@type:koral:term,key:grüne,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";;
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ // group and disjunction
+ query = "([pos=\"NN\"]|[cnx:pos=\"N\"]|[text=\"Mann\"])";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:N,foundry:cnx,layer:p,type:type:regex,match:match:eq}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", jsonLd);
+
+ // a group contains a sequence
+ query = "([text=\"blaue\"][pos=\"NN\"])";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:blaue,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ // -------------------------------------------------------------------------
+ // main-query ::= simple-query
+ // | simple-query "|" main-query /* or */
+ // | simple-query main-query /* sequence */
+ // | simple-query quantifier /* quatification */
+ // -------------------------------------------------------------------------
+
+ // | simple-query "|" main-query /* or */
+ @Test
+ public void testOrQuery() throws IOException {
+ 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}},"
+ + "{@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\"]|\"Mann\"";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/0", jsonLd);
+
+ // group with two segment queries
+ query = "[pos=\"NN\"]|[text=\"Mann\"]";
+ jsonLd = "{@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:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ // | simple-query main-query /* sequence */
+ @Test
+ public void testSequenceQuery() throws IOException {
+ 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}},"
+ + "{@type:koral:token, wrap:{@type:koral:term, key:NN, foundry:tt, layer:p, type:type:regex, match:match:eq}}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[text=\"blaue|grüne\"][pos = \"NN\"]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "\"blaue\" \"grüne\" [pos = \"NN\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:grüne, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
+ 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);
+
+ // sequence of groups
+ }
+
+ // | simple-query quantifier /* quatification */
+ @Test
+ public void testSimpleQueryWithQuantifier() 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);
+
+ // segment query with quantifier
+ query = "[cnx:pos=\"A\"]*";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:[{@type:koral:token,wrap:{@type:koral:term,key:A,foundry:cnx,layer:p,type:type:regex,match:match:eq}}],"
+ + "boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ @Test
+ public void testGroupQueryWithQuantifier() throws JsonProcessingException {
+ // group with quantifier
+ query = "(\"blaue\"|\"grüne\")*";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@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}},"
+ + "{@type:koral:token, wrap:{@type:koral:term,key:grüne,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}"
+ + "]}]," + "boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, 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 testDistanceQuery() throws IOException {
+ // distance query
+ query = "\"Katze\" [] \"Hund\"";
+ jsonLd = "{@type:koral:group,operation:operation:sequence,inOrder:true,"
+ + "distances:["
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1,max:1}}"
+ + "],"
+ + "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);
+ }
+
+ @Test
+ public void testDistanceQueryWithQuantifier() throws IOException {
+ query = "\"Katze\" []* \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []+ \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []{3} \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:3}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []{2,3} \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:2,max:3}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+ }
+
+ @Test
+ public void testDistanceQueryWithMultipleWildcards() throws IOException {
+ // 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\" []{3}[]? \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,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);
+ }
+
+ // -------------------------------------------------------------------------
+ // query ::= main-query within-part?
+ // -------------------------------------------------------------------------
+ // within-part ::= simple-within-part
+ // simple-within-part ::= "within" simple-within-scope
+
+ @Test
+ public void testWithinQuery() throws IOException {
+ 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}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:VVFIN,foundry:cnx,layer:p,type:type:regex,match:match:eq}}"
+ + "]}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[cnx:pos=\"VVFIN\"] within sentence";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[cnx:pos=\"VVFIN\"] within p";
+ jsonLd = "{@type:koral:span,wrap:{@type:koral:term,key:p,foundry:base,layer:s}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/0", jsonLd);
+
+ query = "[cnx:pos=\"VVFIN\"] within text";
+ jsonLd = "{@type:koral:span,wrap:{@type:koral:term,key:t,foundry:base,layer:s}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/0", jsonLd);
+
+ query = "[cnx:pos=\"VVFIN\"] within u";
+ 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);
+
+ query = "[]+ within s";
+ jsonLd = "{@type:koral:group," + "operation:operation:repetition,"
+ + "operands:[{@type:koral:token}],"
+ + "boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", jsonLd);
+ }
+
+ @Test
+ public void testWithinQueryWithGroupQuery() throws IOException {
+ query = "(\"blaue\"|\"grüne\")+ within s";
+ jsonLd = "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/0", jsonLd);
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@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}},"
+ + "{@type:koral:token, wrap:{@type:koral:term,key:grüne,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}"
+ + "]}]," + "boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", 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
new file mode 100644
index 0000000..666bff1
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
@@ -0,0 +1,314 @@
+package de.ids_mannheim.korap.query.serialize;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * @author margaretha
+ *
+ */
+public class FCSQLQueryProcessorTest {
+
+ 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)
+ throws JsonProcessingException {
+ FCSQLQueryProcessor processor = new FCSQLQueryProcessor(query, "2.0");
+ String serializedQuery = mapper.writeValueAsString(processor
+ .getRequestMap().get("query"));
+ assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
+ }
+
+ public static void validateNode(String query, String path, String jsonLd)
+ throws JsonProcessingException, IOException {
+ qs.setQuery(query, "fcsql", "2.0");
+ node = mapper.readTree(qs.toJSON());
+ String serializedQuery = mapper.writeValueAsString(node.at(path));
+ assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
+ }
+
+ public static List<Object> getError(FCSQLQueryProcessor processor) {
+ List<Object> errors = (List<Object>) processor.requestMap.get("errors");
+ return (List<Object>) errors.get(0);
+ }
+
+ @Test
+ public void testVersion() throws JsonProcessingException {
+ error = getError(new FCSQLQueryProcessor("\"Sonne\"", "1.0"));
+ assertEquals(309, error.get(0));
+ assertEquals("SRU diagnostic 5: Only supports SRU version 2.0.",
+ error.get(1));
+
+ error = getError(new FCSQLQueryProcessor("\"Sonne\"", null));
+ assertEquals(309, error.get(0));
+ assertEquals("SRU diagnostic 7: Version number is missing.",
+ error.get(1));
+ }
+
+ // regexp ::= quoted-string
+ @Test
+ public void testTermQuery() throws JsonProcessingException {
+ 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 {
+ 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);
+
+ query = "\".*?Mann.*?\"";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:.*?Mann.*?,"
+ + "foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}";
+ runAndValidate(query, jsonLd);
+
+ query = "\"z.B.\"";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:z.B.,"
+ + "foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}";
+ runAndValidate(query, jsonLd);
+
+ query = "\"Sonne&scheint\"";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:Sonne&scheint,"
+ + "foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}";
+ runAndValidate(query, jsonLd);
+
+ // Not possible
+ // query = "\"a\\.\"";
+ }
+
+ // flagged-regexp ::= regexp
+ // | regexp "/" regexp-flag+
+ @Test
+ public void testTermQueryWithRegexFlag() throws IOException {
+ 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);
+
+ query = "[text = \"Fliegen\" /i]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "\"Fliegen\" /C";
+ jsonLd = "{@type:koral:term, key:Fliegen, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/wrap", jsonLd);
+
+ query = "\"Fliegen\" /I";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/wrap", jsonLd);
+
+ query = "\"Fliegen\" /l";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(306, error.get(0));
+ String msg = (String) error.get(1);
+ assertEquals(true, msg.startsWith("SRU diagnostic 48: Regexflags"));
+
+ query = "\"Fliegen\" /d";
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
+ assertEquals(306, error.get(0));
+ assertEquals(
+ "SRU diagnostic 48: Regexflag: IGNORE_DIACRITICS is unsupported.",
+ (String) error.get(1));
+ }
+
+ // operator ::= "=" /* equals */
+ // | "!=" /* non-equals */
+ @Test
+ public void testOperator() throws IOException {
+ 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);
+ }
+
+ // attribute operator flagged-regexp
+ // -------------------------------------------------------------------------
+ // attribute ::= simple-attribute | qualified-attribute
+ // -------------------------------------------------------------------------
+
+ // simple-attribute ::= identifier
+ @Test
+ public void testTermQueryWithSpecificLayer() throws JsonProcessingException {
+ 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);
+
+ query = "[lemma = \"sein\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:sein, "
+ + "foundry:tt, layer:l, type:type:regex, match:match:eq}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[pos = \"NN\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:NN, "
+ + "foundry:tt, layer:p, type:type:regex, match:match:eq}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ // qualified-attribute ::= identifier ":" identifier
+ @Test
+ public void testTermQueryWithQualifier() throws JsonProcessingException {
+ 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);
+
+ query = "[cnx:pos = \"N\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:N, "
+ + "foundry:cnx, layer:p, type:type:regex, match:match:eq}}";
+ runAndValidate(query, jsonLd);
+ }
+
+ // segment-query ::= "[" expression? "]"
+ // -------------------------------------------------------------------------
+ // expression ::= basic-expression
+ // | expression "|" expression /* or */
+ // | expression "&" expression /* and */
+ // -------------------------------------------------------------------------
+
+ // | expression "|" expression /* or */
+ @Test
+ public void testExpressionOr() throws IOException {
+ query = "[mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { @type: koral:termGroup,"
+ + "relation: relation:or,"
+ + " operands:["
+ + "{@type: koral:term, key: sein, foundry: mate, layer: l, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:eq}]}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[cnx:lemma=\"sein\" | mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:term, key: sein, foundry: cnx, layer: l, type:type:regex, match: match:eq}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/wrap/operands/0",
+ jsonLd);
+
+ }
+
+ // | expression "&" expression /* and */
+ @Test
+ public void testExpressionAnd() throws IOException {
+ query = "[mate:lemma=\"sein\" & mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { @type: koral:termGroup,"
+ + "relation: relation:and,"
+ + " operands:["
+ + "{@type: koral:term, key: sein, foundry: mate, layer: l, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:eq}]}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ // -------------------------------------------------------------------------
+ // basic-expression ::= '(' expression ')' /* grouping */
+ // | "!" expression /* not */
+ // | attribute operator flagged-regexp
+ // -------------------------------------------------------------------------
+
+ // basic-expression ::= '(' expression ')' /* grouping */
+
+ @Test
+ public void testExpressionGroup() throws JsonProcessingException {
+ query = "[(text=\"blau\"|pos=\"ADJ\")]";
+ jsonLd = "{@type: koral:token,"
+ + "wrap: {@type: koral:termGroup,"
+ + "relation: relation:or,"
+ + "operands: ["
+ + "{@type: koral:term, key: blau, foundry: opennlp, layer: orth, type:type:regex,match: match:eq},"
+ + "{@type: koral:term, key: ADJ, foundry: tt, layer: p, type:type:regex, match: match:eq}]}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ @Test
+ public void testMultipleBooleanExpressions() throws IOException {
+ query = "[mate:lemma=\"sein\" & (mate:pos=\"PPOSS\"|mate:pos=\"VAFIN\")]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { @type: koral:termGroup,"
+ + "relation: relation:or,"
+ + " operands:["
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: VAFIN, foundry: mate, layer: p, type:type:regex, match: match:eq}]}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/wrap/operands/1",
+ jsonLd);
+ }
+
+ // "!" expression /* not */
+ @Test
+ public void testExpressionNot() throws IOException {
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:NN, "
+ + "foundry:tt, layer:p, type:type:regex, match:match:eq}}";
+ query = "[!pos != \"NN\"]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ query = "[!!pos = \"NN\"]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ query = "[!!!pos != \"NN\"]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[mate:lemma=\"sein\" & !mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { "
+ + "@type: koral:termGroup,"
+ + "relation: relation:and,"
+ + " operands:["
+ + "{@type: koral:term, key: sein, foundry: mate, layer: l, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:ne}]}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[!(mate:lemma=\"sein\" & mate:pos=\"PPOSS\")]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ @Test
+ public void testExceptions() throws JsonProcessingException {
+ // unsupported lemma und qualifier
+ query = "[opennlp:lemma = \"sein\"]";
+ 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 = "[tt:morph = \"sein\"]";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ 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 fb82f28..167ee0e 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
@@ -155,18 +155,54 @@
assertEquals("type:regex", res.at("/query/wrap/type").asText());
assertEquals("orth", res.at("/query/wrap/layer").asText());
assertEquals("match:eq", res.at("/query/wrap/match").asText());
+ }
+ @Test
+ public void testRegexEscape () throws JsonProcessingException, IOException {
// Escape regex symbols
+ query = "\"a.+?\"";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:term", res.at("/query/wrap/@type").asText());
+ assertEquals("type:regex", res.at("/query/wrap/type").asText());
+ assertEquals("orth", res.at("/query/wrap/layer").asText());
+ assertEquals("match:eq", res.at("/query/wrap/match").asText());
+ assertEquals("a.+?", res.at("/query/wrap/key").asText());
+
query = "\"a\\.\"";
qs.setQuery(query, "poliqarpplus");
res = mapper.readTree(qs.toJSON());
- System.out.println("QUERY IS "+ res);
assertEquals("koral:token", res.at("/query/@type").asText());
assertEquals("koral:term", res.at("/query/wrap/@type").asText());
assertEquals("type:regex", res.at("/query/wrap/type").asText());
assertEquals("orth", res.at("/query/wrap/layer").asText());
assertEquals("match:eq", res.at("/query/wrap/match").asText());
assertEquals("a\\.", res.at("/query/wrap/key").asText());
+
+ query = "\"a\\.\\+\\?\\\\\"";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:term", res.at("/query/wrap/@type").asText());
+ assertEquals("type:regex", res.at("/query/wrap/type").asText());
+ assertEquals("orth", res.at("/query/wrap/layer").asText());
+ assertEquals("match:eq", res.at("/query/wrap/match").asText());
+ assertEquals("a\\.\\+\\?\\\\", res.at("/query/wrap/key").asText());
+ }
+
+ @Test
+ public void testRegexWhiteSpace () throws JsonProcessingException, IOException {
+ // Escape regex symbols
+ query = "\"a b\"";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:term", res.at("/query/wrap/@type").asText());
+ assertEquals("type:regex", res.at("/query/wrap/type").asText());
+ assertEquals("orth", res.at("/query/wrap/layer").asText());
+ assertEquals("match:eq", res.at("/query/wrap/match").asText());
+ assertEquals("a b", res.at("/query/wrap/key").asText());
}
@@ -280,7 +316,7 @@
query = "<\".*\">";
qs.setQuery(query, "poliqarpplus");
- res = mapper.readTree(qs.toJSON());
+ res = mapper.readTree(qs.toJSON());
assertEquals("koral:span", res.at("/query/@type").asText());
assertEquals(".*", res.at("/query/wrap/key").asText());
assertEquals("type:regex", res.at("/query/wrap/type").asText());
@@ -658,7 +694,7 @@
res = mapper.readTree(qs.toJSON());
assertEquals("koral:token", res.at("/query/@type").asText());
assertEquals(true, res.at("/query/key").isMissingNode());
-
+
query = "contains(<s>, [])";
qs.setQuery(query, "poliqarpplus");
res = mapper.readTree(qs.toJSON());
@@ -703,6 +739,78 @@
@Test
+ public void testEmptyTokenSequence () throws JsonProcessingException, IOException {
+ query = "[]{3}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+
+ assertEquals("koral:group",
+ res.at("/query/@type").asText());
+ assertEquals("operation:repetition",
+ res.at("/query/operation").asText());
+ assertEquals("koral:token",
+ res.at("/query/operands/0/@type").asText());
+ assertEquals("koral:boundary",
+ res.at("/query/boundary/@type").asText());
+ assertEquals(3,
+ res.at("/query/boundary/min").asInt());
+ assertEquals(3,
+ res.at("/query/boundary/max").asInt());
+
+ query = "[]{1,3}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+
+ assertEquals("koral:group",
+ res.at("/query/@type").asText());
+ assertEquals("operation:repetition",
+ res.at("/query/operation").asText());
+ assertEquals("koral:token",
+ res.at("/query/operands/0/@type").asText());
+ assertEquals("koral:boundary",
+ res.at("/query/boundary/@type").asText());
+ assertEquals(1,
+ res.at("/query/boundary/min").asInt());
+ assertEquals(3,
+ res.at("/query/boundary/max").asInt());
+
+
+ query = "[]{ , 3}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+
+ assertEquals("koral:group",
+ res.at("/query/@type").asText());
+ assertEquals("operation:repetition",
+ res.at("/query/operation").asText());
+ assertEquals("koral:token",
+ res.at("/query/operands/0/@type").asText());
+ assertEquals("koral:boundary",
+ res.at("/query/boundary/@type").asText());
+ assertEquals(0,
+ res.at("/query/boundary/min").asInt());
+ assertEquals(3,
+ res.at("/query/boundary/max").asInt());
+
+ query = "[]{4,}";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+
+ assertEquals("koral:group",
+ res.at("/query/@type").asText());
+ assertEquals("operation:repetition",
+ res.at("/query/operation").asText());
+ assertEquals("koral:token",
+ res.at("/query/operands/0/@type").asText());
+ assertEquals("koral:boundary",
+ res.at("/query/boundary/@type").asText());
+ assertEquals(4,
+ res.at("/query/boundary/min").asInt());
+ assertTrue(res.at("/query/boundary/max").isMissingNode());
+ }
+
+
+ @Test
public void testLeadingTrailingEmptyTokens ()
throws JsonProcessingException, IOException {
query = "[][base=Mann]";
@@ -726,6 +834,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());
@@ -976,6 +1102,79 @@
.asText());
}
+ @Test
+ public void testUnnecessaryParentheses () throws JsonProcessingException,
+ IOException {
+ query = "[(base=Mann)]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("Mann", res.at("/query/wrap/key").asText());
+ assertEquals("lemma", res.at("/query/wrap/layer").asText());
+ assertEquals("match:eq", res.at("/query/wrap/match").asText());
+
+ query = "[(((base=Mann)))]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("Mann", res.at("/query/wrap/key").asText());
+ assertEquals("lemma", res.at("/query/wrap/layer").asText());
+ assertEquals("match:eq", res.at("/query/wrap/match").asText());
+
+ query = "[(base=Mann&cas=N)]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:termGroup", res.at("/query/wrap/@type")
+ .asText());
+ assertEquals("relation:and", res.at("/query/wrap/relation")
+ .asText());
+ assertEquals("Mann", res.at("/query/wrap/operands/0/key")
+ .asText());
+ assertEquals("lemma", res.at("/query/wrap/operands/0/layer")
+ .asText());
+ assertEquals("N", res.at("/query/wrap/operands/1/key")
+ .asText());
+ assertEquals("cas", res.at("/query/wrap/operands/1/layer")
+ .asText());
+
+
+ query = "[(((base=Mann&cas=N)))]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:termGroup", res.at("/query/wrap/@type")
+ .asText());
+ assertEquals("relation:and", res.at("/query/wrap/relation")
+ .asText());
+ assertEquals("Mann", res.at("/query/wrap/operands/0/key")
+ .asText());
+ assertEquals("lemma", res.at("/query/wrap/operands/0/layer")
+ .asText());
+ assertEquals("N", res.at("/query/wrap/operands/1/key")
+ .asText());
+ assertEquals("cas", res.at("/query/wrap/operands/1/layer")
+ .asText());
+
+
+ query = "[(((base=Mann&((cas=N)))))]";
+ qs.setQuery(query, "poliqarpplus");
+ res = mapper.readTree(qs.toJSON());
+ assertEquals("koral:token", res.at("/query/@type").asText());
+ assertEquals("koral:termGroup", res.at("/query/wrap/@type")
+ .asText());
+ assertEquals("relation:and", res.at("/query/wrap/relation")
+ .asText());
+ assertEquals("Mann", res.at("/query/wrap/operands/0/key")
+ .asText());
+ assertEquals("lemma", res.at("/query/wrap/operands/0/layer")
+ .asText());
+ assertEquals("N", res.at("/query/wrap/operands/1/key")
+ .asText());
+ assertEquals("cas", res.at("/query/wrap/operands/1/layer")
+ .asText());
+
+ };
@Test
public void testTokenSequence () throws JsonProcessingException,
@@ -1703,8 +1902,10 @@
assertEquals("VVFIN", res.at("/query/operands/1/wrap/key").asText());
}
+
@Test
- public void testSpanSerialization () throws JsonProcessingException, IOException {
+ public void testSpanSerialization () throws JsonProcessingException,
+ IOException {
// Both constructs should be serialized identically
query = "contains(<s>, der)";