Added null query support (untested)
diff --git a/src/main/java/de/ids_mannheim/korap/KorapIndex.java b/src/main/java/de/ids_mannheim/korap/KorapIndex.java
index 685d268..e2cc91a 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapIndex.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapIndex.java
@@ -84,6 +84,10 @@
/*
TODO: Support layer for specific foundries (IMPORTANT)
+ TODO: Implement timeout!!!
+ - https://lucene.apache.org/core/2_9_4/api/all/org/apache/lucene/search/TimeLimitingCollector.html
+ - https://lucene.apache.org/core/2_9_4/api/all/org/apache/lucene/search/TimeLimitingCollector.html
+ - http://stackoverflow.com/questions/19557476/timing-out-a-query-in-solr
TODO: Use FieldCache!
TODO: Reuse the indexreader everywhere - it should be threadsafe!
diff --git a/src/main/java/de/ids_mannheim/korap/KorapQuery.java b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
index b0ed21e..d05d4d2 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
@@ -161,7 +161,6 @@
if (json.has("exclude") && json.get("exclude").asBoolean())
throw new QueryException("Exclusion is currently not supported in position operations");
-
return new SpanWithinQueryWrapper(
this.fromJSON(operands.get(0)),
this.fromJSON(operands.get(1)),
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
index bc706f2..fd7c65d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
@@ -1,6 +1,7 @@
package de.ids_mannheim.korap.query.wrap;
import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
import de.ids_mannheim.korap.query.wrap.SpanSegmentQueryWrapper;
import de.ids_mannheim.korap.query.wrap.SpanQueryWrapperInterface;
@@ -15,7 +16,7 @@
private String field;
private SpanQuery query;
private List<SpanQuery> alternatives;
-
+ private boolean isNull = true;
public SpanAlterQueryWrapper (String field) {
this.field = field;
@@ -26,26 +27,41 @@
this.field = field;
this.alternatives = new ArrayList<>();
for (String term : terms) {
+ this.isNull = false;
this.alternatives.add(new SpanTermQuery(new Term(this.field, term)));
};
};
public SpanAlterQueryWrapper or (String term) {
this.alternatives.add(new SpanTermQuery(new Term(this.field, term)));
+ this.isNull = false;
return this;
};
public SpanAlterQueryWrapper or (SpanQueryWrapperInterface term) {
+ if (term.isNull())
+ return this;
this.alternatives.add( term.toQuery() );
+ this.isNull = false;
return this;
};
public SpanAlterQueryWrapper or (SpanRegexQueryWrapper term) {
this.alternatives.add( term.toQuery() );
+ this.isNull = false;
+ return this;
+ };
+
+ public SpanAlterQueryWrapper or (SpanWildcardQueryWrapper wc) {
+ this.alternatives.add( wc.toQuery() );
+ this.isNull = false;
return this;
};
public SpanQuery toQuery() {
+ if (this.isNull || this.alternatives.size() == 0)
+ return (SpanQuery) null;
+
if (this.alternatives.size() == 1) {
return (SpanQuery) this.alternatives.get(0);
};
@@ -57,4 +73,12 @@
};
return (SpanQuery) soquery;
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.isNull;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
index 312c005..5a6c1a4 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
@@ -33,9 +33,20 @@
};
public SpanQuery toQuery () {
+ if (this.subquery.isNull())
+ return (SpanQuery) null;
+
if (this.number == (byte) 0) {
return new SpanClassQuery((SpanQuery) this.subquery.toQuery());
};
return new SpanClassQuery((SpanQuery) this.subquery.toQuery(), (byte) this.number);
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.subquery.isNull();
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
index acf0638..c5da7fc 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
@@ -17,4 +17,12 @@
public SpanQuery toQuery () {
return (SpanQuery) new SpanElementQuery(this.field, this.element);
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return false;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanMatchModifyQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanMatchModifyQueryWrapper.java
index aa25021..85926e2 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanMatchModifyQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanMatchModifyQueryWrapper.java
@@ -33,6 +33,16 @@
};
public SpanQuery toQuery () {
+ if (this.subquery.isNull())
+ return (SpanQuery) null;
return new SpanMatchModifyClassQuery(this.subquery.toQuery(), this.number);
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.subquery.isNull();
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQuantifierQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQuantifierQueryWrapper.java
index 521cb0a..4a29118 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQuantifierQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQuantifierQueryWrapper.java
@@ -8,6 +8,8 @@
import de.ids_mannheim.korap.query.wrap.SpanQueryWrapperInterface;
import org.apache.lucene.search.spans.SpanQuery;
+// This might be irrelevant now with repetition!
+
public class SpanQuantifierQueryWrapper implements SpanQueryWrapperInterface {
private String field;
@@ -19,6 +21,14 @@
return (SpanQuery) null;
};
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return false;
+ };
+
/*
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapperInterface.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapperInterface.java
index 035e867..b88af57 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapperInterface.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapperInterface.java
@@ -3,9 +3,10 @@
import org.apache.lucene.search.spans.SpanQuery;
// Todo: Make this an abstract class to deal with regexes in a parent abstract class!
-
-// Add optional and null attributes
+// Add warning and error
public interface SpanQueryWrapperInterface {
public SpanQuery toQuery ();
+ public boolean isOptional ();
+ public boolean isNull ();
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
index 3cd4051..cf788dc 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
@@ -8,6 +8,10 @@
import java.util.*;
+/*
+ TODO: Don't allow queries like ".*?"!!!
+*/
+
public class SpanRegexQueryWrapper {
private SpanQuery query;
@@ -38,4 +42,12 @@
public SpanQuery toQuery() {
return this.query;
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return false;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
index 8ab2937..68ffb5b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
@@ -10,20 +10,49 @@
private SpanQueryWrapperInterface subquery;
private int min = 1;
private int max = 1;
+ private boolean optional = false;
+ private boolean isNull = false;
public SpanRepetitionQueryWrapper (SpanQueryWrapperInterface subquery, int exact) {
this.subquery = subquery;
+
+ if (exact < 1 || this.subquery.isNull()) {
+ this.isNull = true;
+ return;
+ };
+
this.min = exact;
this.max = exact;
};
public SpanRepetitionQueryWrapper (SpanQueryWrapperInterface subquery, int min, int max) {
this.subquery = subquery;
+
+ if (this.subquery.isNull()) {
+ this.isNull = true;
+ return;
+ };
+
+ if (min == 0) {
+ this.optional = true;
+ if (max == 0)
+ this.isNull = true;
+ };
this.min = min;
this.max = max;
};
public SpanQuery toQuery () {
+ if (this.isNull)
+ return (SpanQuery) null;
return new SpanRepetitionQuery(this.subquery.toQuery(), this.min, this.max, true);
};
+
+ public boolean isOptional () {
+ return this.optional;
+ };
+
+ public boolean isNull () {
+ return this.isNull;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
index e59316a..1d007c3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
@@ -25,6 +25,7 @@
public ArrayList<SpanQuery> inclusive;
public ArrayList<SpanQuery> exclusive;
private String field;
+ private boolean isNull = true;
/**
* Constructor.
@@ -47,92 +48,119 @@
this(field);
for (int i = 0; i < terms.length; i++) {
this.inclusive.add((SpanQuery) new SpanTermQuery(new Term(field, terms[i])));
+ this.isNull = false;
};
};
public SpanSegmentQueryWrapper (String field, SpanRegexQueryWrapper re) {
this(field);
this.inclusive.add((SpanQuery) re.toQuery());
+ this.isNull = false;
};
public SpanSegmentQueryWrapper (String field, SpanAlterQueryWrapper alter) {
this(field);
- this.inclusive.add((SpanQuery) alter.toQuery());
+ if (!alter.isNull()) {
+ this.inclusive.add((SpanQuery) alter.toQuery());
+ this.isNull = false;
+ };
};
public SpanSegmentQueryWrapper (String field, SpanSegmentQueryWrapper ssq) {
this(field);
- Iterator<SpanQuery> clause = ssq.inclusive.iterator();
- while (clause.hasNext()) {
- this.inclusive.add( (SpanQuery) clause.next().clone() );
- };
+ if (!ssq.isNull()) {
+ Iterator<SpanQuery> clause = ssq.inclusive.iterator();
+ while (clause.hasNext()) {
+ this.inclusive.add( (SpanQuery) clause.next().clone() );
+ };
- clause = ssq.exclusive.iterator();
- while (clause.hasNext()) {
- this.exclusive.add( (SpanQuery) clause.next().clone() );
+ clause = ssq.exclusive.iterator();
+ while (clause.hasNext()) {
+ this.exclusive.add( (SpanQuery) clause.next().clone() );
+ };
+ this.isNull = false;
};
};
public SpanSegmentQueryWrapper with (String term) {
this.inclusive.add(new SpanTermQuery(new Term(field, term)));
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper with (SpanRegexQueryWrapper re) {
this.inclusive.add((SpanQuery) re.toQuery());
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper with (SpanWildcardQueryWrapper wc) {
this.inclusive.add((SpanQuery) wc.toQuery());
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper with (SpanAlterQueryWrapper alter) {
- this.inclusive.add((SpanQuery) alter.toQuery());
+ if (!alter.isNull()) {
+ this.inclusive.add((SpanQuery) alter.toQuery());
+ this.isNull = false;
+ };
return this;
};
// Identical to without
public SpanSegmentQueryWrapper with (SpanSegmentQueryWrapper seg) {
- for (SpanQuery sq : seg.inclusive) {
- this.inclusive.add(sq);
- };
- for (SpanQuery sq : seg.exclusive) {
- this.exclusive.add(sq);
+ if (!seg.isNull()) {
+ for (SpanQuery sq : seg.inclusive) {
+ this.inclusive.add(sq);
+ };
+ for (SpanQuery sq : seg.exclusive) {
+ this.exclusive.add(sq);
+ };
+ this.isNull = false;
};
return this;
};
public SpanSegmentQueryWrapper without (String term) {
this.exclusive.add(new SpanTermQuery(new Term(field, term)));
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper without (SpanRegexQueryWrapper re) {
this.exclusive.add((SpanQuery) re.toQuery());
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper without (SpanWildcardQueryWrapper wc) {
this.exclusive.add((SpanQuery) wc.toQuery());
+ this.isNull = false;
return this;
};
public SpanSegmentQueryWrapper without (SpanAlterQueryWrapper alter) {
- this.exclusive.add((SpanQuery) alter.toQuery());
+ if (!alter.isNull()) {
+ this.exclusive.add((SpanQuery) alter.toQuery());
+ this.isNull = false;
+ };
return this;
};
// Identical to with
public SpanSegmentQueryWrapper without (SpanSegmentQueryWrapper seg) {
- return this.with(seg);
+ if (!seg.isNull()) {
+ this.with(seg);
+ this.isNull = false;
+ };
+ return this;
};
public SpanQuery toQuery () {
- if (this.inclusive.size() + this.exclusive.size() == 0) {
- return null;
+ if (this.isNull || (this.inclusive.size() + this.exclusive.size() == 0)) {
+ return (SpanQuery) null;
}
else if (this.inclusive.size() >= 1 && this.exclusive.size() >= 1) {
return (SpanQuery) new SpanNotQuery(
@@ -186,5 +214,13 @@
public SpanSegmentQueryWrapper clone () {
return new SpanSegmentQueryWrapper(this.field, this);
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.isNull;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
index 5e1c91e..e3b755d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
@@ -9,6 +9,7 @@
import de.ids_mannheim.korap.query.wrap.SpanSegmentQueryWrapper;
import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.spans.SpanQuery;
@@ -23,6 +24,7 @@
private ArrayList<SpanQuery> segments;
private ArrayList<DistanceConstraint> constraints;
private boolean isInOrder = true;
+ private boolean isNull = true;
public SpanSequenceQueryWrapper (String field) {
this.field = field;
@@ -34,21 +36,37 @@
for (int i = 0; i < terms.length; i++) {
this.segments.add((SpanQuery) new SpanTermQuery(new Term(field, terms[i])));
};
+ this.isNull = false;
};
public SpanSequenceQueryWrapper (String field, SpanQuery sq) {
this(field);
this.segments.add((SpanQuery) sq);
+ this.isNull = false;
};
public SpanSequenceQueryWrapper (String field, SpanQueryWrapperInterface sswq) {
this(field);
- this.segments.add((SpanQuery) sswq.toQuery());
+ if (!sswq.isNull()) {
+ this.segments.add((SpanQuery) sswq.toQuery());
+ this.isNull = false;
+ };
};
public SpanSequenceQueryWrapper (String field, SpanRegexQueryWrapper re) {
this(field);
- this.segments.add((SpanQuery) re.toQuery());
+ if (!re.isNull()) {
+ this.segments.add((SpanQuery) re.toQuery());
+ this.isNull = false;
+ };
+ };
+
+ public SpanSequenceQueryWrapper (String field, SpanWildcardQueryWrapper wc) {
+ this(field);
+ if (!wc.isNull()) {
+ this.segments.add((SpanQuery) wc.toQuery());
+ this.isNull = false;
+ };
};
public SpanQuery get (int index) {
@@ -61,31 +79,61 @@
public SpanSequenceQueryWrapper append (String term) {
this.segments.add((SpanQuery) new SpanTermQuery(new Term(field, term)));
+ this.isNull = false;
return this;
};
public SpanSequenceQueryWrapper append (SpanQueryWrapperInterface ssq) {
- this.segments.add((SpanQuery) ssq.toQuery());
+ if (!ssq.isNull()) {
+ this.segments.add((SpanQuery) ssq.toQuery());
+ this.isNull = false;
+ };
return this;
};
public SpanSequenceQueryWrapper append (SpanRegexQueryWrapper srqw) {
- this.segments.add((SpanQuery) srqw.toQuery());
+ if (!srqw.isNull()) {
+ this.segments.add((SpanQuery) srqw.toQuery());
+ this.isNull = false;
+ };
+ return this;
+ };
+
+ public SpanSequenceQueryWrapper append (SpanWildcardQueryWrapper swqw) {
+ if (!swqw.isNull()) {
+ this.segments.add((SpanQuery) swqw.toQuery());
+ this.isNull = false;
+ };
return this;
};
public SpanSequenceQueryWrapper prepend (String term) {
this.segments.add(0, (SpanQuery) new SpanTermQuery(new Term(field, term)));
+ this.isNull = false;
return this;
};
public SpanSequenceQueryWrapper prepend (SpanSegmentQueryWrapper ssq) {
- this.segments.add(0, (SpanQuery) ssq.toQuery());
+ if (!ssq.isNull()) {
+ this.segments.add(0, (SpanQuery) ssq.toQuery());
+ this.isNull = false;
+ };
return this;
};
public SpanSequenceQueryWrapper prepend (SpanRegexQueryWrapper re) {
- this.segments.add(0, (SpanQuery) re.toQuery());
+ if (!re.isNull()) {
+ this.segments.add(0, (SpanQuery) re.toQuery());
+ this.isNull = false;
+ };
+ return this;
+ };
+
+ public SpanSequenceQueryWrapper prepend (SpanWildcardQueryWrapper swqw) {
+ if (!swqw.isNull()) {
+ this.segments.add(0, (SpanQuery) swqw.toQuery());
+ this.isNull = false;
+ };
return this;
};
@@ -122,7 +170,7 @@
public SpanQuery toQuery () {
- if (this.segments.size() == 0) {
+ if (this.segments.size() == 0 || this.isNull) {
return (SpanQuery) null;
};
@@ -204,4 +252,12 @@
return false;
return true;
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.isNull;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
index 7289bfa..94179f3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
@@ -28,4 +28,12 @@
public SpanQuery toQuery() {
return this.query;
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return false;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
index 4372fdf..fe6f9c2 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
@@ -16,20 +16,36 @@
private SpanQueryWrapperInterface element;
private SpanQueryWrapperInterface wrap;
private byte flag;
+ private boolean isNull = true;;
public SpanWithinQueryWrapper (SpanQueryWrapperInterface element, SpanQueryWrapperInterface wrap) {
this.element = element;
this.wrap = wrap;
this.flag = (byte) SpanWithinQuery.WITHIN;
+ if (!element.isNull() && !wrap.isNull())
+ this.isNull = false;
};
public SpanWithinQueryWrapper (SpanQueryWrapperInterface element, SpanQueryWrapperInterface wrap, byte flag) {
this.element = element;
this.wrap = wrap;
this.flag = flag;
+ if (!element.isNull() && !wrap.isNull())
+ this.isNull = false;
};
public SpanQuery toQuery () {
+ if (this.isNull)
+ return (SpanQuery) null;
+
return new SpanWithinQuery(this.element.toQuery(), this.wrap.toQuery(), this.flag);
};
+
+ public boolean isOptional () {
+ return false;
+ };
+
+ public boolean isNull () {
+ return this.isNull;
+ };
};