Element distance exclusion
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanDistanceQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanDistanceQuery.java
index 95ff5cb..3368ef9 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanDistanceQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanDistanceQuery.java
@@ -12,6 +12,7 @@
import org.apache.lucene.util.ToStringUtils;
import de.ids_mannheim.korap.query.spans.DistanceExclusionSpan;
+import de.ids_mannheim.korap.query.spans.ElementDistanceExclusionSpan;
import de.ids_mannheim.korap.query.spans.ElementDistanceSpans;
import de.ids_mannheim.korap.query.spans.TokenDistanceSpans;
import de.ids_mannheim.korap.query.spans.UnorderedElementDistanceSpans;
@@ -19,7 +20,9 @@
/** Match two ordered or unordered Spans with minimum and maximum
* distance constraints. The distance unit can be word (token),
- * sentence or paragraph.
+ * sentence or paragraph. The distance constraint can also be
+ * specified to match some Spans which do not co-occur with some
+ * other Spans within a min and max distance.
*
* @author margaretha
* */
@@ -105,7 +108,8 @@
if (this.elementQuery != null) {
if (isExclusion()){
-
+ return new ElementDistanceExclusionSpan(this, context, acceptDocs,
+ termContexts, isOrdered);
}
else if (isOrdered){
return new ElementDistanceSpans(this, context, acceptDocs,
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpan.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpan.java
new file mode 100644
index 0000000..520ff75
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpan.java
@@ -0,0 +1,251 @@
+package de.ids_mannheim.korap.query.spans;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermContext;
+import org.apache.lucene.search.spans.Spans;
+import org.apache.lucene.util.Bits;
+
+import de.ids_mannheim.korap.query.SpanDistanceQuery;
+
+/** Span enumeration of the first spans which do NOT occur together
+ * with the second spans within a range of some element-based distance
+ * (sentence or paragraph). Note: The element distance unit does not
+ * overlap to each other.
+ *
+ * @author margaretha
+ * */
+public class ElementDistanceExclusionSpan extends DistanceSpans{
+
+ private Spans elements;
+ private boolean hasMoreElements;
+ private int elementPosition;
+
+ private boolean isOrdered;
+ private boolean hasMoreSecondSpans;
+
+ protected List<CandidateSpan> candidateList, targetList;
+ private int currentDocNum;
+
+ private int minDistance, maxDistance;
+ private int firstSpanPostion;
+
+ public ElementDistanceExclusionSpan(SpanDistanceQuery query,
+ AtomicReaderContext context, Bits acceptDocs,
+ Map<Term, TermContext> termContexts, boolean isOrdered)
+ throws IOException {
+ super(query, context, acceptDocs, termContexts);
+
+ elements = query.getElementQuery().
+ getSpans(context, acceptDocs, termContexts);
+ hasMoreElements = elements.next();
+ hasMoreSpans = firstSpans.next() && hasMoreElements;
+ hasMoreSecondSpans = secondSpans.next();
+
+ elementPosition=0;
+ this.isOrdered = isOrdered;
+ candidateList = new ArrayList<CandidateSpan>();
+ targetList = new ArrayList<CandidateSpan>();
+ currentDocNum = firstSpans.doc();
+
+ minDistance = query.getMinDistance();
+ maxDistance = query.getMaxDistance();
+ }
+
+ @Override
+ protected boolean advance() throws IOException {
+ while(!targetList.isEmpty() || (hasMoreSpans && ensureSameDoc(firstSpans, elements))){
+ if (!targetList.isEmpty()){
+ if (isTargetValid()) return true;
+ else continue;
+ }
+ if (checkFirstSpan()) return true;
+ }
+ return false;
+ }
+
+ private boolean isTargetValid() throws IOException{
+ CandidateSpan target = targetList.get(0);
+ targetList.remove(0);
+ firstSpanPostion = target.getPosition();
+ filterCandidateList(firstSpanPostion);
+ collectRightCandidates();
+
+ if (isWithinDistance()){
+ return false;
+ }
+ setMatchProperties(target);
+ return true;
+ }
+
+ private boolean checkFirstSpan() throws IOException{
+ if (firstSpans.doc() != currentDocNum){
+ currentDocNum = firstSpans.doc();
+ candidateList.clear();
+ }
+
+ if (hasMoreSecondSpans) {
+ if (secondSpans.doc() == firstSpans.doc()){
+ return (findMatch() ? true : false);
+ }
+ else if (secondSpans.doc() < firstSpans.doc()){
+ hasMoreSecondSpans = secondSpans.skipTo(firstSpans.doc());
+ return false;
+ }
+ }
+ return (isFirstSpanValid() ? true : false);
+ }
+
+ private boolean isFirstSpanValid() throws IOException{
+ if (candidateList.isEmpty()){
+ if (isFirstSpanInElement()){
+ setMatchProperties(new CandidateSpan(firstSpans,elementPosition));
+ hasMoreSpans = firstSpans.next();
+ return true;
+ }
+ hasMoreSpans = firstSpans.next();
+ return false;
+ }
+ return (findMatch() ? true : false);
+ }
+
+ private boolean advanceElementTo(Spans span) throws IOException{
+ while (hasMoreElements &&
+ elements.doc() == currentDocNum &&
+ elements.start() < span.end()){
+
+ if (span.start() >= elements.start() &&
+ span.end() <= elements.end()){
+ return true;
+ }
+
+ hasMoreElements = elements.next();
+ elementPosition++;
+ }
+ return false;
+ }
+
+ private boolean findMatch() throws IOException {
+ if (!isOrdered) collectLeftCandidates();
+
+ if (isFirstSpanInElement()){
+ CandidateSpan target = new CandidateSpan(firstSpans,elementPosition);
+ hasMoreSpans = firstSpans.next();
+ // Checking the secondspans in the left side
+ if (!isOrdered && isWithinDistance()) return false;
+ // Checking the secondspans in the right side
+ collectRightCandidates();
+ if (isWithinDistance()) return false;
+
+ setMatchProperties(target);
+ return true;
+ }
+ hasMoreSpans = firstSpans.next();
+ return false;
+ }
+
+ private void collectRightCandidates() throws IOException{
+ while (hasMoreSecondSpans && secondSpans.doc() == currentDocNum){
+
+ if (elementPosition > firstSpanPostion+maxDistance){
+ break;
+ }
+ if (hasMoreSpans && firstSpans.start() < secondSpans.start() &&
+ firstSpans.doc() == currentDocNum){
+ if (advanceElementTo(firstSpans)){
+ targetList.add(new CandidateSpan(firstSpans, elementPosition));
+ }
+ hasMoreSpans = firstSpans.next();
+ continue;
+ }
+
+ if (advanceElementTo(secondSpans)){
+ candidateList.add(new CandidateSpan(secondSpans,elementPosition));
+ }
+ hasMoreSecondSpans = secondSpans.next();
+ }
+ }
+
+ private void collectLeftCandidates() throws IOException{
+ while(hasMoreSecondSpans && secondSpans.doc() == firstSpans.doc() &&
+ secondSpans.start() < firstSpans.end()){
+ if (advanceElementTo(secondSpans)){
+ candidateList.add(new CandidateSpan(secondSpans,elementPosition));
+ filterCandidateList(elementPosition);
+ }
+ hasMoreSecondSpans = secondSpans.next();
+ }
+ }
+
+ private boolean isWithinDistance(){
+ int actualDistance;
+ for (CandidateSpan cs: candidateList){
+ actualDistance = cs.getPosition() - firstSpanPostion;
+ if (!isOrdered) actualDistance = Math.abs(actualDistance);
+
+ if (minDistance <= actualDistance && actualDistance <= maxDistance)
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isFirstSpanInElement() throws IOException {
+ if (advanceElementTo(firstSpans)){
+ firstSpanPostion = elementPosition;
+ filterCandidateList(firstSpanPostion);
+ return true;
+ }
+ return false;
+ }
+
+ private void filterCandidateList(int position){
+
+ Iterator<CandidateSpan> i = candidateList.iterator();
+ CandidateSpan cs;
+ while(i.hasNext()){
+ cs = i.next();
+ if (cs.getPosition() == position ||
+ cs.getPosition()+maxDistance >= position){
+ break;
+ }
+ i.remove();
+ }
+ }
+
+ private void setMatchProperties(CandidateSpan match) throws IOException{
+ matchDocNumber = match.getDoc();
+ matchStartPosition = match.getStart();
+ matchEndPosition = match.getEnd();
+
+ if (collectPayloads && match.getPayloads() != null)
+ matchPayload.addAll(match.getPayloads());
+
+ setMatchFirstSpan(match);
+
+ log.trace("doc# {}, start {}, end {}",matchDocNumber,matchStartPosition,
+ matchEndPosition);
+ }
+
+ @Override
+ public boolean skipTo(int target) throws IOException {
+ if (hasMoreSpans && firstSpans.doc() < target){
+ if (!firstSpans.skipTo(target)){
+ hasMoreSpans = false;
+ return false;
+ }
+ }
+ return advance();
+ }
+
+ @Override
+ public long cost() {
+ return elements.cost() + firstSpans.cost() + secondSpans.cost();
+ }
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
index b079c72..229004e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
@@ -19,6 +19,8 @@
* or a paragraph. All other child spans occurrence which are not in
* a sentence or a paragraph (with respect to the element distance type
* current used), are ignored.
+ *
+ * Note: elements cannot overlap to each other.
*
* @author margaretha
* */
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
index 440d76f..732eb42 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
@@ -109,8 +109,6 @@
log.trace("doc# {}, start {}, end {}",matchDocNumber,matchStartPosition,
matchEndPosition);
- // System.out.println("firstspan "+getMatchFirstSpan().getStart()+" "+ getMatchFirstSpan().getEnd());
- // System.out.println("secondspan "+getMatchSecondSpan().getStart()+" "+ getMatchSecondSpan().getEnd());
}
@Override
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceExclusionIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceExclusionIndex.java
new file mode 100644
index 0000000..49c1906
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceExclusionIndex.java
@@ -0,0 +1,207 @@
+package de.ids_mannheim.korap.index;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanTermQuery;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.KorapIndex;
+import de.ids_mannheim.korap.KorapResult;
+import de.ids_mannheim.korap.query.SpanDistanceQuery;
+import de.ids_mannheim.korap.query.SpanElementQuery;
+import de.ids_mannheim.korap.query.SpanNextQuery;
+
+public class TestElementDistanceExclusionIndex {
+
+ KorapResult kr;
+ KorapIndex ki;
+
+ private SpanQuery createQuery(String e, String x, String y, int min, int max, boolean isOrdered,
+ boolean exclusion){
+ SpanDistanceQuery sq = new SpanDistanceQuery(
+ new SpanElementQuery("base",e),
+ new SpanTermQuery(new Term("base",x)),
+ new SpanTermQuery(new Term("base",y)),
+ min,
+ max,
+ isOrdered,
+ true
+ );
+ sq.setExclusion(exclusion);
+ return sq;
+ }
+
+ private FieldDocument createFieldDoc0(){
+ FieldDocument fd = new FieldDocument();
+ fd.addString("ID", "doc-0");
+ fd.addTV("base",
+ "text",
+ "[(0-1)s:c|_1#0-1|<>:s#0-1$<i>1]" +
+ "[(1-2)s:e|_2#1-2|<>:s#1-2$<i>2]" +
+ "[(2-3)s:c|_3#2-3|<>:s#2-4$<i>4]" +
+ "[(3-4)s:c|_4#3-4]" +
+ "[(4-5)s:d|_5#4-5|<>:s#4-6$<i>6]" +
+ "[(5-6)s:c|_6#5-6]" +
+ "[(6-7)s:d|_7#6-7|<>:s#6-7$<i>7]" +
+ "[(7-8)s:e|_8#7-8|<>:s#7-9$<i>9]" +
+ "[(8-9)s:c|_9#8-9]" +
+ "[(9-10)s:d|_10#9-10]");
+ return fd;
+ }
+
+ private FieldDocument createFieldDoc1() {
+ FieldDocument fd = new FieldDocument();
+ fd.addString("ID", "doc-1");
+ fd.addTV("base",
+ "text",
+ "[(0-1)s:e|_1#0-1|<>:s#0-1$<i>1]" +
+ "[(1-2)s:e|_2#1-2|<>:s#1-2$<i>2]" +
+ "[(2-3)s:d|_3#2-3|<>:s#2-4$<i>4]" +
+ "[(3-4)s:a|_4#3-4]" +
+ "[(4-5)s:d|_5#4-5|<>:s#4-7$<i>6]" +
+ "[(5-6)s:a|_6#5-6]" +
+ "[(6-7)s:e|_7#6-7|<>:s#6-7$<i>9]" +
+ "[(7-8)s:e|_8#7-8]" +
+ "[(8-9)s:d|_9#8-9]");
+ return fd;
+ }
+
+ private FieldDocument createFieldDoc2(){
+ FieldDocument fd = new FieldDocument();
+ fd.addString("ID", "doc-");
+ fd.addTV("base",
+ "text",
+ "[(0-1)s:d|_1#0-1|<>:s#0-1$<i>1]" +
+ "[(1-2)s:c|_2#1-2|<>:s#1-2$<i>2]" +
+ "[(2-3)s:a|_3#2-3|<>:s#2-4$<i>4]" +
+ "[(3-4)s:c|_4#3-4]" +
+ "[(4-5)s:a|_5#4-5|<>:s#4-6$<i>6]" +
+ "[(5-6)s:c|_6#5-6]" +
+ "[(6-7)s:d|_7#6-7|<>:s#6-7$<i>7]" +
+ "[(7-8)s:a|_8#7-8|<>:s#7-9$<i>9]" +
+ "[(8-9)s:c|_9#8-9]");
+ return fd;
+ }
+
+ /** Distance Zero, unordered
+ * There is a secondspan on the right side
+ * */
+ @Test
+ public void testCase1() throws IOException{
+ ki = new KorapIndex();
+ ki.addDoc(createFieldDoc0());
+ ki.commit();
+ SpanQuery sq;
+ sq = createQuery("s","s:d","s:c",0,0,false,true);
+ kr = ki.search(sq, (short) 10);
+ assertEquals(1, kr.totalResults());
+ assertEquals(6, kr.match(0).startPos);
+ assertEquals(7, kr.match(0).endPos);
+ }
+
+ /** There is another firstspan within max distance
+ * Unordered
+ * */
+ @Test
+ public void testCase2() throws IOException{
+ ki = new KorapIndex();
+ ki.addDoc(createFieldDoc0());
+ ki.commit();
+ SpanQuery sq;
+
+ sq = createQuery("s","s:c","s:d",0,0,false,true);
+ kr = ki.search(sq, (short) 10);
+
+ assertEquals(4, kr.totalResults());
+ assertEquals(0, kr.match(0).startPos);
+ assertEquals(1, kr.match(0).endPos);
+ assertEquals(2, kr.match(1).startPos);
+ assertEquals(3, kr.match(1).endPos);
+ assertEquals(3, kr.match(2).startPos);
+ assertEquals(4, kr.match(2).endPos);
+ assertEquals(8, kr.match(3).startPos);
+ assertEquals(9, kr.match(3).endPos);
+ }
+
+ /** Distance 0-1, ordered, unordered
+ * */
+ @Test
+ public void testCase3() throws IOException{
+ ki = new KorapIndex();
+ ki.addDoc(createFieldDoc0());
+ ki.commit();
+ SpanQuery sq;
+ // unordered
+ sq = createQuery("s","s:c","s:e",0,1,false,true);
+ kr = ki.search(sq, (short) 10);
+ assertEquals(1, kr.totalResults());
+ assertEquals(5, kr.match(0).startPos);
+ assertEquals(6, kr.match(0).endPos);
+
+ //ordered
+ sq = createQuery("s","s:c","s:e",0,1,true,true);
+ kr = ki.search(sq, (short) 10);
+ assertEquals(3, kr.totalResults());
+ assertEquals(2, kr.match(0).startPos);
+ assertEquals(3, kr.match(0).endPos);
+ assertEquals(3, kr.match(1).startPos);
+ assertEquals(4, kr.match(1).endPos);
+ }
+
+ /** Multiple documents, ordered
+ * No more secondspans, but there is still a firstspan
+ * */
+ @Test
+ public void testCase4() throws IOException{
+ ki = new KorapIndex();
+ ki.addDoc(createFieldDoc0());
+ ki.addDoc(createFieldDoc1());
+ ki.commit();
+ SpanQuery sq;
+
+ sq = createQuery("s","s:d","s:e",1,1,true,true);
+ kr = ki.search(sq, (short) 10);
+
+ assertEquals(3, kr.totalResults());
+ assertEquals(4, kr.match(0).startPos);
+ assertEquals(5, kr.match(0).endPos);
+ assertEquals(1, kr.match(1).getLocalDocID());
+ assertEquals(2, kr.match(1).startPos);
+ assertEquals(3, kr.match(1).endPos);
+ assertEquals(8, kr.match(2).startPos);
+ assertEquals(9, kr.match(2).endPos);
+ }
+
+ /** Skip to
+ * */
+ @Test
+ public void testCase5() throws IOException{
+ ki = new KorapIndex();
+ ki.addDoc(createFieldDoc0());
+ ki.addDoc(createFieldDoc1());
+ ki.addDoc(createFieldDoc0());
+ ki.addDoc(createFieldDoc2());
+ ki.commit();
+
+ SpanQuery sq = createQuery("s","s:c","s:d",1,1,false,true);
+ kr = ki.search(sq, (short) 10);
+ assertEquals(3, kr.totalResults());
+ assertEquals(3, kr.match(2).getLocalDocID());
+ assertEquals(3, kr.match(2).startPos);
+ assertEquals(4, kr.match(2).endPos);
+
+ sq = new SpanNextQuery(
+ createQuery("s","s:c","s:d",1,1,false,true),
+ new SpanTermQuery(new Term("base", "s:a")));
+
+ kr = ki.search(sq, (short) 10);
+ assertEquals(1, kr.totalResults());
+ assertEquals(3, kr.match(0).getLocalDocID());
+ assertEquals(3, kr.match(0).startPos);
+ assertEquals(5, kr.match(0).endPos);
+ }
+}
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestMultipleDistanceIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestMultipleDistanceIndex.java
index c21ebb1..2136f9c 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestMultipleDistanceIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestMultipleDistanceIndex.java
@@ -82,7 +82,8 @@
"[(2-3)s:e|_3#2-3|<>:s#2-3$<i>4]" +
"[(3-4)s:b|s:c|_4#3-4]" +
"[(4-5)s:e|_5#4-5|<>:s#4-6$<i>6|<>:p#4-6$<i>6]" +
- "[(5-6)s:d|_6#5-6]");
+ "[(5-6)s:d|_6#5-6]" +
+ "[(6-7)s:b|_7#6-7|<>:s#6-7$<i>7|<>:p#6-7$<i>7]" );
return fd;
}
@@ -193,7 +194,7 @@
mdq = createQuery("s:b", "s:e", constraints, false);
kr = ki.search(mdq, (short) 10);
- assertEquals(4, kr.getTotalResults());
+ assertEquals(5, kr.getTotalResults());
assertEquals(3, kr.getMatch(0).getStartPos());
assertEquals(6, kr.getMatch(0).getEndPos());
assertEquals(2, kr.getMatch(1).getLocalDocID());
@@ -201,6 +202,17 @@
assertEquals(4, kr.getMatch(2).getEndPos());
assertEquals(3, kr.getMatch(3).getStartPos());
assertEquals(5, kr.getMatch(3).getEndPos());
+ assertEquals(4, kr.getMatch(4).getStartPos());
+ assertEquals(7, kr.getMatch(4).getEndPos());
+
+// System.out.print(kr.getTotalResults()+"\n");
+// for (int i=0; i< kr.getTotalResults(); i++){
+// System.out.println(
+// kr.match(i).getLocalDocID()+" "+
+// kr.match(i).startPos + " " +
+// kr.match(i).endPos
+// );
+// }
}
@@ -310,16 +322,23 @@
/** Exclusion, multiple documents
* wait for element distance exclusion
* */
-/* @Test
+ @Test
public void testCase7() throws IOException {
- ki = new KorapIndex();
- //ki.addDoc(createFieldDoc3());
- ki.addDoc(createFieldDoc0());
+ ki = new KorapIndex();
ki.addDoc(createFieldDoc2());
ki.commit();
+ SpanQuery sx = new SpanTermQuery(new Term("base","s:b"));
+ SpanQuery sy = new SpanTermQuery(new Term("base","s:c"));
+ // Second constraint
+ SpanDistanceQuery sq = new SpanDistanceQuery(new SpanElementQuery("base", "s"), sx,
+ sy, 0, 0, false, true);
+ sq.setExclusion(true);
+ kr = ki.search(sq, (short) 10);
+ // 0-1, 1-2, 6-7
+
List<DistanceConstraint> constraints = new ArrayList<DistanceConstraint>();
- constraints.add(new DistanceConstraint(0, 1,true));
+ constraints.add(new DistanceConstraint(0, 2,true));
constraints.add(new DistanceConstraint(new SpanElementQuery("base", "s"),
0, 0,true));
@@ -327,14 +346,27 @@
mdq = createQuery("s:b", "s:c", constraints, false);
kr = ki.search(mdq, (short) 10);
- System.out.print(kr.getTotalResults()+"\n");
- for (int i=0; i< kr.getTotalResults(); i++){
- System.out.println(
- kr.match(i).getLocalDocID()+" "+
- kr.match(i).startPos + " " +
- kr.match(i).endPos
- );
- }
- }*/
+ assertEquals(2, kr.getTotalResults());
+ assertEquals(0, kr.getMatch(0).getStartPos());
+ assertEquals(1, kr.getMatch(0).getEndPos());
+ assertEquals(6, kr.getMatch(1).getStartPos());
+ assertEquals(7, kr.getMatch(1).getEndPos());
+
+ // Third constraint
+ sq = new SpanDistanceQuery(new SpanElementQuery("base", "p"), sx,
+ sy, 0, 0, false, true);
+ sq.setExclusion(true);
+ // 6-7
+
+ constraints.add(new DistanceConstraint(new SpanElementQuery("base", "p"),
+ 0, 0,true));
+ mdq = createQuery("s:b", "s:c", constraints, false);
+ kr = ki.search(mdq, (short) 10);
+
+ assertEquals(1, kr.getTotalResults());
+ assertEquals(6, kr.getMatch(0).getStartPos());
+ assertEquals(7, kr.getMatch(0).getEndPos());
+
+ }
}