Hello! I'm having problems with parsing my XML code. I'm using DOM (org.w3c.dom and javax.xml.parsers packages). I want to dynamically construct objects from XML documents, but I'm new to DOM and have very little experience with it. I've tried to filter out DOM-generated noise, I've tried putting the arguments to the <define/> tag both as attributes and as children; both of them have thrown me a NullPointerException. I'm extremely confused as to why this doesn't work, as it should work in my theory (might just be wishful thinking...). Below is my code.
Resources.java
ResourceTest.java
test.xml
Resources.java
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@SuppressWarnings("unchecked")
public class Resources {
private final Document document;
private final DocumentBuilder builder;
private final DocumentBuilderFactory builderFactory;
private final Map<String, Class<?>> classMap = new HashMap<>();
private final Map<String, Resource> resources = new HashMap<>();
public final DecoderGroup decoderGroup = new DecoderGroup();
public Resources(InputStream inputStream) throws ResourceException {
try {
this.builderFactory = DocumentBuilderFactory.newInstance();
this.builder = this.builderFactory.newDocumentBuilder();
this.document = this.builder.parse(inputStream);
if(!this.document.getFirstChild().getNodeName().equals("resources")) {
throw new ResourceException("Invalid top-level tag.");
}
} catch(ParserConfigurationException | SAXException | IOException exception) {
throw new ResourceException(exception);
}
}
public Resources(URL url) throws IOException, ResourceException {
this(url.openStream());
}
public <E extends Resource> E getResource(String name) throws ResourceException {
if(this.resources.containsKey(name))
return (E) this.resources.get(name);
else
throw new ResourceException("Resource not loaded!");
}
public void loadResources(boolean silent) throws ResourceException {
if(silent) {
new Thread() {
public void run() {
try {
loadResources(false);
} catch(ResourceException exception) {
exception.printStackTrace();
throw new RuntimeException(exception);
}
}
}.start();
} else {
if(this.document.getFirstChild().hasChildNodes()) {
for(Node i : ResourceUtils.toList(this.document.getFirstChild().getChildNodes())) {
if(i.getNodeName().equals("#text") ||
i.getNodeValue() == null ||
i.getNodeValue().equals("null")) {
continue;
} else if(i.getNodeName().equals("define")) {
} else if(this.classMap.containsKey(i.getNodeName())) {
String name = null;
for(Node j : ResourceUtils.toList(i.getAttributes())) {
if(j.getNodeName().equals("name")) {
name = j.getNodeValue();
break;
}
}
this.resources.put(name, this.loadResource(i));
} else {
throw new ResourceException("Uknown error!");
}
}
}
}
}
public Resource loadResource(Node rootNode) throws ResourceException {
try {
Class<?> resourceClass = this.classMap.get(rootNode.getNodeValue());
Resource resource;
resource = (Resource) resourceClass.newInstance();
if(rootNode.hasChildNodes()) {
for(Node node : ResourceUtils.toList(rootNode.getChildNodes())) {
Field field = resourceClass.getField(node.getNodeName());
if(!this.decoderGroup.containsKey(field.getType())) {
if(node.hasChildNodes()) {
field.set(resource, loadResource(node));
} else {
throw new ResourceException("Unable to parse node.");
}
}
field.set(resource,
this.decoderGroup.get(field.getType()).decode(node.getNodeValue()));
}
}
return resource;
} catch(IllegalAccessException | InstantiationException |
NoSuchFieldException exception) {
exception.printStackTrace();
throw new ResourceException(exception);
}
}
}
ResourceTest.java
import java.io.FileInputStream;
public class ResourceTest implements Resource {
public String yay;
public static void main(String[] args) throws Exception {
Resources resources = new Resources(new FileInputStream("test.xml"));
resources.loadResources(false);
ResourceTest resourceTest = (ResourceTest) resources.getResource("test");
System.out.println(resourceTest.yay);
}
}
test.xml
<resources> <define name="ResourceTest" class="org.angl.resource.ResourceTest" /> <ResourceTest name="test"> <yay>"YAY!"</yay> </ResourceTest> </resources>