You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2013/11/02 18:08:54 UTC
svn commit: r1538225 - in /jena/trunk/jena-arq/src:
main/java/org/apache/jena/atlas/json/JsonBuilder.java
test/java/org/apache/jena/atlas/json/TS_JSON.java
test/java/org/apache/jena/atlas/json/TestJsonBuilder.java
Author: andy
Date: Sat Nov 2 17:08:54 2013
New Revision: 1538225
URL: http://svn.apache.org/r1538225
Log:
Builder pattern for JSON.
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/json/JsonBuilder.java
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TestJsonBuilder.java
Modified:
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TS_JSON.java
Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/json/JsonBuilder.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/json/JsonBuilder.java?rev=1538225&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/json/JsonBuilder.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/json/JsonBuilder.java Sat Nov 2 17:08:54 2013
@@ -0,0 +1,208 @@
+/**
+ * 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.jena.atlas.json ;
+
+import java.math.BigDecimal ;
+import java.util.ArrayDeque ;
+import java.util.Deque ;
+
+import org.apache.jena.atlas.logging.Log ;
+
+/* Builder pattern for JSON.
+ * The JsonValue built can be an array or object at the outmost leve, but not a atomic value.
+ */
+public class JsonBuilder {
+
+ public static void main(String... argv) throws Exception {
+
+ // c.f. JSWriter
+
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startArray().value(3).value(4).finishArray() ;
+ JsonValue value1 = builder.build() ;
+ JSON.write(value1) ;
+ System.out.println() ;
+ System.out.println() ;
+
+ builder.reset() ;
+ builder.startObject() ;
+
+ builder.key("bar").value("foo") ;
+ builder.key("bar2").value(5) ;
+ builder.key("bar3").startObject().key("inner1").value(true).key("inner2").value(false).finishObject() ;
+
+ builder.key("outer") ;
+ builder.startObject().key("array").startArray().value(3).value(4).finishArray().finishObject() ;
+
+ builder.finishObject() ;
+
+ JsonValue value2 = builder.build() ;
+ JSON.write(value2) ;
+ System.out.println() ;
+ System.out.println() ;
+ System.out.println("DONE") ;
+
+ }
+
+ // =============
+
+ // If not an array or object.
+ private JsonValue builtValue = null ;
+ private Deque<JsonArray> arrays = new ArrayDeque<JsonArray>() ;
+ private Deque<JsonObject> objects = new ArrayDeque<JsonObject>() ;
+
+ private static enum State {
+ ARRAY, OBJECT
+ }
+ private Deque<State> stack = new ArrayDeque<State>() ;
+
+ // The depth of this stack is the object depth.
+ private Deque<String> keys = new ArrayDeque<String>() ;
+
+ public JsonBuilder() {
+
+ }
+
+ public JsonValue build() {
+ if ( builtValue == null ) {
+ if ( objects.isEmpty() && arrays.isEmpty() )
+ throw new JsonException("Alignment error: no object or array started") ;
+ throw new JsonException("Alignment error: unfinished outer object or array") ;
+ }
+ return builtValue ;
+ }
+
+ public void reset() {
+ builtValue = null ;
+ stack.clear() ;
+ objects.clear() ;
+ keys.clear();
+ arrays.clear();
+ }
+
+ public JsonBuilder startObject() {
+ objects.push(new JsonObject()) ;
+ stack.push(State.OBJECT) ;
+ return this ;
+ }
+
+ public JsonBuilder finishObject() {
+ if ( stack.isEmpty() )
+ throw new JsonException("Alignment error : already built outer most object or array") ;
+ State state = stack.pop() ;
+ if ( state != State.OBJECT )
+ throw new JsonException("JSON build error : not in an object") ;
+ JsonValue value = objects.pop() ;
+ maybeObjectOrArray(value) ;
+ if ( stack.isEmpty() )
+ builtValue = value ;
+ return this ;
+ }
+
+ public JsonBuilder startArray() {
+ arrays.push(new JsonArray()) ;
+ stack.push(State.ARRAY) ;
+ return this ;
+ }
+
+ public JsonBuilder finishArray() {
+ if ( stack.isEmpty() )
+ throw new JsonException("Alignment error : already built outer most object or array") ;
+
+ State state = stack.pop() ;
+ if ( state != State.ARRAY )
+ throw new JsonException("JSON build error : not in an array") ;
+
+ JsonValue value = arrays.pop() ;
+ maybeObjectOrArray(value) ;
+ if ( stack.isEmpty() )
+ builtValue = value ;
+ return this ;
+ }
+
+ public JsonBuilder key(String key) {
+ State state = stack.peek() ;
+ if ( state != State.OBJECT )
+ throw new JsonException("JSON build error : not in an object") ;
+ keys.push(key) ;
+ return this ;
+ }
+
+ private void maybeObjectOrArray(JsonValue value) {
+ if ( stack.size() == 0 )
+ // Error.
+ return ;
+
+ switch (stack.peek()) {
+ case OBJECT : {
+ String k = keys.pop() ;
+ JsonObject obj = objects.peek() ;
+ if ( obj.hasKey(k) )
+ Log.warn(this, "Duplicate key '" + k + "' for object") ;
+ obj.put(k, value) ;
+ return ;
+ }
+ case ARRAY : {
+ arrays.peek().add(value) ;
+ return ;
+ }
+ }
+ }
+
+ public JsonBuilder value(JsonValue v) {
+ maybeObjectOrArray(v) ;
+ return this ;
+ }
+
+ public JsonBuilder value(boolean b) {
+ JsonValue value = new JsonBoolean(b) ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+
+ public JsonBuilder value(BigDecimal decimal) {
+ JsonValue value = JsonNumber.value(decimal) ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+
+ public JsonBuilder value(double d) {
+ JsonValue value = JsonNumber.value(d) ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+
+ public JsonBuilder value(long val) {
+ JsonValue value = JsonNumber.value(val) ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+
+ public JsonBuilder valueNull() {
+ JsonValue value = JsonNull.instance ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+
+ public JsonBuilder value(String string) {
+ JsonValue value = new JsonString(string) ;
+ maybeObjectOrArray(value) ;
+ return this ;
+ }
+}
Modified: jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TS_JSON.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TS_JSON.java?rev=1538225&r1=1538224&r2=1538225&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TS_JSON.java (original)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TS_JSON.java Sat Nov 2 17:08:54 2013
@@ -26,6 +26,7 @@ import org.junit.runners.Suite ;
TestJson.class
, TestJsonExt.class
, TestJsonWriter.class
+ , TestJsonBuilder.class
})
public class TS_JSON
{}
Added: jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TestJsonBuilder.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TestJsonBuilder.java?rev=1538225&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TestJsonBuilder.java (added)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/json/TestJsonBuilder.java Sat Nov 2 17:08:54 2013
@@ -0,0 +1,103 @@
+/**
+ * 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.jena.atlas.json;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestJsonBuilder extends BaseTest{
+ // The Jena JSON parser is more livberal than strict JSON to make embedding easier.
+ // * Keys do not need quotes
+ // * Strings can use ''
+
+ @Test public void jsonBuild01() {
+ JsonValue x = JSON.parseAny("{ }") ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject() ;
+ builder.finishObject() ;
+ JsonValue v = builder.build() ;
+ assertEquals(x,v) ;
+ }
+
+ @Test public void jsonBuild02() {
+ JsonValue x = JSON.parseAny("{ a: 'A', b:'B'}") ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject() ;
+ builder.key("a").value("A") ;
+ builder.key("b").value("B") ;
+ builder.finishObject() ;
+ JsonValue v = builder.build() ;
+ assertEquals(x,v) ;
+ }
+
+
+ @Test public void jsonBuild03() {
+ JsonValue x = JSON.parseAny("[ ]") ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startArray() ;
+ builder.finishArray() ;
+ JsonValue v = builder.build() ;
+ assertEquals(x,v) ;
+ }
+
+ @Test public void jsonBuild04() {
+ JsonValue x = JSON.parseAny("{ a: [1], b:'B'}") ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject() ;
+ builder.key("a").startArray().value(1).finishArray() ;
+ builder.key("b").value("B") ;
+ builder.finishObject() ;
+ JsonValue v = builder.build() ;
+ assertEquals(x,v) ;
+ }
+
+ @Test public void jsonBuild05() {
+ JsonValue x = JSON.parseAny("[ { a: 'B'} , 56]") ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startArray() ;
+
+ builder.startObject().key("a").value("B").finishObject() ;
+ builder.value(56) ;
+
+ builder.finishArray() ;
+ JsonValue v = builder.build() ;
+ assertEquals(x,v) ;
+ }
+
+
+ @Test(expected=JsonException.class)
+ public void jsonBuildErr00() {
+ JsonBuilder builder = new JsonBuilder() ;
+ JsonValue v = builder.build() ;
+ }
+
+ @Test(expected=JsonException.class)
+ public void jsonBuildErr01() {
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startArray() ;
+ builder.finishObject() ;
+ }
+
+ @Test(expected=JsonException.class)
+ public void jsonBuildErr02() {
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject() ;
+ builder.finishArray() ;
+ }
+}