package fr.prcaen.externalresources.converter;
import android.support.annotation.Nullable;
import fr.prcaen.externalresources.model.Resource;
import fr.prcaen.externalresources.model.Resources;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public final class XmlConverter implements Converter {
private static final String ATTRIBUTE_NAME = "name";
private static final String STRING_NODE_NAME = "string";
private static final String COLOR_NODE_NAME = "color";
private static final String DIMEN_NODE_NAME = "dimen";
private static final String INTEGER_NODE_NAME = "integer";
private static final String BOOL_NODE_NAME = "bool";
private static final String STRING_ARRAY_NODE_NAME = "string-array";
private static final String INTEGER_ARRAY_NODE_NAME = "integer-array";
protected static Document read(Reader xml)
throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
factory.setNamespaceAware(true);
return factory.newDocumentBuilder().parse(new InputSource(xml));
}
@Override public Resources fromReader(Reader reader) throws IOException {
try {
Document document = read(reader);
Resources resources = new Resources();
Element root = document.getDocumentElement();
for (int i = 0; i < root.getChildNodes().getLength(); i++) {
Node node = root.getChildNodes().item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
SimpleEntry<String, Resource> entry = get(node);
if (null != entry) {
resources.add(entry.getKey(), entry.getValue());
}
}
}
return resources;
} catch (ParserConfigurationException | SAXException e) {
throw new IOException(e);
}
}
@SuppressWarnings("unused") public Resources fromString(String string) throws IOException {
return fromReader(new StringReader(string));
}
@Nullable protected SimpleEntry<String, Resource> get(Node node) throws DOMException {
final String key = node.getAttributes().getNamedItem(ATTRIBUTE_NAME).getNodeValue();
final Resource value = getResource(node);
if (null != value) {
return new SimpleEntry<>(key, value);
} else {
return null;
}
}
@Nullable protected Resource getResource(Node node) {
switch (node.getNodeName()) {
case STRING_NODE_NAME:
case COLOR_NODE_NAME:
case DIMEN_NODE_NAME:
return new Resource(node.getTextContent());
case INTEGER_NODE_NAME:
return new Resource(Integer.valueOf(node.getTextContent()));
case BOOL_NODE_NAME:
return new Resource(Boolean.valueOf(node.getTextContent()));
case STRING_ARRAY_NODE_NAME:
return getResource(String.class, node.getChildNodes());
case INTEGER_ARRAY_NODE_NAME:
return getResource(Integer.class, node.getChildNodes());
default:
return null;
}
}
@Nullable protected <T> Resource getResource(Class<T> clazz, Node node) {
if (clazz.equals(Integer.class)) {
return new Resource(Integer.valueOf(node.getTextContent()));
} else if (clazz.equals(String.class)) {
return new Resource(node.getTextContent());
} else {
return null;
}
}
protected <T> Resource getResource(Class<T> clazz, NodeList nodeList) {
ArrayList<Resource> resources = new ArrayList<>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Resource resource = getResource(clazz, node);
if (null != resource) {
resources.add(resource);
}
}
}
return new Resource(resources.toArray(new Resource[resources.size()]));
}
}