You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2014/07/13 09:56:33 UTC

git commit: FLEECE-8 various enhancements from Hendrik Saly, thanks a lot.

Repository: incubator-fleece
Updated Branches:
  refs/heads/master badf44a23 -> d6c1bb8b2


FLEECE-8 various enhancements from Hendrik Saly, thanks a lot.


Project: http://git-wip-us.apache.org/repos/asf/incubator-fleece/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fleece/commit/d6c1bb8b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fleece/tree/d6c1bb8b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fleece/diff/d6c1bb8b

Branch: refs/heads/master
Commit: d6c1bb8b21c7da316b223be7e8979fa8d89af71b
Parents: badf44a
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Sun Jul 13 09:56:04 2014 +0200
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Sun Jul 13 09:56:04 2014 +0200

----------------------------------------------------------------------
 .travis.yml                                     |   6 +
 .../fleece/core/JsonBaseStreamParser.java       |  66 +++--
 .../apache/fleece/core/JsonGeneratorImpl.java   |   4 +-
 .../fleece/core/JsonParserFactoryImpl.java      |   4 +
 .../fleece/core/JsonReaderFactoryImpl.java      |   9 +-
 .../fleece/core/JsonGeneratorImplTest.java      |  55 +++-
 .../org/apache/fleece/core/JsonParserTest.java  | 227 +++++++++++++++
 .../apache/fleece/core/JsonReaderImplTest.java  | 280 +++++++++++++++----
 .../resources/bench/unicode_chars_1400kb.txt    | Bin 0 -> 1424384 bytes
 .../resources/bench/unicode_chars_170kb.json    | Bin 178048 -> 0 bytes
 .../resources/bench/unicode_chars_170kb.txt     | Bin 0 -> 178048 bytes
 .../resources/bench/unicode_chars_huge.json     | Bin 1424384 -> 0 bytes
 .../src/test/resources/bench/unicodes.json      | Bin 178048 -> 0 bytes
 .../src/test/resources/bench/unicodes_big.json  | Bin 1424384 -> 0 bytes
 .../src/test/resources/json/numbers.json        |  18 ++
 .../fleece/jaxrs/FleeceMessageBodyReader.java   |   2 +-
 .../java/org/apache/fleece/mapper/Mapper.java   |  37 ++-
 .../fleece/mapper/reflection/Mappings.java      |   6 +
 .../fleece/mapper/MapperEnhancedTests.java      | 235 ++++++++++++++++
 .../org/apache/fleece/mapper/MapperTest.java    |  11 +-
 pom.xml                                         |  35 +++
 src/site/site.xml                               |   2 +-
 22 files changed, 904 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6b929a1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,6 @@
+language: java
+
+jdk:
+  - openjdk6
+  - openjdk7
+  - oraclejdk7

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/main/java/org/apache/fleece/core/JsonBaseStreamParser.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonBaseStreamParser.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonBaseStreamParser.java
index bd29c33..abbdeaf 100644
--- a/fleece-core/src/main/java/org/apache/fleece/core/JsonBaseStreamParser.java
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonBaseStreamParser.java
@@ -52,6 +52,10 @@ public abstract class JsonBaseStreamParser implements JsonChars,
     private boolean constructingStringValue = false;
     private boolean withinArray = false;
     private boolean stringValueIsKey = false;
+    
+    private boolean isCurrentNumberIntegral = false;
+    private Integer currentIntegralNumber = null; //for number from 0 - 9
+    private BigDecimal currentBigDecimalNumber = null;
 
     private int openObjects = 0;
     private int openArrays = 0;
@@ -211,10 +215,18 @@ public abstract class JsonBaseStreamParser implements JsonChars,
 
     @Override
     public final Event next() {
+        
+        //fast fail
+        if(!hasNext()) {
+            throw new NoSuchElementException();
+        }
 
         int dosCount = 0;
         lastEvent = event;
         event = null;
+        isCurrentNumberIntegral = false;
+        currentBigDecimalNumber = null;
+        currentIntegralNumber = null;
 
         resetValue();
 
@@ -609,6 +621,7 @@ public abstract class JsonBaseStreamParser implements JsonChars,
 
                 boolean endExpected = false;
                 final boolean zeropassed = c == '0';
+                final boolean beginningMinusPassed = c == '-';
                 boolean dotpassed = false;
                 boolean epassed = false;
                 char last = c;
@@ -627,7 +640,20 @@ public abstract class JsonBaseStreamParser implements JsonChars,
                     if (n == COMMA || n == END_ARRAY_CHAR
                             || n == END_OBJECT_CHAR) {
                         resetToMark();
-
+                        
+                        isCurrentNumberIntegral=(!dotpassed && !epassed);
+                        
+                        if(isCurrentNumberIntegral && beginningMinusPassed && i==1 && last >= '0' && last <= '9')
+                        {
+                            currentIntegralNumber=-((int)last - 48); //optimize -0 till -99
+                        }
+                        
+                        if(isCurrentNumberIntegral && !beginningMinusPassed && i==0 && last >= '0' && last <= '9')
+                        {
+                            currentIntegralNumber=((int)last - 48); //optimize 0 till 9
+                        }
+                        
+                        
                         event = Event.VALUE_NUMBER;
                         break;
                     }
@@ -735,41 +761,49 @@ public abstract class JsonBaseStreamParser implements JsonChars,
 
         if (event != Event.VALUE_NUMBER) {
             throw new IllegalStateException(event
-                    + " doesn't supportisIntegralNumber()");
-        }
-
-        for (int i = 0; i < valueLength; i++) {
-            if (!isAsciiDigit(currentValue[i])) {
-                return false;
-            }
+                    + " doesn't support isIntegralNumber()");
         }
 
-        return true;
+        return isCurrentNumberIntegral;
     }
 
     @Override
     public int getInt() {
         if (event != Event.VALUE_NUMBER) {
-            throw new IllegalStateException(event + " doesn't supportgetInt()");
+            throw new IllegalStateException(event + " doesn't support getInt()");
         }
-        return Integer.parseInt(getValue());
+
+        if (isCurrentNumberIntegral && currentIntegralNumber != null) {
+            return currentIntegralNumber.intValue();
+        }
+
+        return getBigDecimal().intValue();
     }
 
     @Override
     public long getLong() {
         if (event != Event.VALUE_NUMBER) {
-            throw new IllegalStateException(event + " doesn't supporgetLong()");
+            throw new IllegalStateException(event + " doesn't support getLong()");
         }
-        return Long.parseLong(getValue());
+
+        if (isCurrentNumberIntegral && currentIntegralNumber != null) {
+            return currentIntegralNumber.intValue();
+        } // int is ok, its only from 0-9
+
+        return getBigDecimal().longValue();
     }
 
     @Override
     public BigDecimal getBigDecimal() {
         if (event != Event.VALUE_NUMBER) {
-            throw new IllegalStateException(event
-                    + " doesn't support getBigDecimal()");
+            throw new IllegalStateException(event + " doesn't support getBigDecimal()");
+        }
+
+        if (currentBigDecimalNumber != null) {
+            return currentBigDecimalNumber;
         }
-        return new BigDecimal(getValue());
+
+        return (currentBigDecimalNumber = new BigDecimal(getString()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java
index 02f46da..f36166f 100644
--- a/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java
@@ -1,5 +1,5 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
+esc * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership. The ASF licenses this file
@@ -200,7 +200,7 @@ public class JsonGeneratorImpl<P extends JsonGeneratorImpl<?>> implements JsonGe
     @Override
     public JsonGenerator write(final String value) {
         checkArray();
-        noCheckWriteAndForceComma(value);
+        noCheckWriteAndForceComma(QUOTE+Strings.escape(value)+QUOTE);
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java
index 8e7916b..6195d83 100644
--- a/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java
@@ -119,6 +119,10 @@ public class JsonParserFactoryImpl implements JsonParserFactory, Serializable {
     public EscapedStringAwareJsonParser createInternalParser(final InputStream in) {
         return getDefaultJsonParserImpl(in);
     }
+    
+    public EscapedStringAwareJsonParser createInternalParser(final InputStream in, final Charset charset) {
+        return getDefaultJsonParserImpl(in, charset);
+    }
 
     public EscapedStringAwareJsonParser createInternalParser(final Reader reader) {
         return getDefaultJsonParserImpl(reader);

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java
index 9fa2fa9..1d04f26 100644
--- a/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java
@@ -18,16 +18,17 @@
  */
 package org.apache.fleece.core;
 
-import javax.json.JsonReader;
-import javax.json.JsonReaderFactory;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.Serializable;
 import java.nio.charset.Charset;
 import java.util.Collections;
 import java.util.Map;
 
+import javax.json.JsonReader;
+import javax.json.JsonReaderFactory;
+
+@SuppressWarnings("unused")
 public class JsonReaderFactoryImpl implements JsonReaderFactory, Serializable {
     private final Map<String, ?> config;
     private final JsonParserFactoryImpl parserFactory;
@@ -49,7 +50,7 @@ public class JsonReaderFactoryImpl implements JsonReaderFactory, Serializable {
 
     @Override
     public JsonReader createReader(final InputStream in, final Charset charset) {
-        return createReader(new InputStreamReader(in, charset));
+        return new JsonReaderImpl(parserFactory.createInternalParser(in, charset));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/java/org/apache/fleece/core/JsonGeneratorImplTest.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/java/org/apache/fleece/core/JsonGeneratorImplTest.java b/fleece-core/src/test/java/org/apache/fleece/core/JsonGeneratorImplTest.java
index e66e62d..a6e750f 100644
--- a/fleece-core/src/test/java/org/apache/fleece/core/JsonGeneratorImplTest.java
+++ b/fleece-core/src/test/java/org/apache/fleece/core/JsonGeneratorImplTest.java
@@ -21,7 +21,9 @@ package org.apache.fleece.core;
 import org.junit.Test;
 
 import javax.json.Json;
+import javax.json.JsonValue;
 import javax.json.stream.JsonGenerator;
+
 import java.io.ByteArrayOutputStream;
 import java.util.HashMap;
 
@@ -54,15 +56,57 @@ public class JsonGeneratorImplTest {
         Json.createGenerator(baos).writeStartArray().write(1).write(2).writeEnd().close();
         assertEquals("[1,2]", new String(baos.toByteArray()));
     }
+    
+    @Test
+    public void stringArray() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().write("val1").write("val2").writeEnd().close();
+        assertEquals("[\"val1\",\"val2\"]", new String(baos.toByteArray()));
+    }
+    
+    @Test
+    public void stringArrayEscapes() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().write("\"val1\t\u0080").write("val2\\").writeEnd().close();
+        assertEquals("[\"\\\"val1\\t\\u0080\",\"val2\\\\\"]", new String(baos.toByteArray()));
+    }
+    
+    @Test
+    public void emptyStringArray() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().writeNull().write("").writeEnd().close();
+        assertEquals("[null,\"\"]", new String(baos.toByteArray()));
+    }
+    
+    @Test
+    public void nullLiteralArray() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().writeNull().write(JsonValue.NULL).writeEnd().close();
+        assertEquals("[null,null]", new String(baos.toByteArray()));
+    }
+    
+    @Test
+    public void boolLiteralArray() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().write(JsonValue.FALSE).write(JsonValue.TRUE).writeEnd().close();
+        assertEquals("[false,true]", new String(baos.toByteArray()));
+    }
 
     @Test
     public void generate() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         final JsonGenerator generator = Json.createGenerator(baos);
 
-        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25).writeStartObject("address").write("streetAddress", "21 2nd Street").write("city", "New York").write("state", "NY").write("postalCode", "10021").writeEnd().writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234").writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd().close();
+        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25)
+        .writeStartObject("address").write("streetAddress", "21 2nd Street").write("city", "New York")
+        .write("state", "NY").write("postalCode", "10021").writeEnd().writeStartArray("phoneNumber")
+        .writeStartObject().write("type", "home").write("number", "212 555-1234").writeEnd().writeStartObject()
+        .write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd().close();
 
-        assertEquals("{\"firstName\":\"John\",\"lastName\":\"Smith\",\"age\":25,\"address\":{\"streetAddress\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"postalCode\":\"10021\"},\"phoneNumber\":[{\"type\":\"home\",\"number\":\"212 555-1234\"},{\"type\":\"fax\",\"number\":\"646 555-4567\"}]}", new String(baos.toByteArray()));
+        assertEquals("{\"firstName\":\"John\",\"lastName\":\"Smith\",\"age\":25,\"address\":"
+                + "{\"streetAddress\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"postalCode\":\"10021\"},"
+                + "\"phoneNumber\":[{\"type\":\"home\",\"number\":\"212 555-1234\"},{\"type\":\"fax\",\"number\":\"646 555-4567\"}]}", 
+                new String(baos.toByteArray()));
     }
 
     @Test
@@ -72,7 +116,12 @@ public class JsonGeneratorImplTest {
             put(JsonGenerator.PRETTY_PRINTING, true);
         }}).createGenerator(baos);
 
-        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25).writeStartObject("address").write("streetAddress", "21 2nd Street").write("city", "New York").write("state", "NY").write("postalCode", "10021").writeEnd().writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234").writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd().close();
+        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith")
+        .write("age", 25).writeStartObject("address").write("streetAddress", "21 2nd Street")
+        .write("city", "New York").write("state", "NY").write("postalCode", "10021").writeEnd()
+        .writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234")
+        .writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd()
+        .writeEnd().close();
 
         assertEquals("{\n" +
                         "  \"firstName\":\"John\",\n" +

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/java/org/apache/fleece/core/JsonParserTest.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/java/org/apache/fleece/core/JsonParserTest.java b/fleece-core/src/test/java/org/apache/fleece/core/JsonParserTest.java
index 34bb7ca..5be07b2 100644
--- a/fleece-core/src/test/java/org/apache/fleece/core/JsonParserTest.java
+++ b/fleece-core/src/test/java/org/apache/fleece/core/JsonParserTest.java
@@ -305,6 +305,198 @@ public class JsonParserTest {
         parser.close();
     }
 
+    
+    @Test
+    public void numbers() {
+        final JsonParser parser = Json.createParser(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/numbers.json"));
+        assertNotNull(parser);
+        parser.next();
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(0, parser.getInt());
+            assertEquals(0, parser.getLong());
+            assertEquals(new BigDecimal(0), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(0, parser.getInt());
+            assertEquals(0, parser.getLong());
+            assertEquals(new BigDecimal(0), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(1, parser.getInt());
+            assertEquals(1, parser.getLong());
+            assertEquals(new BigDecimal(1), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(-1, parser.getInt());
+            assertEquals(-1L, parser.getLong());
+            assertEquals(new BigDecimal(-1), parser.getBigDecimal());
+        }
+
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(9, parser.getInt());
+            assertEquals(9L, parser.getLong());
+            assertEquals(new BigDecimal(9), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(-9, parser.getInt());
+            assertEquals(-9, parser.getLong());
+            assertEquals(new BigDecimal(-9), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(10, parser.getInt());
+            assertEquals(10, parser.getLong());
+            assertEquals(new BigDecimal(10), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(-10, parser.getInt());
+            assertEquals(-10, parser.getLong());
+            assertEquals(new BigDecimal(-10), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(100, parser.getInt());
+            assertEquals(100, parser.getLong());
+            assertEquals(new BigDecimal(100), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(-100, parser.getInt());
+            assertEquals(-100, parser.getLong());
+            assertEquals(new BigDecimal(-100), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(456, parser.getInt());
+            assertEquals(456, parser.getLong());
+            assertEquals(new BigDecimal(456), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            assertEquals(-456, parser.getInt());
+            assertEquals(-456, parser.getLong());
+            assertEquals(new BigDecimal(-456), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(!parser.isIntegralNumber());
+            assertEquals(123, parser.getInt());
+            assertEquals(123, parser.getLong());
+            assertEquals(new BigDecimal("123.12345"), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(!parser.isIntegralNumber());
+            assertEquals(-123, parser.getInt());
+            assertEquals(-123, parser.getLong());
+            assertEquals(new BigDecimal("-123.12345"), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            //assertEquals(Integer.MAX_VALUE, parser.getInt());
+            //assertEquals(Long.MAX_VALUE, parser.getLong());
+            assertEquals(new BigDecimal("999999999999999999999999999999"), parser.getBigDecimal());
+        }
+        parser.next();
+        {
+            assertTrue(parser.hasNext());
+            final JsonParser.Event event = parser.next();
+            assertNotNull(event);
+            assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+            assertTrue(parser.isIntegralNumber());
+            //assertEquals(Integer.MIN_VALUE, parser.getInt());
+            //assertEquals(Long.MIN_VALUE, parser.getLong());
+            assertEquals(new BigDecimal("-999999999999999999999999999999"), parser.getBigDecimal());
+        }
+        parser.next();
+        
+        {
+            assertFalse(parser.hasNext());
+        }
+        parser.close();
+    }
+    
+    
     @Test
     public void bigdecimal() {
         final JsonParser parser = Json.createParser(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/bigdecimal.json"));
@@ -496,6 +688,41 @@ public class JsonParserTest {
         Json.createReader(new ByteArrayInputStream("{\"z\":\"b\"\"j\":\"d\"}".getBytes())).read();
     }
     
+    @Test(expected = JsonParsingException.class)
+    public void literalFailChecksTrue() {
+        // using a reader as wrapper of parser
+  
+        Json.createReader(new ByteArrayInputStream("{\"z\":truet}".getBytes())).read();
+    }
+    
+    @Test(expected = JsonParsingException.class)
+    public void literalFailChecksNull() {
+        // using a reader as wrapper of parser
+  
+        Json.createReader(new ByteArrayInputStream("{\"z\":nulll}".getBytes())).read();
+    }
+    
+    @Test(expected = JsonParsingException.class)
+    public void zeroByteInput() {
+        // using a reader as wrapper of parser
+  
+        Json.createReader(new ByteArrayInputStream(new byte[]{})).read();
+    }
+    
+    @Test
+    public void shortestNonEmtyJsonFile() {
+        // using a reader as wrapper of parser
+  
+        assertEquals(0L, Json.createReader(new ByteArrayInputStream("[0]".getBytes())).readArray().getJsonNumber(0).longValue());
+    }
+    
+    @Test
+    public void shortestNonEmtyJsonFileWithWhiteSpaceChars() {
+        // using a reader as wrapper of parser
+  
+        assertEquals(0L, Json.createReader(new ByteArrayInputStream("  \n\n   [   0  ]  \n\n".getBytes())).readArray().getJsonNumber(0).longValue());
+    }
+    
     
     @Test(expected = JsonParsingException.class)
     public void fail1() {

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/java/org/apache/fleece/core/JsonReaderImplTest.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/java/org/apache/fleece/core/JsonReaderImplTest.java b/fleece-core/src/test/java/org/apache/fleece/core/JsonReaderImplTest.java
index 0672587..2cb95c1 100644
--- a/fleece-core/src/test/java/org/apache/fleece/core/JsonReaderImplTest.java
+++ b/fleece-core/src/test/java/org/apache/fleece/core/JsonReaderImplTest.java
@@ -18,8 +18,19 @@
  */
 package org.apache.fleece.core;
 
-import org.junit.Before;
-import org.junit.Test;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.json.Json;
 import javax.json.JsonArray;
@@ -27,18 +38,22 @@ import javax.json.JsonObject;
 import javax.json.JsonReader;
 import javax.json.JsonStructure;
 
-import java.util.HashMap;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
 
 public class JsonReaderImplTest {
+    
+    protected static Charset utf8Charset = Charset.forName("UTF8");
+    protected static Charset asciiCharset = Charset.forName("ASCII");
+
+    @SuppressWarnings("unchecked")
+    protected Map<String, ?> getFactoryConfig() {
+        return Collections.EMPTY_MAP;
+    }
+
     @Test
     public void simple() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -53,11 +68,11 @@ public class JsonReaderImplTest {
         assertEquals(-2, array.getInt(1));
         reader.close();
     }
-    
-    
+
     @Test
     public void unicode() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/unicode.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("json/unicode.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -74,15 +89,37 @@ public class JsonReaderImplTest {
         assertEquals(5, object.size());
         reader.close();
     }
-    
+
+    @Test
+    public void unicodeWithIoReader() {
+        final Reader ioReader = new InputStreamReader(Thread.currentThread().getContextClassLoader()
+                .getResourceAsStream("json/unicode.json"), utf8Charset);
+        final JsonReader reader = Json.createReader(ioReader);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(String.valueOf('\u6565'), object.getString("a"));
+        assertEquals("", object.getString("z"));
+        assertEquals(String.valueOf('\u0000'), object.getString("c"));
+        assertThat(object.get("d"), instanceOf(JsonArray.class));
+        final JsonArray array = object.getJsonArray("d");
+        assertNotNull(array);
+        assertEquals(3, array.size());
+        assertEquals(-2, array.getInt(0));
+        assertEquals(" ", array.getString(1));
+        assertEquals("", array.getString(2));
+        assertEquals(5, object.size());
+        reader.close();
+    }
+
     @Test
     public void special() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/special.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("json/special.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
         assertEquals(9, object.size());
-        
         assertEquals("b,,", object.getString("a{"));
         assertEquals(":4::,[{", object.getString("c::::"));
         assertTrue(object.getJsonNumber("w").doubleValue() > 4 && object.getJsonNumber("w").doubleValue() < 5);
@@ -91,68 +128,183 @@ public class JsonReaderImplTest {
         assertEquals("ন:4::,[{", object.getString("থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#"));
         reader.close();
     }
-    
-    
+
+    @Test
+    public void specialWithIoReader() {
+        final Reader ioReader = new InputStreamReader(Thread.currentThread().getContextClassLoader()
+                .getResourceAsStream("json/special.json"), utf8Charset);
+        final JsonReader reader = Json.createReader(ioReader);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(9, object.size());
+        assertEquals("b,,", object.getString("a{"));
+        assertEquals(":4::,[{", object.getString("c::::"));
+        assertTrue(object.getJsonNumber("w").doubleValue() > 4 && object.getJsonNumber("w").doubleValue() < 5);
+        assertEquals(110, object.getInt("1.4312"));
+        assertEquals("\"", object.getString("\""));
+        assertEquals("ন:4::,[{", object.getString("থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#"));
+        reader.close();
+    }
+
+    @Test
+    public void specialWithStringAsByteArrayInputStream() {
+        final String s = "{\"নa\":\"hallo\u20acö\uffff \u08a5 থ?ߧ$%&´'`*+#\udbff\udfff\"}";
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                new ByteArrayInputStream(s.getBytes(utf8Charset)), utf8Charset);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(1, object.size());
+        assertEquals("hallo\u20acö\uffff \u08a5 থ?ߧ$%&´'`*+#\udbff\udfff", object.getString("নa"));
+        reader.close();
+    }
+
+    @Test
+    public void specialWithStringReader() {
+        final String s = "{\"ন:4::,[{\u08a5\":\"থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\ua5a5\"}";
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                new InputStreamReader(new ByteArrayInputStream(s.getBytes(utf8Charset)), utf8Charset));
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(1, object.size());
+        assertEquals("থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\ua5a5", object.getString("ন:4::,[{\u08a5"));
+        reader.close();
+    }
+
+    @Test
+    public void unicode4Bytes() {
+        final int codepoint = 128149;
+        final char[] charPair = Character.toChars(codepoint);
+        assertNotNull(charPair);
+        assertEquals(2, charPair.length);
+        assertTrue(Character.isHighSurrogate(charPair[0]));
+        assertTrue(Character.isLowSurrogate(charPair[1]));
+        assertTrue(Character.isSurrogatePair(charPair[0], charPair[1]));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                (new ByteArrayInputStream(("{\"\":\"Ö" + charPair[0] + charPair[1] + "\"}").getBytes(utf8Charset))),
+                utf8Charset);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+
+        assertEquals(codepoint, object.getString("").codePointAt(1));
+        assertEquals("Ö" + new String(charPair), object.getString(""));
+        assertEquals(1, object.size());
+        reader.close();
+    }
+
+    @Test
+    public void unicode3Bytes() {
+        final char[] charPair = Character.toChars("\uffff".codePointAt(0));
+        assertNotNull(charPair);
+        assertEquals(1, charPair.length);
+        assertTrue(!Character.isLowSurrogate(charPair[0]));
+        assertTrue(!Character.isHighSurrogate(charPair[0]));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                new ByteArrayInputStream(("{\"\":\"\uffff\"}").getBytes(utf8Charset)), utf8Charset);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(String.valueOf('\uffff'), object.getString(""));
+        assertEquals(1, object.size());
+        reader.close();
+    }
+
+    @Test
+    public void unicode2Bytes() {
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                new ByteArrayInputStream(("{\"\":\"Ö\u00d6\"}").getBytes(utf8Charset)), utf8Charset);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals("Ö\u00d6", object.getString(""));
+        assertEquals(1, object.size());
+        reader.close();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void unicodeFailAscii() {
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                new ByteArrayInputStream(
+                        "{\"ন:4::,[{\udbff\udfff\":\"থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\udbff\udfff\"}".getBytes(asciiCharset)),
+                utf8Charset);
+        assertNotNull(reader);
+        final JsonObject object = reader.readObject();
+        assertNotNull(object);
+        assertEquals(1, object.size());
+        assertEquals("থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\udbff\udfff", object.getString("ন:4::,[{\udbff\udfff"));
+        reader.close();
+    }
+
     @Test
     public void parseHuge1MbJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/huge_1mb.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/huge_1mb.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
+
     @Test
     public void parseBig600KbJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/big_600kb.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/big_600kb.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
+
     @Test
     public void parseLarge130KbJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/large_130kb.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/large_130kb.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
+
     @Test
     public void parseMedium11KbJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/medium_11kb.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/medium_11kb.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
+
     @Test
     public void parseSmall3KbJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/small_3kb.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/small_3kb.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
+
     @Test
     public void parseTiny50BJsonFile() {
-        final JsonReader reader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/tiny_50b.json"));
+        final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("bench/tiny_50b.json"), utf8Charset);
         assertNotNull(reader);
         final JsonStructure object = reader.read();
         assertNotNull(object);
         reader.close();
     }
-    
-    
+
     @Test
     public void simpleBadBufferSize8() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.fleece.default-char-buffer", "8");
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.fleece.default-char-buffer", "8");
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -167,11 +319,14 @@ public class JsonReaderImplTest {
         assertEquals(-2, array.getInt(1));
         reader.close();
     }
+
     @Test
     public void simpleBadBufferSize9() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.fleece.default-char-buffer", "9");
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.fleece.default-char-buffer", "9");
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -186,53 +341,60 @@ public class JsonReaderImplTest {
         assertEquals(-2, array.getInt(1));
         reader.close();
     }
-    
-    @Test(expected=IllegalArgumentException.class)
+
+    @Test(expected = IllegalArgumentException.class)
     public void emptyZeroCharBuffersize() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.fleece.default-char-buffer", "0");
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/empty.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.fleece.default-char-buffer", "0");
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/empty.json"), utf8Charset);
         assertNotNull(reader);
         reader.readObject();
         reader.close();
     }
-    
+
     @Test
     public void emptyOneCharBufferSize() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.fleece.default-char-buffer", "1");
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/empty.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.fleece.default-char-buffer", "1");
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/empty.json"), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
         assertEquals(0, object.size());
         reader.close();
     }
-    
+
     @Test
     public void emptyArrayOneCharBufferSize() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.fleece.default-char-buffer", "1");
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/emptyarray.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.fleece.default-char-buffer", "1");
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/emptyarray.json"), utf8Charset);
         assertNotNull(reader);
         final JsonArray array = reader.readArray();
         assertNotNull(array);
         assertEquals(0, array.size());
         reader.close();
     }
-    
-    
+
     @Test
     public void stringescapeVariousBufferSizes() {
-
-        int[] buffersizes = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-                28, 32, 64, 128, 1024, 8192 };
+        final int[] buffersizes = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+                26, 27, 28, 32, 64, 128, 1024, 8192 };
 
         for (int i = 0; i < buffersizes.length; i++) {
             final String value = String.valueOf(buffersizes[i]);
-            final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-                put("org.apache.fleece.default-char-buffer", value);
-            }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/stringescape.json"));
+            final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+                {
+                    put("org.apache.fleece.default-char-buffer", value);
+                }
+            }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/stringescape.json"),
+                    utf8Charset);
             assertNotNull(reader);
             final JsonObject object = reader.readObject();
             assertNotNull(object);
@@ -241,4 +403,4 @@ public class JsonReaderImplTest {
             reader.close();
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicode_chars_1400kb.txt
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicode_chars_1400kb.txt b/fleece-core/src/test/resources/bench/unicode_chars_1400kb.txt
new file mode 100644
index 0000000..576c24d
Binary files /dev/null and b/fleece-core/src/test/resources/bench/unicode_chars_1400kb.txt differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicode_chars_170kb.json
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicode_chars_170kb.json b/fleece-core/src/test/resources/bench/unicode_chars_170kb.json
deleted file mode 100644
index b06ecff..0000000
Binary files a/fleece-core/src/test/resources/bench/unicode_chars_170kb.json and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicode_chars_170kb.txt
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicode_chars_170kb.txt b/fleece-core/src/test/resources/bench/unicode_chars_170kb.txt
new file mode 100644
index 0000000..b06ecff
Binary files /dev/null and b/fleece-core/src/test/resources/bench/unicode_chars_170kb.txt differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicode_chars_huge.json
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicode_chars_huge.json b/fleece-core/src/test/resources/bench/unicode_chars_huge.json
deleted file mode 100644
index 576c24d..0000000
Binary files a/fleece-core/src/test/resources/bench/unicode_chars_huge.json and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicodes.json
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicodes.json b/fleece-core/src/test/resources/bench/unicodes.json
deleted file mode 100644
index b06ecff..0000000
Binary files a/fleece-core/src/test/resources/bench/unicodes.json and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/bench/unicodes_big.json
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/bench/unicodes_big.json b/fleece-core/src/test/resources/bench/unicodes_big.json
deleted file mode 100644
index 576c24d..0000000
Binary files a/fleece-core/src/test/resources/bench/unicodes_big.json and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-core/src/test/resources/json/numbers.json
----------------------------------------------------------------------
diff --git a/fleece-core/src/test/resources/json/numbers.json b/fleece-core/src/test/resources/json/numbers.json
new file mode 100644
index 0000000..d300022
--- /dev/null
+++ b/fleece-core/src/test/resources/json/numbers.json
@@ -0,0 +1,18 @@
+{
+    "0": 0,
+    "0": -0,
+    "1": 1,
+    "-1": -1,
+    "9": 9,
+    "-9": -9,
+    "10": 10,
+    "-10", -10,
+    "100": 100,
+    "-100", -100,
+    "456": 456,
+    "-456": -456,
+    "123.12345": 123.12345,
+    "-123.12345": -123.12345,
+    "999999999999999999999999999999": 999999999999999999999999999999,
+    "-999999999999999999999999999999": -999999999999999999999999999999
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-jaxrs/src/main/java/org/apache/fleece/jaxrs/FleeceMessageBodyReader.java
----------------------------------------------------------------------
diff --git a/fleece-jaxrs/src/main/java/org/apache/fleece/jaxrs/FleeceMessageBodyReader.java b/fleece-jaxrs/src/main/java/org/apache/fleece/jaxrs/FleeceMessageBodyReader.java
index 4a06e25..c34727a 100644
--- a/fleece-jaxrs/src/main/java/org/apache/fleece/jaxrs/FleeceMessageBodyReader.java
+++ b/fleece-jaxrs/src/main/java/org/apache/fleece/jaxrs/FleeceMessageBodyReader.java
@@ -68,7 +68,7 @@ public class FleeceMessageBodyReader<T> implements MessageBodyReader<T> {
         if (rawType.isArray()) {
             return (T) mapper.readArray(entityStream, rawType.getComponentType());
         } else if (Collection.class.isAssignableFrom(rawType) && ParameterizedType.class.isInstance(genericType)) {
-            return (T) mapper.readCollection(entityStream, ParameterizedType.class.cast(genericType), rawType);
+            return (T) mapper.<Collection<T>,T>readCollection(entityStream, ParameterizedType.class.cast(genericType), rawType);
         }
         return mapper.readObject(entityStream, genericType);
     }

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-mapper/src/main/java/org/apache/fleece/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/fleece-mapper/src/main/java/org/apache/fleece/mapper/Mapper.java b/fleece-mapper/src/main/java/org/apache/fleece/mapper/Mapper.java
index 956dd2c..815426f 100644
--- a/fleece-mapper/src/main/java/org/apache/fleece/mapper/Mapper.java
+++ b/fleece-mapper/src/main/java/org/apache/fleece/mapper/Mapper.java
@@ -30,6 +30,7 @@ import javax.json.JsonReaderFactory;
 import javax.json.JsonValue;
 import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonGeneratorFactory;
+
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -48,7 +49,13 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -444,9 +451,11 @@ public class Mapper {
                 final Type[] fieldArgTypes = aType.getActualTypeArguments();
                 if (fieldArgTypes.length >= 2) {
                     final Class<?> raw = Class.class.cast(aType.getRawType());
-
+                    
                     final Map map;
-                    if (ConcurrentMap.class.isAssignableFrom(raw)) {
+                    if (SortedMap.class.isAssignableFrom(raw)) {
+                        map = new TreeMap();
+                    } else if (ConcurrentMap.class.isAssignableFrom(raw)) {
                         map = new ConcurrentHashMap(object.size());
                     } else if (Map.class.isAssignableFrom(raw)) {
                         map = new HashMap(object.size());
@@ -455,7 +464,16 @@ public class Mapper {
                     }
 
                     if (map != null) {
-                        final Class<?> keyType = Class.class.cast(fieldArgTypes[0]);
+                        
+                        Class<?> keyType = null;
+                        if (ParameterizedType.class.isInstance(fieldArgTypes[0])) {
+                            //class cast exception when  fieldArgTypes[0] is parameterized
+                            //FIXME
+                            keyType = Class.class.cast(fieldArgTypes[0]); 
+                        } else {
+                            keyType = Class.class.cast(fieldArgTypes[0]);
+                        }
+                         
                         for (final Map.Entry<String, JsonValue> value : object.entrySet()) {
                             map.put(convertTo(keyType, value.getKey()), toObject(value.getValue(), fieldArgTypes[1]));
                         }
@@ -476,6 +494,7 @@ public class Mapper {
             final Method setterMethod = value.setter;
             final Object convertedValue = value.converter == null?
                     toObject(jsonValue, value.paramType) : value.converter.fromString(jsonValue.toString());
+                
             if (convertedValue != null) {
                 try {
                     setterMethod.invoke(t, convertedValue);
@@ -489,6 +508,7 @@ public class Mapper {
     }
 
     private Object toObject(final JsonValue jsonValue, final Type type) throws InstantiationException, IllegalAccessException {
+        
         Object convertedValue = null;
         if (JsonObject.class.isInstance(jsonValue)) {
             convertedValue = buildObject(type, JsonObject.class.cast(jsonValue));
@@ -516,6 +536,7 @@ public class Mapper {
 
             final String text = jsonValue.toString();
             if (text != null) {
+                
                 convertedValue = convertTo(Class.class.cast(type), text);
             }
         }
@@ -544,10 +565,16 @@ public class Mapper {
 
     private <T> Collection<T> mapCollection(final Mappings.CollectionMapping mapping, final JsonArray jsonArray) throws InstantiationException, IllegalAccessException {
         final Collection collection;
-        if (List.class == mapping.raw || Collection.class == mapping.raw) {
-            collection = new ArrayList<T>(jsonArray.size());
+        
+        if (SortedSet.class == mapping.raw) {
+            collection = new TreeSet<T>();
         } else if (Set.class == mapping.raw) {
             collection = new HashSet<T>(jsonArray.size());
+        } else if (Queue.class == mapping.raw) {
+            collection = new ArrayBlockingQueue<T>(jsonArray.size());
+          //fail fast if collection is not know, assume Collection.class to be compatible with ArrayList is wrong for almost all cases
+        } else if (List.class == mapping.raw /*|| Collection.class == mapping.raw*/) {
+            collection = new ArrayList<T>(jsonArray.size());
         } else {
             throw new IllegalStateException("not supported collection type: " + mapping.raw.getName());
         }

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-mapper/src/main/java/org/apache/fleece/mapper/reflection/Mappings.java
----------------------------------------------------------------------
diff --git a/fleece-mapper/src/main/java/org/apache/fleece/mapper/reflection/Mappings.java b/fleece-mapper/src/main/java/org/apache/fleece/mapper/reflection/Mappings.java
index 2fbf950..f5e6e6d 100644
--- a/fleece-mapper/src/main/java/org/apache/fleece/mapper/reflection/Mappings.java
+++ b/fleece-mapper/src/main/java/org/apache/fleece/mapper/reflection/Mappings.java
@@ -35,7 +35,9 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
+import java.util.SortedSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -128,8 +130,12 @@ public class Mappings {
             final Class<?> collectionType;
             if (List.class.isAssignableFrom(raw)) {
                 collectionType = List.class;
+            }else if (SortedSet.class.isAssignableFrom(raw)) {
+                collectionType = SortedSet.class;
             } else if (Set.class.isAssignableFrom(raw)) {
                 collectionType = Set.class;
+            } else if (Queue.class.isAssignableFrom(raw)) {
+                collectionType = Queue.class;
             } else if (Collection.class.isAssignableFrom(raw)) {
                 collectionType = Collection.class;
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperEnhancedTests.java
----------------------------------------------------------------------
diff --git a/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperEnhancedTests.java b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperEnhancedTests.java
new file mode 100644
index 0000000..8169655
--- /dev/null
+++ b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperEnhancedTests.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fleece.mapper;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import org.junit.Test;
+
+public class MapperEnhancedTests {
+
+    @Test
+    public void writeNull() {
+        final StringWriter sw = new StringWriter();
+        new MapperBuilder().build().writeObject(null, sw);
+        assertEquals("{}", sw.toString());
+    }
+   
+    
+    @Test
+    public void writeReadSortedMap() {
+        SomaClass soseClass = new SomaClass();
+        soseClass.getSoma().put("key1", "val1");
+        soseClass.getSoma().put("key2", "val2");
+        final StringWriter sw = new StringWriter();
+        
+        new MapperBuilder().build().writeObject(soseClass, sw);
+        assertEquals("{\"soma\":{\"key1\":\"val1\",\"key2\":\"val2\"}}", sw.toString());
+        new MapperBuilder().build().readObject(new StringReader(sw.toString()), SomaClass.class);
+        
+    }
+    
+    @Test
+    public void writeReadSortedSet() {
+        SoseClass soseClass = new SoseClass();
+        soseClass.getSose().add("string1");
+        soseClass.getSose().add("string2");
+        final StringWriter sw = new StringWriter();
+        
+        new MapperBuilder().build().writeObject(soseClass, sw);
+       
+        assertEquals("{\"sose\":[\"string1\",\"string2\"]}", sw.toString());
+        new MapperBuilder().build().readObject(new StringReader(sw.toString()), SoseClass.class);
+       
+    }
+    
+    @Test
+    public void writeReadQueue() {
+        QueueClass queueClass = new QueueClass();
+        queueClass.getQueue().add("string1");
+        queueClass.getQueue().add("string2");
+        final StringWriter sw = new StringWriter();
+        
+        new MapperBuilder().build().writeObject(queueClass, sw);
+       
+        assertEquals("{\"queue\":[\"string1\",\"string2\"]}", sw.toString());
+        new MapperBuilder().build().readObject(new StringReader(sw.toString()), QueueClass.class);
+       
+    }
+
+   /*@Test
+    public void writeTestclass() {
+        final StringWriter sw = new StringWriter();
+        final TestClass tc1 = new TestClass(null);
+        final Map<String, Integer> m = new TreeMap<String, Integer>();
+        m.put("key1", -100);
+        m.put("key2", +100);
+        final Map<String, Integer> m2 = new TreeMap<String, Integer>();
+        m.put("key11", -1002);
+        m.put("key22", +1002);
+        final List<Map<String, Integer>> l = new ArrayList<Map<String, Integer>>();
+        l.add(m);
+        l.add(m2);
+        tc1.sose.add("string1");
+        tc1.sose.add("string2");
+        tc1.map.put(l, 100L);
+
+        final TestClass tc2 = new TestClass(tc1);
+        final Map<String, Integer> m3 = new TreeMap<String, Integer>();
+        m3.put("key1", -100);
+        m3.put("key2", +100);
+        final Map<String, Integer> m4 = new TreeMap<String, Integer>();
+        m4.put("key11", -1002);
+        m4.put("key22", +1002);
+        final List<Map<String, Integer>> l1 = new ArrayList<Map<String, Integer>>();
+        l1.add(m);
+        l1.add(m2);
+        tc2.map.put(l1, 200L);
+
+        new MapperBuilder().build().writeObject(tc2, sw);
+       
+
+        new MapperBuilder().build().readObject(new StringReader(sw.toString()), TestClass.class);
+    }*/
+
+    
+    public static class QueueClass {
+        private Queue<String> queue = new ArrayBlockingQueue<String>(5);
+
+        public Queue<String> getQueue() {
+            return queue;
+        }
+
+        public void setQueue(Queue<String> queue) {
+            this.queue = queue;
+        }
+
+        
+        
+    }
+    
+    public static class SoseClass {
+        private SortedSet<String> sose = new TreeSet<String>();
+
+        public SortedSet<String> getSose() {
+            return sose;
+        }
+
+        public void setSose(SortedSet<String> sose) {
+            this.sose = sose;
+        }
+        
+    }
+    
+    public static class SomaClass {
+        private SortedMap<String, String> soma = new TreeMap<String, String>();
+
+        public SortedMap<String, String> getSoma() {
+            return soma;
+        }
+
+        public void setSoma(SortedMap<String, String> soma) {
+            this.soma = soma;
+        }        
+    }
+    
+    public static class TestClass {
+
+        private List<Map<String, Date>> dates = new ArrayList<Map<String, Date>>();
+        private Map<List<Map<String, Integer>>, Long> map = new HashMap<List<Map<String, Integer>>, Long>();
+        private TestClass inner;
+        private String string = "some \t \u0001 unicode: ÖÄÜ \u0070\u0070\u0070ন\udbff\udfff";
+        private BigDecimal bd = new BigDecimal("-456.4567890987654321");
+        private SortedSet<String> sose = new TreeSet<String>();
+
+        public SortedSet<String> getSose() {
+            return sose;
+        }
+
+        public void setSose(SortedSet<String> sose) {
+            this.sose = sose;
+        }
+
+        public TestClass(final TestClass inner) {
+            super();
+            this.inner = inner;
+        }
+
+        public TestClass() {
+            super();
+
+        }
+
+        public List<Map<String, Date>> getDates() {
+            return dates;
+        }
+
+        public void setDates(final List<Map<String, Date>> dates) {
+            this.dates = dates;
+        }
+
+        public Map<List<Map<String, Integer>>, Long> getMap() {
+            return map;
+        }
+
+        public void setMap(final Map<List<Map<String, Integer>>, Long> map) {
+            this.map = map;
+        }
+
+        public TestClass getInner() {
+            return inner;
+        }
+
+        public void setInner(final TestClass inner) {
+            this.inner = inner;
+        }
+
+        public String getString() {
+            return string;
+        }
+
+        public void setString(final String string) {
+            this.string = string;
+        }
+
+        public BigDecimal getBd() {
+            return bd;
+        }
+
+        public void setBd(final BigDecimal bd) {
+            this.bd = bd;
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperTest.java
----------------------------------------------------------------------
diff --git a/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperTest.java b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperTest.java
index b01c3d3..fed9c2f 100644
--- a/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperTest.java
+++ b/fleece-mapper/src/test/java/org/apache/fleece/mapper/MapperTest.java
@@ -107,14 +107,21 @@ public class MapperTest {
 
     @Test
     public void writeObject() {
-        final TheObject instance = new MapperBuilder().build().readObject(new ByteArrayInputStream(BIG_OBJECT_STR.getBytes()), TheObject.class); // suppose reader writes but this is tested
+        final TheObject instance = new MapperBuilder().build()
+                .readObject(new ByteArrayInputStream(BIG_OBJECT_STR.getBytes()), TheObject.class); // suppose reader writes but this is tested
         final StringWriter writer = new StringWriter();
         new MapperBuilder().build().writeObject(instance, writer);
         final String serialized = writer.toString();
         assertTrue(serialized.contains("\"primitives\":[1,2,3,4,5]"));
         assertTrue(serialized.contains("\"collectionWrapper\":[1,2,3,4,5]"));
         assertTrue(serialized.contains("\"bool\":true"));
-        assertTrue(serialized.contains("\"map\":{\"duos\":false,\"uno\":true}"));
+        
+        //Assert fail with oracle java 1.7.0_45, works well with apple java 1.6.0_65 
+        //assertTrue(serialized.contains("\"map\":{\"uno\":true,\"duos\":false}"));
+        
+        assertTrue(serialized.contains("\"map\":{"));
+        assertTrue(serialized.contains("\"uno\":true"));
+        assertTrue(serialized.contains("\"duos\":false"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ed634d1..563d172 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,6 +21,10 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
+  
+  <prerequisites>
+		<maven>3.1.0</maven>
+</prerequisites>
 
   <parent>
     <groupId>org.apache</groupId>
@@ -33,6 +37,9 @@
   <packaging>pom</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>Fleece</name>
+  <description>Apache Fleece is an implementation of JSR-353 (JavaTM API for JSON Processing).</description>
+  <inceptionYear>2014</inceptionYear>
+  <url>http://incubator.apache.org/projects/fleece.html</url>
 
   <modules>
     <module>fleece-core</module>
@@ -65,6 +72,9 @@
         <configuration>
           <source>1.6</source>
           <target>1.6</target>
+          <encoding>UTF-8</encoding>
+          <showDeprecation>true</showDeprecation>
+		  <showWarnings>true</showWarnings>
         </configuration>
       </plugin>
       <plugin>
@@ -86,6 +96,8 @@
             <exclude>*.ipr</exclude>
             <exclude>**/META-INF/services/javax.json.spi.JsonProvider</exclude>
             <exclude>**/*.json</exclude>
+            <exclude>**/*.yml</exclude>
+            <exclude>**/bench/*.txt</exclude>
           </excludes>
         </configuration>
         <executions>
@@ -246,6 +258,21 @@
   <reporting>
     <plugins>
       <plugin>
+		<groupId>org.codehaus.mojo</groupId>
+		<artifactId>findbugs-maven-plugin</artifactId>
+		<version>2.5.3</version>
+		<configuration>
+          <xmlOutput>true</xmlOutput>
+          <!-- Optional directory to put findbugs xdoc xml report -->
+          <xmlOutputDirectory>target/site</xmlOutputDirectory>
+        </configuration>
+	  </plugin>
+	  <plugin>
+		<groupId>org.apache.maven.plugins</groupId>
+		<artifactId>maven-pmd-plugin</artifactId>
+		<version>3.1</version>
+	  </plugin>
+      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-project-info-reports-plugin</artifactId>
         <version>2.7</version>
@@ -273,4 +300,12 @@
       </plugin>
     </plugins>
   </reporting>
+  
+  <licenses>
+		<license>
+			<name>The Apache Software License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+			<distribution>repo</distribution>
+		</license>
+  </licenses>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/d6c1bb8b/src/site/site.xml
----------------------------------------------------------------------
diff --git a/src/site/site.xml b/src/site/site.xml
index 62bf04e..75cfd61 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -33,7 +33,7 @@
   <custom>
     <fluidoSkin>
       <topBarEnabled>true</topBarEnabled>
-      <sideBarEnabled>false</sideBarEnabled>
+      <sideBarEnabled>true</sideBarEnabled>
       <sourceLineNumbersEnabled>true</sourceLineNumbersEnabled>
       <ohloh>
         <projectId>apache-fleece</projectId>