changeset 930:b65a8ddf4f12

JsonConfigurationReader
author Devel 2
date Mon, 07 May 2018 13:01:36 +0200
parents bc5dbd2db8c9
children 5ce6fbe6a4e7
files stress-tester/pom.xml stress-tester/src/main/java/com/passus/st/config/JsonConfigurationReader.java stress-tester/src/main/java/com/passus/st/utils/JsonUtils.java stress-tester/src/test/java/com/passus/st/config/ConfigurationTestUtils.java stress-tester/src/test/java/com/passus/st/config/JsonConfigurationReaderTest.java
diffstat 5 files changed, 322 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/stress-tester/pom.xml	Fri Apr 27 16:02:48 2018 +0200
+++ b/stress-tester/pom.xml	Mon May 07 13:01:36 2018 +0200
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<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">
+<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">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.passus.st</groupId>
     <artifactId>stress-tester</artifactId>
@@ -13,7 +14,7 @@
         <sonar.jdbc.url>jdbc:h2:tcp://172.16.60.100/sonar</sonar.jdbc.url>
         <sonar.host.url>http://172.16.60.100:9000</sonar.host.url>
     </properties>
-    
+
     <repositories>
         <repository>
             <id>repo.dev.passus.com.pl-release</id>
@@ -24,7 +25,7 @@
             <url>http://repo.dev.passus.com.pl/libs-snapshot-local</url>
         </repository>
     </repositories>
-    
+
     <build>
         <finalName>${project.artifactId}</finalName>
         <plugins>
@@ -82,7 +83,7 @@
             </plugin>
         </plugins>
     </build>
-    
+
     <dependencies>
 
         <dependency>
@@ -150,6 +151,18 @@
         </dependency>
 
         <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.9.5</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.9.5</version>
+        </dependency>
+
+        <dependency>
             <groupId>com.jayway.jsonpath</groupId>
             <artifactId>json-path</artifactId>
             <version>2.4.0</version>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/config/JsonConfigurationReader.java	Mon May 07 13:01:36 2018 +0200
@@ -0,0 +1,123 @@
+package com.passus.st.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.passus.commons.Assert;
+import com.passus.config.*;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.passus.st.utils.JsonUtils.*;
+
+public class JsonConfigurationReader implements ConfigurationReader, Closeable {
+
+    private final Reader reader;
+
+    public JsonConfigurationReader(String content) {
+        this(new StringReader(content));
+    }
+
+    public JsonConfigurationReader(File file) throws FileNotFoundException {
+        this(new FileReader(file));
+    }
+
+    public JsonConfigurationReader(Reader reader) {
+        Assert.notNull(reader, "reader");
+        this.reader = reader;
+    }
+
+    private CCompositeNode readRootNode() throws IOException, NodeException {
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jNode = mapper.readTree(reader);
+
+        if (jNode == null) {
+            return new CMapNode();
+        }
+
+        checkNodeType(jNode, JsonNodeType.OBJECT);
+        return (CCompositeNode) readNode(jNode);
+    }
+
+    public CCompositeNode readNode() throws IOException, NodeException {
+        return readRootNode();
+    }
+
+    private CNode readNode(JsonNode jNode) throws NodeException {
+        if (jNode.isObject()) {
+            CMapNode mNode = new CMapNode();
+            ObjectNode jObjNode = ((ObjectNode) jNode);
+
+            Iterator<Map.Entry<String, JsonNode>> it = jObjNode.fields();
+            while (it.hasNext()) {
+                Map.Entry<String, JsonNode> entry = it.next();
+                String name = entry.getKey();
+                JsonNode jTupleNode = entry.getValue();
+
+                CTupleNode tuple = new CTupleNode(name);
+                tuple.setNode(readNode(jTupleNode));
+                mNode.add(tuple);
+            }
+
+            return mNode;
+        } else if (jNode.isArray()) {
+            CListNode lNode = new CListNode();
+            ArrayNode jArrNode = (ArrayNode) jNode;
+
+            for (int i = 0; i < jArrNode.size(); i++) {
+                JsonNode child = jArrNode.get(i);
+                lNode.add(readNode(child));
+            }
+
+            return lNode;
+        } else if (jNode.isValueNode()) {
+            return toValueNode(jNode);
+        } else {
+            throw nodeException("Invalid node type '" + jNode.getNodeType() + "'.", jNode);
+        }
+    }
+
+    @Override
+    public Configuration read() throws IOException, NodeException {
+        CCompositeNode node = readRootNode();
+        return new ConfigurationImpl((CCompositeNode) node);
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (reader != null) {
+            try {
+                reader.close();
+            } catch (Exception ignore) {
+            }
+        }
+    }
+
+    public static CCompositeNode readNodeFromString(String content) throws IOException, NodeException {
+        try (JsonConfigurationReader cfgReader = new JsonConfigurationReader(content)) {
+            return cfgReader.readNode();
+        }
+    }
+
+    public static CCompositeNode readNodeFromFile(File file) throws IOException, NodeException {
+        try (JsonConfigurationReader cfgReader = new JsonConfigurationReader(file)) {
+            return cfgReader.readNode();
+        }
+    }
+
+    public static Configuration readFromString(String content) throws IOException, NodeException {
+        try (JsonConfigurationReader cfgReader = new JsonConfigurationReader(content)) {
+            return cfgReader.read();
+        }
+    }
+
+    public static Configuration readFromFile(File file) throws IOException, NodeException {
+        try (JsonConfigurationReader cfgReader = new JsonConfigurationReader(file)) {
+            return cfgReader.read();
+        }
+    }
+}
--- a/stress-tester/src/main/java/com/passus/st/utils/JsonUtils.java	Fri Apr 27 16:02:48 2018 +0200
+++ b/stress-tester/src/main/java/com/passus/st/utils/JsonUtils.java	Mon May 07 13:01:36 2018 +0200
@@ -1,7 +1,14 @@
 package com.passus.st.utils;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.fasterxml.jackson.databind.node.ValueNode;
+import com.passus.commons.ConversionException;
+import com.passus.config.CValueNode;
+import com.passus.config.NodeException;
+import com.passus.data.type.Type;
+
 /**
- *
  * @author Mirosław Hawrot
  */
 public class JsonUtils {
@@ -22,6 +29,66 @@
     private JsonUtils() {
     }
 
+    public static CValueNode toValueNode(JsonNode node) throws NodeException {
+        checkValueNode(node);
+        ValueNode vNode = (ValueNode) node;
+
+        if (node.isNull()) {
+            return new CValueNode(null);
+        } else if (node.isBoolean()) {
+            return new CValueNode(vNode.booleanValue());
+        } else if (node.isInt() || node.isLong()) {
+            return new CValueNode(vNode.longValue());
+        } else if (node.isFloat() || node.isDouble()) {
+            return new CValueNode(vNode.doubleValue());
+        } else if (node.isTextual()) {
+            return new CValueNode(vNode.textValue());
+        }
+
+        throw nodeException("Not supported value type '" + vNode.getNodeType() + ".", vNode);
+    }
+
+    public static Object convertTo(JsonNode node, Type type) throws NodeException {
+        checkValueNode(node);
+        ValueNode vNode = (ValueNode) node;
+
+        try {
+            if (node.isBoolean()) {
+                return type.convert(vNode.booleanValue());
+            } else if (node.isNumber()) {
+                return type.convert(vNode.numberValue());
+            } else if (node.isTextual()) {
+                return type.convert(vNode.textValue());
+            }
+
+            throw nodeException("Value must be '" + type.getName() + "' type.", node);
+        } catch (ConversionException e) {
+            throw nodeException("Value must be '" + type.getName() + "' type.", node);
+        }
+    }
+
+    public static String convertToString(JsonNode node) throws NodeException {
+        return (String) convertTo(node, Type.STRING);
+    }
+
+    public static void checkValueNode(JsonNode node) throws NodeException {
+        if (!node.isValueNode()) {
+            throw nodeException("Required value node ('" + node.getNodeType() + " given').", node);
+        }
+    }
+
+    public static void checkNodeType(JsonNode node, JsonNodeType nodeType) throws NodeException {
+        if (node.getNodeType() != nodeType) {
+            throw nodeException("Required '" + nodeType + "' node ('" + node.getNodeType() + " given').", node);
+        }
+    }
+
+    public static NodeException nodeException(String message, JsonNode node) {
+        //node.
+        //Mark mark = node.getStartMark();
+        return new NodeException(message, 0, 0);
+    }
+
     public static String escape(String value) {
         StringBuilder sb = new StringBuilder();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/config/ConfigurationTestUtils.java	Mon May 07 13:01:36 2018 +0200
@@ -0,0 +1,55 @@
+package com.passus.st.config;
+
+import com.passus.config.CMapNode;
+
+import static com.passus.config.ConfigurationBuilder.*;
+
+/**
+ * @author Mirosław Hawrot
+ */
+public class ConfigurationTestUtils {
+
+    public static final CMapNode SIMPLE_CONFIG_NODE;
+
+    public static final String SIMPLE_CONFIG = "{\"scalar\": \"value\",\n"
+            + "\"listValue\": [\"a\", \"b\"],\n"
+            + "\"nullValue\": null,\n"
+            + "\"longValue\": 100,\n"
+            + "\"floatValue\": 10.1,\n"
+            + "\"booleanValue\": true,\n"
+            + "\"mapValue\": {\n"
+            + "  \"mapKey1\": \"mapValue1\",\n"
+            + "  \"mapListValue\": [\"c\", \"d\"]\n"
+            + "},\n"
+            + "\"list\":\n"
+            + " [{\"map1\": \"value1\"}]\n" +
+            "}";
+
+    static {
+        SIMPLE_CONFIG_NODE = map(
+                tuple("scalar", "value"),
+                tuple("listValue", list("a", "b")),
+                tuple("nullValue", null),
+                tuple("longValue", 100L),
+                tuple("floatValue", 10.1D),
+                tuple("booleanValue", true),
+                tuple("mapValue",
+                        map(
+                                tuple("mapKey1", "mapValue1"),
+                                tuple("mapListValue", list("c", "d"))
+                        )
+                ),
+                tuple("list",
+                        list(
+                                map(
+                                        tuple("map1", "value1")
+                                )
+                        )
+                )
+        );
+    }
+
+    private ConfigurationTestUtils() {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/config/JsonConfigurationReaderTest.java	Mon May 07 13:01:36 2018 +0200
@@ -0,0 +1,59 @@
+package com.passus.st.config;
+
+import com.passus.config.*;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import static com.passus.st.config.ConfigurationTestUtils.SIMPLE_CONFIG;
+import static com.passus.st.config.ConfigurationTestUtils.SIMPLE_CONFIG_NODE;
+import static org.testng.AssertJUnit.assertEquals;
+
+public class JsonConfigurationReaderTest {
+
+    private void assertNodeLoc(CNode node, int row, int col) {
+        //assertEquals(row, node.getRow());
+        //assertEquals(col, node.getColumn());
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        JsonConfigurationReader reader = new JsonConfigurationReader(SIMPLE_CONFIG);
+        Configuration cfg = reader.read();
+
+        CMapNode rootNode = (CMapNode) cfg.getRootNode();
+        assertEquals(SIMPLE_CONFIG_NODE, rootNode);
+
+        assertNodeLoc(rootNode, 1, 1);
+        List<CTupleNode> children = rootNode.getChildren();
+        assertNodeLoc(children.get(0), 1, 1);
+        assertNodeLoc(children.get(1), 2, 1);
+        assertNodeLoc(children.get(2), 3, 1);
+        assertNodeLoc(children.get(3), 4, 1);
+        assertNodeLoc(children.get(4), 5, 1);
+        assertNodeLoc(children.get(5), 6, 1);
+        assertNodeLoc(children.get(6), 7, 1);
+        assertNodeLoc(children.get(7), 10, 1);
+
+        CNode childNode = children.get(0).getNode();
+        assertNodeLoc(childNode, 1, 9);
+
+        childNode = children.get(6).getNode();
+        assertNodeLoc(childNode, 8, 3);
+
+        CListNode childListNode = (CListNode) children.get(7).getNode();
+        assertNodeLoc(childListNode, 11, 1);
+
+        childNode = childListNode.get(0);
+        assertNodeLoc(childNode, 11, 3);
+    }
+
+    @Test
+    public void testRead_EmptyString() throws Exception {
+        JsonConfigurationReader reader = new JsonConfigurationReader("");
+        Configuration cfg = reader.read();
+
+        assertEquals(0, cfg.keys().size());
+    }
+
+}
\ No newline at end of file