mirror of
https://github.com/valitydev/geck.git
synced 2024-11-06 01:35:22 +00:00
Ft/bj-139/xml (#27)
* BJ-139: Added xml handler * Added object types, constants moved to other class * fix constant's modifiers * Added handler's reuseable, support null-values * Added xml processor * Moved constants to other class * Added some exception handling * fix * Added additional description in exception handling * Fixed after comments * Removed main method, fixed doc * Removed error handling in method writeEndElement * Added throwing runtime exception when init * Added snapshot-version in poms * Fixed filter parent pom version
This commit is contained in:
parent
502e9f32a2
commit
d327db4ab2
@ -3,7 +3,7 @@
|
||||
![default](https://cloud.githubusercontent.com/assets/5084395/23034038/cf7e5eb0-f493-11e6-8698-66262306ca81.png)
|
||||
|
||||
### В комплекте ```нужное зачеркнуть```:
|
||||
- serializer (msgpack, jolt, thrift, ~~json~~)
|
||||
- serializer (msgpack, jolt, thrift, xml, ~~json~~)
|
||||
- mock
|
||||
- ~~migrator~~
|
||||
- ~~filter~~
|
||||
@ -14,4 +14,4 @@
|
||||
|
||||
Собрать и инсталировать jar(s) в локальный мавен репозиторий(без локально установленного трифта):
|
||||
|
||||
* make wc_java_install LOCAL_BUILD=true SETTINGS_XML=path_to_rbk_maven_settings
|
||||
* make wc_java_install LOCAL_BUILD=true SETTINGS_XML=path_to_rbk_maven_settings
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common</artifactId>
|
||||
@ -18,5 +18,5 @@
|
||||
<artifactId>libthrift</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
</project>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>filter</artifactId>
|
||||
@ -37,4 +37,4 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>migrator</artifactId>
|
||||
@ -25,4 +25,4 @@
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
4
pom.xml
4
pom.xml
@ -12,7 +12,7 @@
|
||||
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
@ -126,4 +126,4 @@
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>serializer</artifactId>
|
||||
|
@ -11,7 +11,13 @@ public enum StructType {
|
||||
SET("set"),
|
||||
LIST("list"),
|
||||
STRUCT("struct"),
|
||||
BOOL("bool"),
|
||||
STRING("string"),
|
||||
DOUBLE("double"),
|
||||
LONG("long"),
|
||||
NULL("null"),
|
||||
BYTEARRAY("bytearray"),
|
||||
MAP_ENTRY("map_entry"),
|
||||
OTHER("");
|
||||
private static class Holder {
|
||||
static Map<String, StructType> MAP = new HashMap<>();
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.rbkmoney.geck.serializer.kit.xml;
|
||||
|
||||
/**
|
||||
* Created by inalarsanukaev on 16.03.17.
|
||||
*/
|
||||
public interface XMLConstants {
|
||||
String KEY = "key";
|
||||
String VALUE = "value";
|
||||
String ROOT = "root";
|
||||
String ELEMENT = "elem";
|
||||
String ATTRIBUTE_TYPE = "type";
|
||||
String ATTRIBUTE_SIZE = "size";
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
package com.rbkmoney.geck.serializer.kit.xml;
|
||||
|
||||
import com.rbkmoney.geck.common.stack.ByteStack;
|
||||
import com.rbkmoney.geck.serializer.StructHandler;
|
||||
import com.rbkmoney.geck.serializer.exception.BadFormatException;
|
||||
import com.rbkmoney.geck.serializer.kit.EventFlags;
|
||||
import com.rbkmoney.geck.serializer.kit.StructType;
|
||||
import static com.rbkmoney.geck.serializer.kit.xml.XMLConstants.*;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Created by inalarsanukaev on 14.03.17.
|
||||
*/
|
||||
public class XMLHandler implements StructHandler<DOMResult> {
|
||||
|
||||
private ByteStack stack = new ByteStack();
|
||||
private DOMResult result;
|
||||
private XMLStreamWriter out;
|
||||
private DocumentBuilder documentBuilder;
|
||||
private XMLOutputFactory xmlOutputFactory;
|
||||
|
||||
{
|
||||
try {
|
||||
init();
|
||||
} catch (BadFormatException e) {
|
||||
throw new RuntimeException(e);//TODO
|
||||
}
|
||||
}
|
||||
|
||||
private void init() throws BadFormatException {
|
||||
try {
|
||||
getDocumentBuilder().reset();
|
||||
result = new DOMResult(getDocumentBuilder().newDocument());
|
||||
out = getXmlOutputFactory().createXMLStreamWriter(result);
|
||||
out.writeStartDocument();
|
||||
out.writeStartElement(ROOT);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when init", e);
|
||||
}
|
||||
}
|
||||
|
||||
private XMLOutputFactory getXmlOutputFactory() {
|
||||
if (xmlOutputFactory == null) {
|
||||
xmlOutputFactory = XMLOutputFactory.newInstance();
|
||||
}
|
||||
return xmlOutputFactory;
|
||||
}
|
||||
|
||||
private DocumentBuilder getDocumentBuilder() throws BadFormatException {
|
||||
if (documentBuilder == null) {
|
||||
try {
|
||||
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new BadFormatException("Unknown error when getDocumentBuilder", e);
|
||||
}
|
||||
}
|
||||
return documentBuilder;
|
||||
}
|
||||
|
||||
private void writeStartElement(String type, int size) throws BadFormatException {
|
||||
try {
|
||||
if (!stack.isEmpty()) {
|
||||
byte x = stack.peek();
|
||||
if (x == EventFlags.startList || x == EventFlags.startSet) {
|
||||
out.writeStartElement(ELEMENT);
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
out.writeAttribute(ATTRIBUTE_TYPE, type);
|
||||
}
|
||||
if (size >= 0) {
|
||||
out.writeAttribute(ATTRIBUTE_SIZE, String.valueOf(size));
|
||||
}
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when writeStartElement", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStartElement(String type) throws BadFormatException {
|
||||
writeStartElement(type, -1);
|
||||
}
|
||||
private void writeValue(String value, String type) throws BadFormatException {
|
||||
try {
|
||||
writeStartElement(type);
|
||||
if (value != null) {
|
||||
out.writeCharacters(value.toString());
|
||||
}
|
||||
out.writeEndElement();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when writeValue", e);
|
||||
}
|
||||
}
|
||||
private void writeEndElement() throws BadFormatException {
|
||||
try {
|
||||
out.writeEndElement();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when writeEndElement", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginStruct(int size) throws IOException {
|
||||
writeStartElement(StructType.STRUCT.getKey(), size);
|
||||
stack.push(EventFlags.startStruct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endStruct() throws IOException {
|
||||
stack.pop();
|
||||
writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginList(int size) throws IOException {
|
||||
writeStartElement(StructType.LIST.getKey(), size);
|
||||
stack.push(EventFlags.startList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endList() throws IOException {
|
||||
stack.pop();
|
||||
writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginSet(int size) throws IOException {
|
||||
writeStartElement(StructType.SET.getKey(), size);
|
||||
stack.push(EventFlags.startSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endSet() throws IOException {
|
||||
stack.pop();
|
||||
writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginMap(int size) throws IOException {
|
||||
stack.push(EventFlags.startMap);
|
||||
try {
|
||||
out.writeAttribute(ATTRIBUTE_TYPE, StructType.MAP.getKey());
|
||||
out.writeAttribute(ATTRIBUTE_SIZE, String.valueOf(size));
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when beginMap", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endMap() throws IOException {
|
||||
stack.pop();
|
||||
writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginKey() throws IOException {
|
||||
try {
|
||||
out.writeStartElement(ELEMENT);
|
||||
out.writeAttribute(ATTRIBUTE_TYPE, StructType.MAP_ENTRY.getKey());
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when beginKey", e);
|
||||
}
|
||||
name(KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endKey() throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginValue() throws IOException {
|
||||
name(VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endValue() throws IOException {
|
||||
writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void name(String name) throws IOException {
|
||||
try {
|
||||
out.writeStartElement(name);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when name", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void value(boolean value) throws IOException {
|
||||
writeValue(String.valueOf(value), StructType.BOOL.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void value(String value) throws IOException {
|
||||
writeValue(value, StructType.STRING.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void value(double value) throws IOException {
|
||||
writeValue(String.valueOf(value), StructType.DOUBLE.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void value(long value) throws IOException {
|
||||
writeValue(String.valueOf(value), StructType.LONG.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void value(byte[] value) throws IOException {
|
||||
writeValue(Base64.getEncoder().encodeToString(value), StructType.BYTEARRAY.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullValue() throws IOException {
|
||||
writeValue(null, StructType.NULL.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DOMResult getResult() throws IOException {
|
||||
try {
|
||||
out.writeEndDocument();
|
||||
out.flush();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new BadFormatException("Unknown error when getResult", e);
|
||||
}
|
||||
DOMResult readyResult = result;
|
||||
init();
|
||||
return readyResult;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.rbkmoney.geck.serializer.kit.xml;
|
||||
|
||||
import com.rbkmoney.geck.serializer.StructHandler;
|
||||
import com.rbkmoney.geck.serializer.StructProcessor;
|
||||
import com.rbkmoney.geck.serializer.exception.BadFormatException;
|
||||
import com.rbkmoney.geck.serializer.kit.StructType;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import java.io.IOException;
|
||||
import java.sql.Struct;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Created by inalarsanukaev on 16.03.17.
|
||||
*/
|
||||
public class XMLProcessor implements StructProcessor<DOMResult> {
|
||||
@Override
|
||||
public <R> R process(DOMResult value, StructHandler<R> handler) throws IOException {
|
||||
Node document = value.getNode().getFirstChild();
|
||||
String nodeName = document.getNodeName();
|
||||
if (!nodeName.equals(XMLConstants.ROOT)) {
|
||||
throw new BadFormatException("Wrong root element name. Expected '"+XMLConstants.ROOT+"', actual '"+nodeName+"'");
|
||||
}
|
||||
processNode((Element) document, handler, false);
|
||||
return handler.getResult();
|
||||
}
|
||||
|
||||
protected void processNode(Element node, StructHandler handler, boolean printName) throws IOException {
|
||||
if (node != null){
|
||||
String nodeName = node.getNodeName();
|
||||
if (printName) {
|
||||
handler.name(nodeName);
|
||||
}
|
||||
StructType type = StructType.valueOfKey(node.getAttribute(XMLConstants.ATTRIBUTE_TYPE));
|
||||
if (type == null) {
|
||||
throw new BadFormatException("Attribute 'type' must not be null. Node name: "+nodeName);
|
||||
}
|
||||
switch (type) {
|
||||
case STRING:
|
||||
handler.value(node.getTextContent());
|
||||
break;
|
||||
case BOOL:
|
||||
handler.value(Boolean.valueOf(node.getTextContent()));
|
||||
break;
|
||||
case BYTEARRAY:
|
||||
handler.value(Base64.getDecoder().decode(node.getTextContent()));
|
||||
break;
|
||||
case DOUBLE:
|
||||
handler.value(Double.valueOf(node.getTextContent()));
|
||||
break;
|
||||
case LONG:
|
||||
handler.value(Long.valueOf(node.getTextContent()));
|
||||
break;
|
||||
case NULL:
|
||||
handler.nullValue();
|
||||
break;
|
||||
case STRUCT:
|
||||
handler.beginStruct(Integer.parseInt(node.getAttribute(XMLConstants.ATTRIBUTE_SIZE)));
|
||||
processChildNodes(node, handler, true);
|
||||
handler.endStruct();
|
||||
break;
|
||||
case LIST:
|
||||
handler.beginList(Integer.parseInt(node.getAttribute(XMLConstants.ATTRIBUTE_SIZE)));
|
||||
processChildNodes(node, handler, false);
|
||||
handler.endList();
|
||||
break;
|
||||
case SET:
|
||||
handler.beginSet(Integer.parseInt(node.getAttribute(XMLConstants.ATTRIBUTE_SIZE)));
|
||||
processChildNodes(node, handler, false);
|
||||
handler.endSet();
|
||||
break;
|
||||
case MAP:
|
||||
handler.beginMap(Integer.parseInt(node.getAttribute(XMLConstants.ATTRIBUTE_SIZE)));
|
||||
processChildNodes(node, handler, false);
|
||||
handler.endMap();
|
||||
break;
|
||||
case MAP_ENTRY :
|
||||
handler.beginKey();
|
||||
processNode((Element) node.getFirstChild(), handler, false);
|
||||
handler.endKey();
|
||||
handler.beginValue();
|
||||
processNode((Element) node.getLastChild(), handler, false);
|
||||
handler.endValue();
|
||||
break;
|
||||
default:
|
||||
new BadFormatException("Unknown type of node: "+type+". Must be on of them : "+ Arrays.toString(StructType.values()));
|
||||
}
|
||||
}
|
||||
}
|
||||
private void processChildNodes(Element node, StructHandler handler, boolean printName) throws IOException {
|
||||
NodeList nodeList = node.getChildNodes();
|
||||
for (int i = 0; i < nodeList.getLength(); ++i) {
|
||||
Node item = nodeList.item(i);
|
||||
if (item.getNodeType() == Node.ELEMENT_NODE) {
|
||||
processNode((Element) item, handler, printName);
|
||||
} else {
|
||||
throw new BadFormatException("Wrong type of node. Expected - "+Node.ELEMENT_NODE+", actual - "+item.getNodeType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,15 +16,14 @@ import com.rbkmoney.geck.serializer.kit.object.ObjectHandler;
|
||||
import com.rbkmoney.geck.serializer.kit.object.ObjectProcessor;
|
||||
import com.rbkmoney.geck.serializer.kit.tbase.TBaseHandler;
|
||||
import com.rbkmoney.geck.serializer.kit.tbase.TBaseProcessor;
|
||||
import com.rbkmoney.geck.serializer.kit.xml.XMLHandler;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by inalarsanukaev on 22.02.17.
|
||||
@ -38,7 +37,12 @@ public class DamselTest {
|
||||
System.out.println(json);
|
||||
new JSONObject(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlInvoiceTest() throws Exception {
|
||||
com.rbkmoney.damsel.v130.payment_processing.InvoicePaymentStarted invoice = new MockTBaseProcessor(MockMode.ALL, new FixedValueGenerator()).process(new com.rbkmoney.damsel.v130.payment_processing.InvoicePaymentStarted(), new TBaseHandler<>(com.rbkmoney.damsel.v130.payment_processing.InvoicePaymentStarted.class));
|
||||
String xml = new TBaseProcessor().process(invoice, new XMLHandler()).toString();
|
||||
System.out.println(xml);
|
||||
}
|
||||
@Test
|
||||
public void testInvoiceMsgPack() throws IOException {
|
||||
InvoicePaymentStarted invoice = GeckTestUtil.getInvoicePaymentStarted();
|
||||
@ -60,7 +64,6 @@ public class DamselTest {
|
||||
new TBaseHandler<>(InvoicePaymentStarted.class));
|
||||
Assert.assertEquals(invoice1, invoice2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvoiceBackTransform2() throws IOException {
|
||||
InvoicePaymentStarted invoice1 = GeckTestUtil.getInvoicePaymentStarted();
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.rbkmoney.geck.serializer.kit.xml;
|
||||
|
||||
import com.rbkmoney.damsel.v130.payment_processing.InvoicePaymentStarted;
|
||||
import com.rbkmoney.geck.serializer.GeckTestUtil;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.FixedValueGenerator;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.MockMode;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.MockTBaseProcessor;
|
||||
import com.rbkmoney.geck.serializer.kit.tbase.TBaseHandler;
|
||||
import com.rbkmoney.geck.serializer.kit.tbase.TBaseProcessor;
|
||||
import com.rbkmoney.geck.serializer.test.TestObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by inalarsanukaev on 17.03.17.
|
||||
*/
|
||||
public class XMLTest {
|
||||
@Test
|
||||
public void testInvoiceBackTransform1() throws IOException {
|
||||
InvoicePaymentStarted invoice1 = GeckTestUtil.getInvoicePaymentStarted();
|
||||
InvoicePaymentStarted invoice2 =
|
||||
new XMLProcessor().process(
|
||||
new TBaseProcessor().process(invoice1, new XMLHandler()),
|
||||
new TBaseHandler<>(InvoicePaymentStarted.class));
|
||||
Assert.assertEquals(invoice1, invoice2);
|
||||
}
|
||||
@Test
|
||||
public void xmlKebabTest() throws Exception {
|
||||
TestObject invoice = new MockTBaseProcessor(MockMode.ALL, new FixedValueGenerator()).process(new TestObject(), new TBaseHandler<>(TestObject.class));
|
||||
XMLHandler handler = new XMLHandler();
|
||||
String xml = new TBaseProcessor().process(invoice, handler).toString();
|
||||
//test re-use handler
|
||||
new TBaseProcessor().process(invoice, handler);
|
||||
System.out.println(xml);
|
||||
}
|
||||
}
|
@ -10,9 +10,10 @@
|
||||
},
|
||||
"*" : "payment.&"
|
||||
},
|
||||
"*": {
|
||||
"@" : "&"
|
||||
}
|
||||
"cash_flow": {
|
||||
"@" : "cash_flow.final_cash_flow"
|
||||
},
|
||||
"*": "&"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user