1 | |
package org.jtheque.core.managers.state; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
import org.jdom.Attribute; |
20 | |
import org.jdom.Element; |
21 | |
import org.jtheque.core.managers.AbstractManager; |
22 | |
import org.jtheque.core.managers.ManagerException; |
23 | |
import org.jtheque.core.managers.Managers; |
24 | |
import org.jtheque.core.managers.error.IErrorManager; |
25 | |
import org.jtheque.core.managers.error.JThequeError; |
26 | |
import org.jtheque.core.utils.file.XMLException; |
27 | |
import org.jtheque.core.utils.file.XMLReader; |
28 | |
import org.jtheque.core.utils.file.XMLWriter; |
29 | |
import org.jtheque.utils.io.FileUtils; |
30 | |
|
31 | |
import java.io.File; |
32 | |
import java.util.ArrayList; |
33 | |
import java.util.Collection; |
34 | |
import java.util.HashMap; |
35 | |
import java.util.Map; |
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | 0 | public final class StateManager extends AbstractManager implements IStateManager { |
43 | 0 | private final Map<Class<? extends IState>, IState> states = new HashMap<Class<? extends IState>, IState>(10); |
44 | |
|
45 | |
@Override |
46 | |
public void preInit() { |
47 | |
try { |
48 | 0 | loadStates(); |
49 | 0 | } catch (ManagerException e1) { |
50 | 0 | Managers.getManager(IErrorManager.class).addError(new JThequeError(e1)); |
51 | 0 | } |
52 | 0 | } |
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
@Override |
60 | |
public void loadStates() throws ManagerException { |
61 | 0 | XMLReader reader = new XMLReader(); |
62 | |
|
63 | |
try { |
64 | 0 | reader.openFile(getConfigFile()); |
65 | |
|
66 | 0 | for (Object currentNode : reader.getNodes("state", reader.getRootElement())) { |
67 | |
|
68 | 0 | Class<?> stateClass = Class.forName(reader.readString("@class", currentNode), true, getClass().getClassLoader()); |
69 | |
|
70 | 0 | if (IState.class.isAssignableFrom(stateClass)) { |
71 | 0 | IState state = (IState) stateClass.newInstance(); |
72 | |
|
73 | 0 | loadState(reader, currentNode, state); |
74 | |
|
75 | 0 | states.put(state.getClass(), state); |
76 | |
} |
77 | 0 | } |
78 | 0 | } catch (Exception e) { |
79 | 0 | throw new ConfigException(e); |
80 | |
} finally { |
81 | 0 | FileUtils.close(reader); |
82 | 0 | } |
83 | 0 | } |
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
|
93 | |
private static void loadState(XMLReader reader, Object currentNode, IState state) throws XMLException { |
94 | 0 | if (state.isDelegated()) { |
95 | 0 | Collection<Element> nodes = reader.getNodes("*", currentNode); |
96 | |
|
97 | 0 | state.delegateLoad(resolveNodeStates(nodes)); |
98 | 0 | } else { |
99 | 0 | for (Object propertyNode : reader.getNodes("properties/property", currentNode)) { |
100 | 0 | state.setProperty(reader.readString("@key", propertyNode), reader.readString("@value", propertyNode)); |
101 | |
} |
102 | |
} |
103 | 0 | } |
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
private static Collection<NodeState> resolveNodeStates(Collection<Element> nodes) { |
112 | 0 | Collection<NodeState> nodeStates = new ArrayList<NodeState>(nodes.size()); |
113 | |
|
114 | 0 | for (Element element : nodes) { |
115 | 0 | NodeState nodeState = resolve(element); |
116 | |
|
117 | 0 | nodeStates.add(nodeState); |
118 | 0 | } |
119 | |
|
120 | 0 | return nodeStates; |
121 | |
} |
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
|
127 | |
|
128 | |
private static File getConfigFile() { |
129 | 0 | File configFile = new File(Managers.getCore().getFolders().getApplicationFolder(), "/core/config.xml"); |
130 | |
|
131 | 0 | if (!configFile.exists()) { |
132 | 0 | FileUtils.createEmptyFile(configFile.getAbsolutePath()); |
133 | |
|
134 | 0 | initConfigFile(configFile); |
135 | |
} |
136 | |
|
137 | 0 | return configFile; |
138 | |
} |
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
private static void initConfigFile(File file) { |
146 | 0 | XMLWriter writer = new XMLWriter("states"); |
147 | |
|
148 | 0 | writer.write(file.getAbsolutePath()); |
149 | 0 | } |
150 | |
|
151 | |
@Override |
152 | |
public void close(){ |
153 | 0 | saveStates(); |
154 | 0 | } |
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | |
private void saveStates() { |
160 | 0 | XMLWriter writer = new XMLWriter("states"); |
161 | |
|
162 | 0 | for (IState state : states.values()) { |
163 | 0 | writer.add("state"); |
164 | 0 | writer.addAttribute("class", state.getClass().getCanonicalName()); |
165 | |
|
166 | 0 | if (state.isDelegated()) { |
167 | 0 | delegateSave(state, writer); |
168 | |
} else { |
169 | 0 | save(state, writer); |
170 | |
} |
171 | |
|
172 | 0 | writer.switchToParent(); |
173 | |
} |
174 | |
|
175 | 0 | writer.write(getConfigFile().getAbsolutePath()); |
176 | 0 | } |
177 | |
|
178 | |
|
179 | |
|
180 | |
|
181 | |
|
182 | |
|
183 | |
|
184 | |
private static void save(IState state, XMLWriter writer) { |
185 | 0 | writer.add("properties"); |
186 | |
|
187 | 0 | for (String key : state.getProperties()) { |
188 | 0 | if (state.getProperty(key) != null) { |
189 | 0 | writer.add("property"); |
190 | 0 | writer.addAttribute("key", key); |
191 | 0 | writer.addAttribute("value", state.getProperty(key)); |
192 | |
|
193 | 0 | writer.switchToParent(); |
194 | |
} |
195 | |
} |
196 | |
|
197 | 0 | writer.switchToParent(); |
198 | 0 | } |
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
private static void delegateSave(IState state, XMLWriter writer) { |
207 | 0 | Collection<NodeState> nodes = state.delegateSave(); |
208 | |
|
209 | 0 | for (NodeState node : nodes) { |
210 | 0 | add(node, writer); |
211 | |
} |
212 | 0 | } |
213 | |
|
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
|
219 | |
|
220 | |
private static void add(NodeState node, XMLWriter writer) { |
221 | 0 | if (node.hasChildren()) { |
222 | 0 | writer.add(node.getName()); |
223 | |
|
224 | 0 | for (NodeState children : node.getChildrens()) { |
225 | 0 | add(children, writer); |
226 | |
} |
227 | |
} else { |
228 | 0 | writer.add(node.getName(), node.getText()); |
229 | |
} |
230 | |
|
231 | 0 | if (node.hasAttribute()) { |
232 | 0 | for (NodeStateAttribute attribute : node.getAttributes()) { |
233 | 0 | writer.addAttribute(attribute.getKey(), attribute.getValue()); |
234 | |
} |
235 | |
} |
236 | |
|
237 | 0 | writer.switchToParent(); |
238 | 0 | } |
239 | |
|
240 | |
|
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
|
246 | |
private static NodeState resolve(Element element) { |
247 | 0 | NodeState nodeState = new NodeState(element.getName()); |
248 | |
|
249 | 0 | readNode(element, nodeState); |
250 | 0 | readAttributes(element, nodeState); |
251 | |
|
252 | 0 | return nodeState; |
253 | |
} |
254 | |
|
255 | |
|
256 | |
|
257 | |
|
258 | |
|
259 | |
|
260 | |
|
261 | |
private static void readNode(Element element, NodeState nodeState) { |
262 | 0 | if (element.getChildren().isEmpty()) { |
263 | 0 | String text = element.getText(); |
264 | |
|
265 | 0 | if (text != null && !text.isEmpty()) { |
266 | 0 | nodeState.setText(text); |
267 | |
} |
268 | 0 | } else { |
269 | 0 | Collection<Element> childrenElements = element.getChildren(); |
270 | |
|
271 | 0 | Collection<NodeState> childrens = new ArrayList<NodeState>(childrenElements.size()); |
272 | |
|
273 | 0 | for (Element childrenElement : childrenElements) { |
274 | 0 | childrens.add(resolve(childrenElement)); |
275 | |
} |
276 | |
|
277 | 0 | nodeState.setChildrens(childrens); |
278 | |
} |
279 | 0 | } |
280 | |
|
281 | |
|
282 | |
|
283 | |
|
284 | |
|
285 | |
|
286 | |
|
287 | |
private static void readAttributes(Element element, NodeState nodeState) { |
288 | 0 | if (!element.getAttributes().isEmpty()) { |
289 | 0 | Collection<Attribute> attributes = element.getAttributes(); |
290 | |
|
291 | 0 | Collection<NodeStateAttribute> nodeAttributes = new ArrayList<NodeStateAttribute>(attributes.size()); |
292 | |
|
293 | 0 | for (Attribute attribute : attributes) { |
294 | 0 | nodeAttributes.add(new NodeStateAttribute(attribute.getName(), attribute.getValue())); |
295 | |
} |
296 | |
|
297 | 0 | nodeState.setAttributes(nodeAttributes); |
298 | |
} |
299 | 0 | } |
300 | |
|
301 | |
@Override |
302 | |
public <T extends IState> T getState(Class<T> c) { |
303 | 0 | T state = null; |
304 | |
|
305 | 0 | if (states.containsKey(c)) { |
306 | 0 | state = (T) states.get(c); |
307 | |
} |
308 | |
|
309 | 0 | return state; |
310 | |
} |
311 | |
|
312 | |
@Override |
313 | |
public <T extends IState> T getOrCreateState(Class<T> c) throws StateException { |
314 | 0 | return states.containsKey(c) ? (T) states.get(c) : createState(c); |
315 | |
} |
316 | |
|
317 | |
@Override |
318 | |
public <T extends IState> T createState(Class<T> c) throws StateException { |
319 | |
T state; |
320 | |
try { |
321 | 0 | Object o = c.newInstance(); |
322 | |
|
323 | 0 | state = (T) o; |
324 | 0 | } catch (InstantiationException e) { |
325 | 0 | throw new StateException(e); |
326 | 0 | } catch (IllegalAccessException e) { |
327 | 0 | throw new StateException(e); |
328 | 0 | } |
329 | |
|
330 | 0 | states.put(c, state); |
331 | |
|
332 | 0 | return state; |
333 | |
} |
334 | |
|
335 | |
@Override |
336 | |
public void registerState(IState state) { |
337 | 0 | states.put(state.getClass(), state); |
338 | 0 | } |
339 | |
} |