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/06/13 15:45:16 UTC
[4/6] initial import
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/pom.xml
----------------------------------------------------------------------
diff --git a/fleece-core/pom.xml b/fleece-core/pom.xml
new file mode 100644
index 0000000..cb2a0d2
--- /dev/null
+++ b/fleece-core/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ 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">
+ <parent>
+ <artifactId>fleece</artifactId>
+ <groupId>org.apache.fleece</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>fleece-core</artifactId>
+ <name>Fleece :: Core</name>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/BufferCache.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/BufferCache.java b/fleece-core/src/main/java/org/apache/fleece/core/BufferCache.java
new file mode 100644
index 0000000..9510959
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/BufferCache.java
@@ -0,0 +1,51 @@
+/*
+ * 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.core;
+
+public abstract class BufferCache<T> {
+ // alloc are expensive so using a very trivial buffer, we remove from TL to say we use it and reset it when we are done (close)
+ private final ThreadLocal<T> buffers;
+ private final int defaultSize;
+
+ public BufferCache(final int defaultSize) {
+ this.buffers = new ThreadLocal<T>() {
+ @Override
+ protected T initialValue() {
+ return BufferCache.this.newValue(defaultSize);
+ }
+ };
+ this.defaultSize = defaultSize;
+ }
+
+ protected abstract T newValue(final int defaultSize);
+
+ public T getCache() {
+ final T cachedLoadedChars = buffers.get();
+ if (cachedLoadedChars == null) {
+ return newValue(defaultSize);
+ }
+ buffers.set(null); // remove just kills the buffers
+ return cachedLoadedChars;
+ }
+
+
+ public void release(final T buffer) {
+ buffers.set(buffer);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/EscapedStringAwareJsonParser.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/EscapedStringAwareJsonParser.java b/fleece-core/src/main/java/org/apache/fleece/core/EscapedStringAwareJsonParser.java
new file mode 100644
index 0000000..56cb7a5
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/EscapedStringAwareJsonParser.java
@@ -0,0 +1,25 @@
+/*
+ * 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.core;
+
+import javax.json.stream.JsonParser;
+
+public interface EscapedStringAwareJsonParser extends JsonParser {
+ String getEscapedString();
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayBuilderImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayBuilderImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayBuilderImpl.java
new file mode 100644
index 0000000..d903134
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayBuilderImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonArrayBuilderImpl implements JsonArrayBuilder {
+ private final JsonArrayImpl array = new JsonArrayImpl();
+
+ @Override
+ public JsonArrayBuilder add(final JsonValue value) {
+ array.addInternal(value);
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final String value) {
+ array.addInternal(new JsonStringImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final BigDecimal value) {
+ array.addInternal(new JsonNumberImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final BigInteger value) {
+ array.addInternal(new JsonNumberImpl(new BigDecimal(value)));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final int value) {
+ array.addInternal(new JsonLongImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final long value) {
+ array.addInternal(new JsonLongImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final double value) {
+ array.addInternal(new JsonDoubleImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final boolean value) {
+ array.add(value ? JsonValue.TRUE : JsonValue.FALSE);
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder addNull() {
+ array.add(JsonValue.NULL);
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final JsonObjectBuilder builder) {
+ array.add(builder.build());
+ return this;
+ }
+
+ @Override
+ public JsonArrayBuilder add(final JsonArrayBuilder builder) {
+ array.add(builder.build());
+ return this;
+ }
+
+ @Override
+ public JsonArray build() {
+ return array;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayImpl.java
new file mode 100644
index 0000000..a2fb350
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonArrayImpl.java
@@ -0,0 +1,203 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class JsonArrayImpl extends LinkedList<JsonValue> implements JsonArray {
+ private Integer hashCode = null;
+
+ private <T> T value(final int idx, final Class<T> type) {
+ if (idx > size()) {
+ throw new IndexOutOfBoundsException(idx + "/" + size());
+ }
+ return type.cast(get(idx));
+ }
+
+ @Override
+ public JsonObject getJsonObject(final int index) {
+ return value(index, JsonObject.class);
+ }
+
+ @Override
+ public JsonArray getJsonArray(final int index) {
+ return value(index, JsonArray.class);
+ }
+
+ @Override
+ public JsonNumber getJsonNumber(final int index) {
+ return value(index, JsonNumber.class);
+ }
+
+ @Override
+ public JsonString getJsonString(final int index) {
+ return value(index, JsonString.class);
+ }
+
+ @Override
+ public <T extends JsonValue> List<T> getValuesAs(final Class<T> clazz) {
+ return (List<T>) this;
+ }
+
+ @Override
+ public String getString(final int index) {
+ return value(index, JsonString.class).getString();
+ }
+
+ @Override
+ public String getString(final int index, final String defaultValue) {
+ try {
+ return getString(index);
+ } catch (final IndexOutOfBoundsException ioobe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return value(index, JsonNumber.class).intValue();
+ }
+
+ @Override
+ public int getInt(final int index, final int defaultValue) {
+ try {
+ return getInt(index);
+ } catch (final IndexOutOfBoundsException ioobe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public boolean getBoolean(final int index) {
+ return value(index, JsonValue.class) == JsonValue.TRUE;
+ }
+
+ @Override
+ public boolean getBoolean(final int index, final boolean defaultValue) {
+ try {
+ return getBoolean(index);
+ } catch (final IndexOutOfBoundsException ioobe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public boolean isNull(final int index) {
+ return value(index, JsonValue.class) == JsonValue.NULL;
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return ValueType.ARRAY;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder("[");
+ final Iterator<JsonValue> it = iterator();
+ boolean hasNext = it.hasNext();
+ while (hasNext) {
+ final JsonValue jsonValue = it.next();
+ if (JsonString.class.isInstance(jsonValue)) {
+ builder.append(JsonChars.QUOTE).append(jsonValue.toString()).append(JsonChars.QUOTE);
+ } else {
+ builder.append(jsonValue != JsonValue.NULL ? jsonValue.toString() : JsonChars.NULL);
+ }
+ hasNext = it.hasNext();
+ if (hasNext) {
+ builder.append(",");
+ }
+ }
+ return builder.append(']').toString();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return JsonArray.class.isInstance(obj) && super.equals(obj);
+ }
+
+ public void addInternal(final JsonValue value) {
+ super.add(value);
+ }
+
+ @Override
+ public boolean add(final JsonValue element) {
+ throw immutable();
+ }
+
+ @Override
+ public boolean addAll(final int index, final Collection<? extends JsonValue> c) {
+ throw immutable();
+ }
+
+ @Override
+ public boolean remove(final Object o) {
+ throw immutable();
+ }
+
+ @Override
+ public JsonValue remove(final int index) {
+ throw immutable();
+ }
+
+ @Override
+ public void add(final int index, final JsonValue element) {
+ throw immutable();
+ }
+
+ @Override
+ public void clear() {
+ throw immutable();
+ }
+
+ @Override
+ public boolean retainAll(final Collection<?> c) {
+ throw immutable();
+ }
+
+ @Override
+ public boolean removeAll(final Collection<?> c) {
+ throw immutable();
+ }
+
+ @Override
+ public JsonValue set(final int index, final JsonValue element) {
+ throw immutable();
+ }
+
+ private static UnsupportedOperationException immutable() {
+ throw new UnsupportedOperationException("JsonArray is immutable. You can create another one thanks to JsonArrayBuilder");
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == null) {
+ hashCode = super.hashCode();
+ }
+ return hashCode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonBuilderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonBuilderFactoryImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonBuilderFactoryImpl.java
new file mode 100644
index 0000000..710aa54
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonBuilderFactoryImpl.java
@@ -0,0 +1,47 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonObjectBuilder;
+import java.util.Map;
+
+public class JsonBuilderFactoryImpl implements JsonBuilderFactory {
+ private final Map<String, ?> config;
+
+ public JsonBuilderFactoryImpl(final Map<String, ?> config) {
+ this.config = config;
+ }
+
+ @Override
+ public JsonObjectBuilder createObjectBuilder() {
+ return new JsonObjectBuilderImpl();
+ }
+
+ @Override
+ public JsonArrayBuilder createArrayBuilder() {
+ return new JsonArrayBuilderImpl();
+ }
+
+ @Override
+ public Map<String, ?> getConfigInUse() {
+ return config;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonChars.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonChars.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonChars.java
new file mode 100644
index 0000000..3fbc5b4
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonChars.java
@@ -0,0 +1,55 @@
+/*
+ * 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.core;
+
+public interface JsonChars {
+ char EOF = Character.MIN_VALUE;
+
+ char START_OBJECT_CHAR = '{';
+ char END_OBJECT_CHAR = '}';
+ char START_ARRAY_CHAR = '[';
+ char END_ARRAY_CHAR = ']';
+ char EOL = '\n';
+ char COMMA = ',';
+ char SPACE = ' ';
+ char KEY_SEPARATOR = ':';
+ char TRUE_T = 't';
+ char TRUE_R = 'r';
+ char TRUE_U = 'u';
+ char TRUE_E = 'e';
+ char FALSE_F = 'f';
+ char FALSE_A = 'a';
+ char FALSE_L = 'l';
+ char FALSE_S = 's';
+ char FALSE_E = 'e';
+ char NULL_N = 'n';
+ char NULL_U = 'u';
+ char NULL_L = 'l';
+ char QUOTE = '"';
+ char ZERO = '0';
+ char NINE = '9';
+ char DOT = '.';
+ char MINUS = '-';
+ char PLUS = '+';
+ char EXP_LOWERCASE = 'e';
+ char EXP_UPPERCASE = 'E';
+ char ESCAPE_CHAR = '\\';
+
+ String NULL = "null";
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonDoubleImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonDoubleImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonDoubleImpl.java
new file mode 100644
index 0000000..6d9d370
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonDoubleImpl.java
@@ -0,0 +1,96 @@
+/*
+ * 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.core;
+
+import javax.json.JsonNumber;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonDoubleImpl implements JsonNumber {
+ private final double value;
+
+ public JsonDoubleImpl(final double value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean isIntegral() {
+ return false;
+ }
+
+ @Override
+ public int intValue() {
+ return (int) value;
+ }
+
+ @Override
+ public int intValueExact() {
+ return intValue();
+ }
+
+ @Override
+ public long longValue() {
+ return (long) value;
+ }
+
+ @Override
+ public long longValueExact() {
+ return (long) value;
+ }
+
+ @Override
+ public BigInteger bigIntegerValue() {
+ return new BigInteger(toString());
+ }
+
+ @Override
+ public BigInteger bigIntegerValueExact() {
+ return bigIntegerValue();
+ }
+
+ @Override
+ public double doubleValue() {
+ return value;
+ }
+
+ @Override
+ public BigDecimal bigDecimalValue() {
+ return new BigDecimal(toString());
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return ValueType.NUMBER;
+ }
+
+ @Override
+ public String toString() {
+ return Double.toString(value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Double.valueOf(value).hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).doubleValue() == value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorFactoryImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorFactoryImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorFactoryImpl.java
new file mode 100644
index 0000000..b855943
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorFactoryImpl.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core;
+
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class JsonGeneratorFactoryImpl implements JsonGeneratorFactory {
+ private final Map<String, ?> config;
+ private final ConcurrentMap<String, String> cache = new ConcurrentHashMap<String, String>();
+ private final boolean pretty;
+
+ public JsonGeneratorFactoryImpl(final Map<String, ?> config) {
+ this.config = config;
+ this.pretty = Boolean.TRUE.equals(config.get(JsonGenerator.PRETTY_PRINTING)) || "true".equals(config.get(JsonGenerator.PRETTY_PRINTING));
+ }
+
+ @Override
+ public JsonGenerator createGenerator(final Writer writer) {
+ if (pretty) {
+ return new JsonPrettyGeneratorImpl(writer, cache);
+ }
+ return new JsonGeneratorImpl<JsonGeneratorImpl<?>>(writer, cache);
+ }
+
+ @Override
+ public JsonGenerator createGenerator(final OutputStream out) {
+ return createGenerator(new OutputStreamWriter(out));
+ }
+
+ @Override
+ public JsonGenerator createGenerator(final OutputStream out, final Charset charset) {
+ return createGenerator(new OutputStreamWriter(out, charset));
+ }
+
+ @Override
+ public Map<String, ?> getConfigInUse() {
+ return config;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/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
new file mode 100644
index 0000000..e0dd287
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonGeneratorImpl.java
@@ -0,0 +1,317 @@
+/*
+ * 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.core;
+
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.stream.JsonGenerationException;
+import javax.json.stream.JsonGenerator;
+import java.io.IOException;
+import java.io.Writer;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.ConcurrentMap;
+
+public class JsonGeneratorImpl<P extends JsonGeneratorImpl<?>> implements JsonGenerator, JsonChars {
+ protected static final String START_ARRAY = "[";
+ protected static final String END_ARRAY = "]";
+ protected static final String END_OBJECT = "}";
+ protected static final String START_OBJECT = "{";
+ protected static final String NULL = "null";
+ protected static final String NULL_KEY = "null:";
+
+ protected final Writer writer;
+ protected final P parent;
+ protected final boolean array;
+ protected final ConcurrentMap<String, String> cache;
+
+ protected boolean needComma = false;
+
+ public JsonGeneratorImpl(final Writer writer, final ConcurrentMap<String, String> cache) {
+ this(writer, null, false, cache);
+ }
+
+ public JsonGeneratorImpl(final Writer writer, final P parent, final boolean array,
+ final ConcurrentMap<String, String> cache) {
+ this.writer = writer;
+ this.parent = parent;
+ this.array = array;
+ this.cache = cache;
+ }
+
+ private void addCommaIfNeeded() {
+ if (needComma) {
+ try {
+ writer.write(',');
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ needComma = false;
+ }
+ }
+
+ protected JsonGenerator newJsonGenerator(final Writer writer, final P parent, final boolean array) {
+ return new JsonGeneratorImpl<P>(writer, parent, array, cache);
+ }
+
+ // we cache key only since they are generally fixed
+ private String key(final String name) {
+ if (name == null) {
+ return NULL_KEY;
+ }
+ String k = cache.get(name);
+ if (k == null) {
+ k = '"' + Strings.escape(name) + "\":";
+ cache.putIfAbsent(name, k);
+ }
+ return k;
+ }
+
+ @Override
+ public JsonGenerator writeStartObject() {
+ noCheckWriteAndForceComma(START_OBJECT);
+ return newJsonGenerator(writer, (P) this, false);
+ }
+
+ @Override
+ public JsonGenerator writeStartObject(final String name) {
+ noCheckWriteAndForceComma(key(name) + START_OBJECT);
+ return newJsonGenerator(writer, (P) this, false);
+ }
+
+ @Override
+ public JsonGenerator writeStartArray() {
+ noCheckWriteAndForceComma(START_ARRAY);
+ return newJsonGenerator(writer, (P) this, true);
+ }
+
+ @Override
+ public JsonGenerator writeStartArray(final String name) {
+ noCheckWriteAndForceComma(key(name) + START_ARRAY);
+ return newJsonGenerator(writer, (P) this, true);
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final JsonValue value) {
+ if (JsonString.class.isInstance(value)) {
+ return write(name, value == null ? null : value.toString());
+ }
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(value == null ? NULL : value.toString());
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final String value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(value == null ? NULL : "\"" + Strings.escape(value) + "\"");
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final BigInteger value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(value == null ? NULL : value.toString());
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final BigDecimal value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(value == null ? NULL : value.toString());
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final int value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final long value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final double value) {
+ checkObject();
+ checkDoubleRange(value);
+ noCheckWriteAndForceComma(key(name));
+ justWrite(String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String name, final boolean value) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public JsonGenerator writeNull(final String name) {
+ checkObject();
+ noCheckWriteAndForceComma(key(name));
+ justWrite(NULL);
+ return this;
+ }
+
+ @Override
+ public JsonGenerator writeEnd() {
+ needComma = false;
+ noCheckWriteAndForceComma(array ? END_ARRAY : END_OBJECT);
+ return parent != null ? parent : this;
+ }
+
+ @Override
+ public JsonGenerator write(final JsonValue value) {
+ noCheckWriteAndForceComma(String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final String value) {
+ checkArray();
+ noCheckWriteAndForceComma(value);
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final BigDecimal value) {
+ checkArray();
+ noCheckWrite(String.valueOf(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final BigInteger value) {
+ checkArray();
+ noCheckWrite(String.valueOf(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final int value) {
+ checkArray();
+ noCheckWrite(Integer.toString(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final long value) {
+ checkArray();
+ noCheckWrite(Long.toString(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final double value) {
+ checkArray();
+ checkDoubleRange(value);
+ noCheckWrite(Double.toString(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator write(final boolean value) {
+ checkArray();
+ noCheckWrite(Boolean.toString(value));
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public JsonGenerator writeNull() {
+ checkArray();
+ noCheckWriteAndForceComma(NULL);
+ needComma = true;
+ return this;
+ }
+
+ @Override
+ public void close() {
+ try {
+ writer.close();
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ try {
+ writer.flush();
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ }
+
+ protected JsonGenerator noCheckWriteAndForceComma(final String value) {
+ noCheckWrite(value);
+ needComma = true;
+ return this;
+ }
+
+ private void noCheckWrite(String value) {
+ addCommaIfNeeded();
+ justWrite(value);
+ }
+
+ private void justWrite(final String value) {
+ try {
+ writer.write(value);
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ }
+
+ private void checkObject() {
+ if (array) {
+ throw new JsonGenerationException("write(name, param) is only valid in objects");
+ }
+ }
+
+ private void checkArray() {
+ if (!array) {
+ throw new JsonGenerationException("write(param) is only valid in arrays");
+ }
+ }
+
+ private static void checkDoubleRange(final double value) {
+ if (Double.isInfinite(value) || Double.isNaN(value)) {
+ throw new NumberFormatException("double can't be infinite and NaN");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonInMemoryParser.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonInMemoryParser.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonInMemoryParser.java
new file mode 100644
index 0000000..3f26de9
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonInMemoryParser.java
@@ -0,0 +1,165 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.stream.JsonLocation;
+import javax.json.stream.JsonParser;
+import java.math.BigDecimal;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+// we don't use visitor pattern to ensure we work with other impl of JsonObject and JsonArray
+public class JsonInMemoryParser implements EscapedStringAwareJsonParser {
+ private final Iterator<Entry> iterator;
+
+ private Entry next = null;
+
+ public JsonInMemoryParser(final JsonObject object) {
+ final List<Entry> events = new LinkedList<Entry>();
+ generateObjectEvents(events, object);
+ iterator = events.iterator();
+ }
+
+ public JsonInMemoryParser(final JsonArray array) {
+ final List<Entry> events = new LinkedList<Entry>();
+ generateArrayEvents(events, array);
+ iterator = events.iterator();
+ }
+
+ private static void generateObjectEvents(final List<Entry> events, final JsonObject object) {
+ events.add(new Entry(Event.START_OBJECT, object));
+ for (final Map.Entry<String, JsonValue> entry : object.entrySet()) {
+ events.add(new Entry(Event.KEY_NAME, new JsonStringImpl(entry.getKey())));
+ final JsonValue value = entry.getValue();
+ addValueEvents(events, value);
+ }
+ events.add(new Entry(Event.END_OBJECT, object));
+ }
+
+ private static void generateArrayEvents(final List<Entry> events, final JsonArray array) {
+ events.add(new Entry(Event.START_ARRAY, array));
+ for (final JsonValue value : array) {
+ addValueEvents(events, value);
+ }
+ events.add(new Entry(Event.END_ARRAY, array));
+ }
+
+ private static void addValueEvents(final List<Entry> events, final JsonValue value) {
+ if (JsonArray.class.isInstance(value)) {
+ generateArrayEvents(events, JsonArray.class.cast(value));
+ } else if (JsonObject.class.isInstance(value)) {
+ generateObjectEvents(events, JsonObject.class.cast(value));
+ } else if (JsonString.class.isInstance(value)) {
+ events.add(new Entry(Event.VALUE_STRING, JsonValue.class.cast(value)));
+ } else if (JsonNumber.class.isInstance(value)) {
+ events.add(new Entry(Event.VALUE_NUMBER, JsonValue.class.cast(value)));
+ } else if (value == JsonValue.TRUE) {
+ events.add(new Entry(Event.VALUE_TRUE, value));
+ } else if (value == JsonValue.FALSE) {
+ events.add(new Entry(Event.VALUE_FALSE, value));
+ } else if (value == JsonValue.NULL) {
+ events.add(new Entry(Event.VALUE_NULL, value));
+ } else {
+ throw new IllegalArgumentException(value + " not supported");
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public Event next() {
+ next = iterator.next();
+ return next.event;
+ }
+
+ @Override
+ public String getString() {
+ if (JsonObject.class.isInstance(next.value) || JsonArray.class.isInstance(next.value)) {
+ throw new IllegalStateException("String is for numbers and strings");
+ }
+ return getEscapedString();
+ }
+
+ @Override
+ public boolean isIntegralNumber() {
+ if (!JsonNumber.class.isInstance(next.value)) {
+ throw new IllegalStateException("isIntegralNumber is for numbers");
+ }
+ return JsonNumber.class.cast(next.value).isIntegral();
+ }
+
+ @Override
+ public int getInt() {
+ if (!JsonNumber.class.isInstance(next.value)) {
+ throw new IllegalStateException("getInt is for numbers");
+ }
+ return JsonNumber.class.cast(next.value).intValue();
+ }
+
+ @Override
+ public long getLong() {
+ if (!JsonNumber.class.isInstance(next.value)) {
+ throw new IllegalStateException("getLong is for numbers");
+ }
+ return JsonNumber.class.cast(next.value).longValue();
+ }
+
+ @Override
+ public BigDecimal getBigDecimal() {
+ if (!JsonNumber.class.isInstance(next.value)) {
+ throw new IllegalStateException("getBigDecimal is for numbers");
+ }
+ return JsonNumber.class.cast(next.value).bigDecimalValue();
+ }
+
+ @Override
+ public JsonLocation getLocation() { // no location for in memory parsers
+ return new JsonLocationImpl(-1, -1, -1);
+ }
+
+ @Override
+ public String getEscapedString() {
+ return JsonValue.class.cast(next.value).toString();
+ }
+
+ @Override
+ public void close() {
+ // no-op
+ }
+
+ private static class Entry {
+ private final Event event;
+ private final JsonValue value;
+
+ private Entry(final Event event, final JsonValue value) {
+ this.event = event;
+ this.value = value;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonLocationImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonLocationImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonLocationImpl.java
new file mode 100644
index 0000000..7b20e5b
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonLocationImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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.core;
+
+import javax.json.stream.JsonLocation;
+import java.io.Serializable;
+
+public class JsonLocationImpl implements JsonLocation, Serializable {
+ private final long lineNumber;
+ private final long columnNumber;
+ private final long streamOffset;
+
+ public JsonLocationImpl(final long lineNumber, final long columnNumber, final long streamOffset) {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ this.streamOffset = streamOffset;
+ }
+
+ @Override
+ public long getLineNumber() {
+ return lineNumber;
+ }
+
+ @Override
+ public long getColumnNumber() {
+ return columnNumber;
+ }
+
+ @Override
+ public long getStreamOffset() {
+ return streamOffset;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final JsonLocationImpl that = JsonLocationImpl.class.cast(o);
+ return columnNumber == that.columnNumber && lineNumber == that.lineNumber && streamOffset == that.streamOffset;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (lineNumber ^ (lineNumber >>> 32));
+ result = 31 * result + (int) (columnNumber ^ (columnNumber >>> 32));
+ result = 31 * result + (int) (streamOffset ^ (streamOffset >>> 32));
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonLongImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonLongImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonLongImpl.java
new file mode 100644
index 0000000..f54e4b7
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonLongImpl.java
@@ -0,0 +1,96 @@
+/*
+ * 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.core;
+
+import javax.json.JsonNumber;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonLongImpl implements JsonNumber {
+ private final long value;
+
+ public JsonLongImpl(final long value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean isIntegral() {
+ return false;
+ }
+
+ @Override
+ public int intValue() {
+ return (int) value;
+ }
+
+ @Override
+ public int intValueExact() {
+ return intValue();
+ }
+
+ @Override
+ public long longValue() {
+ return value;
+ }
+
+ @Override
+ public long longValueExact() {
+ return value;
+ }
+
+ @Override
+ public BigInteger bigIntegerValue() {
+ return new BigInteger(toString());
+ }
+
+ @Override
+ public BigInteger bigIntegerValueExact() {
+ return bigIntegerValue();
+ }
+
+ @Override
+ public double doubleValue() {
+ return value;
+ }
+
+ @Override
+ public BigDecimal bigDecimalValue() {
+ return new BigDecimal(toString());
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return ValueType.NUMBER;
+ }
+
+ @Override
+ public String toString() {
+ return Long.toString(value);
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) value;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).longValue() == value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonNumberImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonNumberImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonNumberImpl.java
new file mode 100644
index 0000000..c992a9f
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonNumberImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.core;
+
+import javax.json.JsonNumber;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonNumberImpl implements JsonNumber {
+ private final BigDecimal value;
+ private Integer hashCode = null;
+
+ public JsonNumberImpl(final BigDecimal decimal) {
+ this.value = decimal;
+ }
+
+ @Override
+ public boolean isIntegral() {
+ return value.scale() == 0;
+ }
+
+ @Override
+ public int intValue() {
+ return value.intValue();
+ }
+
+ @Override
+ public int intValueExact() {
+ return value.intValueExact();
+ }
+
+ @Override
+ public long longValue() {
+ return value.longValue();
+ }
+
+ @Override
+ public long longValueExact() {
+ return value.longValueExact();
+ }
+
+ @Override
+ public BigInteger bigIntegerValue() {
+ return value.toBigInteger();
+ }
+
+ @Override
+ public BigInteger bigIntegerValueExact() {
+ return value.toBigIntegerExact();
+ }
+
+ @Override
+ public double doubleValue() {
+ return value.doubleValue();
+ }
+
+ @Override
+ public BigDecimal bigDecimalValue() {
+ return value;
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return ValueType.NUMBER;
+ }
+
+ @Override
+ public String toString() {
+ return value.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == null) {
+ hashCode = value.hashCode();
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).bigDecimalValue().equals(value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectBuilderImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectBuilderImpl.java
new file mode 100644
index 0000000..8b545a2
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectBuilderImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonObjectBuilderImpl implements JsonObjectBuilder {
+ private final JsonObjectImpl delegate = new JsonObjectImpl();
+
+ @Override
+ public JsonObjectBuilder add(final String name, final JsonValue value) {
+ delegate.putInternal(name, value);
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final String value) {
+ delegate.putInternal(name, new JsonStringImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final BigInteger value) {
+ delegate.putInternal(name, new JsonNumberImpl(new BigDecimal(value)));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final BigDecimal value) {
+ delegate.putInternal(name, new JsonNumberImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final int value) {
+ delegate.putInternal(name, new JsonLongImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final long value) {
+ delegate.putInternal(name, new JsonLongImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final double value) {
+ delegate.putInternal(name, new JsonDoubleImpl(value));
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final boolean value) {
+ delegate.putInternal(name, value ? JsonValue.TRUE : JsonValue.FALSE);
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder addNull(final String name) {
+ delegate.putInternal(name, JsonValue.NULL);
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final JsonObjectBuilder builder) {
+ delegate.putInternal(name, builder.build());
+ return this;
+ }
+
+ @Override
+ public JsonObjectBuilder add(final String name, final JsonArrayBuilder builder) {
+ delegate.putInternal(name, builder.build());
+ return this;
+ }
+
+ @Override
+ public JsonObject build() {
+ return delegate;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectImpl.java
new file mode 100644
index 0000000..01a2615
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonObjectImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class JsonObjectImpl extends LinkedHashMap<String, JsonValue> implements JsonObject {
+ private Integer hashCode = null;
+
+ private <T> T value(final String name, final Class<T> clazz) {
+ final Object v = get(name);
+ if (v != null) {
+ return clazz.cast(v);
+ }
+ throw new NullPointerException("no mapping for " + name);
+ }
+
+ @Override
+ public JsonArray getJsonArray(final String name) {
+ return value(name, JsonArray.class);
+ }
+
+ @Override
+ public JsonObject getJsonObject(final String name) {
+ return value(name, JsonObject.class);
+ }
+
+ @Override
+ public JsonNumber getJsonNumber(final String name) {
+ return value(name, JsonNumber.class);
+ }
+
+ @Override
+ public JsonString getJsonString(final String name) {
+ return value(name, JsonString.class);
+ }
+
+ @Override
+ public String getString(final String name) {
+ final JsonString str = getJsonString(name);
+ return str != null ? str.getString() : null;
+ }
+
+ @Override
+ public String getString(final String name, final String defaultValue) {
+ try {
+ return getJsonString(name).getString();
+ } catch (final NullPointerException npe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public int getInt(final String name) {
+ return getJsonNumber(name).intValue();
+ }
+
+ @Override
+ public int getInt(final String name, final int defaultValue) {
+ try {
+ return getJsonNumber(name).intValue();
+ } catch (final NullPointerException npe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public boolean getBoolean(final String name) {
+ return value(name, JsonValue.class) == JsonValue.TRUE;
+ }
+
+ @Override
+ public boolean getBoolean(final String name, final boolean defaultValue) {
+ try {
+ return getBoolean(name);
+ } catch (final NullPointerException npe) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public boolean isNull(final String name) {
+ return value(name, JsonValue.class) == JsonValue.NULL;
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return ValueType.OBJECT;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder("{");
+ final Iterator<Map.Entry<String, JsonValue>> it = entrySet().iterator();
+ boolean hasNext = it.hasNext();
+ while (hasNext) {
+ final Map.Entry<String, JsonValue> entry = it.next();
+
+ builder.append('"').append(entry.getKey()).append("\":");
+
+ final JsonValue value = entry.getValue();
+ if (JsonString.class.isInstance(value)) {
+ builder.append(JsonChars.QUOTE).append(value.toString()).append(JsonChars.QUOTE);
+ } else {
+ builder.append(value != JsonValue.NULL ? value.toString() : JsonChars.NULL);
+ }
+
+ hasNext = it.hasNext();
+ if (hasNext) {
+ builder.append(",");
+ }
+ }
+ return builder.append('}').toString();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return JsonObject.class.isInstance(obj) && super.equals(obj);
+ }
+
+ @Override
+ public void clear() {
+ throw immutable();
+ }
+
+ @Override
+ public JsonValue put(String key, JsonValue value) {
+ throw immutable();
+ }
+
+ @Override
+ public void putAll(Map<? extends String, ? extends JsonValue> jsonObject) {
+ throw immutable();
+ }
+
+ @Override
+ public JsonValue remove(Object key) {
+ throw immutable();
+ }
+
+ private static UnsupportedOperationException immutable() {
+ throw new UnsupportedOperationException("JsonObject is immutable. You can create another one thanks to JsonObjectBuilder");
+ }
+
+ public void putInternal(final String name, final JsonValue value) {
+ super.put(name, value);
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == null) {
+ hashCode = super.hashCode();
+ }
+ return hashCode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/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
new file mode 100644
index 0000000..b138d84
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonParserFactoryImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.stream.JsonParser;
+import javax.json.stream.JsonParserFactory;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+public class JsonParserFactoryImpl implements JsonParserFactory {
+ public static final String MAX_STRING_LENGTH = "org.apache.fleece.max-string-length";
+ public static final int DEFAULT_MAX_SIZE = Integer.getInteger(MAX_STRING_LENGTH, 8192);
+
+ private final Map<String, ?> config;
+ private final int maxSize;
+
+ public JsonParserFactoryImpl(final Map<String, ?> config) {
+ this.config = config;
+ final Object maxStringSize = config.get(MAX_STRING_LENGTH);
+ if (maxStringSize == null) {
+ maxSize = DEFAULT_MAX_SIZE;
+ } else if (Number.class.isInstance(maxStringSize)) {
+ maxSize = Number.class.cast(maxStringSize).intValue();
+ } else {
+ maxSize = Integer.parseInt(maxStringSize.toString());
+ }
+ }
+
+ @Override
+ public JsonParser createParser(final Reader reader) {
+ return new JsonStreamParser(reader, maxSize);
+ }
+
+ @Override
+ public JsonParser createParser(final InputStream in) {
+ return new JsonStreamParser(in, maxSize);
+ }
+
+ @Override
+ public JsonParser createParser(final InputStream in, final Charset charset) {
+ return new JsonStreamParser(in, charset, maxSize);
+ }
+
+ @Override
+ public JsonParser createParser(final JsonObject obj) {
+ return new JsonInMemoryParser(obj);
+ }
+
+ @Override
+ public JsonParser createParser(final JsonArray array) {
+ return new JsonInMemoryParser(array);
+ }
+
+ @Override
+ public Map<String, ?> getConfigInUse() {
+ return config;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonPrettyGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonPrettyGeneratorImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonPrettyGeneratorImpl.java
new file mode 100644
index 0000000..ff965bd
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonPrettyGeneratorImpl.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core;
+
+import javax.json.stream.JsonGenerationException;
+import javax.json.stream.JsonGenerator;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.concurrent.ConcurrentMap;
+
+public class JsonPrettyGeneratorImpl extends JsonGeneratorImpl<JsonPrettyGeneratorImpl> {
+ private static final String DEFAULT_INDENTATION = " ";
+
+ private String indent; // should be final but writeEnd needs it not final, we could change write() to support indent
+
+ public JsonPrettyGeneratorImpl(final Writer writer, final ConcurrentMap<String, String> cache) {
+ this(writer, null, false, "", cache);
+ }
+
+ public JsonPrettyGeneratorImpl(final Writer writer, final JsonPrettyGeneratorImpl parent,
+ final boolean array, final String prefix,
+ final ConcurrentMap<String, String> cache) {
+ super(writer, parent, array, cache);
+ this.indent = prefix;
+ }
+
+ private void addCommaIfNeeded() {
+ if (needComma) {
+ try {
+ writer.write(',');
+ ln();
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ needComma = false;
+ }
+ }
+
+ private void ln() {
+ try {
+ writer.write('\n');
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ }
+
+ private String nextIndent() {
+ return indent != null ? indent + DEFAULT_INDENTATION : null;
+ }
+
+ @Override
+ protected JsonGenerator newJsonGenerator(final Writer writer, final JsonPrettyGeneratorImpl parent, final boolean array) {
+ return new JsonPrettyGeneratorImpl(writer, parent, array, nextIndent(), cache);
+ }
+
+ @Override
+ public JsonGenerator writeStartObject() {
+ final JsonGenerator generator = super.writeStartObject();
+ ln();
+ return generator;
+ }
+
+ @Override
+ public JsonGenerator writeStartObject(final String name) {
+ final JsonGenerator generator = super.writeStartObject(name);
+ ln();
+ return generator;
+ }
+
+ @Override
+ public JsonGenerator writeStartArray() {
+ final JsonGenerator generator = super.writeStartArray();
+ ln();
+ return generator;
+ }
+
+ @Override
+ public JsonGenerator writeStartArray(final String name) {
+ final JsonGenerator generator = super.writeStartArray(name);
+ ln();
+ return generator;
+ }
+
+ @Override
+ public JsonGenerator writeEnd() {
+ ln();
+ needComma = false;
+ final String thisIndent = indent;
+ indent = parent != null ? parent.indent : indent;
+ noCheckWriteAndForceComma(array ? "]" : "}");
+ indent = thisIndent;
+ return parent != null ? parent : this;
+ }
+
+ @Override
+ protected JsonGenerator noCheckWriteAndForceComma(final String value) {
+ addCommaIfNeeded();
+ try {
+ if (indent != null) {
+ writer.write(indent);
+ }
+ writer.write(value);
+ } catch (final IOException e) {
+ throw new JsonGenerationException(e.getMessage(), e);
+ }
+ needComma = true;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonProviderImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonProviderImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonProviderImpl.java
new file mode 100644
index 0000000..efd33ce
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonProviderImpl.java
@@ -0,0 +1,117 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
+import javax.json.JsonReaderFactory;
+import javax.json.JsonWriter;
+import javax.json.JsonWriterFactory;
+import javax.json.spi.JsonProvider;
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
+import javax.json.stream.JsonParser;
+import javax.json.stream.JsonParserFactory;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class JsonProviderImpl extends JsonProvider {
+ @Override
+ public JsonParser createParser(final InputStream in) {
+ return createParserFactory(Collections.<String, Object>emptyMap()).createParser(in);
+ }
+
+ @Override
+ public JsonParser createParser(final Reader reader) {
+ return createParserFactory(Collections.<String, Object>emptyMap()).createParser(reader);
+ }
+
+ @Override
+ public JsonReader createReader(final InputStream in) {
+ return new JsonReaderImpl(in);
+ }
+
+ @Override
+ public JsonReader createReader(final Reader reader) {
+ return new JsonReaderImpl(reader);
+ }
+
+ @Override
+ public JsonParserFactory createParserFactory(final Map<String, ?> config) {
+ return new JsonParserFactoryImpl(config);
+ }
+
+ @Override
+ public JsonReaderFactory createReaderFactory(final Map<String, ?> config) {
+ return new JsonReaderFactoryImpl(config);
+ }
+
+ @Override
+ public JsonGenerator createGenerator(final Writer writer) {
+ return new JsonGeneratorImpl(writer, new ConcurrentHashMap<String, String>());
+ }
+
+ @Override
+ public JsonGenerator createGenerator(final OutputStream out) {
+ return createGenerator(new OutputStreamWriter(out));
+ }
+
+ @Override
+ public JsonGeneratorFactory createGeneratorFactory(final Map<String, ?> config) {
+ return new JsonGeneratorFactoryImpl(config);
+ }
+
+ @Override
+ public JsonWriter createWriter(final Writer writer) {
+ return new JsonWriterImpl(createGenerator(writer));
+ }
+
+ @Override
+ public JsonWriter createWriter(final OutputStream out) {
+ return createWriter(new OutputStreamWriter(out));
+ }
+
+ @Override
+ public JsonWriterFactory createWriterFactory(final Map<String, ?> config) {
+ return new JsonWriterFactoryImpl(config);
+ }
+
+ @Override
+ public JsonObjectBuilder createObjectBuilder() {
+ return new JsonObjectBuilderImpl();
+ }
+
+ @Override
+ public JsonArrayBuilder createArrayBuilder() {
+ return new JsonArrayBuilderImpl();
+ }
+
+ @Override
+ public JsonBuilderFactory createBuilderFactory(final Map<String, ?> config) {
+ return new JsonBuilderFactoryImpl(config);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/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
new file mode 100644
index 0000000..934a299
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderFactoryImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.core;
+
+import javax.json.JsonReader;
+import javax.json.JsonReaderFactory;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+public class JsonReaderFactoryImpl implements JsonReaderFactory {
+ private final Map<String, ?> config;
+
+ public JsonReaderFactoryImpl(final Map<String, ?> config) {
+ this.config = config;
+ }
+
+ @Override
+ public JsonReader createReader(final Reader reader) {
+ return new JsonReaderImpl(reader);
+ }
+
+ @Override
+ public JsonReader createReader(final InputStream in) {
+ return new JsonReaderImpl(in);
+ }
+
+ @Override
+ public JsonReader createReader(final InputStream in, final Charset charset) {
+ return new JsonReaderImpl(new InputStreamReader(in, charset));
+ }
+
+ @Override
+ public Map<String, ?> getConfigInUse() {
+ return config;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderImpl.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderImpl.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderImpl.java
new file mode 100644
index 0000000..03d52f2
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderImpl.java
@@ -0,0 +1,331 @@
+/*
+ * 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.core;
+
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import javax.json.stream.JsonParser;
+import javax.json.stream.JsonParsingException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+
+public class JsonReaderImpl implements JsonReader {
+ private final EscapedStringAwareJsonParser parser;
+ private final JsonReaderListenerFactory listenerFactory;
+
+ public JsonReaderImpl(final InputStream in) {
+ this(new JsonStreamParser(in, JsonParserFactoryImpl.DEFAULT_MAX_SIZE), new JsonListenerFactory());
+ }
+
+ public JsonReaderImpl(final Reader in) {
+ this(new JsonStreamParser(in, JsonParserFactoryImpl.DEFAULT_MAX_SIZE), new JsonListenerFactory());
+ }
+
+ public JsonReaderImpl(final EscapedStringAwareJsonParser parser, final JsonReaderListenerFactory listenerFactory) {
+ this.parser = parser;
+ this.listenerFactory = listenerFactory;
+ }
+
+ @Override
+ public JsonStructure read() {
+ if (!parser.hasNext()) {
+ throw new JsonParsingException("Nothing to read", new JsonLocationImpl(1, 1, 0));
+ }
+ switch (parser.next()) {
+ case START_OBJECT:
+ final JsonReaderListener subObject = listenerFactory.subObject();
+ parseObject(subObject);
+ return JsonObject.class.cast(subObject.getObject());
+ case START_ARRAY:
+ final JsonReaderListener subArray = listenerFactory.subArray();
+ parseArray(subArray);
+ return JsonArray.class.cast(subArray.getObject());
+ default:
+ throw new JsonParsingException("Unknown structure: " + parser.next(), parser.getLocation());
+ }
+ }
+
+ @Override
+ public JsonObject readObject() {
+ return JsonObject.class.cast(read());
+ }
+
+ @Override
+ public JsonArray readArray() {
+ return JsonArray.class.cast(read());
+ }
+
+ @Override
+ public void close() {
+ parser.close();
+ }
+
+ private static class JsonListenerFactory implements JsonReaderListenerFactory {
+ @Override
+ public JsonReaderListener subObject() {
+ return new JsonObjectListener();
+ }
+
+ @Override
+ public JsonReaderListener subArray() {
+ return new JsonArrayListener();
+ }
+ }
+
+ private static class JsonObjectListener implements JsonReaderListener {
+ private JsonObjectImpl object = new JsonObjectImpl();
+ private String key = null;
+
+ @Override
+ public Object getObject() {
+ return object;
+ }
+
+ @Override
+ public void onKey(final String string) {
+ key = string;
+ }
+
+ @Override
+ public void onValue(final String string, final String escaped) {
+ final JsonStringImpl value = new JsonStringImpl(string, escaped);
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onLong(final long aLong) {
+ final JsonLongImpl value = new JsonLongImpl(aLong);
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onBigDecimal(final BigDecimal bigDecimal) {
+ final JsonNumberImpl value = new JsonNumberImpl(bigDecimal);
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onNull() {
+ final JsonValue value = JsonValue.NULL;
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onTrue() {
+ final JsonValue value = JsonValue.TRUE;
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onFalse() {
+ final JsonValue value = JsonValue.FALSE;
+ object.putInternal(key, value);
+ }
+
+ @Override
+ public void onObject(final Object obj) {
+ final JsonObject jsonObject = JsonObject.class.cast(obj);
+ object.putInternal(key, jsonObject);
+ }
+
+ @Override
+ public void onArray(final Object arr) {
+ final JsonArray jsonArry = JsonArray.class.cast(arr);
+ object.putInternal(key, jsonArry);
+ }
+ }
+
+ private static class JsonArrayListener implements JsonReaderListener {
+ private JsonArrayImpl array = new JsonArrayImpl();
+ private String key = null;
+
+ @Override
+ public Object getObject() {
+ return array;
+ }
+
+ @Override
+ public void onKey(final String string) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onValue(final String string, final String escaped) {
+ final JsonStringImpl value = new JsonStringImpl(string, escaped);
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onLong(final long aLong) {
+ final JsonLongImpl value = new JsonLongImpl(aLong);
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onBigDecimal(final BigDecimal bigDecimal) {
+ final JsonNumberImpl value = new JsonNumberImpl(bigDecimal);
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onNull() {
+ final JsonValue value = JsonValue.NULL;
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onTrue() {
+ final JsonValue value = JsonValue.TRUE;
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onFalse() {
+ final JsonValue value = JsonValue.FALSE;
+ array.addInternal(value);
+ }
+
+ @Override
+ public void onObject(final Object obj) {
+ final JsonObject jsonObject = JsonObject.class.cast(obj);
+ array.addInternal(jsonObject);
+ }
+
+ @Override
+ public void onArray(final Object arr) {
+ final JsonArray jsonArry = JsonArray.class.cast(arr);
+ array.addInternal(jsonArry);
+ }
+ }
+
+ private void parseObject(final JsonReaderListener listener) {
+ while (parser.hasNext()) {
+ final JsonParser.Event next = parser.next();
+ switch (next) {
+ case KEY_NAME:
+ listener.onKey(parser.getString());
+ break;
+
+ case VALUE_STRING:
+ listener.onValue(parser.getString(), parser.getEscapedString());
+ break;
+
+ case START_OBJECT:
+ final JsonReaderListener subListenerObject = listenerFactory.subObject();
+ parseObject(subListenerObject);
+ listener.onObject(subListenerObject.getObject());
+ break;
+
+ case START_ARRAY:
+ final JsonReaderListener subListenerArray = listenerFactory.subArray();
+ parseArray(subListenerArray);
+ listener.onArray(subListenerArray.getObject());
+ break;
+
+ case VALUE_NUMBER:
+ if (parser.isIntegralNumber()) {
+ listener.onLong(parser.getLong());
+ } else {
+ listener.onBigDecimal(parser.getBigDecimal());
+ }
+ break;
+
+ case VALUE_NULL:
+ listener.onNull();
+ break;
+
+ case VALUE_TRUE:
+ listener.onTrue();
+ break;
+
+ case VALUE_FALSE:
+ listener.onFalse();
+ break;
+
+ case END_OBJECT:
+ return;
+
+ case END_ARRAY:
+ throw new JsonParsingException("']', shouldn't occur", JsonStreamParser.location(parser));
+
+ default:
+ throw new JsonParsingException(next.name() + ", shouldn't occur", JsonStreamParser.location(parser));
+ }
+ }
+ }
+
+ private void parseArray(final JsonReaderListener listener) {
+ while (parser.hasNext()) {
+ final JsonParser.Event next = parser.next();
+ switch (next) {
+ case VALUE_STRING:
+ listener.onValue(parser.getString(), parser.getEscapedString());
+ break;
+
+ case VALUE_NUMBER:
+ if (parser.isIntegralNumber()) {
+ listener.onLong(parser.getLong());
+ } else {
+ listener.onBigDecimal(parser.getBigDecimal());
+ }
+ break;
+
+ case START_OBJECT:
+ final JsonReaderListener subListenerObject = listenerFactory.subObject();
+ parseObject(subListenerObject);
+ listener.onObject(subListenerObject.getObject());
+ break;
+
+ case START_ARRAY:
+ final JsonReaderListener subListenerArray = listenerFactory.subArray();
+ parseArray(subListenerArray);
+ listener.onArray(subListenerArray.getObject());
+ break;
+
+ case END_ARRAY:
+ return;
+
+ case VALUE_NULL:
+ listener.onNull();
+ break;
+
+ case VALUE_TRUE:
+ listener.onTrue();
+ break;
+
+ case VALUE_FALSE:
+ listener.onFalse();
+ break;
+
+ case KEY_NAME:
+ throw new JsonParsingException("array doesn't have keys", JsonStreamParser.location(parser));
+
+ case END_OBJECT:
+ throw new JsonParsingException("'}', shouldn't occur", JsonStreamParser.location(parser));
+
+ default:
+ throw new JsonParsingException(next.name() + ", shouldn't occur", JsonStreamParser.location(parser));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fleece/blob/422e96f3/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderListener.java
----------------------------------------------------------------------
diff --git a/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderListener.java b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderListener.java
new file mode 100644
index 0000000..b3ba294
--- /dev/null
+++ b/fleece-core/src/main/java/org/apache/fleece/core/JsonReaderListener.java
@@ -0,0 +1,43 @@
+/*
+ * 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.core;
+
+import java.math.BigDecimal;
+
+public interface JsonReaderListener {
+ Object getObject();
+
+ void onKey(String string);
+
+ void onValue(String string, String escaped);
+
+ void onLong(long aLong);
+
+ void onBigDecimal(BigDecimal bigDecimal);
+
+ void onNull();
+
+ void onTrue();
+
+ void onFalse();
+
+ void onObject(Object object);
+
+ void onArray(Object array);
+}