Added arbitrary element with attribute(s) deserialization and test examples.
diff --git a/src/main/java/de/ids_mannheim/korap/KorapQuery.java b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
index d18d9cb..d2a1660 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
@@ -12,7 +12,21 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import de.ids_mannheim.korap.query.SpanWithinQuery;
-import de.ids_mannheim.korap.query.wrap.*;
+import de.ids_mannheim.korap.query.wrap.SpanAlterQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanAttributeQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanClassQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanElementQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanFocusQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanRepetitionQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanSegmentQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanSequenceQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanSimpleQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanSubspanQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWithAttributeQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWithinQueryWrapper;
import de.ids_mannheim.korap.response.Notifications;
import de.ids_mannheim.korap.util.QueryException;
@@ -944,78 +958,103 @@
"JSON-LD group has no @type attribute");
}
- SpanQueryWrapper elementWithIdWrapper = null;
if (value.toString().isEmpty()) {
- // attribute with arbitraty elements
-
- this.addWarning(771,
- "Arbitraty elements with attributes are currently not supported.");
- return null;
+ return createElementAttrFromJson(null, json, attrNode);
+ // this.addWarning(771,
+ // "Arbitraty elements with attributes are currently not supported.");
}
else{
- elementWithIdWrapper = tag(value.toString());
- if (elementWithIdWrapper == null) return null;
+ SpanQueryWrapper elementWithIdWrapper = tag(value.toString());
+ if (elementWithIdWrapper == null){ return null; }
+ return createElementAttrFromJson(elementWithIdWrapper, json,
+ attrNode);
}
-
- if (attrNode.get("@type").asText().equals("koral:term")) {
- SpanQueryWrapper attrWrapper = _attrFromJson(json.get("attr"));
- if (attrWrapper != null) {
- return new SpanWithAttributeQueryWrapper(
- elementWithIdWrapper, attrWrapper);
- }
- else {
- throw new QueryException(747, "Attribute is null");
- }
- }
- else if (attrNode.get("@type").asText().equals("koral:termGroup")) {
- if (!attrNode.has("relation")) {
- throw new QueryException(743, "Term group expects a relation");
- }
-
- if (!attrNode.has("operands")) {
- throw new QueryException(742, "Term group needs operand list");
- }
-
- String relation = attrNode.get("relation").asText();
- JsonNode operands = attrNode.get("operands");
-
- SpanQueryWrapper attrWrapper;
- if ("relation:and".equals(relation)) {
- List<SpanQueryWrapper> wrapperList = new ArrayList<SpanQueryWrapper>();
- for (JsonNode operand : operands) {
- attrWrapper = _termFromJson(operand);
- if (attrWrapper == null) {
- throw new QueryException(747, "Attribute is null");
- }
- wrapperList.add(attrWrapper);
- }
-
- return new SpanWithAttributeQueryWrapper(
- elementWithIdWrapper, wrapperList);
- }
- else if ("relation:or".equals(relation)){
- SpanAlterQueryWrapper saq = new SpanAlterQueryWrapper(field);
- for (JsonNode operand : operands) {
- attrWrapper = _termFromJson(operand);
- if (attrWrapper == null) {
- throw new QueryException(747, "Attribute is null");
- }
- saq.or(new SpanWithAttributeQueryWrapper(
- elementWithIdWrapper, attrWrapper));
- }
- return saq;
- }
- else {
- throw new QueryException(716, "Unknown relation");
- }
- }
- else {
- this.addWarning(715, "Attribute type is not supported");
- }
};
return this.tag(value.toString());
};
+ private SpanQueryWrapper createElementAttrFromJson(
+ SpanQueryWrapper elementWithIdWrapper, JsonNode json,
+ JsonNode attrNode) throws QueryException {
+
+ if (attrNode.get("@type").asText().equals("koral:term")) {
+ SpanQueryWrapper attrWrapper = _attrFromJson(json.get("attr"));
+ if (attrWrapper != null) {
+ if (elementWithIdWrapper != null){
+ return new SpanWithAttributeQueryWrapper(elementWithIdWrapper,
+ attrWrapper);
+ }
+ else {
+ return new SpanWithAttributeQueryWrapper(attrWrapper);
+ }
+ }
+ else {
+ throw new QueryException(747, "Attribute is null");
+ }
+ }
+ else if (attrNode.get("@type").asText().equals("koral:termGroup")) {
+ return handleAttrGroup(elementWithIdWrapper, attrNode);
+ }
+ else {
+ this.addWarning(715, "Attribute type is not supported");
+ }
+ return elementWithIdWrapper;
+ }
+
+ private SpanQueryWrapper handleAttrGroup(
+ SpanQueryWrapper elementWithIdWrapper, JsonNode attrNode)
+ throws QueryException {
+ if (!attrNode.has("relation")) {
+ throw new QueryException(743, "Term group expects a relation");
+ }
+ if (!attrNode.has("operands")) {
+ throw new QueryException(742, "Term group needs operand list");
+ }
+
+ String relation = attrNode.get("relation").asText();
+ JsonNode operands = attrNode.get("operands");
+
+ SpanQueryWrapper attrWrapper;
+ if ("relation:and".equals(relation)) {
+ List<SpanQueryWrapper> wrapperList = new ArrayList<SpanQueryWrapper>();
+ for (JsonNode operand : operands) {
+ attrWrapper = _termFromJson(operand);
+ if (attrWrapper == null) {
+ throw new QueryException(747, "Attribute is null");
+ }
+ wrapperList.add(attrWrapper);
+ }
+
+ if (elementWithIdWrapper != null){
+ return new SpanWithAttributeQueryWrapper(elementWithIdWrapper,
+ wrapperList);
+ }
+ else {
+ return new SpanWithAttributeQueryWrapper(wrapperList);
+ }
+ }
+ else if ("relation:or".equals(relation)) {
+ SpanAlterQueryWrapper saq = new SpanAlterQueryWrapper(field);
+ SpanWithAttributeQueryWrapper saqw;
+ for (JsonNode operand : operands) {
+ attrWrapper = _termFromJson(operand);
+ if (attrWrapper == null) {
+ throw new QueryException(747, "Attribute is null");
+ }
+ if (elementWithIdWrapper != null) {
+ saqw = new SpanWithAttributeQueryWrapper(
+ elementWithIdWrapper, attrWrapper);
+ } else {
+ saqw = new SpanWithAttributeQueryWrapper(attrWrapper);
+ }
+ saq.or(saqw);
+ }
+ return saq;
+ }
+ else {
+ throw new QueryException(716, "Unknown relation");
+ }
+ }
// Get attributes from a json termgroup
private SpanQueryWrapper _attrFromJson (JsonNode attrNode)
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
index 7b7418f..7b633c0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
@@ -23,12 +23,16 @@
private List<SpanQueryWrapper> queryWrapperList = null;
private boolean isSingleAttribute = false;
- public SpanWithAttributeQueryWrapper(SpanQueryWrapper attrQuery) {
+ public SpanWithAttributeQueryWrapper(SpanQueryWrapper attrQuery)
+ throws QueryException {
if (attrQuery != null) isNull = false;
if (attrQuery.isEmpty()) {
isEmpty = true;
return;
}
+ if (attrQuery.isNegative) {
+ throw new QueryException("The query requires a positive attribute.");
+ }
this.attrQueryWrapper = attrQuery;
this.isSingleAttribute = true;
}
@@ -41,6 +45,7 @@
throw new QueryException("No attribute is defined.");
}
+ boolean isAllNegative = true;
for (SpanQueryWrapper sqw : attrList) {
if (sqw == null) {
isNull = true;
@@ -50,6 +55,12 @@
isEmpty = true;
return;
}
+ if (!sqw.isNegative) {
+ isAllNegative = false;
+ }
+ }
+ if (isAllNegative) {
+ throw new QueryException("No positive attribute is defined.");
}
this.queryWrapperList = attrList;
}
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
index a04e6f7..976958a 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
@@ -67,8 +67,46 @@
"/queries/attribute/any-element-with-attribute.jsonld")
.getFile();
SpanQueryWrapper sqwi = getJSONQuery(filepath);
- // SpanQuery sq = sqwi.toQuery();
- assertEquals(null, sqwi);
+ SpanQuery sq = sqwi.toQuery();
+ assertEquals(
+ "spanWithAttribute(spanAttribute(tokens:type:top))",
+ sq.toString());
+ }
+
+ @Test
+ public void testAnyElementWithMultipleOrAttributes() throws QueryException {
+ String filepath = getClass().getResource(
+ "/queries/attribute/any-element-with-multiple-or-attributes.jsonld")
+ .getFile();
+ SpanQueryWrapper sqwi = getJSONQuery(filepath);
+ SpanQuery sq = sqwi.toQuery();
+ assertEquals(
+ "spanOr([spanWithAttribute(spanAttribute(tokens:type:Zeitschrift)), "
+ + "spanWithAttribute(spanAttribute(tokens:complete:Y)), "
+ + "spanWithAttribute(spanAttribute(tokens:n:0))])",
+ sq.toString());
+ }
+
+ @Test
+ public void testAnyElementMultipleAndNotAttributes() throws QueryException {
+ String filepath = getClass()
+ .getResource(
+ "/queries/attribute/any-element-with-multiple-and-not-attributes.jsonld")
+ .getFile();
+ SpanQueryWrapper sqwi = getJSONQuery(filepath);
+ SpanQuery sq = sqwi.toQuery();
+ assertEquals(
+ "spanWithAttribute([spanAttribute(tokens:type:Zeitschrift), "
+ + "spanAttribute(!tokens:complete:Y), spanAttribute(tokens:n:0)])",
+ sq.toString());
+ }
+
+ @Test(expected = QueryException.class)
+ public void testAnyElementSingleNotAttribute() throws QueryException {
+ String filepath = getClass().getResource(
+ "/queries/attribute/any-element-with-single-not-attribute.jsonld")
+ .getFile();
+ SpanQueryWrapper sqwi = getJSONQuery(filepath);
}
}
diff --git a/src/test/resources/queries/attribute/any-element-with-attribute.jsonld b/src/test/resources/queries/attribute/any-element-with-attribute.jsonld
index ead458e..f53906d 100644
--- a/src/test/resources/queries/attribute/any-element-with-attribute.jsonld
+++ b/src/test/resources/queries/attribute/any-element-with-attribute.jsonld
@@ -8,11 +8,9 @@
"@type": "koral:span",
"attr": {
"@type": "koral:term",
- "arity": {
- "@type": "koral:boundary",
- "min": 2,
- "max": 2
- }
+ "layer": "type",
+ "key": "top",
+ "match": "match:eq"
}
},
"meta": {}
diff --git a/src/test/resources/queries/attribute/any-element-with-multiple-and-not-attributes.jsonld b/src/test/resources/queries/attribute/any-element-with-multiple-and-not-attributes.jsonld
new file mode 100644
index 0000000..db21c70
--- /dev/null
+++ b/src/test/resources/queries/attribute/any-element-with-multiple-and-not-attributes.jsonld
@@ -0,0 +1,35 @@
+{
+ "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+ "errors": [],
+ "warnings": [],
+ "messages": [],
+ "collection": {},
+ "query": {
+ "@type": "korap:span",
+ "attr": {
+ "@type": "korap:termGroup",
+ "relation": "relation:and",
+ "operands": [
+ {
+ "@type": "korap:term",
+ "layer": "type",
+ "key": "Zeitschrift",
+ "match": "match:eq"
+ },
+ {
+ "@type": "korap:term",
+ "layer": "complete",
+ "key": "Y",
+ "match": "match:ne"
+ },
+ {
+ "@type": "korap:term",
+ "layer": "n",
+ "key": "0",
+ "match": "match:eq"
+ }
+ ]
+ }
+ },
+ "meta": {}
+}
\ No newline at end of file
diff --git a/src/test/resources/queries/attribute/any-element-with-multiple-or-attributes.jsonld b/src/test/resources/queries/attribute/any-element-with-multiple-or-attributes.jsonld
new file mode 100644
index 0000000..765531c
--- /dev/null
+++ b/src/test/resources/queries/attribute/any-element-with-multiple-or-attributes.jsonld
@@ -0,0 +1,35 @@
+{
+ "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+ "errors": [],
+ "warnings": [],
+ "messages": [],
+ "collection": {},
+ "query": {
+ "@type": "korap:span",
+ "attr": {
+ "@type": "korap:termGroup",
+ "relation": "relation:or",
+ "operands": [
+ {
+ "@type": "korap:term",
+ "layer": "type",
+ "key": "Zeitschrift",
+ "match": "match:eq"
+ },
+ {
+ "@type": "korap:term",
+ "layer": "complete",
+ "key": "Y",
+ "match": "match:eq"
+ },
+ {
+ "@type": "korap:term",
+ "layer": "n",
+ "key": "0",
+ "match": "match:eq"
+ }
+ ]
+ }
+ },
+ "meta": {}
+}
\ No newline at end of file
diff --git a/src/test/resources/queries/attribute/any-element-with-single-not-attribute.jsonld b/src/test/resources/queries/attribute/any-element-with-single-not-attribute.jsonld
new file mode 100644
index 0000000..3c1ed4f
--- /dev/null
+++ b/src/test/resources/queries/attribute/any-element-with-single-not-attribute.jsonld
@@ -0,0 +1,17 @@
+{
+ "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+ "errors": [],
+ "warnings": [],
+ "messages": [],
+ "collection": {},
+ "query": {
+ "@type": "korap:span",
+ "attr": {
+ "@type": "korap:term",
+ "layer": "type",
+ "key": "top",
+ "match": "match:ne"
+ }
+ },
+ "meta": {}
+}
\ No newline at end of file