View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of Java-Common.
5    *
6    * Java-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * Java-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with Java-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.application.state.impl;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import javax.xml.parsers.DocumentBuilder;
31  import javax.xml.parsers.DocumentBuilderFactory;
32  import javax.xml.transform.TransformerFactory;
33  import javax.xml.transform.dom.DOMSource;
34  import javax.xml.transform.stream.StreamResult;
35  
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.NamedNodeMap;
39  import org.w3c.dom.Node;
40  import org.w3c.dom.NodeList;
41  import org.xml.sax.InputSource;
42  
43  import com.cosylab.application.state.State;
44  import com.cosylab.application.state.StateFactory;
45  import com.cosylab.application.state.StateStorage;
46  
47  
48  /**
49   * This class is an implementation of the <code>StateStorage</code> that uses a
50   * XML file to store the array of the <code>State</code> objects.
51   *
52   * @author dvitas
53   */
54  public class OldXMLStateStorage extends DefaultStateStorage
55  {
56  	/**
57  	 * DOCUMENT ME!
58  	 *
59  	 * @param outStates DOCUMENT ME!
60  	 * @param os DOCUMENT ME!
61  	 *
62  	 * @throws IOException DOCUMENT ME!
63  	 */
64  	public static final void storeStates(State[] outStates, OutputStream os)
65  		throws IOException
66  	{
67  		storeStates(Arrays.asList(outStates), os);
68  	}
69  
70  	private static final void storeStates(List outStates, OutputStream os)
71  		throws IOException
72  	{
73  		try {
74  			// setup XML
75  			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
76  			factory.setValidating(false);
77  			factory.setNamespaceAware(false);
78  
79  			DocumentBuilder builder = factory.newDocumentBuilder();
80  			Document doc = builder.newDocument();
81  			Element mainEl = doc.createElement("states");
82  			doc.appendChild(mainEl);
83  
84  			for (int i = 0; i < outStates.size(); i++) {
85  				State s = (State)outStates.get(i);
86  				Element el = doc.createElement("state");
87  				mainEl.appendChild(el);
88  				saveState(doc, el, s);
89  			}
90  
91  			if (os == null) {
92  				return;
93  			}
94  
95  			// use this instead of casting because it doesn't need to be the Crimson parser
96  			TransformerFactory.newInstance().newTransformer().transform(new DOMSource(
97  			        doc), new StreamResult(os));
98  
99  			//((XmlDocument)doc).write(os);
100 			// close file buffers
101 			os.flush();
102 			os.close();
103 		} catch (Exception e) {
104 			e.printStackTrace();
105 
106 			IOException exc = new IOException("Unable to store state! "
107 				    + e.getMessage());
108 			exc.initCause(e);
109 			throw exc;
110 		}
111 	}
112 
113 	private static final void readStateFromNode(Node node, State state)
114 	{
115 		NamedNodeMap nnm = node.getAttributes();
116 
117 		// load attributes
118 		String key;
119 
120 		// load attributes
121 		String value;
122 
123 		for (int i = 0; i < nnm.getLength(); i++) {
124 			key = nnm.item(i).getNodeName();
125 			value = nnm.item(i).getNodeValue();
126 
127 			//          if(key.startsWith("ID")) {
128 			//              if(!value.startsWith("null"))
129 			//                  state.setID(value);
130 			//          }
131 			//          else
132 			state.putString(key, value);
133 		}
134 
135 		// and childs if any
136 		NodeList nl = node.getChildNodes();
137 
138 		for (int i = 0; i < nl.getLength(); i++) {
139 			Node child = nl.item(i);
140 
141 			if (child instanceof Element) {
142 				State s = state.createState(child.getNodeName());
143 				readStateFromNode(child, s);
144 			}
145 		}
146 	}
147 
148 	/**
149 	 * DOCUMENT ME!
150 	 *
151 	 * @param is DOCUMENT ME!
152 	 *
153 	 * @return DOCUMENT ME!
154 	 *
155 	 * @throws IOException DOCUMENT ME!
156 	 */
157 	public static final State[] loadStates(InputSource is)
158 		throws IOException
159 	{
160 		List retList = new ArrayList();
161 		loadStates(is, retList);
162 
163 		State[] ret = new State[retList.size()];
164 		retList.toArray(ret);
165 
166 		return ret;
167 	}
168 
169 	private static final void loadStates(InputSource is, List retStates)
170 		throws IOException
171 	{
172 		try {
173 			if (is == null || (is.getByteStream() == null && is.getCharacterStream()==null)) {
174 				return;
175 			}
176 
177 			// setup DOM and parse 
178 			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
179 			factory.setValidating(false);
180 			factory.setNamespaceAware(false);
181 
182 			DocumentBuilder builder = factory.newDocumentBuilder();
183 			Document doc = builder.parse(is);
184 			NodeList nl = doc.getChildNodes();
185 
186 			// node "states" should be the first node in the doc
187 			Node statesNode = null;
188 
189 			for (int i = 0; i < nl.getLength(); i++) {
190 				if (nl.item(i).getNodeName() == "states") {
191 					statesNode = nl.item(i);
192 
193 					break;
194 				}
195 			}
196 
197 			if (statesNode == null) {
198 				throw new IOException("Unable to find node for states in "
199 				    + is.toString());
200 			}
201 
202 			// nl is now states so get its childs
203 			nl = statesNode.getChildNodes();
204 
205 			for (int i = 0; i < nl.getLength(); i++) {
206 				State state = StateFactory.createState();
207 				Node node = nl.item(i);
208 
209 				if (!(node instanceof Element)) {
210 					continue;
211 				}
212 
213 				readStateFromNode(node, state);
214 				retStates.add(state);
215 			}
216 		} catch (Exception e) {
217 			IOException exc = new IOException("Unable to read state from "
218 				    + is.getSystemId() + ": " + e.getMessage());
219 			exc.initCause(e);
220 			throw exc;
221 		}
222 	}
223 
224 	/**
225 			             *
226 			             */
227 	public OldXMLStateStorage()
228 	{
229 		super();
230 	}
231 
232 	/**
233 	 * Creates a new XMLStateStorage object.
234 	 *
235 	 * @param ss DOCUMENT ME!
236 	 */
237 	public OldXMLStateStorage(StateStorage ss)
238 	{
239 		super(ss);
240 	}
241 
242 	/**
243 	 * DOCUMENT ME!
244 	 *
245 	 * @param is DOCUMENT ME!
246 	 *
247 	 * @throws IOException DOCUMENT ME!
248 	 */
249 	public void load(InputStream is) throws IOException
250 	{
251 		load(new InputSource(is));
252 	}
253 
254 	/**
255 	 * DOCUMENT ME!
256 	 *
257 	 * @param is DOCUMENT ME!
258 	 *
259 	 * @throws IOException DOCUMENT ME!
260 	 */
261 	public void load(InputSource is) throws IOException
262 	{
263 		loadStates(is, states);
264 	}
265 
266 	/* (non-Javadoc)
267 	 * @see com.cosylab.application.state.StateStorage#load(java.io.InputStream)
268 	 */
269 	public void load(String filePath, String applicationName)
270 		throws IOException
271 	{
272 		if (delegate != null) {
273 			delegate.load(filePath, applicationName);
274 			addAll(delegate.getStates());
275 
276 			return;
277 		}
278 
279 		// get the InputStream if file exists
280 		InputStream is = getInputStream(filePath, applicationName + ".xml");
281 
282 		if (is != null) {
283 			try {
284 				load(is);
285 			} catch (IOException e) {
286 				IOException ex = new IOException("Failed to load from file '"
287 					    + filePath + "/" + applicationName + ".xml'");
288 				ex.initCause(e);
289 				throw ex;
290 			}
291 		}
292 	}
293 
294 	private static final void saveState(Document doc, Element el, State s)
295 	{
296 		//el.setAttribute("ID", (s.getID()==null)?"null":s.getID());
297 		Iterator iter = s.keySet().iterator();
298 
299 		while (iter.hasNext()) {
300 			String key = (String)iter.next();
301 			Object value = s.getObject(key);
302 
303 			if (value instanceof State) {
304 				Element el1 = doc.createElement(key);
305 				el.appendChild(el1);
306 				saveState(doc, el1, (State)value);
307 
308 				continue;
309 			}
310 
311 			String aa = String.valueOf(value);
312 			//System.out.println("KEY "+key+ " VALUE "+value);
313 			el.setAttribute(key, aa);
314 		}
315 	}
316 
317 	/* (non-Javadoc)
318 	 * @see com.cosylab.application.state.StateStorage#store(java.io.OutputStream)
319 	 */
320 	public void store(String filePath, String applicationName)
321 		throws IOException
322 	{
323 		OutputStream os = getOutputStream(filePath, applicationName + ".xml");
324 		store(os);
325 	}
326 
327 	/* (non-Javadoc)
328 	 * @see com.cosylab.application.state.StateStorage#store(java.io.FileInputStream, java.lang.String)
329 	 */
330 	public void store(OutputStream os) throws IOException
331 	{
332 		storeStates(states, os);
333 	}
334 }
335 
336 /* __oOo__ */