Change order of attribute payloads in attribute queries

Change-Id: Ifae409a53d93b9ce17b663d4ebe9d2b7d80c3e0c
diff --git a/Changes b/Changes
index cdf8c49..5407915 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,10 @@
-0.59.2 2020-06-17
+0.59.2 2020-06-18
     - [feature] Add fingerprint method to index (diewald)
     - [bugfix] Fix deserialization of spans with attributes (diewald)
+    - [bugfix] Change order of attribute payloads in attribute queries
+      (diewald)
+      Warning: This may break compatibility for attribute queries
+               in indices not created using KorAP::XML::Krill.
 
 0.59.1 2020-04-08
     - [bugfix] Fix bug in classed group queries (diewald)
diff --git a/misc/payloads.md b/misc/payloads.md
index 1839543..234a97b 100644
--- a/misc/payloads.md
+++ b/misc/payloads.md
@@ -194,7 +194,7 @@
 
 For example:
 
-    @:class=header$<b>17<i>6<s>1
+    @:dereko/s:mode:direct$<b>17<s>1<i>6
 
 means the attribute belongs to the span in the
 same token position whose TUI is 1 and end position is 6.
diff --git a/src/main/java/de/ids_mannheim/korap/KrillQuery.java b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
index 8853064..0bcde58 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
@@ -319,11 +319,19 @@
 
                 // Term has attribute
                 if (json.has("attr")) {
+
+                    JsonNode wrap = json.get("wrap");
                     JsonNode attrNode = json.get("attr");
+                    if (wrap.has("foundry")) {
+                        ((ObjectNode)attrNode).put("foundry", wrap.get("foundry"));
+                    };
+                    if (wrap.has("layer")) {
+                        ((ObjectNode)attrNode).put("layer", wrap.get("layer"));
+                    };
                     ((ObjectNode)json.get("wrap")).put("attr",attrNode);
                 };
                 
-                // Get wrapped token
+// Get wrapped token
                 return this._segFromJson(json.get("wrap"));
 
             case "koral:span":                
@@ -340,7 +348,15 @@
 
                 // Term has attribute
                 if (json.has("attr")) {
+
+                    JsonNode wrap = json.get("wrap");
                     JsonNode attrNode = json.get("attr");
+                    if (wrap.has("foundry")) {
+                        ((ObjectNode)attrNode).put("foundry", wrap.get("foundry"));
+                    };
+                    if (wrap.has("layer")) {
+                        ((ObjectNode)attrNode).put("layer", wrap.get("layer"));
+                    };
                     ((ObjectNode)json.get("wrap")).put("attr",attrNode);
                 };
                 
@@ -609,7 +625,7 @@
             }
             else{
                 relationTermWrapper =
-                        _termFromJson(relation.get("wrap"), false, direction);
+                    _termFromJson(relation.get("wrap"), false, false, direction);
                 spanRelationWrapper = new SpanRelationWrapper(relationTermWrapper, operand1, operand2);
             }
             
@@ -1121,16 +1137,22 @@
 
     private SpanQueryWrapper _termFromJson (JsonNode json)
             throws QueryException {
-        return this._termFromJson(json, false, null);
+        return this._termFromJson(json, false, false, null);
     }
     private SpanQueryWrapper _termFromJson (JsonNode json, boolean isSpan)
             throws QueryException {
-        return this._termFromJson(json, isSpan, null);
+        return this._termFromJson(json, isSpan, false, null);
     }
 
+    // Attribute term
+    private SpanQueryWrapper _termFromJson (JsonNode json, boolean isSpan, boolean isAttr)
+            throws QueryException {
+        return this._termFromJson(json, isSpan, true, null);
+    }
+    
     // Deserialize koral:term
     // TODO: Not optimal as it does not respect non-term
-    private SpanQueryWrapper _termFromJson (JsonNode json, boolean isSpan, RelationDirection direction)
+    private SpanQueryWrapper _termFromJson (JsonNode json, boolean isSpan, boolean isAttr, RelationDirection direction)
             throws QueryException {
 
         if (!json.has("@type")) {
@@ -1204,7 +1226,9 @@
 
         if (direction != null)
             value.append(direction.value());
-            
+        else if (isAttr)
+            value.append("@:");
+        
         if (json.has("foundry") &&
             json.get("foundry").asText().length() > 0) {
             value.append(json.get("foundry").asText()).append('/');
@@ -1467,7 +1491,7 @@
         if ("relation:and".equals(relation)) {
             List<SpanQueryWrapper> wrapperList = new ArrayList<SpanQueryWrapper>();
             for (JsonNode operand : operands) {
-                attrWrapper = _termFromJson(operand);
+                attrWrapper = _termFromJson(operand, false, true);
                 if (attrWrapper == null) {
                     throw new QueryException(747, "Attribute is null");
                 }
@@ -1486,7 +1510,7 @@
             SpanAlterQueryWrapper saq = new SpanAlterQueryWrapper(field);
             SpanWithAttributeQueryWrapper saqw;
             for (JsonNode operand : operands) {
-                attrWrapper = _termFromJson(operand);
+                attrWrapper = _termFromJson(operand, false, true);
                 if (attrWrapper == null) {
                     throw new QueryException(747, "Attribute is null");
                 }
@@ -1512,7 +1536,7 @@
             throws QueryException {
 
         if (attrNode.has("key")) {
-            return _termFromJson(attrNode);
+            return _termFromJson(attrNode, false, true);
         }
         else if (attrNode.has("tokenarity") || attrNode.has("arity")) {
             this.addWarning(770, "Arity attributes are currently not supported"
diff --git a/src/main/java/de/ids_mannheim/korap/index/TermInfo.java b/src/main/java/de/ids_mannheim/korap/index/TermInfo.java
index 60b177d..efb5535 100644
--- a/src/main/java/de/ids_mannheim/korap/index/TermInfo.java
+++ b/src/main/java/de/ids_mannheim/korap/index/TermInfo.java
@@ -94,7 +94,7 @@
                 // pos
                 this.type = "attr";
                 ttype = 4;
-                tterm = tterm.substring(1);
+                tterm = tterm.substring(2);
                 break;
 
             default:
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
index 5ee5e75..0e96652 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
@@ -164,8 +164,10 @@
         ByteBuffer payloadBuffer = ByteBuffer.wrap(payload.get(0));
 
         byte payloadTypeIdentifier = payloadBuffer.get(0);
-        short spanId = payloadBuffer.getShort(5);
-        int end = payloadBuffer.getInt(1);
+        // short spanId = payloadBuffer.getShort(5);
+        // int end = payloadBuffer.getInt(1);
+        short spanId = payloadBuffer.getShort(1);
+        int end = payloadBuffer.getInt(3);
 
         return new CandidateAttributeSpan(firstSpans, payloadTypeIdentifier,
                 spanId, end);
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestAttributeIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestAttributeIndex.java
index 3fc9ea5..b69bc75 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestAttributeIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestAttributeIndex.java
@@ -2,6 +2,8 @@
 
 import static org.junit.Assert.assertEquals;
 
+import static de.ids_mannheim.korap.TestSimple.*;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -11,13 +13,17 @@
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.junit.Test;
 
+import de.ids_mannheim.korap.Krill;
 import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.query.SpanAttributeQuery;
 import de.ids_mannheim.korap.query.SpanElementQuery;
 import de.ids_mannheim.korap.query.SpanNextQuery;
 import de.ids_mannheim.korap.query.SpanWithAttributeQuery;
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 import de.ids_mannheim.korap.response.Result;
 
+import de.ids_mannheim.korap.util.QueryException;
+
 public class TestAttributeIndex {
 
     private KrillIndex ki = new KrillIndex();
@@ -37,28 +43,28 @@
                 + "<>:s$<b>64<i>0<i>5<i>5<b>0<s>3|"
                 + "<>:div$<b>64<i>0<i>2<i>2<b>0<s>2|"
                 + "<>:div$<b>64<i>0<i>3<i>3<b>0<s>1|"
-                + "@:class=header$<b>17<i>3<s>1|@:class=header$<b>17<i>2<s>2]"
+                + "@:class=header$<b>17<s>1<i>3|@:class=header$<b>17<s>2<i>2]"
 
                 + "[(1-2)s:e|_2$<i>1<i>2|"
-                + "<>:a$<b>64<i>1<i>2<i>2<b>0<s>1|@:class=header$<b>17<i>2<s>1]"
+                + "<>:a$<b>64<i>1<i>2<i>2<b>0<s>1|@:class=header$<b>17<s>1<i>2]"
 
                 + "[(2-3)s:e|_3$<i>2<i>3|"
-                + "<>:div$<b>64<i>2<i>5<i>5<b>0<s>1|@:class=time$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>2<i>5<i>5<b>0<s>1|@:class=time$<b>17<s>1<i>5]"
 
                 + "[(3-4)s:a|_4$<i>3<i>4|"
-                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=header$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=header$<b>17<s>1<i>5]"
 
                 + "[(4-5)s:b|_5$<i>4<i>5|" + "<>:a$<b>64<i>4<i>5<i>5<b>0<s>2|"
                 + "<>:div$<b>64<i>4<i>5<i>5<b>0<s>1|"
-                + "@:class=header$<b>17<i>5<s>2]"
+                + "@:class=header$<b>17<s>2<i>5]"
 
                 + "[(5-6)s:d|_6$<i>5<i>6|" + "<>:div$<b>64<i>5<i>6<i>6<b>0<s>2|"
                 + "<>:s$<b>64<i>5<i>6<i>6<b>0<s>1|"
-                + "@:class=header$<b>17<i>6<s>1]"
+                + "@:class=header$<b>17<s>1<i>6]"
 
                 + "[(6-7)s:d|_7$<i>6<i>7|" + "<>:s$<b>64<i>6<i>7<i>7<b>0<s>2|"
                 + "<>:div$<b>64<i>6<i>7<i>7<b>0<s>1"
-                + "|@:class=header$<b>17<i>7<s>1|@:class=header$<b>17<i>7<s>2]");
+                + "|@:class=header$<b>17<s>1<i>7|@:class=header$<b>17<s>2<i>7]");
 
         return fd;
     }
@@ -70,26 +76,26 @@
         fd.addTV("base", "bcbabd", "[(0-1)s:b|_1$<i>0<i>1|"
                 + "<>:s<b>64<i>0<i>5<i>5<b>0<s>2|"
                 + "<>:div$<b>64<i>0<i>3<i>3<b>0<s>1|"
-                + "@:class=header$<b>17<i>3<s>1|@:class=title$<b>17<i>3<s>1|@:class=book$<b>17<i>3<s>1]"
+                + "@:class=header$<b>17<s>1<i>3|@:class=title$<b>17<s>1<i>3|@:class=book$<b>17<s>1<i>3]"
 
                 + "[(1-2)s:c|_2$<i>1<i>2|" + "<>:div$<b>64<i>1<i>2<i>2<b>0<s>1|"
-                + "@:class=header$<b>17<i>2<s>1|@:class=title$<b>17<i>2<s>1]"
+                + "@:class=header$<b>17<s>1<i>2|@:class=title$<b>17<s>1<i>2]"
 
                 + "[(2-3)s:b|_3$<i>2<i>3|"
-                + "<>:div$<b>64<i>2<i>5<i>5<b>0<s>1|@:class=book$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>2<i>5<i>5<b>0<s>1|@:class=book$<b>17<s>1<i>5]"
 
                 + "[(3-4)s:a|_4$<i>3<i>4|"
-                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=title$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=title$<b>17<s>1<i>5]"
 
                 + "[(4-5)s:b|_5$<i>4<i>5|" + "<>:div$<b>64<i>4<i>5<i>5<b>0<s>1|"
-                + "@:class=header$<b>17<i>5<s>1|@:class=book$<b>17<i>5<s>1|@:class=title$<b>17<i>5<s>1]"
+                + "@:class=header$<b>17<s>1<i>5|@:class=book$<b>17<s>1<i>5|@:class=title$<b>17<s>1<i>5]"
 
                 + "[(5-6)s:d|_6$<i>5<i>6|" + "<>:s$<b>64<i>5<i>6<i>6<b>0<s>2|"
-                + "<>:div$<b>64<i>5<i>6<i>6<b>0<s>1|@:class=header$<b>17<i>6<s>1]"
+                + "<>:div$<b>64<i>5<i>6<i>6<b>0<s>1|@:class=header$<b>17<s>1<i>6]"
 
                 + "[(6-7)s:d|_7$<i>6<i>7|" + "<>:s$<b>64<i>6<i>7<i>7<b>0<s>2|"
                 + "<>:div$<b>64<i>6<i>7<i>7<b>0<s>1|"
-                + "@:class=header$<b>17<i>7<s>1|@:class=title$<b>17<i>7<s>1]");
+                + "@:class=header$<b>17<s>1<i>7|@:class=title$<b>17<s>1<i>7]");
 
         return fd;
     }
@@ -101,28 +107,28 @@
         fd.addTV("base", "bcbabd", "[(0-1)s:b|_1$<i>0<i>1|"
                 + "<>:div$<b>64<i>0<i>3<i>3<b>0<s>2|"
                 + "<>:s$<b>64<i>0<i>5<i>5<b>0<s>1|"
-                + "@:class=header$<b>17<i>3<s>2|@:class=book$<b>17<i>5<s>1|@:class=book$<b>17<i>3<s>2]"
+                + "@:class=header$<b>17<s>2<i>3|@:class=book$<b>17<s>1<i>5|@:class=book$<b>17<s>2<i>3]"
 
                 + "[(1-2)s:e|_2$<i>1<i>2|" + "<>:a$<b>64<i>1<i>2<i>2<b>0<s>2|"
                 + "<>:div$<b>64<i>1<i>2<i>2<b>0<s>1|"
-                + "@:class=book$<b>17<i>2<s>2|@:class=header$<b>17<i>2<s>1]"
+                + "@:class=book$<b>17<s>2<i>2|@:class=header$<b>17<s>1<i>2]"
 
                 + "[(2-3)s:b|_3$<i>2<i>3|" + "<>:a$<b>64<i>1<i>2<i>2<b>0<s>2|"
                 + "<>:div$<b>64<i>2<i>3<i>5<b>0<s>1|"
-                + "@:class=header$<b>17<i>2<s>2|@:class=book$<b>17<i>5<s>1]"
+                + "@:class=header$<b>17<s>2<i>2|@:class=book$<b>17<s>1<i>5]"
 
                 + "[(3-4)s:a|_4$<i>3<i>4|"
-                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=title$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>3<i>5<i>5<b>0<s>1|@:class=title$<b>17<s>1<i>5]"
 
                 + "[(4-5)s:b|_5$<i>4<i>5|"
-                + "<>:div$<b>64<i>4<i>5<i>5<b>0<s>1|@:class=header$<b>17<i>5<s>1|@:class=book$<b>17<i>5<s>1]"
+                + "<>:div$<b>64<i>4<i>5<i>5<b>0<s>1|@:class=header$<b>17<s>1<i>5|@:class=book$<b>17<s>1<i>5]"
 
                 + "[(5-6)s:d|_6$<i>5<i>6|" + "<>:s$<b>64<i>5<i>6<i>6<b>0<s>1|"
-                + "<>:div$<b>64<i>5<i>6<i>6<b>0<s>1|@:class=header$<b>17<i>6<s>1]"
+                + "<>:div$<b>64<i>5<i>6<i>6<b>0<s>1|@:class=header$<b>17<s>1<i>6]"
 
                 + "[(6-7)s:d|_7$<i>6<i>7|" + "<>:s$<b>64<i>6<i>7<i>7<b>0<s>2|"
                 + "<>:div$<b>64<i>6<i>7<i>7<b>0<s>1|"
-                + "@:class=header$<b>17<i>7<s>1|@:class=book$<b>17<i>7<s>2]");
+                + "@:class=header$<b>17<s>1<i>7|@:class=book$<b>17<s>2<i>7]");
 
         return fd;
     }
@@ -223,6 +229,11 @@
         sq = new SpanWithAttributeQuery(new SpanElementQuery("base", "div"),
                 sql, true);
 
+        assertEquals("spanElementWithAttribute(<base:div />, "+
+                     "[spanAttribute(base:@:class=header), "+
+                     "spanAttribute(!base:@:class=book), "+
+                     "spanAttribute(!base:@:class=title)])", sq.toString());
+        
         kr = ki.search(sq, (short) 10);
         assertEquals((long) 1, kr.getTotalResults());
         assertEquals(5, kr.getMatch(0).getStartPos());
@@ -452,4 +463,45 @@
         kr = ki.search(swaq, (short) 10);
     }
 
+
+    @Test
+    public void testAttributeRealIndex () throws QueryException, IOException {
+        // Construct index
+        KrillIndex ki = new KrillIndex();
+        // Indexing test files
+        ki.addDoc(getClass().getResourceAsStream("/others/REDEW-DOC1-00001.json.gz"),
+                    true);
+        ki.commit();
+
+        SpanTermQuery stq = new SpanTermQuery(new Term("tokens", "@:dereko/s:mode:direct"));
+        kr = ki.search(stq, (short) 10);
+        assertEquals((long) 4, kr.getTotalResults());
+        
+
+        SpanAttributeQuery saq = new SpanAttributeQuery(
+            new SpanTermQuery(new Term("tokens", "@:dereko/s:mode:direct")), true);
+
+        SpanElementQuery seq = new SpanElementQuery("tokens", "dereko/s:said");
+
+        // div with @class=header
+        SpanQuery sq = new SpanWithAttributeQuery(seq, saq, true);
+        assertEquals("spanElementWithAttribute(<tokens:dereko/s:said />, " +
+                     "spanAttribute(tokens:@:dereko/s:mode:direct))", sq.toString());
+
+        kr = ki.search(sq, (short) 10);
+        assertEquals((long) 4, kr.getTotalResults());
+
+
+        String filepath = getClass()
+                .getResource(
+                        "/queries/attribute/element-single-attribute-2.jsonld")
+                .getFile();
+
+        SpanQueryWrapper sqw = getJsonQuery(filepath);        
+        Krill krill = new Krill(sqw);
+        assertEquals("spanElementWithAttribute(<tokens:dereko/s:said />, " +
+                     "spanAttribute(tokens:@:dereko/s:mode:direct))", krill.getSpanQuery().toString());
+        Result kr = krill.apply(ki);
+        assertEquals(kr.getTotalResults(), 4);
+    }
 }
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
index 8f50f41..e232499 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
@@ -161,8 +161,8 @@
                         + "<:child-of$<b>35<i>0<i>38<i>0<i>3<i>7<i>0<i>1<s>2<s>3<s>0|"
                         + "<:child-of$<b>35<i>0<i>38<i>4<i>9<i>7<i>1<i>7<s>2<s>2<s>0|"
                         + "<:dep$<b>32<i>0<s>1<s>1<s>0|"
-                        + "@:func=sbj$<b>18<i>7<s>4|" // attribute belongs to a relation
-                        + "@:case=nominative$<b>18<i>1<s>3]" // attribute belongs to a relation node
+                        + "@:func=sbj$<b>18<s>4<i>7|" // attribute belongs to a relation
+                        + "@:case=nominative$<b>18<s>3<i>1]" // attribute belongs to a relation node
 
                         + "[(1-2)s:kaufe|_1$<i>4<i>9|pos:V$<s>1|<>:vp$<b>64<i>4<i>38<i>7<b>0<s>2|"
                         + ">:child-of$<b>35<i>4<i>38<i>0<i>38<i>7<i>0<i>7<s>2<s>2<s>0|"
@@ -185,16 +185,16 @@
                         + "<:child-of$<b>35<i>10<i>38<i>21<i>38<i>7<i>4<i>7<s>4<s>2<s>0|"
                         + ">:parent-of$<b>35<i>10<i>38<i>21<i>38<i>7<i>4<i>7<s>4<s>2<s>0|"
                         + "<:dep$<b>32<i>3<s>1<s>1<s>3|"
-                        + "@:func=head$<b>18<i>4<s>3|"
-                        + "@:case=accusative$<b>18<i>4<s>3|" // attribute belongs to a relation node
-                        + "@:case=accusative$<b>18<i>7<s>2]" // attribute belongs to a relation node
+                        + "@:func=head$<b>18<s>3<i>4|"
+                        + "@:case=accusative$<b>18<s>3<i>4|" // attribute belongs to a relation node
+                        + "@:case=accusative$<b>18<s>2<i>7]" // attribute belongs to a relation node
 
                         + "[(3-4)s:Blümen|_3$<i>14<i>20|pos:NN$<s>1|"
                         + ">:child-of$<b>33<i>10<i>24<i>2<i>4<s>1<s>3<s>0|"
                         + "<:dep$<b>32<i>1<s>1<s>1<s>0|"
                         + ">:dep$<b>32<i>2<s>1<s>1<s>2|"
                         + ">:dep$<b>32<i>4<s>1<s>1<s>0|"
-                        + "@:func=obj$<b>18<i>4<s>2]"
+                        + "@:func=obj$<b>18<s>2<i>4]"
 
                         + "[(4-5)s:für|_4$<i>21<i>24|pos:PREP$<s>1|<>:pp$<b>64<i>21<i>38<i>7<b>0<s>2|"
                         + ">:child-of$<b>33<i>21<i>38<i>4<i>7<s>1<s>2<s>0|"
@@ -212,8 +212,8 @@
                         + "<:child-of$<b>34<i>25<i>38<i>7<i>5<s>2<s>1<s>0|"
                         + "<:child-of$<b>34<i>25<i>38<i>7<i>6<s>2<s>1<s>0|"
                         + "<:dep$<b>32<i>6<s>1<s>1<s>3<s>0|"
-                        + "@:func=head$<b>18<i>7<s>3|"
-                        + "@:case=accusative$<b>18<i>7<s>2]" // attribute belongs to a relation node
+                        + "@:func=head$<b>18<s>3<i>7|"
+                        + "@:case=accusative$<b>18<s>2<i>7]" // attribute belongs to a relation node
 
                         + "[(6-7)s:Mutter.|_6$<i>31<i>38|pos:NN$<s>1|"
                         + ">:child-of$<b>33<i>25<i>38<i>5<i>7<s>1<s>2<s>0|"
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestTermInfo.java b/src/test/java/de/ids_mannheim/korap/index/TestTermInfo.java
index 1458000..a0080ab 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestTermInfo.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestTermInfo.java
@@ -124,5 +124,20 @@
         assertEquals("startChar", term.getStartChar(), 20);
         assertEquals("endChar", term.getEndChar(), 25);
         assertEquals("depth", term.getDepth(), 0);
+
+        bb.clear();
+        bb.put((byte) 17);   // att PTI
+        bb.putShort((short)1);
+        bb.putInt(25);
+        term = new TermInfo("@:dereko/s:mode:direct", 20, bb).analyze();
+        assertEquals("type", term.getType(), "attr");
+        assertEquals("value", term.getValue(), "mode:direct");
+        assertEquals("foundry", term.getFoundry(), "dereko");
+        assertEquals("layer", term.getLayer(), "s");
+        assertEquals("startPos", term.getStartPos(), 20);
+        assertEquals("endPos", term.getEndPos(), 20);
+        assertEquals("startChar", term.getStartChar(), -1);
+        assertEquals("endChar", term.getEndChar(), -1);
+        assertEquals("depth", term.getDepth(), 0);
     };
 };
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
index 3a55968..99b2e54 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
@@ -29,7 +29,7 @@
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "spanWithAttribute(spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
+                        + "spanWithAttribute(spanAttribute(tokens:@:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -47,7 +47,7 @@
                 // +
                 // "<tokens:c:vp />)), spanWithAttribute(spanAttribute(tokens:type:case:accusative))))",
                 //
-                "focus(#[1,2]spanSegment(spanWithAttribute(spanAttribute(tokens:type:case:accusative)), "
+                "focus(#[1,2]spanSegment(spanWithAttribute(spanAttribute(tokens:@:type:case:accusative)), "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "<tokens:c:vp />),sorting)),sorting)",
                 sq.toString());
@@ -70,7 +70,7 @@
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "spanElementWithAttribute(<tokens:c:np />, "
-                        + "spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
+                        + "spanAttribute(tokens:@:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -86,10 +86,10 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(#[1,2]spanSegment(spanElementWithAttribute(<tokens:c: />, "
-                        + "spanAttribute(tokens:type:case:accusative)), "
+                        + "spanAttribute(tokens:@:type:case:accusative)), "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "spanElementWithAttribute(<tokens:c: />, "
-                        + "spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
+                        + "spanAttribute(tokens:@:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -173,7 +173,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:type:top))),sorting)),sorting)",
+                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:@:type:top))),sorting)),sorting)",
                 sq.toString());
     }
 
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 23a1beb..481949d 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
@@ -25,7 +25,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:head />, spanAttribute(tokens:type:top))",
+                "spanElementWithAttribute(<tokens:head />, spanAttribute(tokens:@:type:top))",
                 sq.toString());
     }
 
@@ -38,7 +38,8 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:dereko/s:said />, spanAttribute(tokens:mode:indirects))",
+                "spanElementWithAttribute(<tokens:dereko/s:said />, " +
+                "spanAttribute(tokens:@:dereko/s:mode:direct))",
                 sq.toString());
     }
 
@@ -51,7 +52,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:head />, spanAttribute(!tokens:type:top))",
+                "spanElementWithAttribute(<tokens:head />, spanAttribute(!tokens:@:type:top))",
                 sq.toString());
     }
 
@@ -64,7 +65,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:head />, spanAttribute(!tokens:type:top))",
+                "spanElementWithAttribute(<tokens:head />, spanAttribute(!tokens:@:type:top))",
                 sq.toString());
     }
     
@@ -78,8 +79,8 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:div />, [spanAttribute(tokens:type:Zeitschrift), "
-                        + "spanAttribute(!tokens:complete:Y), spanAttribute(tokens:n:0)])",
+                "spanElementWithAttribute(<tokens:div />, [spanAttribute(tokens:@:type:Zeitschrift), "
+                        + "spanAttribute(!tokens:@:complete:Y), spanAttribute(tokens:@:n:0)])",
                 sq.toString());
     }
 
@@ -92,8 +93,8 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanElementWithAttribute(<tokens:div />, [spanAttribute(tokens:type:Zeitschrift), "
-                        + "spanAttribute(!tokens:complete:Y), spanAttribute(tokens:n:0)])",
+                "spanElementWithAttribute(<tokens:div />, [spanAttribute(tokens:@:type:Zeitschrift), "
+                        + "spanAttribute(!tokens:@:complete:Y), spanAttribute(tokens:@:n:0)])",
                 sq.toString());
     }
     
@@ -107,9 +108,9 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanOr([spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:type:Zeitschrift)), "
-                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:complete:Y)), "
-                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:n:0))])",
+                "spanOr([spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:type:Zeitschrift)), "
+                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:complete:Y)), "
+                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:n:0))])",
                 sq.toString());
     }
 
@@ -123,9 +124,9 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanOr([spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:type:Zeitschrift)), "
-                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:complete:Y)), "
-                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:n:0))])",
+                "spanOr([spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:type:Zeitschrift)), "
+                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:complete:Y)), "
+                        + "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:@:n:0))])",
                 sq.toString());
     }
     
@@ -138,7 +139,7 @@
                 .getFile();
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
-        assertEquals("spanWithAttribute(spanAttribute(tokens:type:top))",
+        assertEquals("spanWithAttribute(spanAttribute(tokens:@:type:top))",
                 sq.toString());
     }
 
@@ -152,9 +153,9 @@
         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))])",
+                "spanOr([spanWithAttribute(spanAttribute(tokens:@:type:Zeitschrift)), "
+                        + "spanWithAttribute(spanAttribute(tokens:@:complete:Y)), "
+                        + "spanWithAttribute(spanAttribute(tokens:@:n:0))])",
                 sq.toString());
     }
 
@@ -169,8 +170,8 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "spanWithAttribute([spanAttribute(tokens:type:Zeitschrift), "
-                        + "spanAttribute(!tokens:complete:Y), spanAttribute(tokens:n:0)])",
+                "spanWithAttribute([spanAttribute(tokens:@:type:Zeitschrift), "
+                        + "spanAttribute(!tokens:@:complete:Y), spanAttribute(tokens:@:n:0)])",
                 sq.toString());
     }
 
@@ -187,5 +188,4 @@
         SpanQuery sq = sqwi.toQuery();
         //        assertEquals("tokens:???", sq.toString());
     }
-
 }
diff --git a/src/test/resources/others/REDEW-DOC1-00001.json.gz b/src/test/resources/others/REDEW-DOC1-00001.json.gz
new file mode 100644
index 0000000..d551bfb
--- /dev/null
+++ b/src/test/resources/others/REDEW-DOC1-00001.json.gz
Binary files differ
diff --git a/src/test/resources/queries/attribute/element-single-attribute-2.jsonld b/src/test/resources/queries/attribute/element-single-attribute-2.jsonld
index 59d0c74..79d682a 100644
--- a/src/test/resources/queries/attribute/element-single-attribute-2.jsonld
+++ b/src/test/resources/queries/attribute/element-single-attribute-2.jsonld
@@ -10,7 +10,7 @@
       "@type": "koral:term",
       "key": "mode",
       "match": "match:eq",
-      "value": "indirects"
+      "value": "direct"
     },
     "wrap": {
       "@type": "koral:term",