Added FCS WithinQuery.
Change-Id: I9c3f8cde68986a8d2eddedd289d53f1d86c75728
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/Element.java b/src/main/java/de/ids_mannheim/korap/query/elements/Element.java
index a7da5b4..73f580a 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/Element.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/Element.java
@@ -2,6 +2,10 @@
import java.util.Map;
+/**
+ * @author margaretha
+ *
+ */
public interface Element {
public Map<String, Object> buildMap();
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralGroup.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralGroup.java
index 7d8a9a1..61a2e04 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralGroup.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralGroup.java
@@ -7,6 +7,10 @@
import de.ids_mannheim.korap.query.serialize.MapBuilder;
+/**
+ * @author margaretha
+ *
+ */
public class KoralGroup implements Element {
private static final KoralType type = KoralType.GROUP;
@@ -16,6 +20,7 @@
private boolean inOrder = false;
private List<Object> operands;
private List<Distance> distances;
+ private List<Frame> frames;
public KoralGroup (KoralOperation operation) {
this.operation = operation;
@@ -45,6 +50,14 @@
this.distances = distances;
}
+ public List<Frame> getFrames() {
+ return frames;
+ }
+
+ public void setFrames(List<Frame> frames) {
+ this.frames = frames;
+ }
+
@Override
public Map<String, Object> buildMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
@@ -60,6 +73,14 @@
map.put("distances", distanceList);
}
+ if (getFrames() != null) {
+ List<String> frameList = new ArrayList<String>();
+ for (Frame f : getFrames()) {
+ frameList.add(f.toString());
+ }
+ map.put("frames", frameList);
+ }
+
List<Map<String, Object>> operandList = new ArrayList<Map<String, Object>>();
for (Object o : getOperands()) {
operandList.add(MapBuilder.buildQueryMap(o));
@@ -68,6 +89,26 @@
return map;
}
+ public enum Frame {
+ SUCCEDS("succeds"), 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"), PRECEDES_DIRECTLY("precedesDirectly"), PRECEDES(
+ "precedes");
+
+ String value;
+
+ Frame (String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "frames:" + value;
+ };
+ }
+
public class Distance implements Element {
private final KoralType type = KoralType.DISTANCE;
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralOperation.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralOperation.java
index 0e8b30a..21fa833 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralOperation.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralOperation.java
@@ -1,20 +1,15 @@
package de.ids_mannheim.korap.query.elements;
+/**
+ * @author margaretha
+ *
+ */
public enum KoralOperation {
- SEQUENCE("operation:sequence"), POSITION("operation:position"), DISJUNCTION(
- "operation:disjunction"), REPETITION("operation:repetition"), CLASS(
- "operation:class"), MERGE("operation:merge"), RELATION(
- "operation:relation");
-
- String value;
-
- KoralOperation (String value) {
- this.value = value;
- }
+ SEQUENCE, POSITION, DISJUNCTION, REPETITION, CLASS, MERGE, RELATION;
@Override
public String toString() {
- return value;
+ return "operation:" + super.toString().toLowerCase();
}
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralRelation.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralRelation.java
index 9f0d3eb..f1bfa91 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralRelation.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralRelation.java
@@ -1,17 +1,15 @@
package de.ids_mannheim.korap.query.elements;
+/**
+ * @author margaretha
+ *
+ */
public enum KoralRelation {
- AND("relation:and"), OR("relation:or");
-
- String value;
-
- KoralRelation (String value) {
- this.value = value;
- }
+ AND, OR;
@Override
public String toString() {
- return value;
+ return "relation:" + super.toString().toLowerCase();
}
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralSpan.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralSpan.java
new file mode 100644
index 0000000..bec50a3
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralSpan.java
@@ -0,0 +1,75 @@
+package de.ids_mannheim.korap.query.elements;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class KoralSpan implements Element {
+
+ private static final KoralType koralType = KoralType.SPAN;
+
+ private String key;
+ private String foundry;
+ private String layer;
+ private String matchOperator;
+ private List<KoralTerm> attr;
+
+ public KoralSpan (String key, String foundry, String layer,
+ MatchOperator operator) {
+ this.key = key;
+ this.foundry = foundry;
+ this.layer = layer;
+ this.matchOperator = operator.toString();
+ }
+
+ 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 String getMatchOperator() {
+ return matchOperator;
+ }
+
+ public void setMatchOperator(String matchOperator) {
+ this.matchOperator = matchOperator;
+ }
+
+ public List<KoralTerm> getAttr() {
+ return attr;
+ }
+
+ public void setAttr(List<KoralTerm> attr) {
+ this.attr = attr;
+ }
+
+ @Override
+ public Map<String, Object> buildMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ map.put("@type", koralType.toString());
+ map.put("key", getKey());
+ map.put("foundry", getFoundry());
+ map.put("layer", getLayer());
+ map.put("match", getMatchOperator());
+ return map;
+ }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralTerm.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralTerm.java
index 8f1f1c5..1960799 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralTerm.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralTerm.java
@@ -3,6 +3,10 @@
import java.util.LinkedHashMap;
import java.util.Map;
+/**
+ * @author margaretha
+ *
+ */
public class KoralTerm implements Element {
public enum KoralTermType {
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralTermGroup.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralTermGroup.java
index 94e6f3d..54515fd 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralTermGroup.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralTermGroup.java
@@ -9,6 +9,10 @@
import de.ids_mannheim.korap.query.serialize.MapBuilder;
import eu.clarin.sru.server.fcs.parser.QueryNode;
+/**
+ * @author margaretha
+ *
+ */
public class KoralTermGroup implements Element {
private static final KoralType type = KoralType.TERMGROUP;
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralToken.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralToken.java
index 751655f..6f3f221 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralToken.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralToken.java
@@ -3,6 +3,10 @@
import java.util.LinkedHashMap;
import java.util.Map;
+/**
+ * @author margaretha
+ *
+ */
public class KoralToken implements Element {
private final static KoralType type = KoralType.TOKEN;
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/KoralType.java b/src/main/java/de/ids_mannheim/korap/query/elements/KoralType.java
index 23c45a6..ed5c456 100644
--- a/src/main/java/de/ids_mannheim/korap/query/elements/KoralType.java
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/KoralType.java
@@ -1,5 +1,9 @@
package de.ids_mannheim.korap.query.elements;
+/**
+ * @author margaretha
+ *
+ */
public enum KoralType {
TERMGROUP("koral:termGroup"), TERM("koral:term"), TOKEN("koral:token"), SPAN(
"koral:span"), GROUP("koral:group"), BOUNDARY("koral:boundary"), RELATION(
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/MatchOperator.java b/src/main/java/de/ids_mannheim/korap/query/elements/MatchOperator.java
new file mode 100644
index 0000000..2963744
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/MatchOperator.java
@@ -0,0 +1,16 @@
+package de.ids_mannheim.korap.query.elements;
+
+public enum MatchOperator {
+ EQUALS("eq"), NOT_EQUALS("ne");
+
+ String value;
+
+ MatchOperator (String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "match:" + value;
+ };
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/elements/Scope.java b/src/main/java/de/ids_mannheim/korap/query/elements/Scope.java
new file mode 100644
index 0000000..02cc60f
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/elements/Scope.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.query.elements;
+
+public enum Scope {
+ SENTENCE("s"), PARAGRAPH("p"), TEXT("t");
+ String value;
+
+ Scope (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
index 1dc4a4b..82b75de 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
@@ -1,18 +1,15 @@
package de.ids_mannheim.korap.query.parse.fcsql;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
-import org.hamcrest.core.IsNot;
-
+import de.ids_mannheim.korap.query.elements.KoralRelation;
import de.ids_mannheim.korap.query.elements.KoralTerm;
import de.ids_mannheim.korap.query.elements.KoralTerm.KoralTermType;
import de.ids_mannheim.korap.query.elements.KoralTermGroup;
import de.ids_mannheim.korap.query.elements.KoralToken;
-import de.ids_mannheim.korap.query.elements.KoralRelation;
-import de.ids_mannheim.korap.query.elements.KoralGroup.Distance;
+import de.ids_mannheim.korap.query.elements.MatchOperator;
import de.ids_mannheim.korap.query.serialize.FCSQLQueryProcessor;
import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import eu.clarin.sru.server.fcs.parser.Expression;
@@ -23,6 +20,10 @@
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";
@@ -173,12 +174,14 @@
private void parseOperator(KoralTerm koralTerm, Operator operator,
boolean isNot) {
- String matchOperator = null;
+ MatchOperator matchOperator = null;
if (operator == null || operator == Operator.EQUALS) {
- matchOperator = isNot ? "match:ne" : "match:eq";
+ matchOperator = isNot ? MatchOperator.NOT_EQUALS
+ : MatchOperator.EQUALS;
}
else if (operator == Operator.NOT_EQUALS) {
- matchOperator = isNot ? "match:eq" : "match:ne";
+ matchOperator = isNot ? MatchOperator.EQUALS
+ : MatchOperator.NOT_EQUALS;
}
else {
processor
@@ -187,7 +190,7 @@
+ " is unsupported.");
koralTerm.setInvalid(true);
}
- koralTerm.setOperator(matchOperator);
+ koralTerm.setOperator(matchOperator.toString());
}
private void parseRegexFlags(KoralTerm koralTerm, Set<RegexFlag> set) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
index ba440a3..a1c981f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
@@ -1,10 +1,15 @@
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.elements.KoralGroup;
import de.ids_mannheim.korap.query.elements.KoralOperation;
+import de.ids_mannheim.korap.query.elements.KoralGroup.Frame;
+import de.ids_mannheim.korap.query.elements.KoralSpan;
+import de.ids_mannheim.korap.query.elements.MatchOperator;
+import de.ids_mannheim.korap.query.elements.Scope;
import de.ids_mannheim.korap.query.serialize.FCSQLQueryProcessor;
import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import eu.clarin.sru.server.fcs.parser.QueryDisjunction;
@@ -12,7 +17,13 @@
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;
+/**
+ * @author margaretha
+ *
+ */
public class FCSSRUQueryParser {
private FCSQLQueryProcessor processor;
@@ -38,8 +49,12 @@
else if (queryNode instanceof QueryDisjunction) {
return parseGroupQuery(queryNode.getChildren(),
KoralOperation.DISJUNCTION);
- // } else if (queryNode instanceof QueryWithWithin) {
-
+ }
+ else if (queryNode instanceof QueryWithWithin) {
+ return parseWithinQuery((QueryWithWithin) queryNode);
+ }
+ else if (queryNode instanceof SimpleWithin) {
+ return parseFrame((SimpleWithin) queryNode);
}
else {
processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
@@ -49,6 +64,38 @@
}
}
+ private KoralSpan parseFrame(SimpleWithin frame) {
+ String foundry = "base";
+ String layer = "s"; // structure
+
+ if (frame.getScope() == null) {
+ processor.addError(StatusCodes.MALFORMED_QUERY,
+ "FCS diagnostic 10: Within context is missing.");
+ }
+ switch (frame.getScope()) {
+ case SENTENCE:
+ return new KoralSpan(Scope.SENTENCE.toString(), foundry, layer,
+ MatchOperator.EQUALS);
+ default:
+ processor.addError(StatusCodes.QUERY_TOO_COMPLEX,
+ "FCS diagnostic 11:" + frame.toString()
+ + " is currently unsupported.");
+ return null;
+ }
+ }
+
+ private KoralGroup parseWithinQuery(QueryWithWithin queryNode) {
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.POSITION);
+ koralGroup.setFrames(Arrays.asList(Frame.IS_AROUND));
+
+ List<Object> operands = new ArrayList<Object>();
+ operands.add(parseQueryNode(queryNode.getWithin()));
+ operands.add(parseQueryNode(queryNode.getChild(0)));
+ koralGroup.setOperands(operands);
+
+ return koralGroup;
+ }
+
private KoralGroup parseGroupQuery(List<QueryNode> children,
KoralOperation operation) {
KoralGroup koralGroup = new KoralGroup(operation);
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
index 1e973d8..d2b9d7a 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
@@ -1,15 +1,7 @@
package de.ids_mannheim.korap.query.serialize;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
-import de.ids_mannheim.korap.query.elements.KoralGroup;
-import de.ids_mannheim.korap.query.elements.KoralTerm;
-import de.ids_mannheim.korap.query.elements.KoralOperation;
-import de.ids_mannheim.korap.query.elements.KoralType;
-import de.ids_mannheim.korap.query.elements.KoralGroup.Distance;
import de.ids_mannheim.korap.query.parse.fcsql.FCSSRUQueryParser;
import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import eu.clarin.sru.server.SRUQueryBase;
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
index 9dd6009..531b389 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MapBuilder.java
@@ -3,10 +3,15 @@
import java.util.Map;
import de.ids_mannheim.korap.query.elements.KoralGroup;
+import de.ids_mannheim.korap.query.elements.KoralSpan;
import de.ids_mannheim.korap.query.elements.KoralTerm;
import de.ids_mannheim.korap.query.elements.KoralTermGroup;
import de.ids_mannheim.korap.query.elements.KoralToken;
+/**
+ * @author margaretha
+ *
+ */
public class MapBuilder {
public static Map<String, Object> buildQueryMap(Object o) {
@@ -27,6 +32,10 @@
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/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
index b9026cb..2afb7cb 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
@@ -11,6 +11,10 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+/**
+ * @author margaretha
+ *
+ */
public class FCSQLQueryProcessorTest {
QuerySerializer qs = new QuerySerializer();
@@ -288,4 +292,17 @@
runAndValidate(query, jsonLd);
}
+ @Test
+ public void testWithinQuery() throws JsonProcessingException {
+ String query = "[pos=\"VVFIN\"] within s";
+ String jsonLd = "{@type:koral:group,"
+ + "operation:operation:position,"
+ + "frames:["
+ + "frames:isAround"
+ + "],"
+ + "operands:[{@type: koral:span,key:s,foundry:base,layer:s,match:match:eq},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:VVFIN,foundry:tt,layer:p,type:type:regex,match:match:eq}}"
+ + "]}";
+ runAndValidate(query, jsonLd);
+ }
}