You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2011/03/22 13:58:28 UTC

svn commit: r1084154 - in /jackrabbit/sandbox/jackrabbit-j3/src: main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java main/java/org/apache/jackrabbit/j3/mc/Val.java test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java

Author: thomasm
Date: Tue Mar 22 12:58:27 2011
New Revision: 1084154

URL: http://svn.apache.org/viewvc?rev=1084154&view=rev
Log:
Json/Jsop Tokenizer

Modified:
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java
    jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java?rev=1084154&r1=1084153&r2=1084154&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/json/JsopTokenizer.java Tue Mar 22 12:58:27 2011
@@ -24,16 +24,23 @@ public class JsopTokenizer {
     // "- " is "patch remove", without space is a negative number
     // please note .0 and -.1 are not valid numbers
 
-    final static int END = 0;
-    final static int STRING = 1, NUMBER = 2, TRUE = 3, FALSE = 4, NULL = 5, ERROR = 6;
+    final static int STRING = 0, NUMBER = 1, TRUE = 2, FALSE = 3, NULL = 4;
+    final static int ERROR = 5, END = 6;
+
+    private static final String[] TYPE = {
+        "string", "number", "true", "false", "null", "error", "end"
+    };
 
     private final String jsop;
     private int pos;
-    private int tokenType;
+    private int currentType;
     private String currentToken;
+    private int lastType;
+    private String lastToken;
 
     public JsopTokenizer(String json) {
         this.jsop = json;
+        read();
     }
 
     public String toString() {
@@ -46,7 +53,7 @@ public class JsopTokenizer {
      * @return the token type
      */
     public int getTokenType() {
-        return tokenType;
+        return lastType;
     }
 
     /**
@@ -57,7 +64,35 @@ public class JsopTokenizer {
      * @return the token
      */
     public String getToken() {
-        return currentToken;
+        return lastToken;
+    }
+
+    /**
+     * Read a token which must match a given token type.
+     *
+     * @param type the token type
+     * @throws IllegalStateException if the token type doesn't match
+     */
+    public String read(int type) {
+        String token = currentToken;
+        if (matches(type)) {
+            return token;
+        }
+        throw getFormatException(jsop, pos, getTokenType(type));
+    }
+
+    /**
+     * Read a token which must match a given token type.
+     *
+     * @param type the token type
+     * @throws IllegalStateException if the token type doesn't match
+     */
+    public boolean matches(int type) {
+        if (currentType == type) {
+            read();
+            return true;
+        }
+        return false;
     }
 
     /**
@@ -66,19 +101,25 @@ public class JsopTokenizer {
      * @return the token type
      */
     public int read() {
+        lastType = currentType;
+        lastToken = currentToken;
         try {
-            return readToken();
+            currentType = readToken();
+        } catch (IllegalArgumentException e) {
+            currentType = ERROR;
+            currentToken = e.getMessage();
         } catch (StringIndexOutOfBoundsException e) {
-            tokenType = ERROR;
-            throw getFormatException(jsop, pos);
+            currentType = ERROR;
+            currentToken = addAsterisk(jsop, pos);
         }
+        return lastType;
     }
 
     private int readToken() {
         char ch;
         while (true) {
             if (pos >= jsop.length()) {
-                return tokenType = END;
+                return END;
             }
             ch = jsop.charAt(pos);
             if (ch > ' ') {
@@ -101,12 +142,11 @@ public class JsopTokenizer {
             }
             String s = jsop.substring(start + 1, pos - 1);
             if (escaped) {
-                currentToken = jsonDecode(s);
+                currentToken = decode(s);
             } else {
                 currentToken = s;
             }
-            tokenType = STRING;
-            break;
+            return STRING;
         }
         case '{':
         case '}':
@@ -115,19 +155,16 @@ public class JsopTokenizer {
         case '+':
         case ':':
         case ',':
-            tokenType = ch;
-            break;
+            return ch;
         case '-':
             ch = jsop.charAt(pos);
             if (ch < '0' || ch > '9') {
                 // lookahead
-                tokenType = '-';
-                break;
+                return '-';
             }
             // else fall though
         default:
             if (ch >= '0' && ch <= '9') {
-                tokenType = NUMBER;
                 while (pos < jsop.length()) {
                     ch = jsop.charAt(pos);
                     if (ch < '0' || ch > '9') {
@@ -159,6 +196,7 @@ public class JsopTokenizer {
                     }
                 }
                 currentToken = jsop.substring(start, pos);
+                return NUMBER;
             } else if (ch >= 'a' && ch <= 'z') {
                 while (pos < jsop.length()) {
                     ch = jsop.charAt(pos);
@@ -169,22 +207,19 @@ public class JsopTokenizer {
                 }
                 String s = jsop.substring(start, pos);
                 if ("null".equals(s)) {
-                    tokenType = NULL;
+                    return NULL;
                 } else if ("true".equals(s)) {
-                    tokenType = TRUE;
+                    return TRUE;
                 } else if ("false".equals(s)) {
-                    tokenType = FALSE;
+                    return FALSE;
                 } else {
-                    tokenType = ERROR;
+                    // currentToken = s;
+                    // return STRING;
                     throw getFormatException(jsop, pos);
                 }
-                break;
-            } else {
-                tokenType = ERROR;
-                throw getFormatException(jsop, pos);
             }
+            throw getFormatException(jsop, pos);
         }
-        return tokenType;
     }
 
     /**
@@ -193,7 +228,7 @@ public class JsopTokenizer {
      * @param s the encoded string
      * @return the string
      */
-    public static String jsonDecode(String s) {
+    public static String decode(String s) {
         int length = s.length();
         StringBuilder buff = new StringBuilder(length);
         for (int i = 0; i < length; i++) {
@@ -257,7 +292,7 @@ public class JsopTokenizer {
      * @param s the text to convert
      * @return the Json representation (including double quotes)
      */
-    public static String jsonEncode(String s) {
+    public static String encode(String s) {
         int length = s.length();
         StringBuilder buff = new StringBuilder(length + 2);
         buff.append('\"');
@@ -307,6 +342,14 @@ public class JsopTokenizer {
         return buff.toString();
     }
 
+    private static String getTokenType(int type) {
+        return type <= END ? TYPE[type] : "'" + (char) type + "'";
+    }
+
+    private static IllegalArgumentException getFormatException(String s, int i, String expected) {
+        return new IllegalArgumentException(addAsterisk(s, i) + " expected: " + expected);
+    }
+
     private static IllegalArgumentException getFormatException(String s, int i) {
         return new IllegalArgumentException(addAsterisk(s, i));
     }
@@ -320,7 +363,8 @@ public class JsopTokenizer {
      * @return the text with asterisk
      */
     private static String addAsterisk(String s, int index) {
-        if (s != null && index < s.length()) {
+        if (s != null) {
+            index = Math.min(index, s.length());
             s = s.substring(0, index) + "[*]" + s.substring(index);
         }
         return s;

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java?rev=1084154&r1=1084153&r2=1084154&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java Tue Mar 22 12:58:27 2011
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.j3.mc;
 import java.util.Arrays;
 import java.util.HashMap;
 import javax.jcr.PropertyType;
+import org.apache.jackrabbit.j3.json.JsopTokenizer;
 import org.apache.jackrabbit.j3.util.Constants;
 import org.apache.jackrabbit.j3.util.ExceptionFactory;
 
@@ -303,10 +304,18 @@ public class Val implements Comparable<V
             return buff.append(" ]").toString();
         }
         case TYPE_BINARY_REFERENCE: {
-            return "binaryRef:" + value;
+            return "/* binaryRef */ \"" + value + "\"";
         }
+        case PropertyType.BOOLEAN:
+        case PropertyType.LONG:
+            return value.toString();
+        case PropertyType.DECIMAL:
+        case PropertyType.DOUBLE:
+            return "/* " + PropertyType.nameFromValue(type) + " */ " + value.toString();
+        case PropertyType.STRING:
+            return JsopTokenizer.encode(value.toString());
         default:
-            return value + ":" + PropertyType.nameFromValue(type);
+            return "/* " + PropertyType.nameFromValue(type) + " */ " + JsopTokenizer.encode(value.toString());
         }
     }
 

Modified: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java?rev=1084154&r1=1084153&r2=1084154&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/json/TestTokenizer.java Tue Mar 22 12:58:27 2011
@@ -25,31 +25,32 @@ public class TestTokenizer extends TestC
 
     public void test() {
         try {
-            JsopTokenizer.jsonDecode("test\\");
+            JsopTokenizer.decode("test\\");
             fail();
         } catch (IllegalArgumentException e) {
             // ok
         }
         try {
-            JsopTokenizer.jsonDecode("wrong\\uxxxx");
+            JsopTokenizer.decode("wrong\\uxxxx");
             fail();
         } catch (IllegalArgumentException e) {
             // ok
         }
         try {
-            JsopTokenizer.jsonDecode("wrong\\m");
+            JsopTokenizer.decode("wrong\\m");
             fail();
         } catch (IllegalArgumentException e) {
             // ok
         }
-        test("/* error */", "\"\\");
-        test("/* error */1", ".1");
+        test("/error/", "\"\\");
+        test("/error/1", ".1");
         assertEquals("x", new JsopTokenizer("x").toString());
-        test("/* error */", "true" + "true");
-        test("/* error */", "truer");
-        test("/* error */", "falsehood");
-        test("/* error */", "nil");
-        test("/* error */", "\"invalid");
+        test("/error/", "true" + "true");
+        test("/error/", "truer");
+        test("/error/", "falsehood");
+        test("/error/", "nil");
+        test("/error/1", "nil 1");
+        test("/error/", "\"invalid");
         test("- \"test/test\"", "-\"test\\/test\"");
         test(" {\n\"x\": 1, \"y\": 2\n}\n", "{\"x\":1, \"y\":2}");
         test(" [\ntrue, false, null\n]\n", "[true, false, null]");
@@ -59,6 +60,25 @@ public class TestTokenizer extends TestC
         test("\"Hello\"", "\"Hello\"");
         test(" [\n\n]\n", "[]");
         test(" {\n\n}\n", "{}");
+
+        JsopTokenizer t = new JsopTokenizer("{}123");
+        assertFalse(t.matches('+'));
+        assertTrue(t.matches('{'));
+        t.read('}');
+
+        try {
+            t.read('+');
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals("{}123[*] expected: '+'", e.getMessage());
+        }
+        try {
+            t.read(JsopTokenizer.STRING);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals("{}123[*] expected: string", e.getMessage());
+        }
+
     }
 
     static void test(String expected, String json) {
@@ -70,30 +90,20 @@ public class TestTokenizer extends TestC
         StringBuilder buff = new StringBuilder();
         JsopTokenizer t = new JsopTokenizer(jsop);
         while (true) {
-            try {
-                prettyPrint(buff, t);
-            } catch (IllegalArgumentException e) {
-                buff.append("/* error */");
-            }
+            prettyPrint(buff, t);
             if (t.getTokenType() == JsopTokenizer.END) {
                 return buff.toString();
             }
         }
     }
 
-    static String prettyPrint(String jsop) {
-        StringBuilder buff = new StringBuilder();
-        JsopTokenizer t = new JsopTokenizer(jsop);
-        return prettyPrint(buff, t);
-    }
-
     static String prettyPrint(StringBuilder buff, JsopTokenizer t) {
         while (true) {
             switch (t.read()) {
             case JsopTokenizer.END:
                 return buff.toString();
             case JsopTokenizer.STRING:
-                buff.append(JsopTokenizer.jsonEncode(t.getToken()));
+                buff.append(JsopTokenizer.encode(t.getToken()));
                 break;
             case JsopTokenizer.NUMBER:
                 buff.append(t.getToken());
@@ -107,6 +117,9 @@ public class TestTokenizer extends TestC
             case JsopTokenizer.NULL:
                 buff.append("null");
                 break;
+            case JsopTokenizer.ERROR:
+                buff.append("/error/");
+                break;
             case '{':
                 buff.append(" {\n");
                 break;
@@ -135,7 +148,7 @@ public class TestTokenizer extends TestC
                 buff.append("^ ");
                 break;
             default:
-                throw new IllegalArgumentException("token type: " + t.getTokenType());
+                throw new AssertionError("token type: " + t.getTokenType());
             }
         }
     }