annotate java/src/uk/ac/qmul/eecs/ccmi/gui/persistence/PersistenceManager.java @ 1:e3935c01cde2 tip

moved license of PdPersistenceManager to the beginning of the file
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 19:52:03 +0100
parents 78b7fc5391a2
children
rev   line source
f@0 1 /*
f@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
f@0 3
f@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19
f@0 20 package uk.ac.qmul.eecs.ccmi.gui.persistence;
f@0 21
f@0 22 import java.io.BufferedWriter;
f@0 23 import java.io.File;
f@0 24 import java.io.FileWriter;
f@0 25 import java.io.IOException;
f@0 26 import java.io.InputStream;
f@0 27 import java.io.OutputStream;
f@0 28 import java.text.MessageFormat;
f@0 29 import java.util.ArrayList;
f@0 30 import java.util.Collection;
f@0 31 import java.util.Enumeration;
f@0 32 import java.util.LinkedHashMap;
f@0 33 import java.util.List;
f@0 34 import java.util.Map;
f@0 35 import java.util.ResourceBundle;
f@0 36
f@0 37 import javax.swing.tree.TreeNode;
f@0 38 import javax.xml.parsers.DocumentBuilder;
f@0 39 import javax.xml.parsers.DocumentBuilderFactory;
f@0 40 import javax.xml.parsers.ParserConfigurationException;
f@0 41 import javax.xml.transform.OutputKeys;
f@0 42 import javax.xml.transform.Transformer;
f@0 43 import javax.xml.transform.TransformerConfigurationException;
f@0 44 import javax.xml.transform.TransformerException;
f@0 45 import javax.xml.transform.TransformerFactory;
f@0 46 import javax.xml.transform.dom.DOMSource;
f@0 47 import javax.xml.transform.stream.StreamResult;
f@0 48
f@0 49 import org.w3c.dom.Document;
f@0 50 import org.w3c.dom.Element;
f@0 51 import org.w3c.dom.NodeList;
f@0 52 import org.xml.sax.SAXException;
f@0 53
f@0 54 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel;
f@0 55 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramTreeNode;
f@0 56 import uk.ac.qmul.eecs.ccmi.diagrammodel.TreeModel;
f@0 57 import uk.ac.qmul.eecs.ccmi.gui.Diagram;
f@0 58 import uk.ac.qmul.eecs.ccmi.gui.DiagramEventSource;
f@0 59 import uk.ac.qmul.eecs.ccmi.gui.Edge;
f@0 60 import uk.ac.qmul.eecs.ccmi.gui.Node;
f@0 61 import uk.ac.qmul.eecs.ccmi.utils.CharEscaper;
f@0 62
f@0 63 /**
f@0 64 * The PersistanceManager provides methods for saving and retrieving diagrams from an XML
f@0 65 * file. Both templates diagrams (prototypes from which actual diagram instances are created
f@0 66 * through cloning) and diagram instances can be saved to a file. The tag name used in the XML
f@0 67 * file can be accessed via the static {@code String} variables of this class.
f@0 68 *
f@0 69 */
f@0 70 public abstract class PersistenceManager {
f@0 71 /**
f@0 72 * Encodes a diagram template in a file in XML format
f@0 73 *
f@0 74 * @param diagram the diagram to be encoded
f@0 75 * @param file the file where the diagram is going to be encoded
f@0 76 * @throws IOException if there are any I/O problems with the file
f@0 77 */
f@0 78 public static void encodeDiagramTemplate(Diagram diagram, File file) throws IOException{
f@0 79 ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
f@0 80 if(file.createNewFile() == false)
f@0 81 throw new IOException(resources.getString("dialog.error.file_exists"));
f@0 82
f@0 83 DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
f@0 84 DocumentBuilder docBuilder = null;
f@0 85 try {
f@0 86 docBuilder = dbfac.newDocumentBuilder();
f@0 87 } catch (ParserConfigurationException e) {
f@0 88 throw new IOException(resources.getString("dialog.error.problem.save"),e);
f@0 89 }
f@0 90 Document doc = docBuilder.newDocument();
f@0 91
f@0 92 Element root = doc.createElement(DIAGRAM);
f@0 93 doc.appendChild(root);
f@0 94 /* diagram name and prototypePersstenceDelegate */
f@0 95 root.setAttribute(NAME, diagram.getName());
f@0 96 root.setAttribute(PROTOTYPE_PERSISTENCE_DELEGATE, diagram.getPrototypePersistenceDelegate().getClass().getName());
f@0 97
f@0 98 writePrototypes(doc, root, diagram);
f@0 99
f@0 100 //set up a transformer
f@0 101 TransformerFactory transfac = TransformerFactory.newInstance();
f@0 102 Transformer trans = null;
f@0 103 try {
f@0 104 trans = transfac.newTransformer();
f@0 105 } catch (TransformerConfigurationException tce) {
f@0 106 throw new IOException(resources.getString("dialog.error.problem.save"),tce);
f@0 107 }
f@0 108 trans.setOutputProperty(OutputKeys.INDENT, "yes");
f@0 109 trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(2));
f@0 110
f@0 111 StreamResult result = new StreamResult(new BufferedWriter(new FileWriter(file)));
f@0 112 DOMSource source = new DOMSource(doc);
f@0 113 try {
f@0 114 trans.transform(source, result);
f@0 115 } catch (TransformerException te) {
f@0 116 throw new IOException(resources.getString("dialog.error.problem.save"),te);
f@0 117 }
f@0 118 }
f@0 119
f@0 120 /**
f@0 121 * Decodes a diagram template from a file in XML format
f@0 122 *
f@0 123 * @param XMLFile the file to read the diagram from
f@0 124 * @throws IOException if there are any I/O problems with the file
f@0 125 *
f@0 126 * @return the diagram encoded in {@code XMLFile}
f@0 127 */
f@0 128 public static Diagram decodeDiagramTemplate(File XMLFile) throws IOException{
f@0 129 ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
f@0 130 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
f@0 131 DocumentBuilder dBuilder = null;
f@0 132 try {
f@0 133 dBuilder = dbFactory.newDocumentBuilder();
f@0 134 } catch (ParserConfigurationException pce) {
f@0 135 throw new IOException(resources.getString("dialog.error.problem.open"),pce);
f@0 136 }
f@0 137 Document doc = null;
f@0 138 try {
f@0 139 doc = dBuilder.parse(XMLFile);
f@0 140 } catch (SAXException se) {
f@0 141 throw new IOException(resources.getString("dialog.error.problem.open"),se);
f@0 142 }
f@0 143 doc.getDocumentElement().normalize();
f@0 144
f@0 145 if(doc.getElementsByTagName(DIAGRAM).item(0) == null)
f@0 146 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 147 Element root = (Element)doc.getElementsByTagName(DIAGRAM).item(0);
f@0 148 String diagramName = root.getAttribute(NAME);
f@0 149 if(diagramName.isEmpty())
f@0 150 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 151 String persistenceDelegateClassName = root.getAttribute(PROTOTYPE_PERSISTENCE_DELEGATE);
f@0 152 PrototypePersistenceDelegate persistenceDelegate = null;
f@0 153 try{
f@0 154 Class<? extends PrototypePersistenceDelegate> c = Class.forName(persistenceDelegateClassName).asSubclass(PrototypePersistenceDelegate.class);
f@0 155 persistenceDelegate = c.newInstance();
f@0 156 }catch(Exception e){
f@0 157 throw new IOException(resources.getString("dialog.error.problem.open"),e);
f@0 158 }
f@0 159
f@0 160 final List<Node> nList = readNodePrototypes(doc,persistenceDelegate);
f@0 161 final List<Edge> eList = readEdgePrototypes(doc,persistenceDelegate);
f@0 162 Node[] nArray = new Node[nList.size()];
f@0 163 Edge[] eArray = new Edge[eList.size()];
f@0 164 return Diagram.newInstance(diagramName,nList.toArray(nArray),eList.toArray(eArray),persistenceDelegate);
f@0 165 }
f@0 166
f@0 167 /**
f@0 168 * Encodes a diagram instance into the given output stream. Using output stream
f@0 169 * instead of {@code Writer} as it's advised by the <i>StreamResult API</i>
f@0 170 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
f@0 171 *
f@0 172 * @param diagram the diagram to encode
f@0 173 * @param newName the new name of the diagram to encode. This will also be the name of the file but {@code diagram}
f@0 174 * will still keep the old name, that is the value returned by {@code getName()} won't be changed to {@code newName}.
f@0 175 * If a {@code null} value is passed than the value returned by {@code diagram.getName()} will be used.
f@0 176 *
f@0 177 * @param out where the diagram will be encoded
f@0 178 * @throws IOException if there are any I/O problems with the file
f@0 179 */
f@0 180 public static void encodeDiagramInstance(Diagram diagram, String newName, OutputStream out) throws IOException{
f@0 181 ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
f@0 182 DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
f@0 183 DocumentBuilder docBuilder = null;
f@0 184 try {
f@0 185 docBuilder = dbfac.newDocumentBuilder();
f@0 186 } catch (ParserConfigurationException pce) {
f@0 187 throw new IOException(resources.getString("dialog.error.problem.save"),pce);
f@0 188 }
f@0 189 Document doc = docBuilder.newDocument();
f@0 190
f@0 191 Element root = doc.createElement(DIAGRAM);
f@0 192 root.setAttribute(NAME, (newName != null) ? newName : diagram.getName());
f@0 193 root.setAttribute(PROTOTYPE_PERSISTENCE_DELEGATE, diagram.getPrototypePersistenceDelegate().getClass().getName());
f@0 194 doc.appendChild(root);
f@0 195
f@0 196 /* store bookmarks */
f@0 197 Element bookmarksTag = doc.createElement(BOOKMARKS);
f@0 198 TreeModel<Node,Edge> treeModel = diagram.getTreeModel();
f@0 199 for(String key : treeModel.getBookmarks()){
f@0 200 Element bookmarkTag = doc.createElement(BOOKMARK);
f@0 201 bookmarkTag.setAttribute(KEY, key);
f@0 202 if(treeModel.getBookmarkedTreeNode(key).isRoot())
f@0 203 bookmarkTag.setTextContent(ROOT_AS_STRING);
f@0 204 else
f@0 205 bookmarkTag.setTextContent(getTreeNodeAsString(treeModel.getBookmarkedTreeNode(key)));
f@0 206 bookmarksTag.appendChild(bookmarkTag);
f@0 207 }
f@0 208 if(bookmarksTag.hasChildNodes())
f@0 209 root.appendChild(bookmarksTag);
f@0 210
f@0 211 /* store notes */
f@0 212 Element notesTag = doc.createElement(NOTES);
f@0 213 DiagramTreeNode treeRoot = (DiagramTreeNode)diagram.getTreeModel().getRoot();
f@0 214 for( @SuppressWarnings("unchecked")
f@0 215 Enumeration<DiagramTreeNode> enumeration = treeRoot.depthFirstEnumeration(); enumeration.hasMoreElements();){
f@0 216 DiagramTreeNode treeNode = enumeration.nextElement();
f@0 217 if(!treeNode.getNotes().isEmpty()){
f@0 218 Element noteTag = doc.createElement(NOTE);
f@0 219 Element treeNodeTag = doc.createElement(TREE_NODE);
f@0 220 if(treeNode.isRoot())
f@0 221 treeNodeTag.setTextContent(ROOT_AS_STRING);
f@0 222 else
f@0 223 treeNodeTag.setTextContent(getTreeNodeAsString(treeNode));
f@0 224 Element contentTag = doc.createElement(CONTENT);
f@0 225 contentTag.setTextContent(CharEscaper.replaceNewline(treeNode.getNotes()));
f@0 226 noteTag.appendChild(treeNodeTag);
f@0 227 noteTag.appendChild(contentTag);
f@0 228 notesTag.appendChild(noteTag);
f@0 229 }
f@0 230 }
f@0 231
f@0 232 if(notesTag.hasChildNodes())
f@0 233 root.appendChild(notesTag);
f@0 234
f@0 235 writePrototypes(doc,root,diagram);
f@0 236
f@0 237 Element components = doc.createElement(COMPONENTS);
f@0 238 root.appendChild(components);
f@0 239
f@0 240 synchronized(diagram.getCollectionModel().getMonitor()){
f@0 241 Collection<Node> nodes = diagram.getCollectionModel().getNodes();
f@0 242 Collection<Edge> edges = diagram.getCollectionModel().getEdges();
f@0 243
f@0 244 /* store nodes */
f@0 245 Element nodesTag = doc.createElement(NODES);
f@0 246 components.appendChild(nodesTag);
f@0 247 List<Node> nList = new ArrayList<Node>(nodes);
f@0 248 for(Node n : nList){
f@0 249 Element nodeTag = doc.createElement(NODE);
f@0 250 nodeTag.setAttribute(ID, String.valueOf(n.getId()));
f@0 251 nodeTag.setAttribute(TYPE, n.getType());
f@0 252 nodesTag.appendChild(nodeTag);
f@0 253 n.encode(doc, nodeTag);
f@0 254 }
f@0 255
f@0 256 Element edgesTag = doc.createElement(EDGES);
f@0 257 components.appendChild(edgesTag);
f@0 258 for(Edge e : edges){
f@0 259 Element edgeTag = doc.createElement(EDGE);
f@0 260 edgesTag.appendChild(edgeTag);
f@0 261 e.encode(doc,edgeTag,nList);
f@0 262 }
f@0 263 }
f@0 264 //set up a transformer
f@0 265 TransformerFactory transfac = TransformerFactory.newInstance();
f@0 266 Transformer trans = null;
f@0 267 try {
f@0 268 trans = transfac.newTransformer();
f@0 269 } catch (TransformerConfigurationException tec) {
f@0 270 throw new IOException(resources.getString("dialog.error.problem.save"));
f@0 271 }
f@0 272 trans.setOutputProperty(OutputKeys.INDENT, "yes");
f@0 273 trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(2));
f@0 274
f@0 275
f@0 276 StreamResult result = new StreamResult(out);
f@0 277 DOMSource source = new DOMSource(doc);
f@0 278 try {
f@0 279 trans.transform(source, result);
f@0 280 } catch (TransformerException te) {
f@0 281 throw new IOException(resources.getString("dialog.error.problem.save"),te);
f@0 282 }
f@0 283 }
f@0 284
f@0 285 /**
f@0 286 * Encodes a diagram instance into the given output stream. Using output stream
f@0 287 * instead of {@code Writer} as it's advised by the <i>StreamResult API</i>
f@0 288 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
f@0 289 *
f@0 290 * @param diagram the diagram to encode
f@0 291 * @param out an output stram to the file where the diagram will be encoded
f@0 292 * @throws IOException if there are any I/O problems with the file
f@0 293 */
f@0 294 public static void encodeDiagramInstance(Diagram diagram, OutputStream out) throws IOException{
f@0 295 encodeDiagramInstance(diagram,null,out);
f@0 296 }
f@0 297
f@0 298 /**
f@0 299 * Decodes a diagram instance from the given input stream. Using input stream
f@0 300 * instead of {@code Reader} as it's advised by the <i>StreamResult API</i>
f@0 301 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
f@0 302 *
f@0 303 * @param in an input stream to the file the diagram is decoded from
f@0 304 * @throws IOException if there are any I/O problems with the file
f@0 305 *
f@0 306 * @return the diagram encoded in the file
f@0 307 */
f@0 308 public static Diagram decodeDiagramInstance(InputStream in) throws IOException {
f@0 309 ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
f@0 310 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
f@0 311 DocumentBuilder dBuilder = null;
f@0 312 try {
f@0 313 dBuilder = dbFactory.newDocumentBuilder();
f@0 314 } catch (ParserConfigurationException pce) {
f@0 315 throw new IOException(resources.getString("dialog.error.problem.open"),pce);
f@0 316 }
f@0 317 Document doc = null;
f@0 318 try {
f@0 319 doc = dBuilder.parse(in);
f@0 320 } catch (SAXException se) {
f@0 321 throw new IOException(resources.getString("dialog.error.problem.open"),se);
f@0 322 }
f@0 323 doc.getDocumentElement().normalize();
f@0 324
f@0 325 if(doc.getElementsByTagName(DIAGRAM).item(0) == null)
f@0 326 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 327 Element root = (Element)doc.getElementsByTagName(DIAGRAM).item(0);
f@0 328 String diagramName = root.getAttribute(NAME);
f@0 329 if(diagramName.isEmpty())
f@0 330 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 331 String persistenceDelegateClassName = root.getAttribute(PROTOTYPE_PERSISTENCE_DELEGATE);
f@0 332 PrototypePersistenceDelegate persistenceDelegate = null;
f@0 333 try{
f@0 334 Class<? extends PrototypePersistenceDelegate> c = Class.forName(persistenceDelegateClassName).asSubclass(PrototypePersistenceDelegate.class);
f@0 335 persistenceDelegate = c.newInstance();
f@0 336 }catch(Exception e){
f@0 337 throw new IOException(resources.getString("dialog.error.problem.open"),e);
f@0 338 }
f@0 339
f@0 340 final List<Node> nList = readNodePrototypes(doc,persistenceDelegate);
f@0 341 final List<Edge> eList = readEdgePrototypes(doc,persistenceDelegate);
f@0 342
f@0 343 final Node[] nodes = nList.toArray(new Node[nList.size()]);
f@0 344 final Edge[] edges = eList.toArray(new Edge[eList.size()]);
f@0 345
f@0 346 Diagram diagram = Diagram.newInstance(diagramName, nodes,edges,persistenceDelegate);
f@0 347 CollectionModel<Node,Edge> collectionModel = diagram.getCollectionModel();
f@0 348 TreeModel<Node,Edge> treeModel = diagram.getTreeModel();
f@0 349
f@0 350 /* a map linking node ids in the XML file to the actual Node object they represent */
f@0 351 Map<String,Node> nodesId = new LinkedHashMap<String,Node>();
f@0 352
f@0 353 if(doc.getElementsByTagName(COMPONENTS).item(0) == null)
f@0 354 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 355 Element componentsTag = (Element)doc.getElementsByTagName(COMPONENTS).item(0);
f@0 356 NodeList componentsChildren = componentsTag.getChildNodes();
f@0 357 Element nodesTag = null;
f@0 358 for(int i=0;i<componentsChildren.getLength();i++){
f@0 359 if(NODES.equals(componentsChildren.item(i).getNodeName()))
f@0 360 nodesTag = (Element)componentsChildren.item(i);
f@0 361 }
f@0 362
f@0 363 NodeList elemList = nodesTag.getElementsByTagName(NODE);
f@0 364 for(int i=0; i<elemList.getLength();i++){
f@0 365 Element nodeTag = (Element)elemList.item(i);
f@0 366 String idAsString = nodeTag.getAttribute(ID);
f@0 367 String type = nodeTag.getAttribute(TYPE);
f@0 368 Node prototype = null;
f@0 369 for(Node n : nList)
f@0 370 if(n.getType().equals(type)){
f@0 371 prototype = n;
f@0 372 break;
f@0 373 }
f@0 374 if(prototype == null)
f@0 375 throw new IOException(
f@0 376 MessageFormat.format(
f@0 377 resources.getString("dialog.error.node_type_not_present"),
f@0 378 type));
f@0 379 Node node = (Node)prototype.clone();
f@0 380
f@0 381 nodesId.put(idAsString, node);
f@0 382
f@0 383 try {
f@0 384 Long id = Long.valueOf(idAsString);
f@0 385 node.setId(id);
f@0 386 }catch(NumberFormatException nfe){
f@0 387 throw new IOException(resources.getString("dialog.error.malformed_file"),nfe);
f@0 388 }
f@0 389 collectionModel.insert(node,DiagramEventSource.PERS);
f@0 390 try{
f@0 391 node.decode(doc, nodeTag);
f@0 392 }catch(IOException ioe){ // just give a message to the exception
f@0 393 throw new IOException(resources.getString("dialog.error.malformed_file"),ioe);
f@0 394 }
f@0 395 }
f@0 396
f@0 397 Element edgesTag = null;
f@0 398 for(int i=0;i<componentsChildren.getLength();i++)
f@0 399 if(EDGES.equals(componentsChildren.item(i).getNodeName()))
f@0 400 edgesTag = (Element)componentsChildren.item(i);
f@0 401
f@0 402 elemList = edgesTag.getElementsByTagName(EDGE);
f@0 403 for(int i=0; i<elemList.getLength();i++){
f@0 404 Element edgeTag = (Element)elemList.item(i);
f@0 405 String type = edgeTag.getAttribute(TYPE);
f@0 406
f@0 407 Edge prototype = null;
f@0 408 for(Edge e : eList)
f@0 409 if(e.getType().equals(type)){
f@0 410 prototype = e;
f@0 411 break;
f@0 412 }
f@0 413 if(prototype == null)
f@0 414 throw new IOException(MessageFormat.format(
f@0 415 resources.getString("dialog.error.edge_type_not_present"),
f@0 416 type
f@0 417 ));
f@0 418
f@0 419 Edge edge = (Edge)prototype.clone();
f@0 420
f@0 421 try{
f@0 422 edge.decode(doc, edgeTag, nodesId);
f@0 423 }catch(IOException ioe){
f@0 424 throw new IOException(resources.getString("dialog.error.malformed_file"),ioe);
f@0 425 }
f@0 426 collectionModel.insert(edge,DiagramEventSource.PERS);
f@0 427 }
f@0 428
f@0 429 /* retrieve bookmarks */
f@0 430 NodeList bookmarkList = root.getElementsByTagName(BOOKMARK);
f@0 431 for(int i=0;i<bookmarkList.getLength();i++){
f@0 432 Element bookmarkTag = (Element)bookmarkList.item(i);
f@0 433 String key = bookmarkTag.getAttribute(KEY);
f@0 434 if(key.isEmpty())
f@0 435 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 436 String path = bookmarkTag.getTextContent();
f@0 437 DiagramTreeNode treeNode = getTreeNodeFromString(treeModel,path);
f@0 438 treeModel.putBookmark(key, treeNode,DiagramEventSource.PERS);
f@0 439 }
f@0 440
f@0 441 /* retrieve notes */
f@0 442 NodeList noteList = root.getElementsByTagName(NOTE);
f@0 443 for(int i=0;i<noteList.getLength();i++){
f@0 444 Element noteTag = (Element)noteList.item(i);
f@0 445 if(noteTag.getElementsByTagName(TREE_NODE).item(0) == null )
f@0 446 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 447 Element pathTag = (Element)noteTag.getElementsByTagName(TREE_NODE).item(0);
f@0 448 String path = pathTag.getTextContent();
f@0 449 if(noteTag.getElementsByTagName(CONTENT).item(0) == null)
f@0 450 throw new IOException(resources.getString("dialog.error.malformed_file"));
f@0 451 Element contentTag = (Element)noteTag.getElementsByTagName(CONTENT).item(0);
f@0 452 String content = CharEscaper.restoreNewline(contentTag.getTextContent());
f@0 453 DiagramTreeNode treeNode = getTreeNodeFromString(treeModel,path);
f@0 454 treeModel.setNotes(treeNode,content,DiagramEventSource.PERS);
f@0 455 }
f@0 456
f@0 457 /* normally nodes and edges should be saved in order, this is to prevent *
f@0 458 * a manual editing of the xml to affect the program logic */
f@0 459 collectionModel.sort();
f@0 460 /* we have to do this has the insertion in the model made it modified */
f@0 461 collectionModel.setUnmodified();
f@0 462 return diagram;
f@0 463 }
f@0 464
f@0 465 private static void writePrototypes(Document doc, Element root, Diagram diagram){
f@0 466 Node[] nodes = diagram.getNodePrototypes();
f@0 467 Edge[] edges = diagram.getEdgePrototypes();
f@0 468 Element components = doc.createElement(PROTOTYPES);
f@0 469 root.appendChild(components);
f@0 470
f@0 471 PrototypePersistenceDelegate delegate = diagram.getPrototypePersistenceDelegate();
f@0 472 for(Node n : nodes){
f@0 473 Element nodeTag = doc.createElement(NODE);
f@0 474 components.appendChild(nodeTag);
f@0 475 delegate.encodeNodePrototype(doc, nodeTag, n);
f@0 476 }
f@0 477
f@0 478 for(Edge e : edges){
f@0 479 Element edgeTag = doc.createElement(EDGE);
f@0 480 components.appendChild(edgeTag);
f@0 481 delegate.encodeEdgePrototype(doc, edgeTag, e);
f@0 482 }
f@0 483 }
f@0 484
f@0 485 private static List<Node> readNodePrototypes(Document doc, PrototypePersistenceDelegate delegate) throws IOException{
f@0 486 if(doc.getElementsByTagName(PROTOTYPES).item(0) == null)
f@0 487 throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"));
f@0 488 Element prototypesTag = (Element)doc.getElementsByTagName(PROTOTYPES).item(0);
f@0 489 NodeList elemList = prototypesTag.getElementsByTagName(NODE);
f@0 490 final List<Node> nList = new ArrayList<Node>(elemList.getLength());
f@0 491 for(int i=0; i<elemList.getLength();i++){
f@0 492 Element element = (Element)elemList.item(i);
f@0 493 try{
f@0 494 Node n = delegate.decodeNodePrototype(element);
f@0 495 nList.add(n);
f@0 496 }catch(IOException ioe){ // just set the message for the exception
f@0 497 throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"),ioe);
f@0 498 }
f@0 499 }
f@0 500 return nList;
f@0 501 }
f@0 502
f@0 503 private static List<Edge> readEdgePrototypes(Document doc, PrototypePersistenceDelegate delegate) throws IOException{
f@0 504 if(doc.getElementsByTagName(PROTOTYPES).item(0) == null)
f@0 505 throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"));
f@0 506 Element prototypesTag = (Element)doc.getElementsByTagName(PROTOTYPES).item(0);
f@0 507 NodeList elemList = prototypesTag.getElementsByTagName(EDGE);
f@0 508 final List<Edge> eList = new ArrayList<Edge>(elemList.getLength());
f@0 509 for(int i=0; i<elemList.getLength();i++){
f@0 510 Element element = (Element)elemList.item(i);
f@0 511 try{
f@0 512 Edge e = delegate.decodeEdgePrototype(element);
f@0 513 eList.add(e);
f@0 514 }catch(IOException ioe){
f@0 515 throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"),ioe);
f@0 516 }
f@0 517 }
f@0 518 return eList;
f@0 519 }
f@0 520
f@0 521 private static String getTreeNodeAsString(DiagramTreeNode treeNode){
f@0 522 TreeNode[] path = treeNode.getPath();
f@0 523 StringBuilder builder = new StringBuilder();
f@0 524 for(int i=0;i<path.length-1; i++)
f@0 525 builder.append(String.valueOf(path[i].getIndex(path[i+1]))).append(' ');
f@0 526 if(builder.toString().endsWith(" "))
f@0 527 builder.deleteCharAt(builder.length()-1);
f@0 528 return builder.toString();
f@0 529
f@0 530 }
f@0 531
f@0 532 private static DiagramTreeNode getTreeNodeFromString(TreeModel<Node,Edge> model, String path) throws IOException{
f@0 533 DiagramTreeNode treeNode = (DiagramTreeNode)model.getRoot();
f@0 534 if(ROOT_AS_STRING.equals(path))
f@0 535 return treeNode;
f@0 536 String[] nodesAsString = path.split(" ");
f@0 537
f@0 538 try {
f@0 539 for(String nodeAsString : nodesAsString)
f@0 540 treeNode = (DiagramTreeNode) treeNode.getChildAt(Integer.parseInt(nodeAsString));
f@0 541 }catch(Exception e){
f@0 542 throw new IOException(e);
f@0 543 }
f@0 544 return treeNode;
f@0 545 }
f@0 546
f@0 547 public final static String NAME = "Name";
f@0 548 public final static String DIAGRAM = "Diagram";
f@0 549 public final static String PROTOTYPE_PERSISTENCE_DELEGATE = "PrototypeDelegate";
f@0 550 public final static String COMPONENTS = "Components";
f@0 551 public final static String PROTOTYPES = "Prototypes";
f@0 552 public final static String NODE = "Node";
f@0 553 public final static String NODES = "Nodes";
f@0 554 public final static String EDGE = "Edge";
f@0 555 public final static String EDGES = "Edges";
f@0 556 public final static String POSITION = "Position";
f@0 557 public final static String PROPERTIES = "Properties";
f@0 558 public final static String PROPERTY = "Property";
f@0 559 public final static String TYPE = "Type";
f@0 560 public final static String VALUE = "Value";
f@0 561 public final static String ELEMENT = "Element";
f@0 562 public static final String LABEL = "Label";
f@0 563 public final static String POINTS = "Points";
f@0 564 public final static String POINT = "Point";
f@0 565 public final static String ID = "id";
f@0 566 public final static String NEIGHBOURS = "Neighbours";
f@0 567 public static final String MODIFIER = "Modifier";
f@0 568 public static final String MODIFIERS = "Modifiers";
f@0 569 public static final String X = "x";
f@0 570 public static final String Y = "y";
f@0 571 public static final String BOOKMARKS = "Bookmarks";
f@0 572 public static final String BOOKMARK = "Bookmark";
f@0 573 public static final String KEY = "Key";
f@0 574 public static final String NOTES = "Notes";
f@0 575 public static final String NOTE = "Note";
f@0 576 public static final String CONTENT = "Content";
f@0 577 public static final String TREE_NODE = "TreeNode";
f@0 578 private static final String ROOT_AS_STRING = "-1";
f@0 579 }