view 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
line wrap: on
line source
/*  
 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
  
 Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/  

package uk.ac.qmul.eecs.ccmi.gui.persistence;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel;
import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramTreeNode;
import uk.ac.qmul.eecs.ccmi.diagrammodel.TreeModel;
import uk.ac.qmul.eecs.ccmi.gui.Diagram;
import uk.ac.qmul.eecs.ccmi.gui.DiagramEventSource;
import uk.ac.qmul.eecs.ccmi.gui.Edge;
import uk.ac.qmul.eecs.ccmi.gui.Node;
import uk.ac.qmul.eecs.ccmi.utils.CharEscaper;

/**
 * The PersistanceManager provides methods for saving and retrieving diagrams from an XML
 * file. Both templates diagrams (prototypes from which actual diagram instances are created
 * through cloning) and diagram instances can be saved to a file. The tag name used in the XML 
 * file can be accessed via the static {@code String} variables of this class.  
 * 
 */
public abstract class PersistenceManager {
	/**
	 * Encodes a diagram template in a file in XML format
	 * 
	 * @param diagram the diagram to be encoded
	 * @param file the file where the diagram is going to be encoded
	 * @throws IOException if there are any I/O problems with the file 
	 */
	public static void encodeDiagramTemplate(Diagram diagram, File file) throws IOException{
		ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
		if(file.createNewFile() == false)
			throw new IOException(resources.getString("dialog.error.file_exists"));
		
		DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
		try {
			docBuilder = dbfac.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new IOException(resources.getString("dialog.error.problem.save"),e);
		}
        Document doc = docBuilder.newDocument();
        
        Element root = doc.createElement(DIAGRAM);
        doc.appendChild(root);
        /* diagram name and prototypePersstenceDelegate */
        root.setAttribute(NAME, diagram.getName());
        root.setAttribute(PROTOTYPE_PERSISTENCE_DELEGATE, diagram.getPrototypePersistenceDelegate().getClass().getName());
        
        writePrototypes(doc, root, diagram);
        
        //set up a transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = null;
		try {
			trans = transfac.newTransformer();
		} catch (TransformerConfigurationException tce) {
			throw new IOException(resources.getString("dialog.error.problem.save"),tce);
		}
		trans.setOutputProperty(OutputKeys.INDENT, "yes");
		trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(2));
		 
        StreamResult result = new StreamResult(new BufferedWriter(new FileWriter(file)));
        DOMSource source = new DOMSource(doc);
        try {
			trans.transform(source, result);
		} catch (TransformerException te) {
			throw new IOException(resources.getString("dialog.error.problem.save"),te);
		}
	}
	
	/**
	 * Decodes a diagram template from a file in XML format
	 * 
	 * @param XMLFile the file to read the diagram from 
	 * @throws IOException if there are any I/O problems with the file 
	 * 
	 * @return the diagram encoded in {@code XMLFile}
	 */
	public static Diagram decodeDiagramTemplate(File XMLFile) throws IOException{
		ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
	    DocumentBuilder dBuilder = null;
		try {
			dBuilder = dbFactory.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			throw new IOException(resources.getString("dialog.error.problem.open"),pce);
		}
	    Document doc = null;
		try {
			doc = dBuilder.parse(XMLFile);
		} catch (SAXException se) {
			throw new IOException(resources.getString("dialog.error.problem.open"),se);
		}
	    doc.getDocumentElement().normalize();
	    
	    if(doc.getElementsByTagName(DIAGRAM).item(0) == null)
	    	throw new IOException(resources.getString("dialog.error.malformed_file"));
	    Element root = (Element)doc.getElementsByTagName(DIAGRAM).item(0);
	    String diagramName = root.getAttribute(NAME);
	    if(diagramName.isEmpty())
	    	throw new IOException(resources.getString("dialog.error.malformed_file"));
	    String persistenceDelegateClassName = root.getAttribute(PROTOTYPE_PERSISTENCE_DELEGATE);
	    PrototypePersistenceDelegate persistenceDelegate = null;
	    try{
	    	Class<? extends PrototypePersistenceDelegate> c = Class.forName(persistenceDelegateClassName).asSubclass(PrototypePersistenceDelegate.class);
	    	persistenceDelegate = c.newInstance();
	    }catch(Exception e){
	    	throw new IOException(resources.getString("dialog.error.problem.open"),e);
	    }
	    
	    final List<Node> nList = readNodePrototypes(doc,persistenceDelegate);
	    final List<Edge> eList = readEdgePrototypes(doc,persistenceDelegate);
	    Node[] nArray = new Node[nList.size()];
	    Edge[] eArray = new Edge[eList.size()];
	    return  Diagram.newInstance(diagramName,nList.toArray(nArray),eList.toArray(eArray),persistenceDelegate);
	}
	
	/**
	 * Encodes a diagram instance into the given output stream. Using output stream
	 * instead of {@code Writer} as it's advised by the <i>StreamResult API</i> 
	 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
	 * 
	 * @param diagram the diagram to encode
	 * @param newName the new name of the diagram to encode. This will also be the name of the file but {@code diagram}
	 * will still keep the old name, that is the value returned by {@code getName()} won't be changed to {@code newName}. 
	 * If a {@code null} value is passed than the value returned by {@code diagram.getName()} will be used.
	 * 
	 * @param out where the diagram will be encoded
	 * @throws IOException if there are any I/O problems with the file 
	 */
	public static void encodeDiagramInstance(Diagram diagram, String newName, OutputStream out) throws IOException{
		ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
		DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
		try {
			docBuilder = dbfac.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			throw new IOException(resources.getString("dialog.error.problem.save"),pce);
		}
        Document doc = docBuilder.newDocument();
        
        Element root = doc.createElement(DIAGRAM);
        root.setAttribute(NAME, (newName != null) ? newName : diagram.getName());
        root.setAttribute(PROTOTYPE_PERSISTENCE_DELEGATE, diagram.getPrototypePersistenceDelegate().getClass().getName());
        doc.appendChild(root);
        
        /* store bookmarks */
        Element bookmarksTag = doc.createElement(BOOKMARKS);
        TreeModel<Node,Edge> treeModel = diagram.getTreeModel();
        for(String key : treeModel.getBookmarks()){
        	Element bookmarkTag = doc.createElement(BOOKMARK);
        	bookmarkTag.setAttribute(KEY, key);
        	if(treeModel.getBookmarkedTreeNode(key).isRoot())
        		bookmarkTag.setTextContent(ROOT_AS_STRING);
        	else
        		bookmarkTag.setTextContent(getTreeNodeAsString(treeModel.getBookmarkedTreeNode(key)));
        	bookmarksTag.appendChild(bookmarkTag);
        }
        if(bookmarksTag.hasChildNodes())
        	root.appendChild(bookmarksTag);
        
        /* store notes */
        Element notesTag = doc.createElement(NOTES);
        DiagramTreeNode treeRoot = (DiagramTreeNode)diagram.getTreeModel().getRoot();
        for( @SuppressWarnings("unchecked")
		Enumeration<DiagramTreeNode> enumeration = treeRoot.depthFirstEnumeration(); enumeration.hasMoreElements();){
        	DiagramTreeNode treeNode = enumeration.nextElement();
        	if(!treeNode.getNotes().isEmpty()){
        		Element noteTag = doc.createElement(NOTE);
        		Element treeNodeTag = doc.createElement(TREE_NODE);
        		if(treeNode.isRoot())
        			treeNodeTag.setTextContent(ROOT_AS_STRING);
        		else	
        			treeNodeTag.setTextContent(getTreeNodeAsString(treeNode));
        		Element contentTag = doc.createElement(CONTENT);
        		contentTag.setTextContent(CharEscaper.replaceNewline(treeNode.getNotes()));
        		noteTag.appendChild(treeNodeTag);
        		noteTag.appendChild(contentTag);
        		notesTag.appendChild(noteTag);
        	}
        }
        
        if(notesTag.hasChildNodes())
        	root.appendChild(notesTag);
        
        writePrototypes(doc,root,diagram);
        
        Element components = doc.createElement(COMPONENTS);
        root.appendChild(components);
        
        synchronized(diagram.getCollectionModel().getMonitor()){
	        Collection<Node> nodes = diagram.getCollectionModel().getNodes();
	        Collection<Edge> edges = diagram.getCollectionModel().getEdges();
	        
	        /* store nodes */
	        Element nodesTag = doc.createElement(NODES);
	        components.appendChild(nodesTag);
	        List<Node> nList = new ArrayList<Node>(nodes);        
	        for(Node n : nList){
	        	Element nodeTag = doc.createElement(NODE);
	    		nodeTag.setAttribute(ID, String.valueOf(n.getId()));
	    		nodeTag.setAttribute(TYPE, n.getType());
	    		nodesTag.appendChild(nodeTag);
	        	n.encode(doc, nodeTag);
	        }
	        
	        Element edgesTag = doc.createElement(EDGES);
	        components.appendChild(edgesTag);
	        for(Edge e : edges){
	        	Element edgeTag = doc.createElement(EDGE);
	        	edgesTag.appendChild(edgeTag);
	        	e.encode(doc,edgeTag,nList);
	        }
        }
        //set up a transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = null;
		try {
			trans = transfac.newTransformer();
		} catch (TransformerConfigurationException tec) {
			throw new IOException(resources.getString("dialog.error.problem.save"));
		}
		trans.setOutputProperty(OutputKeys.INDENT, "yes");
		trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(2));
		
        
        StreamResult result = new StreamResult(out);
        DOMSource source = new DOMSource(doc);
        try {
			trans.transform(source, result);
		} catch (TransformerException te) {
			throw new IOException(resources.getString("dialog.error.problem.save"),te);
		}
	}
	
	/**
	 * Encodes a diagram instance into the given output stream. Using output stream
	 * instead of {@code Writer} as it's advised by the <i>StreamResult API</i> 
	 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
	 * 
	 * @param diagram the diagram to encode
	 * @param out an output stram to the file where the diagram will be encoded
	 * @throws IOException if there are any I/O problems with the file 
	 */
	public static void encodeDiagramInstance(Diagram diagram, OutputStream out) throws IOException{
		encodeDiagramInstance(diagram,null,out);
	}
	
	/**
	 * Decodes a diagram instance from the given input stream. Using input stream
	 * instead of {@code Reader} as it's advised by the <i>StreamResult API</i> 
	 * @see http://download.oracle.com/javase/6/docs/api/javax/xml/transform/stream/StreamResult.html
	 * 
	 * @param in an input stream to the file the diagram is decoded from 
	 * @throws IOException if there are any I/O problems with the file 
	 * 
	 * @return the diagram encoded in the file 
	 */
	public static Diagram decodeDiagramInstance(InputStream in) throws IOException {
		ResourceBundle resources = ResourceBundle.getBundle(PersistenceManager.class.getName());
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
	    DocumentBuilder dBuilder = null;
		try {
			dBuilder = dbFactory.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			throw new IOException(resources.getString("dialog.error.problem.open"),pce);
		}
	    Document doc = null;
		try {
			doc = dBuilder.parse(in);
		} catch (SAXException se) {
			throw new IOException(resources.getString("dialog.error.problem.open"),se);
		}
	    doc.getDocumentElement().normalize();
	    
	    if(doc.getElementsByTagName(DIAGRAM).item(0) == null)
	    	throw new IOException(resources.getString("dialog.error.malformed_file"));
	    Element root = (Element)doc.getElementsByTagName(DIAGRAM).item(0);
	    String diagramName = root.getAttribute(NAME);
	    if(diagramName.isEmpty())
	    	throw new IOException(resources.getString("dialog.error.malformed_file"));
	    String persistenceDelegateClassName = root.getAttribute(PROTOTYPE_PERSISTENCE_DELEGATE);
	    PrototypePersistenceDelegate persistenceDelegate = null;
	    try{
	    	Class<? extends PrototypePersistenceDelegate> c = Class.forName(persistenceDelegateClassName).asSubclass(PrototypePersistenceDelegate.class);
	    	persistenceDelegate = c.newInstance();
	    }catch(Exception e){
	    	throw new IOException(resources.getString("dialog.error.problem.open"),e);
	    }
	    
	    final List<Node> nList = readNodePrototypes(doc,persistenceDelegate);
	    final List<Edge> eList = readEdgePrototypes(doc,persistenceDelegate);
	    
	    final Node[] nodes = nList.toArray(new Node[nList.size()]);
	    final Edge[] edges = eList.toArray(new Edge[eList.size()]);
	    
	    Diagram diagram = Diagram.newInstance(diagramName, nodes,edges,persistenceDelegate);
	    CollectionModel<Node,Edge> collectionModel = diagram.getCollectionModel();
	    TreeModel<Node,Edge> treeModel = diagram.getTreeModel();
	    
	    /* a map linking node ids in the XML file to the actual Node object they represent */
	    Map<String,Node> nodesId = new LinkedHashMap<String,Node>();
	    
	    if(doc.getElementsByTagName(COMPONENTS).item(0) == null)
	    	throw new IOException(resources.getString("dialog.error.malformed_file"));
	    Element componentsTag = (Element)doc.getElementsByTagName(COMPONENTS).item(0);
	    NodeList componentsChildren = componentsTag.getChildNodes();
	    Element nodesTag = null;
	    for(int i=0;i<componentsChildren.getLength();i++){
	    	if(NODES.equals(componentsChildren.item(i).getNodeName()))
	    		nodesTag = (Element)componentsChildren.item(i);
	    }
	    
	    NodeList elemList = nodesTag.getElementsByTagName(NODE);
	    for(int i=0; i<elemList.getLength();i++){
	    	Element nodeTag = (Element)elemList.item(i);
	    	String idAsString = nodeTag.getAttribute(ID);
	    	String type = nodeTag.getAttribute(TYPE);
	    	Node prototype = null;	    	
	    	for(Node n : nList)
	    		if(n.getType().equals(type)){
	    			prototype = n;
	    			break;
	    		}
	    	if(prototype == null)
	    		throw new IOException(
	    				MessageFormat.format(
	    						resources.getString("dialog.error.node_type_not_present"),
	    						type));
	    	Node node = (Node)prototype.clone(); 
	    	
	    	nodesId.put(idAsString, node);
	    	
			try {
				Long id = Long.valueOf(idAsString);
				node.setId(id);
			}catch(NumberFormatException nfe){
				throw new IOException(resources.getString("dialog.error.malformed_file"),nfe);
			}
			collectionModel.insert(node,DiagramEventSource.PERS);
			try{
				node.decode(doc, nodeTag);
			}catch(IOException ioe){ // just give a message to the exception 
				throw new IOException(resources.getString("dialog.error.malformed_file"),ioe);
			}
	    }
	    
	    Element edgesTag = null;
	    for(int i=0;i<componentsChildren.getLength();i++)
	    	if(EDGES.equals(componentsChildren.item(i).getNodeName()))
	    		edgesTag = (Element)componentsChildren.item(i);

	    elemList = edgesTag.getElementsByTagName(EDGE);
	    for(int i=0; i<elemList.getLength();i++){
	    	Element edgeTag = (Element)elemList.item(i);
	    	String type = edgeTag.getAttribute(TYPE);
	    	
	    	Edge prototype = null;
	    	for(Edge e : eList)
	    		if(e.getType().equals(type)){
	    			prototype = e;
	    			break;
	    		}
	    	if(prototype == null)
	    		throw new IOException(MessageFormat.format(
	    				resources.getString("dialog.error.edge_type_not_present"),
	    				type
	    				));
	    	
	    	Edge edge = (Edge)prototype.clone();

	    	try{
	    		edge.decode(doc, edgeTag, nodesId);
	    	}catch(IOException ioe){
	    		throw new IOException(resources.getString("dialog.error.malformed_file"),ioe);
	    	}
	    	collectionModel.insert(edge,DiagramEventSource.PERS);
	    }
	    
	    /* retrieve bookmarks */
	    NodeList bookmarkList = root.getElementsByTagName(BOOKMARK);
	    for(int i=0;i<bookmarkList.getLength();i++){
	    	Element bookmarkTag = (Element)bookmarkList.item(i);
	    	String key  = bookmarkTag.getAttribute(KEY);
	    	if(key.isEmpty()) 
	    		throw new IOException(resources.getString("dialog.error.malformed_file"));
	    	String path = bookmarkTag.getTextContent();
	    	DiagramTreeNode treeNode = getTreeNodeFromString(treeModel,path);
	    	treeModel.putBookmark(key, treeNode,DiagramEventSource.PERS);
	    }
	    
	    /* retrieve notes */
	    NodeList noteList = root.getElementsByTagName(NOTE);
	    for(int i=0;i<noteList.getLength();i++){
	    	Element noteTag = (Element)noteList.item(i);
	    	if(noteTag.getElementsByTagName(TREE_NODE).item(0) == null )
	    		throw new IOException(resources.getString("dialog.error.malformed_file"));
	    	Element pathTag = (Element)noteTag.getElementsByTagName(TREE_NODE).item(0);
	    	String path = pathTag.getTextContent();
	    	if(noteTag.getElementsByTagName(CONTENT).item(0) == null)
	    		throw new IOException(resources.getString("dialog.error.malformed_file"));
	    	Element contentTag = (Element)noteTag.getElementsByTagName(CONTENT).item(0);
	    	String content = CharEscaper.restoreNewline(contentTag.getTextContent());
	    	DiagramTreeNode treeNode = getTreeNodeFromString(treeModel,path);
	    	treeModel.setNotes(treeNode,content,DiagramEventSource.PERS);
	    }
	    
	    /* normally nodes and edges should be saved in order, this is to prevent *
	     * a manual editing of the xml to affect  the program logic              */
	    collectionModel.sort();
	    /* we have to do this has the insertion in the model made it modified */
	    collectionModel.setUnmodified();
    	return diagram;	    
	}
	
	private static void writePrototypes(Document doc, Element root, Diagram diagram){
		Node[] nodes = diagram.getNodePrototypes();
		Edge[] edges = diagram.getEdgePrototypes();
		Element components = doc.createElement(PROTOTYPES);
        root.appendChild(components);
        
        PrototypePersistenceDelegate delegate = diagram.getPrototypePersistenceDelegate();
        for(Node n : nodes){
        	Element nodeTag = doc.createElement(NODE);
    		components.appendChild(nodeTag);
        	delegate.encodeNodePrototype(doc, nodeTag, n);
        }
        
        for(Edge e : edges){
        	Element edgeTag = doc.createElement(EDGE);
    		components.appendChild(edgeTag);
    		delegate.encodeEdgePrototype(doc, edgeTag, e);
        }
	}
	
	private static List<Node> readNodePrototypes(Document doc, PrototypePersistenceDelegate delegate) throws IOException{
		if(doc.getElementsByTagName(PROTOTYPES).item(0) == null)
			throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"));
		Element prototypesTag = (Element)doc.getElementsByTagName(PROTOTYPES).item(0);
		NodeList elemList = prototypesTag.getElementsByTagName(NODE);
		final List<Node> nList = new ArrayList<Node>(elemList.getLength());
	    for(int i=0; i<elemList.getLength();i++){
	    	Element element = (Element)elemList.item(i);
	    	try{
	    		Node n = delegate.decodeNodePrototype(element);
	    		nList.add(n);
	    	}catch(IOException ioe){ // just set the message for the exception
	    		throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"),ioe);
	    	}
	    }
	    return nList;
	}
	
	private static List<Edge> readEdgePrototypes(Document doc, PrototypePersistenceDelegate delegate) throws IOException{
		if(doc.getElementsByTagName(PROTOTYPES).item(0) == null)
			throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"));
		Element prototypesTag = (Element)doc.getElementsByTagName(PROTOTYPES).item(0);
		NodeList elemList = prototypesTag.getElementsByTagName(EDGE);
	    final List<Edge> eList = new ArrayList<Edge>(elemList.getLength());
	    for(int i=0; i<elemList.getLength();i++){
	    	Element element = (Element)elemList.item(i);
	    	try{
	    		Edge e = delegate.decodeEdgePrototype(element);
	    		eList.add(e);
	    	}catch(IOException ioe){
	    		throw new IOException(ResourceBundle.getBundle(PersistenceManager.class.getName()).getString("dialog.error.malformed_file"),ioe);
	    	}
	    }
	    return eList;
	}
	
	private static String getTreeNodeAsString(DiagramTreeNode treeNode){
		TreeNode[] path = treeNode.getPath();
		StringBuilder builder = new StringBuilder();
		for(int i=0;i<path.length-1; i++)
			builder.append(String.valueOf(path[i].getIndex(path[i+1]))).append(' ');
		if(builder.toString().endsWith(" "))
			builder.deleteCharAt(builder.length()-1);
		return builder.toString();
		
	}
	
	private static DiagramTreeNode getTreeNodeFromString(TreeModel<Node,Edge> model, String path) throws IOException{
		DiagramTreeNode treeNode = (DiagramTreeNode)model.getRoot();
		if(ROOT_AS_STRING.equals(path))
			return treeNode;
		String[] nodesAsString = path.split(" ");
		
		try {
			for(String nodeAsString : nodesAsString)
				treeNode = (DiagramTreeNode) treeNode.getChildAt(Integer.parseInt(nodeAsString));
		}catch(Exception e){
			throw new IOException(e);
		}
		return treeNode;
	}
	
	public final static String NAME = "Name";
	public final static String DIAGRAM = "Diagram";
	public final static String PROTOTYPE_PERSISTENCE_DELEGATE = "PrototypeDelegate";
	public final static String COMPONENTS = "Components";
	public final static String PROTOTYPES = "Prototypes";
	public final static String NODE = "Node";
	public final static String NODES = "Nodes";
	public final static String EDGE = "Edge";
	public final static String EDGES = "Edges";
	public final static String POSITION = "Position";
	public final static String PROPERTIES = "Properties";
	public final static String PROPERTY = "Property";
	public final static String TYPE = "Type";
	public final static String VALUE = "Value";
	public final static String ELEMENT = "Element";
	public static final String LABEL = "Label";
	public final static String POINTS = "Points";
	public final static String POINT = "Point";
	public final static String ID = "id";
	public final static String NEIGHBOURS = "Neighbours";
	public static final String MODIFIER = "Modifier";
	public static final String MODIFIERS = "Modifiers";
	public static final String X = "x";
	public static final String Y = "y";
	public static final String BOOKMARKS = "Bookmarks";
	public static final String BOOKMARK = "Bookmark";
	public static final String KEY = "Key";
	public static final String NOTES = "Notes";
	public static final String NOTE = "Note";
	public static final String CONTENT = "Content";
	public static final String TREE_NODE = "TreeNode";
	private static final String ROOT_AS_STRING = "-1"; 
}