KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > taskblocks > io > ProjectSaveLoad


1 /*
2  * Copyright (C) Jakub Neubauer, 2007
3  *
4  * This file is part of TaskBlocks
5  *
6  * TaskBlocks 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  * TaskBlocks 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 this program. If not, see <http://www.gnu.org/licenses/>.
18  */

19
20 package taskblocks.io;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
32 import javax.xml.parsers.ParserConfigurationException JavaDoc;
33 import javax.xml.transform.Transformer JavaDoc;
34 import javax.xml.transform.TransformerException JavaDoc;
35 import javax.xml.transform.TransformerFactory JavaDoc;
36 import javax.xml.transform.dom.DOMSource JavaDoc;
37 import javax.xml.transform.stream.StreamResult JavaDoc;
38
39 import org.w3c.dom.Document JavaDoc;
40 import org.w3c.dom.Element JavaDoc;
41 import org.w3c.dom.Node JavaDoc;
42 import org.w3c.dom.NodeList JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44
45 import taskblocks.Pair;
46 import taskblocks.Utils;
47 import taskblocks.modelimpl.ColorLabel;
48 import taskblocks.modelimpl.ManImpl;
49 import taskblocks.modelimpl.TaskImpl;
50 import taskblocks.modelimpl.TaskModelImpl;
51
52 /**
53  * Used to load/save the task project model
54  *
55  * @author jakub
56  *
57  */

58 public class ProjectSaveLoad {
59
60     public static final String JavaDoc TASKMAN_E = "taskman";
61     public static final String JavaDoc TASKS_E = "tasks";
62     public static final String JavaDoc MANS_E = "mans";
63     public static final String JavaDoc TASK_E = "task";
64     public static final String JavaDoc MAN_E = "man";
65     public static final String JavaDoc PREDECESSORS_E = "predecessors";
66     public static final String JavaDoc PREDECESSOR_E = "predecessor";
67     
68     public static final String JavaDoc NAME_A = "name";
69     public static final String JavaDoc ID_A = "id";
70     public static final String JavaDoc START_A = "start";
71     public static final String JavaDoc DURATION_A = "duration";
72     public static final String JavaDoc MAN_A = "man";
73     public static final String JavaDoc PRED_A = "pred";
74     public static final String JavaDoc COLOR_A = "color";
75     
76     TaskModelImpl _model;
77     Map JavaDoc<String JavaDoc, TaskImpl> _taskIds;
78     Map JavaDoc<String JavaDoc, ManImpl> _manIds;
79
80     /**
81      * Loads project data model from given file.
82      * TODO: checks for missing data in elements
83      *
84      * @param f
85      * @return
86      * @throws WrongDataException
87      */

88     public TaskModelImpl loadProject(File JavaDoc f) throws WrongDataException {
89         try {
90             DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
91             Document JavaDoc doc;
92             doc = dbf.newDocumentBuilder().parse(f);
93             Element JavaDoc rootE = doc.getDocumentElement();
94             if(!TASKMAN_E.equals(rootE.getNodeName())) {
95                 throw new WrongDataException("Document is not TaskManager project");
96             }
97             
98             // mapping ID -> ManImpl
99
Map JavaDoc<String JavaDoc, ManImpl> mans = new HashMap JavaDoc<String JavaDoc, ManImpl>();
100             // mapping ID -> TaskImpl
101
Map JavaDoc<String JavaDoc, TaskImpl>tasks = new HashMap JavaDoc<String JavaDoc, TaskImpl>();
102             // mapping tasks -> list of their predecessors IDs
103
List JavaDoc<Pair<TaskImpl, String JavaDoc[]>> taskPredecessorsIds = new ArrayList JavaDoc<Pair<TaskImpl,String JavaDoc[]>>();
104             
105             // 1. load all tasks and mans alone, 2. bind them between each other
106
Element JavaDoc mansE = getFirstChild(rootE, MANS_E);
107             if(mansE != null) {
108                 Element JavaDoc[] manEs = Utils.getChilds(mansE, MAN_E);
109                 for(Element JavaDoc manE: manEs) {
110                     String JavaDoc manName = manE.getAttribute(NAME_A);
111                     String JavaDoc manId = manE.getAttribute(ID_A);
112                     ManImpl man = new ManImpl();
113                     man.setName(manName);
114                     mans.put(manId, man);
115                 }
116             }
117             Element JavaDoc tasksE = getFirstChild(rootE, TASKS_E);
118             if(tasksE != null) {
119                 for(Element JavaDoc taskE: Utils.getChilds(tasksE, TASK_E)) {
120                     String JavaDoc taskId = taskE.getAttribute(ID_A);
121                     String JavaDoc taskName = taskE.getAttribute(NAME_A);
122                     long taskStart = Long.valueOf(taskE.getAttribute(START_A));
123                     long taskDuration = Long.valueOf(taskE.getAttribute(DURATION_A));
124                     String JavaDoc colorTxt = taskE.getAttribute(COLOR_A);
125                     String JavaDoc taskManId = taskE.getAttribute(MAN_A);
126                     ManImpl man = mans.get(taskManId); // mans are already loaded
127

128                     if(man == null) {
129                         throw new WrongDataException("Task with id " + taskId + " is not assigned to any man");
130                     }
131                     
132                     TaskImpl task = new TaskImpl();
133                     task.setName(taskName);
134                     task.setStartTime(taskStart);
135                     task.setDuration(taskDuration);
136                     task.setMan(man);
137                     if(colorTxt != null && colorTxt.length() > 0) {
138                         int colorIndex = Integer.parseInt(colorTxt);
139                         if(colorIndex >= 0 && colorIndex < ColorLabel.COLOR_LABELS.length) {
140                             task.setColorLabel(ColorLabel.COLOR_LABELS[colorIndex]);
141                         }
142                     }
143
144                     // read predecessors ids
145
Element JavaDoc predsE = getFirstChild(taskE, PREDECESSORS_E);
146                     if(predsE != null) {
147                         List JavaDoc<String JavaDoc> preds = new ArrayList JavaDoc<String JavaDoc>();
148                         for(Element JavaDoc predE: Utils.getChilds(predsE, PREDECESSOR_E)) {
149                             preds.add(predE.getAttribute(PRED_A));
150                         }
151                         taskPredecessorsIds.add(new Pair<TaskImpl, String JavaDoc[]>(task, preds.toArray(new String JavaDoc[preds.size()])));
152                     }
153                     
154                     tasks.put(taskId, task);
155                 }
156             }
157             
158             // now count the predecessors of tasks
159
for(Pair<TaskImpl, String JavaDoc[]> taskAndPredIds: taskPredecessorsIds) {
160                 List JavaDoc<TaskImpl> preds = new ArrayList JavaDoc<TaskImpl>();
161                 for(String JavaDoc predId: taskAndPredIds.snd) {
162                     TaskImpl pred = tasks.get(predId);
163                     if(pred == null) {
164                         System.out.println("Warning: Task predecessor with id " + predId + " doesn't exist");
165                     } else if(pred == taskAndPredIds.fst) {
166                         System.out.println("Warning: Task with id " + predId + " is it's own predecessor");
167                     } else {
168                         preds.add(pred);
169                     }
170                 }
171                 taskAndPredIds.fst.setPredecessors(preds.toArray(new TaskImpl[preds.size()]));
172             }
173             
174             TaskModelImpl taskModel = new TaskModelImpl(tasks.values().toArray(new TaskImpl[tasks.size()]), mans.values().toArray(new ManImpl[mans.size()]));
175             
176             return taskModel;
177             
178         } catch (SAXException JavaDoc e) {
179             throw new WrongDataException("Document is not valid data file", e);
180         } catch (IOException JavaDoc e) {
181             throw new WrongDataException("Can't read file: " + e.getMessage(), e);
182         } catch (ParserConfigurationException JavaDoc e) {
183             throw new WrongDataException("Document is not TaskManager project", e);
184         }
185     }
186     
187     /**
188      * Saves project to specified file
189      *
190      * @param f
191      * @param model
192      * @throws TransformerException
193      * @throws ParserConfigurationException
194      */

195     public void saveProject(File JavaDoc f, TaskModelImpl model) throws TransformerException JavaDoc, ParserConfigurationException JavaDoc {
196         DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
197         Document JavaDoc doc;
198         doc = dbf.newDocumentBuilder().newDocument();
199         
200         _model = model;
201         _taskIds = new HashMap JavaDoc<String JavaDoc, TaskImpl>();
202         _manIds = new HashMap JavaDoc<String JavaDoc, ManImpl>();
203
204         // build the xml tree
205
saveProject(doc);
206         prettyLayout((Element JavaDoc)doc.getFirstChild());
207
208         TransformerFactory JavaDoc tf = TransformerFactory.newInstance();
209         Transformer JavaDoc t = tf.newTransformer();
210         t.transform(new DOMSource JavaDoc(doc), new StreamResult JavaDoc(f));
211     }
212     
213     private void saveProject(Document JavaDoc doc) {
214         Element JavaDoc rootE = doc.createElement(TASKMAN_E);
215         doc.appendChild(rootE);
216         Set JavaDoc<ManImpl> mans = new HashSet JavaDoc<ManImpl>();
217
218         // generate list of mans
219
for(TaskImpl t: _model._tasks) {
220             mans.add(t.getMan());
221         }
222         
223         // generate task and man ids
224
int lastTaskId = 1;
225         int lastManId = 1;
226         for(TaskImpl t: _model._tasks) {
227             t._id = String.valueOf(lastTaskId++);
228         }
229         for(ManImpl man: mans) {
230             man._id = String.valueOf(lastManId++);
231         }
232         
233         // save mans
234
Element JavaDoc mansE = doc.createElement(MANS_E);
235         for(ManImpl man : mans) {
236             saveMan(mansE, man);
237         }
238         rootE.appendChild(mansE);
239         
240         // save tasks
241
Element JavaDoc tasksE = doc.createElement(TASKS_E);
242         for(TaskImpl t: _model._tasks) {
243             saveTask(tasksE, t);
244         }
245         rootE.appendChild(tasksE);
246     }
247
248     private void saveMan(Element JavaDoc mansE, ManImpl man) {
249         Element JavaDoc manE = mansE.getOwnerDocument().createElement(MAN_E);
250         manE.setAttribute(ID_A, man._id);
251         manE.setAttribute(NAME_A, man.getName());
252         mansE.appendChild(manE);
253     }
254
255     private void saveTask(Element JavaDoc tasksE, TaskImpl t) {
256         Element JavaDoc taskE = tasksE.getOwnerDocument().createElement(TASK_E);
257         taskE.setAttribute(NAME_A, t.getName());
258         taskE.setAttribute(ID_A, t._id);
259         taskE.setAttribute(START_A, String.valueOf(t.getStartTime()));
260         taskE.setAttribute(DURATION_A, String.valueOf(t.getDuration()));
261         taskE.setAttribute(MAN_A, t.getMan()._id);
262         if(t.getColorLabel() != null) {
263             taskE.setAttribute(COLOR_A, String.valueOf(t.getColorLabel()._index));
264         }
265         
266         // save predecessors
267
if(t.getPredecessors().length > 0) {
268             Element JavaDoc predsE = taskE.getOwnerDocument().createElement(PREDECESSORS_E);
269             for(TaskImpl pred: t.getPredecessors()) {
270                 Element JavaDoc predE = predsE.getOwnerDocument().createElement(PREDECESSOR_E);
271                 predE.setAttribute(PRED_A, pred._id);
272                 predsE.appendChild(predE);
273             }
274             taskE.appendChild(predsE);
275         }
276         tasksE.appendChild(taskE);
277     }
278     
279     private Element JavaDoc getFirstChild(Element JavaDoc e, String JavaDoc name) {
280         NodeList JavaDoc nl = e.getChildNodes();
281         for(int i = 0; i < nl.getLength(); i++) {
282             Node JavaDoc n = nl.item(i);
283             if(n.getNodeType() == Node.ELEMENT_NODE && name.equals(n.getNodeName())) {
284                 return (Element JavaDoc)n;
285             }
286         }
287         return null;
288     }
289     
290     private void prettyLayout(Element JavaDoc e) {
291         prettyLayoutRec(e, "");
292     }
293     
294     private void prettyLayoutRec(Element JavaDoc e, String JavaDoc currentIndent) {
295         
296         // insert spaces before 'e'
297
// but only if indent > 0. This also resolves problem that we cannot insert
298
// anything in Document node (before root element).
299
if(currentIndent.length() > 0) {
300             e.getParentNode().insertBefore(e.getOwnerDocument().createTextNode(currentIndent), e);
301         }
302         
303         // first check if element has some sub-element. if true, prettyLayout them
304
// recursively with increase indent
305
NodeList JavaDoc nl = e.getChildNodes();
306         boolean hasChildrenElems = false;
307         for(int i = 0; i < nl.getLength(); i++) {
308             Node JavaDoc n = nl.item(i);
309             if(n.getNodeType() == Node.ELEMENT_NODE) {
310                 hasChildrenElems = true;
311                 break;
312             }
313         }
314         
315         if(hasChildrenElems) {
316             // \n after start-tag. it means before first child
317
e.insertBefore(e.getOwnerDocument().createTextNode("\n"), e.getFirstChild());
318             
319             // indent before end-tag. It means just as last child
320
e.appendChild(e.getOwnerDocument().createTextNode(currentIndent));
321
322             // recursively indent children
323
currentIndent += " ";
324             // we must get the nodelist again, because previous adding of childs broked
325
// the old nodelist.
326
Node JavaDoc n = e.getFirstChild();
327             while(n != null) {
328                 if(n.getNodeType() == Node.ELEMENT_NODE) {
329                     prettyLayoutRec((Element JavaDoc)n, currentIndent);
330                 }
331                 n = n.getNextSibling();
332             }
333         }
334
335         // \n after end-tag
336
Node JavaDoc text = e.getOwnerDocument().createTextNode("\n");
337         if(e.getNextSibling() == null) {
338             if(e.getParentNode().getNodeType() != Node.DOCUMENT_NODE) {
339                 e.getParentNode().appendChild(text);
340             }
341         } else {
342             e.getParentNode().insertBefore(text, e.getNextSibling());
343         }
344     }
345 }
346
Popular Tags