1 | package com.framsticks.parsers; |
---|
2 | |
---|
3 | import java.io.InputStream; |
---|
4 | |
---|
5 | import javax.xml.parsers.DocumentBuilder; |
---|
6 | import javax.xml.parsers.DocumentBuilderFactory; |
---|
7 | |
---|
8 | import org.apache.log4j.Logger; |
---|
9 | import org.w3c.dom.Document; |
---|
10 | import org.w3c.dom.Element; |
---|
11 | import org.w3c.dom.NamedNodeMap; |
---|
12 | import org.w3c.dom.Node; |
---|
13 | import org.w3c.dom.NodeList; |
---|
14 | |
---|
15 | import com.framsticks.params.AccessInterface; |
---|
16 | import com.framsticks.params.Registry; |
---|
17 | import com.framsticks.util.FramsticksException; |
---|
18 | |
---|
19 | public class XmlLoader { |
---|
20 | private static final Logger log = Logger.getLogger(XmlLoader.class); |
---|
21 | |
---|
22 | protected Registry registry = new Registry(); |
---|
23 | |
---|
24 | /** |
---|
25 | * |
---|
26 | */ |
---|
27 | public XmlLoader() { |
---|
28 | } |
---|
29 | |
---|
30 | /** |
---|
31 | * @return the registry |
---|
32 | */ |
---|
33 | public Registry getRegistry() { |
---|
34 | return registry; |
---|
35 | } |
---|
36 | |
---|
37 | boolean useLowerCase = false; |
---|
38 | |
---|
39 | /** |
---|
40 | * @param useLowerCase the useLowerCase to set |
---|
41 | */ |
---|
42 | public void setUseLowerCase(boolean useLowerCase) { |
---|
43 | this.useLowerCase = useLowerCase; |
---|
44 | } |
---|
45 | |
---|
46 | public Object processElement(Element element) { |
---|
47 | String name = element.getNodeName(); |
---|
48 | if (useLowerCase) { |
---|
49 | name = name.toLowerCase(); |
---|
50 | } |
---|
51 | if (name.equals("import")) { |
---|
52 | String className = element.getAttribute("class"); |
---|
53 | try { |
---|
54 | registry.registerAndBuild(Class.forName(className)); |
---|
55 | return null; |
---|
56 | } catch (ClassNotFoundException e) { |
---|
57 | throw new FramsticksException().msg("failed to import class").arg("name", name).cause(e); |
---|
58 | } |
---|
59 | } |
---|
60 | |
---|
61 | AccessInterface access = registry.createAccess(name); |
---|
62 | |
---|
63 | if (access == null) { |
---|
64 | throw new FramsticksException().msg("failed to find access interface").arg("name", name); |
---|
65 | } |
---|
66 | Object object = access.createAccessee(); |
---|
67 | assert object != null; |
---|
68 | access.select(object); |
---|
69 | |
---|
70 | NamedNodeMap attributes = element.getAttributes(); |
---|
71 | for (int i = 0; i < attributes.getLength(); ++i) { |
---|
72 | Node attributeNode = attributes.item(i); |
---|
73 | access.set(attributeNode.getNodeName().toLowerCase(), attributeNode.getNodeValue()); |
---|
74 | } |
---|
75 | |
---|
76 | NodeList children = element.getChildNodes(); |
---|
77 | log.debug("found " + children.getLength() + " children in " + object); |
---|
78 | for (int i = 0; i < children.getLength(); ++i) { |
---|
79 | Node childNode = children.item(i); |
---|
80 | if (!(childNode instanceof Element)) { |
---|
81 | continue; |
---|
82 | } |
---|
83 | Object childObject = processElement((Element) childNode); |
---|
84 | if (childObject == null) { |
---|
85 | continue; |
---|
86 | } |
---|
87 | |
---|
88 | if (!access.tryAutoAppend(childObject)) { |
---|
89 | throw new FramsticksException().msg("failed to auto append").arg("child", childObject).arg("parent", object); |
---|
90 | } |
---|
91 | } |
---|
92 | log.debug("loaded " + object); |
---|
93 | |
---|
94 | return object; |
---|
95 | } |
---|
96 | |
---|
97 | public Object load(InputStream stream) { |
---|
98 | try { |
---|
99 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
---|
100 | DocumentBuilder db = factory.newDocumentBuilder(); |
---|
101 | |
---|
102 | Document document = db.parse(stream); |
---|
103 | document.getDocumentElement().normalize(); |
---|
104 | Element element = document.getDocumentElement(); |
---|
105 | assert element != null; |
---|
106 | |
---|
107 | return processElement(element); |
---|
108 | |
---|
109 | } catch (Exception e) { |
---|
110 | throw new FramsticksException().msg("failed to load").cause(e); |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | public <T> T load(InputStream stream, Class<T> type) { |
---|
115 | registry.registerAndBuild(type); |
---|
116 | |
---|
117 | Object object = load(stream); |
---|
118 | if (type.isAssignableFrom(object.getClass())) { |
---|
119 | return type.cast(object); |
---|
120 | } |
---|
121 | throw new FramsticksException().msg("invalid type has been loaded"); |
---|
122 | } |
---|
123 | } |
---|
124 | |
---|