From be453ceba3354654b6ac32780a196eb0823abd7c Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Mon, 22 Dec 2014 16:55:28 +0000 Subject: [PATCH] HCOLL-268 simplified the Json Parsing --- .../chronicle/map/VanillaChronicleMap.java | 117 ++++++------------ .../openhft/chronicle/map/XStreamHelper.java | 24 ++-- .../map/ChronicleMapImportExportTest.java | 49 +++++++- 3 files changed, 97 insertions(+), 93 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index ea34acb70..63c619135 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -62,13 +62,11 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import static java.beans.Introspector.getBeanInfo; -import static java.lang.Class.forName; import static java.lang.Long.numberOfTrailingZeros; import static java.lang.Math.max; import static java.lang.Thread.currentThread; import static java.nio.ByteBuffer.allocateDirect; import static net.openhft.chronicle.map.Asserts.assertNotNull; -import static net.openhft.chronicle.map.XStreamHelper.to$$Native; import static net.openhft.lang.MemoryUnit.*; class VanillaChronicleMap, @@ -779,7 +777,7 @@ class VanillaChronicleMap, private void registerConverter(XStream xstream) { final Converter converter = new Converter() { - final Bytes buffer = XStreamConverter.this.buffer; + @Override public boolean canConvert(Class aClass) { @@ -802,17 +800,17 @@ class VanillaChronicleMap, if (WriteThroughEntry.class.isAssignableFrom(o.getClass())) { final SimpleEntry e = (SimpleEntry) o; - writer.startNode("chronicle-key"); - Object key = e.getKey(); - writeType(writer, key, kClass); + writer.startNode(key.getClass().getCanonicalName()); + marshallingContext.convertAnother(key); writer.endNode(); - writer.startNode("chronicle-value"); Object value = e.getValue(); - writeType(writer, value, vClass); + writer.startNode(value.getClass().getCanonicalName()); + + marshallingContext.convertAnother(value); writer.endNode(); @@ -888,12 +886,19 @@ class VanillaChronicleMap, UnmarshallingContext unmarshallingContext) { String canonicalName = unmarshallingContext.getRequiredType().getCanonicalName(); + boolean isNative = canonicalName.endsWith("$$Native"); boolean isHeap = canonicalName.endsWith("$$Heap"); if (isNative || isHeap) { + if (unmarshallingContext.getRequiredType().getCanonicalName().startsWith + ("net.openhft.lang.values")) + return XStreamHelper.toBuiltIn$$(reader, unmarshallingContext.getRequiredType() + ); + + final String nodeName = isNative ? canonicalName.substring(0, canonicalName.length() - "$$Native".length()) : @@ -903,8 +908,12 @@ class VanillaChronicleMap, Object o; + try { - o = DataValueClasses.newDirectInstance(Class.forName(nodeName)); + Class interfaceClass = Class.forName(nodeName); + o = (isNative) ? + DataValueClasses.newDirectInstance(interfaceClass) : + DataValueClasses.newInstance(interfaceClass); final BeanInfo beanInfo = getBeanInfo(o.getClass()); @@ -940,7 +949,7 @@ class VanillaChronicleMap, final String nodeName = reader.getNodeName(); - String type = reader.getAttribute("type"); + switch (nodeName) { case "chronicle-entries": @@ -951,21 +960,26 @@ class VanillaChronicleMap, if (!nodeName0.equals("chronicle-entry")) throw new ConversionException("unable to convert node " + "named=" + nodeName0); - K k = null; - V v = null; + final K k; + final V v; - while (reader.hasMoreChildren()) { - reader.moveDown(); - final String nodeName1 = reader - .getNodeName(); - if ("chronicle-key".equals(nodeName1)) - k = get(reader, unmarshallingContext, kClass); - else if ("chronicle-value".equals(nodeName1)) - v = get(reader, unmarshallingContext, vClass); - else - throw new ConversionException("expecting either a key or value"); - reader.moveUp(); + + reader.moveDown(); + { + + String type = reader.getNodeName(); + Class o = XStreamHelper.forName(type); + k = (K) unmarshallingContext.convertAnother(null, o); } + reader.moveUp(); + reader.moveDown(); + { + String type = reader.getNodeName(); + Class o = XStreamHelper.forName(type); + v = (V) unmarshallingContext.convertAnother(null, o); + } + reader.moveUp(); + if (k != null) VanillaChronicleMap.this.put(k, v); @@ -974,57 +988,13 @@ class VanillaChronicleMap, } return null; - case "chronicle-key": - if (kClass.getCanonicalName().startsWith("net.openhft.lang.values")) { - return to$$Native(reader, vClass, true, VanillaChronicleMap.this, unmarshallingContext); - } else if (type.endsWith("$$Native") || type.endsWith("$$Heap")) { - return XStreamHelper.to$$Native2(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext, type); - } else { - long keySize = keySizeMarshaller.readSize(buffer); - ThreadLocalCopies copies = keyReaderProvider.getCopies(null); - BytesReader keyReader = keyReaderProvider.get(copies, originalKeyReader); - return keyReader.read(buffer, keySize); - } - case "chronicle-value": - - if (vClass.getCanonicalName().startsWith("net.openhft.lang.values")) { - return to$$Native(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext); - } else if (type.endsWith("$$Native") || type.endsWith("$$Heap")) { - return XStreamHelper.to$$Native2(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext, type); - } else { - long valueSize = valueSizeMarshaller.readSize(buffer); - ThreadLocalCopies copies = valueReaderProvider.getCopies(null); - BytesReader valueReader = - valueReaderProvider.get(copies, originalValueReader); - return valueReader.read(buffer, valueSize); - } } return null; } - private E get(HierarchicalStreamReader reader, - UnmarshallingContext unmarshallingContext, - Class clazz) { - - if (clazz == CharSequence.class) - return (E) unmarshallingContext.convertAnother(null, String.class); - - if (reader.getAttributeCount() > 0) { - final String type = reader.getAttribute("type"); - if (type != null) - try { - return (E) unmarshallingContext.convertAnother(null, forName(type)); - } catch (ClassNotFoundException e) { - throw new ConversionException(e); - } - - } - - return (E) unmarshallingContext.convertAnother(null, clazz); - } }; @@ -1032,20 +1002,7 @@ class VanillaChronicleMap, xstream.registerConverter(converter); } - private void writeType(HierarchicalStreamWriter writer, Object o, final Class clazz) { - if (clazz == CharSequence.class) - return; - String simpleName = o.getClass().getCanonicalName(); - if (simpleName.startsWith("net.openhft.lang.values")) { - String nodeName = simpleName.substring(0, simpleName.length() - - "$$Native".length()); - if (!nodeName.equals(clazz.getCanonicalName())) - writer.addAttribute("type", nodeName); - } else if (simpleName.endsWith("$$Native") || !clazz.equals(o.getClass())) { - writer.addAttribute("type", o.getClass().getCanonicalName()); - } - } } @NotNull diff --git a/src/main/java/net/openhft/chronicle/map/XStreamHelper.java b/src/main/java/net/openhft/chronicle/map/XStreamHelper.java index 8d19c795a..1ffe13f57 100644 --- a/src/main/java/net/openhft/chronicle/map/XStreamHelper.java +++ b/src/main/java/net/openhft/chronicle/map/XStreamHelper.java @@ -17,7 +17,6 @@ package net.openhft.chronicle.map; import com.thoughtworks.xstream.converters.ConversionException; -import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import net.openhft.lang.model.DataValueClasses; @@ -30,17 +29,23 @@ import java.lang.reflect.Method; * Created by Rob on 18/12/14. */ class XStreamHelper { - static Object to$$Native2(HierarchicalStreamReader reader, final Class aClass2, final boolean isKey, - ChronicleMap map, UnmarshallingContext unmarshallingContext, String type) { + static Class forName(String type) { boolean isNative = type.endsWith("$$Native"); + if (!isNative && !type.endsWith("$$Heap")) { + try { + return Class.forName(type); + } catch (ClassNotFoundException e1) { + throw new ConversionException(e1); + } + } - Class aClass; try { - aClass = Class.forName(type); + return Class.forName(type); } catch (ClassNotFoundException e) { + String clazz = isNative ? type.substring(0, type.length() - "$$Native".length()) : type.substring(0, type.length() - "$$Heap".length()); @@ -50,23 +55,20 @@ class XStreamHelper { throw new ConversionException(e1); } try { - aClass = Class.forName(type); + return Class.forName(type); } catch (ClassNotFoundException e1) { throw new ConversionException(e1); } } - return unmarshallingContext.convertAnother(null, aClass); } + static Object toBuiltIn$$(HierarchicalStreamReader reader, final Class aClass) { - static Object to$$Native(HierarchicalStreamReader reader, final Class aClass, final boolean isKey, ChronicleMap map, UnmarshallingContext unmarshallingContext) { - - - final Object o = isKey ? map.newKeyInstance() : map.newValueInstance(); + final Object o = DataValueClasses.newDirectInstance(aClass); try { diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java index ab6a1721b..414328c94 100644 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java @@ -1,5 +1,7 @@ package net.openhft.chronicle.map; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.map.fromdocs.BondVOInterface; import net.openhft.lang.model.DataValueClasses; @@ -9,6 +11,7 @@ import org.junit.Ignore; import org.junit.Test; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.util.HashMap; @@ -156,6 +159,47 @@ public class ChronicleMapImportExportTest { } + + @Test + public void testFromHashMap() throws IOException, InterruptedException { + + File file = new File(TMP + "/chronicle-map-" + System.nanoTime() + ".json"); + System.out.println(file.getCanonicalFile()); + + File file2 = new File(TMP + "/chronicle-map-2" + System.nanoTime() + ".json"); + System.out.println(file2.getCanonicalFile()); + + HashMap map = new HashMap(); + map.put(1, "one"); + map.put(2, "two"); + + + final XStream xstream = new XStream(new JettisonMappedXmlDriver()); + xstream.setMode(XStream.NO_REFERENCES); + + xstream.toXML(map, new FileOutputStream(file)); + + + try (ChronicleMap expected = ChronicleMapBuilder.of(Integer.class, + String.class).create()) { + + expected.put(1, "one"); + expected.put(2, "two"); + + expected.getAll(file2); + expected.putAll(file2); + + + Assert.assertEquals(2, expected.size()); + Assert.assertEquals("one", expected.get(1)); + Assert.assertEquals("two", expected.get(2)); + } + + + //file.deleteOnExit(); + } + + @Ignore("HCOLL-239 - The JSON to Map import/export should work on the stateless client.") @Test public void testToJsonWithStatlessClient() throws IOException, InterruptedException { @@ -223,7 +267,7 @@ public class ChronicleMapImportExportTest { public void testBondVOInterface() throws IOException, InterruptedException { File file = new File(TMP + "/chronicle-map-" + System.nanoTime() + ".json"); - file.deleteOnExit(); + // file.deleteOnExit(); System.out.println(file.getAbsolutePath()); try (ChronicleMap expected = @@ -248,7 +292,8 @@ public class ChronicleMapImportExportTest { Assert.assertEquals(expected.get("one").getCoupon(), actual.get("one").getCoupon(), 0); } } finally { - file.delete(); + // file.delete(); } } } +