mirror of https://github.com/M66B/FairEmail.git
parent
3989504073
commit
46ff530412
@ -0,0 +1,217 @@
|
||||
package com.bugsnag.android.repackaged.dslplatform.json;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSOutput;
|
||||
import org.w3c.dom.ls.LSSerializer;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"}) // suppress pre-existing warnings
|
||||
public abstract class XmlConverter {
|
||||
|
||||
static final JsonReader.ReadObject<Element> Reader = new JsonReader.ReadObject<Element>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Element read(JsonReader reader) throws IOException {
|
||||
return reader.wasNull() ? null : deserialize(reader);
|
||||
}
|
||||
};
|
||||
static final JsonWriter.WriteObject<Element> Writer = new JsonWriter.WriteObject<Element>() {
|
||||
@Override
|
||||
public void write(JsonWriter writer, @Nullable Element value) {
|
||||
serializeNullable(value, writer);
|
||||
}
|
||||
};
|
||||
|
||||
private static final DocumentBuilder documentBuilder;
|
||||
|
||||
static {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
documentBuilder = dbFactory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void serializeNullable(@Nullable final Element value, final JsonWriter sw) {
|
||||
if (value == null)
|
||||
sw.writeNull();
|
||||
else
|
||||
serialize(value, sw);
|
||||
}
|
||||
|
||||
public static void serialize(final Element value, final JsonWriter sw) {
|
||||
Document document = value.getOwnerDocument();
|
||||
DOMImplementationLS domImplLS = (DOMImplementationLS) document.getImplementation();
|
||||
LSSerializer serializer = domImplLS.createLSSerializer();
|
||||
LSOutput lsOutput = domImplLS.createLSOutput();
|
||||
lsOutput.setEncoding("UTF-8");
|
||||
StringWriter writer = new StringWriter();
|
||||
lsOutput.setCharacterStream(writer);
|
||||
serializer.write(document, lsOutput);
|
||||
StringConverter.serialize(writer.toString(), sw);
|
||||
}
|
||||
|
||||
public static Element deserialize(final JsonReader reader) throws IOException {
|
||||
if (reader.last() == '"') {
|
||||
try {
|
||||
InputSource source = new InputSource(new StringReader(reader.readString()));
|
||||
return documentBuilder.parse(source).getDocumentElement();
|
||||
} catch (SAXException ex) {
|
||||
throw reader.newParseErrorAt("Invalid XML value", 0, ex);
|
||||
}
|
||||
} else {
|
||||
final Map<String, Object> map = ObjectConverter.deserializeMap(reader);
|
||||
return mapToXml(map);
|
||||
}
|
||||
}
|
||||
|
||||
public static Element mapToXml(final Map<String, Object> map) throws IOException {
|
||||
final Set<String> xmlRootElementNames = map.keySet();
|
||||
if (xmlRootElementNames.size() > 1) {
|
||||
throw ParsingException.create("Invalid XML. Expecting root element", true);
|
||||
}
|
||||
final String rootName = xmlRootElementNames.iterator().next();
|
||||
final Document document = createDocument();
|
||||
final Element rootElement = document.createElement(rootName);
|
||||
document.appendChild(rootElement);
|
||||
buildXmlFromHashMap(document, rootElement, map.get(rootName));
|
||||
return rootElement;
|
||||
}
|
||||
|
||||
private static synchronized Document createDocument() {
|
||||
try {
|
||||
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
final DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
return builder.newDocument();
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new ConfigurationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TEXT_NODE_TAG = "#text";
|
||||
private static final String COMMENT_NODE_TAG = "#comment";
|
||||
private static final String CDATA_NODE_TAG = "#cdata-section";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void buildXmlFromHashMap(
|
||||
final Document doc,
|
||||
final Element subtreeRootElement,
|
||||
@Nullable final Object elementContent) {
|
||||
if (elementContent instanceof HashMap) {
|
||||
final HashMap<String, Object> elementContentMap = (HashMap<String, Object>) elementContent;
|
||||
for (final Map.Entry<String, Object> childEntry : elementContentMap.entrySet()) {
|
||||
final String key = childEntry.getKey();
|
||||
if (key.startsWith("@")) {
|
||||
subtreeRootElement.setAttribute(key.substring(1), childEntry.getValue().toString());
|
||||
} else if (key.startsWith("#")) {
|
||||
if (key.equals(TEXT_NODE_TAG)) {
|
||||
if (childEntry.getValue() instanceof List) {
|
||||
buildTextNodeList(doc, subtreeRootElement, (List<String>) childEntry.getValue());
|
||||
} else {
|
||||
final Node textNode = doc.createTextNode(childEntry.getValue().toString());
|
||||
subtreeRootElement.appendChild(textNode);
|
||||
}
|
||||
} else if (key.equals(CDATA_NODE_TAG)) {
|
||||
if (childEntry.getValue() instanceof List) {
|
||||
buildCDataList(doc, subtreeRootElement, (List<String>) childEntry.getValue());
|
||||
} else {
|
||||
final Node cDataNode = doc.createCDATASection(childEntry.getValue().toString());
|
||||
subtreeRootElement.appendChild(cDataNode);
|
||||
}
|
||||
} else if (key.equals(COMMENT_NODE_TAG)) {
|
||||
if (childEntry.getValue() instanceof List) {
|
||||
buildCommentList(doc, subtreeRootElement, (List<String>) childEntry.getValue());
|
||||
} else {
|
||||
final Node commentNode = doc.createComment(childEntry.getValue().toString());
|
||||
subtreeRootElement.appendChild(commentNode);
|
||||
}
|
||||
} //else if (key.equals(WHITESPACE_NODE_TAG)
|
||||
// || key.equals(SIGNIFICANT_WHITESPACE_NODE_TAG)) {
|
||||
// Ignore
|
||||
//} else {
|
||||
/*
|
||||
* All other nodes whose name starts with a '#' are invalid XML
|
||||
* nodes, and thus ignored:
|
||||
*/
|
||||
//}
|
||||
} else {
|
||||
final Element newElement = doc.createElement(key);
|
||||
subtreeRootElement.appendChild(newElement);
|
||||
buildXmlFromHashMap(doc, newElement, childEntry.getValue());
|
||||
}
|
||||
}
|
||||
} else if (elementContent instanceof List) {
|
||||
buildXmlFromJsonArray(doc, subtreeRootElement, (List<Object>) elementContent);
|
||||
} else {
|
||||
if (elementContent != null) {
|
||||
subtreeRootElement.setTextContent(elementContent.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildTextNodeList(final Document doc, final Node subtreeRoot, final List<String> nodeValues) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final String nodeValue : nodeValues) {
|
||||
sb.append(nodeValue);
|
||||
}
|
||||
subtreeRoot.appendChild(doc.createTextNode(sb.toString()));
|
||||
}
|
||||
|
||||
private static void buildCDataList(final Document doc, final Node subtreeRoot, final List<String> nodeValues) {
|
||||
for (final String nodeValue : nodeValues) {
|
||||
subtreeRoot.appendChild(doc.createCDATASection(nodeValue));
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildCommentList(final Document doc, final Node subtreeRoot, final List<String> nodeValues) {
|
||||
for (final String nodeValue : nodeValues) {
|
||||
subtreeRoot.appendChild(doc.createComment(nodeValue));
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildXmlFromJsonArray(
|
||||
final Document doc,
|
||||
final Node listHeadNode,
|
||||
final List<Object> elementContentList) {
|
||||
final Node subtreeRootNode = listHeadNode.getParentNode();
|
||||
/* The head node (already exists) */
|
||||
buildXmlFromHashMap(doc, (Element) listHeadNode, elementContentList.get(0));
|
||||
/* The rest of the list */
|
||||
for (final Object elementContent : elementContentList.subList(1, elementContentList.size())) {
|
||||
final Element newElement = doc.createElement(listHeadNode.getNodeName());
|
||||
subtreeRootNode.appendChild(newElement);
|
||||
buildXmlFromHashMap(doc, newElement, elementContent);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArrayList<Element> deserializeCollection(final JsonReader reader) throws IOException {
|
||||
return reader.deserializeCollectionCustom(Reader);
|
||||
}
|
||||
|
||||
public static void deserializeCollection(final JsonReader reader, final Collection<Element> res) throws IOException {
|
||||
reader.deserializeCollection(Reader, res);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArrayList<Element> deserializeNullableCollection(final JsonReader reader) throws IOException {
|
||||
return reader.deserializeNullableCollectionCustom(Reader);
|
||||
}
|
||||
|
||||
public static void deserializeNullableCollection(final JsonReader reader, final Collection<Element> res) throws IOException {
|
||||
reader.deserializeNullableCollection(Reader, res);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue