BJ-88: Add serializer and reader interface (#8)

* BJ-88: Add interfaces

* BJ-88: Fix serializer interface

* BJ-88: Change interface logic
This commit is contained in:
Pavel Popov 2017-02-06 20:35:41 +04:00 committed by GitHub
parent 1b6dd53683
commit 4894f4bf96
12 changed files with 82 additions and 76 deletions

View File

@ -1,8 +1,8 @@
package com.rbkmoney.kebab;
import com.rbkmoney.kebab.serializer.TBaseSerializer;
import com.rbkmoney.kebab.writer.JsonStructWriter;
import com.rbkmoney.kebab.writer.MsgPackWriter;
import com.rbkmoney.kebab.handler.JsonStructHandler;
import com.rbkmoney.kebab.handler.MsgPackHandler;
import com.rbkmoney.kebab.processor.TBaseStructProcessor;
import org.apache.thrift.TBase;
import java.io.ByteArrayOutputStream;
@ -17,11 +17,9 @@ public class Kebab<T extends TBase> {
public String toJson(T src) {
try {
StringWriter writer = new StringWriter();
Serializer serializer = new TBaseSerializer();
JsonStructWriter jsonStructWriter = new JsonStructWriter(writer);
serializer.write(jsonStructWriter, src);
jsonStructWriter.close();
return writer.toString();
TBaseStructProcessor structProcessor = new TBaseStructProcessor();
JsonStructHandler jsonStructHandler = new JsonStructHandler(writer);
return structProcessor.process(src, jsonStructHandler);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
@ -30,11 +28,10 @@ public class Kebab<T extends TBase> {
public byte[] toMsgPack(T src, boolean useDict) {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
MsgPackWriter writer = new MsgPackWriter(os, true, true);
TBaseSerializer serializer = new TBaseSerializer();
MsgPackHandler handler = new MsgPackHandler(os, true, true);
TBaseStructProcessor serializer = new TBaseStructProcessor();
serializer.write(writer, src);
writer.close();
serializer.process(src, handler);
return os.toByteArray();
} catch (IOException e) {
@ -42,10 +39,10 @@ public class Kebab<T extends TBase> {
}
}
public byte[] write(T src, StructWriter writer) {
Serializer serializer = new TBaseSerializer();
public byte[] write(T src, StructHandler writer) {
StructProcessor structProcessor = new TBaseStructProcessor();
try {
serializer.write(writer, src);
structProcessor.process(src, writer);
return new byte[0];
} catch (IOException ex) {
throw new RuntimeException(ex);

View File

@ -1,12 +0,0 @@
package com.rbkmoney.kebab;
import java.io.IOException;
/**
* Created by tolkonepiu on 27/01/2017.
*/
public interface Serializer<T> {
void write(StructWriter out, T value) throws IOException;
}

View File

@ -1,12 +1,11 @@
package com.rbkmoney.kebab;
import java.io.Closeable;
import java.io.IOException;
/**
* Created by tolkonepiu on 26/01/2017.
*/
public interface StructWriter extends Closeable {
public interface StructHandler<R> {
void beginStruct(int size) throws IOException;
@ -48,4 +47,6 @@ public interface StructWriter extends Closeable {
void nullValue() throws IOException;
R getResult() throws IOException;
}

View File

@ -0,0 +1,12 @@
package com.rbkmoney.kebab;
import java.io.IOException;
/**
* Created by tolkonepiu on 27/01/2017.
*/
public interface StructProcessor<S> {
<R> R process(S value, StructHandler<R> handler) throws IOException;
}

View File

@ -1,7 +1,7 @@
package com.rbkmoney.kebab.writer;
package com.rbkmoney.kebab.handler;
import com.rbkmoney.kebab.ByteStack;
import com.rbkmoney.kebab.StructWriter;
import com.rbkmoney.kebab.StructHandler;
import com.rbkmoney.kebab.ThriftType;
import com.rbkmoney.kebab.exception.BadFormatException;
@ -13,7 +13,7 @@ import java.util.Objects;
/**
* Created by tolkonepiu on 27/01/2017.
*/
public class JsonStructWriter implements StructWriter {
public class JsonStructHandler implements StructHandler<String> {
static final byte EMPTY_STRUCT = 1;
@ -43,11 +43,11 @@ public class JsonStructWriter implements StructWriter {
stack.push(EMPTY_DOCUMENT);
}
public JsonStructWriter(Writer out) {
public JsonStructHandler(Writer out) {
this(out, false);
}
public JsonStructWriter(Writer out, boolean pretty) {
public JsonStructHandler(Writer out, boolean pretty) {
Objects.requireNonNull(out, "Writer must not be null");
this.out = out;
this.pretty = pretty;
@ -262,11 +262,14 @@ public class JsonStructWriter implements StructWriter {
}
@Override
public void close() throws IOException {
public String getResult() throws IOException {
out.close();
if (stack.size() > 1 || stack.size() == 1 && stack.peek() != NONEMPTY_DOCUMENT) {
throw new BadFormatException();
}
return out.toString();
}
}

View File

@ -1,6 +1,6 @@
package com.rbkmoney.kebab.writer;
package com.rbkmoney.kebab.handler;
import com.rbkmoney.kebab.StructWriter;
import com.rbkmoney.kebab.StructHandler;
import com.rbkmoney.kebab.exception.BadFormatException;
import gnu.trove.map.hash.TObjectCharHashMap;
import org.msgpack.core.MessagePack;
@ -9,21 +9,21 @@ import org.msgpack.core.MessagePacker;
import java.io.IOException;
import java.io.OutputStream;
import static com.rbkmoney.kebab.writer.StringUtil.compressAsciiString;
import static com.rbkmoney.kebab.writer.StringUtil.toAsciiBytes;
import static com.rbkmoney.kebab.handler.StringUtil.compressAsciiString;
import static com.rbkmoney.kebab.handler.StringUtil.toAsciiBytes;
/**
* Created by vpankrashkin on 31.01.17.
*/
public class MsgPackWriter implements StructWriter {
public class MsgPackHandler implements StructHandler<OutputStream> {
private static final byte nop = 0;
private static final byte startStruct = 1;
private static final byte endStruct = 2;
private static final byte startList = 3;
private static final byte endList = 4;
private static final byte startMap = 5;
private static final byte endMap= 6;
private static final byte startMapKey= 7;
private static final byte endMap = 6;
private static final byte startMapKey = 7;
private static final byte endMapKey = 8;
private static final byte startMapValue = 9;
private static final byte endMapValue = 10;
@ -39,7 +39,7 @@ public class MsgPackWriter implements StructWriter {
private final char noDictEntryValue = 0;
private char nextDictIdx = 0;
public MsgPackWriter(OutputStream stream, boolean autoClose, boolean useDictionary) {
public MsgPackHandler(OutputStream stream, boolean autoClose, boolean useDictionary) {
this.autoClose = autoClose;
this.msgPacker = MessagePack.newDefaultPacker(stream);
this.useDictionary = useDictionary;
@ -58,7 +58,7 @@ public class MsgPackWriter implements StructWriter {
/**
* @param size if >= 0, expected to be defined list size; if < 0, means stream mode with not fixed size
* */
*/
@Override
public void beginList(int size) throws IOException {
if (size >= 0) {
@ -111,7 +111,7 @@ public class MsgPackWriter implements StructWriter {
/**
* @param name - only ASCII symbols expected
* */
*/
@Override
public void name(String name) throws IOException {
int length = name.length();
@ -140,7 +140,7 @@ public class MsgPackWriter implements StructWriter {
@Override
public void value(String value) throws IOException {
msgPacker.packString(value);
msgPacker.packString(value);
}
@Override
@ -180,12 +180,14 @@ public class MsgPackWriter implements StructWriter {
}
@Override
public void close() throws IOException {
public OutputStream getResult() throws IOException {
if (autoClose) {
msgPacker.close();
} else {
msgPacker.flush();
}
return null;
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.kebab.writer;
package com.rbkmoney.kebab.handler;
import com.rbkmoney.kebab.exception.BadFormatException;

View File

@ -1,7 +1,7 @@
package com.rbkmoney.kebab.serializer;
package com.rbkmoney.kebab.processor;
import com.rbkmoney.kebab.Serializer;
import com.rbkmoney.kebab.StructWriter;
import com.rbkmoney.kebab.StructProcessor;
import com.rbkmoney.kebab.StructHandler;
import com.rbkmoney.kebab.ThriftType;
import org.apache.thrift.TBase;
import org.apache.thrift.TFieldIdEnum;
@ -16,19 +16,21 @@ import java.util.Set;
/**
* Created by tolkonepiu on 27/01/2017.
*/
public class TBaseSerializer implements Serializer<TBase> {
public class TBaseStructProcessor implements StructProcessor<TBase> {
@Override
public void write(StructWriter out, TBase value) throws IOException {
public <R> R process(TBase value, StructHandler<R> handler) throws IOException {
if (value == null) {
out.nullValue();
return;
handler.nullValue();
return null;
}
writeStruct(out, value);
writeStruct(handler, value);
return handler.getResult();
}
private void writeStruct(StructWriter out, TBase value) throws IOException {
private void writeStruct(StructHandler out, TBase value) throws IOException {
TFieldIdEnum[] tFieldIdEnums = value.getFields();
Map<TFieldIdEnum, FieldMetaData> fieldMetaDataMap = value.getFieldMetaData();
int size = getFieldsCount(value, tFieldIdEnums);
@ -57,7 +59,7 @@ public class TBaseSerializer implements Serializer<TBase> {
return size;
}
private void write(StructWriter out, Object object, FieldValueMetaData fieldValueMetaData) throws IOException {
private void write(StructHandler out, Object object, FieldValueMetaData fieldValueMetaData) throws IOException {
if (object == null) {
out.nullValue();
return;
@ -112,7 +114,7 @@ public class TBaseSerializer implements Serializer<TBase> {
}
}
private void writeSet(StructWriter out, Set objectSet, SetMetaData metaData) throws IOException {
private void writeSet(StructHandler out, Set objectSet, SetMetaData metaData) throws IOException {
out.beginList(objectSet.size());
for (Object object : objectSet) {
write(out, object, metaData.getElementMetaData());
@ -120,7 +122,7 @@ public class TBaseSerializer implements Serializer<TBase> {
out.endList();
}
private void writeList(StructWriter out, List objectList, ListMetaData metaData) throws IOException {
private void writeList(StructHandler out, List objectList, ListMetaData metaData) throws IOException {
out.beginList(objectList.size());
for (Object object : objectList) {
write(out, object, metaData.getElementMetaData());
@ -128,7 +130,7 @@ public class TBaseSerializer implements Serializer<TBase> {
out.endList();
}
private void writeMap(StructWriter out, Map objectMap, MapMetaData metaData) throws IOException {
private void writeMap(StructHandler out, Map objectMap, MapMetaData metaData) throws IOException {
out.beginMap(objectMap.size());
for (Map.Entry entry : (Set<Map.Entry>) objectMap.entrySet()) {
out.beginKey();

View File

@ -1,8 +1,8 @@
package com.rbkmoney.kebab;
import com.rbkmoney.kebab.serializer.TBaseSerializer;
import com.rbkmoney.kebab.processor.TBaseStructProcessor;
import com.rbkmoney.kebab.test.*;
import com.rbkmoney.kebab.writer.WriterStub;
import com.rbkmoney.kebab.handler.HandlerStub;
import org.apache.thrift.TException;
import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TBinaryProtocol;
@ -29,7 +29,7 @@ public class KebabTest {
public void tBaseSerializerTest() throws IOException {
TestObject testObject = getTestObject();
long start = System.currentTimeMillis();
new TBaseSerializer().write(new MockStructWriter(), testObject);
new TBaseStructProcessor().process(testObject, new MockStructHandler());
long end = System.currentTimeMillis();
System.out.println("TBaseSerializer: execution time " + (end - start) + " ms");
}
@ -104,7 +104,7 @@ public class KebabTest {
boolean useDict = true;
TestObject testObject = getTestObject(100, () -> Status.unknown(new Unknown("SomeData")));
//warmup
WriterStub writerStub = new WriterStub();
HandlerStub writerStub = new HandlerStub();
TSerializer serializer = new TSerializer(new TBinaryProtocol.Factory());
IntConsumer stubConsumer = i -> kebab.write(testObject, writerStub);
IntConsumer msgPackConsumer = i -> kebab.toMsgPack(testObject, useDict);

View File

@ -5,7 +5,7 @@ import java.io.IOException;
/**
* Created by tolkonepiu on 03/02/2017.
*/
public class MockStructWriter implements StructWriter {
public class MockStructHandler implements StructHandler {
@Override
public void beginStruct(int size) throws IOException {
//do nothing
@ -107,7 +107,7 @@ public class MockStructWriter implements StructWriter {
}
@Override
public void close() throws IOException {
//do nothing
public Object getResult() throws IOException {
return null;
}
}

View File

@ -1,13 +1,13 @@
package com.rbkmoney.kebab.writer;
package com.rbkmoney.kebab.handler;
import com.rbkmoney.kebab.StructWriter;
import com.rbkmoney.kebab.StructHandler;
import java.io.IOException;
/**
* Created by vpankrashkin on 03.02.17.
*/
public class WriterStub implements StructWriter {
public class HandlerStub implements StructHandler {
@Override
public void beginStruct(int size) throws IOException {
@ -109,7 +109,8 @@ public class WriterStub implements StructWriter {
}
@Override
public void close() throws IOException {
public Object getResult() throws IOException {
return null;
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.kebab.writer;
package com.rbkmoney.kebab.handler;
import com.rbkmoney.kebab.exception.BadFormatException;
import org.junit.Test;
@ -8,8 +8,8 @@ import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static com.rbkmoney.kebab.writer.StringUtil.intToString;
import static com.rbkmoney.kebab.writer.StringUtil.isAsciiString;
import static com.rbkmoney.kebab.handler.StringUtil.intToString;
import static com.rbkmoney.kebab.handler.StringUtil.isAsciiString;
import static org.junit.Assert.*;
import static java.lang.System.*;