]> gerrit.simantics Code Review - simantics/interop.git/commitdiff
Fix plug-in dependencies + use fastutils hashmaps.
authorMarko Luukkainen <marko.luukkainen@vtt.fi>
Mon, 13 Mar 2017 10:56:09 +0000 (12:56 +0200)
committerMarko Luukkainen <marko.luukkainen@vtt.fi>
Mon, 13 Mar 2017 10:56:09 +0000 (12:56 +0200)
fixes #7086

Change-Id: I74282dd545ce42f9d44484b119f92a3fe3f03103

org.simantics.interop.xmlio/META-INF/MANIFEST.MF
org.simantics.interop.xmlio/src/org/simantics/interop/xmlio/LoadXML.java
org.simantics.interop.xmlio/src/org/simantics/interop/xmlio/SaveXML.java

index a5c223af209853ed3ca8d0e60a8b6369f6e4a220..75e6d2bedebec2e4cd5dad5079d60566b1442f1f 100644 (file)
@@ -9,9 +9,8 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
  org.simantics.db;bundle-version="1.1.0",
  org.simantics.db.common;bundle-version="1.1.0",
- org.apache.xerces;bundle-version="2.9.0",
  org.simantics.db.layer0;bundle-version="1.1.0",
org.cojen;bundle-version="2.2.1"
it.unimi.dsi.fastutil;bundle-version="7.0.13"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
 Export-Package: org.simantics.interop.xmlio
index c79ace686e8e39bb5ee2a639e52e16f451d6478a..a2cae0c49428d5b241efebf267692a5123c493ef 100644 (file)
-package org.simantics.interop.xmlio;\r
-\r
-import java.io.BufferedReader;\r
-import java.io.File;\r
-import java.io.FileReader;\r
-import java.io.Reader;\r
-import java.io.Serializable;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Stack;\r
-\r
-import javax.xml.parsers.SAXParser;\r
-import javax.xml.parsers.SAXParserFactory;\r
-\r
-import org.cojen.util.IntHashMap;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.DelayedWriteRequest;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.util.Layer0Utils;\r
-import org.simantics.db.layer0.util.SessionGarbageCollection;\r
-import org.simantics.layer0.Layer0;\r
-import org.xml.sax.Attributes;\r
-import org.xml.sax.InputSource;\r
-import org.xml.sax.SAXException;\r
-import org.xml.sax.XMLReader;\r
-import org.xml.sax.helpers.DefaultHandler;\r
-\r
-\r
-\r
-public class LoadXML {\r
-\r
-       private Session session;\r
-       private Resource resultRoot;\r
-       \r
-       private File file;\r
-       \r
-       \r
-       //private Map<Integer,Resource> idMap = new HashMap<Integer, Resource>();\r
-       private IntHashMap<Resource> idMap = new IntHashMap<Resource>();\r
-       \r
-       //private Map<String,Resource> uriMap = new HashMap<String, Resource>();\r
-       \r
-       private WriteGraph graph;\r
-       private Layer0 l0;\r
-       private LoadRule rule;\r
-       \r
-       private int resources;\r
-       private int statements;\r
-       \r
-       private static final boolean USE_DELAYED = true;\r
-       \r
-       public LoadXML(Session session, File file) {\r
-               this.session = session;\r
-               this.file = file;\r
-               this.rule = new DefaultLoadRule();\r
-       }\r
-       \r
-       public void setRule(LoadRule rule) {\r
-               this.rule = rule;\r
-       }\r
-       \r
-       public void load(Resource subj, Resource pred) throws Exception {\r
-               resources = 0;\r
-               statements = 0;\r
-               \r
-               if (USE_DELAYED) {\r
-                       session.syncRequest(new ImportDelayedRequest(subj,pred));       \r
-               } else {\r
-                       session.syncRequest(new ImportRequest(subj,pred));      \r
-               }\r
-               //session.syncRequest(new DelayedWriteRequest() {\r
-               \r
-               \r
-               System.out.println("Import done.");\r
-       }\r
-       \r
-       private class ImportRequest extends WriteRequest {\r
-               Resource subj;Resource pred;\r
-               \r
-               \r
-               public ImportRequest(Resource subj, Resource pred) {\r
-                       super();\r
-                       this.subj = subj;\r
-                       this.pred = pred;\r
-               }\r
-\r
-               @Override\r
-               public void perform(WriteGraph graph) throws DatabaseException {\r
-                       doImport(graph, subj, pred);\r
-               }\r
-       }\r
-       \r
-       private class ImportDelayedRequest extends DelayedWriteRequest {\r
-               Resource subj;Resource pred;\r
-               \r
-               \r
-               public ImportDelayedRequest(Resource subj, Resource pred) {\r
-                       super();\r
-                       this.subj = subj;\r
-                       this.pred = pred;\r
-               }\r
-\r
-               @Override\r
-               public void perform(WriteGraph graph) throws DatabaseException {\r
-                       doImport(graph, subj, pred);\r
-               }\r
-       }\r
-       \r
-       private void doImport(WriteGraph graph, Resource subj, Resource pred) throws DatabaseException {\r
-               LoadXML.this.graph = graph;\r
-               l0 = Layer0.getInstance(graph);\r
-               Layer0Utils.setDependenciesIndexingDisabled(graph, true);\r
-               try {\r
-                       XMLParser parser = new XMLParser();\r
-                       parser.parse(file.getAbsolutePath());\r
-                       System.out.println("Imported " + statements + " Statements, " + resources + " Resources.");\r
-               } catch (Exception e) {\r
-                       throw new DatabaseException(e);\r
-               } finally {\r
-                       resultRoot = idMap.get(0);\r
-                       graph.claim(subj, pred, resultRoot);\r
-                       idMap.clear();\r
-               }\r
-       }\r
-       \r
-       \r
-//     public Resource getResult() {\r
-//             return resultRoot;\r
-//     }\r
-       \r
-       protected Resource getResource(ReadGraph graph, String uri) throws DatabaseException {\r
-               return rule.getResource(graph, uri);\r
-       }\r
-       \r
-       protected Object createValue(ReadGraph graph, List<String> value, List<String> types) throws DatabaseException {\r
-               return rule.createValue(graph, value, types);\r
-       }\r
-       \r
-       protected void initializeWithBundles(ReadGraph graph, List<Bundle> bundles) throws DatabaseException {\r
-               rule.initializeWithBundles(graph, bundles);\r
-       }\r
-       \r
-       \r
-       public class XMLParser  extends DefaultHandler implements Serializable {\r
-\r
-               private static final long serialVersionUID = -4995836637014958966L;\r
-               \r
-               private Stack<Element> current = new Stack<Element>();\r
-               \r
-               private void loadElement(Element element) throws SAXException{\r
-                       String name = element.qName;\r
-                       if ("graphexport".equals(name))\r
-                               return;\r
-                       if ("graphbundles".equals(name)) {\r
-                               element.setData(new ArrayList<Bundle>());\r
-                               return;\r
-                       }\r
-                       if ("bundle".equals(name))\r
-                               return;\r
-                       if ("resource".equals(name)) {\r
-                               element.setData(new Res());\r
-                               return;\r
-                       }\r
-                       if ("type".equals(name)) {\r
-                               return;\r
-                       }\r
-                       if ("statement".equals(name))\r
-                               return;\r
-                       \r
-               }\r
-               \r
-               private void handleElement(Stack<Element> parents, Element element) throws SAXException{\r
-                       try {\r
-                       String elementName = element.qName;\r
-                       if ("graphexport".equals(elementName))\r
-                               return;\r
-                       if ("graphbundles".equals(elementName)) {\r
-                               List<Bundle> list = (List<Bundle>)element.getData();\r
-                               initializeWithBundles(graph, list);\r
-                               element.setData(null);\r
-                               return;\r
-                       }\r
-                       if ("bundle".equals(elementName)) {\r
-                               List<Bundle> list = (List<Bundle>)parents.peek().getData();\r
-                               String name = null;\r
-                               String versionId = null;\r
-                               for (Attribute a : element.getAttributes()) {\r
-                                       if ("name".equals(a.qName))\r
-                                               name = a.value;\r
-                                       if ("versionid".equals(a.qName))\r
-                                               versionId = a.value;\r
-                               } \r
-                               list.add(new Bundle(name,versionId));\r
-                               return;\r
-                       }\r
-                       if ("resource".equals(elementName)) {\r
-                               Res res = (Res)element.getData();\r
-                               boolean rel = false;\r
-                               String uri = null;\r
-                               int id = -1;\r
-                               Resource r = null;\r
-                               for (Attribute a : element.getAttributes()) {\r
-                                       if ("id".equals(a.qName))\r
-                                               id = Integer.parseInt(a.value);\r
-                                       if ("rel".equals(a.qName))\r
-                                               rel = "true".equals(a.value);\r
-                                       if ("uri".equals(a.qName))\r
-                                               uri = a.value;\r
-                               } \r
-                               if (rel) {\r
-                                       r = getResource(graph, uri);\r
-                               } else {\r
-                                       \r
-                                       r = graph.newResource();\r
-                                       for (String typeUri : res.types) {\r
-                                               Resource type =getResource(graph, typeUri);\r
-                                               graph.claim(r, l0.InstanceOf, type);\r
-                                       }\r
-                                       \r
-                                       if (res.values.size() > 0 ) {\r
-                                               Object valObj = createValue(graph, res.values, res.types);\r
-                                               graph.claimValue(r, valObj);\r
-                                       }\r
-                               }\r
-                               if (id == -1)\r
-                                       throw new SAXException("Resource id missing");\r
-                               idMap.put(id, r);\r
-                               \r
-                               res.types.clear();\r
-                               res.values.clear();\r
-                               element.setData(null);\r
-                               resources++;\r
-                               return;\r
-                       }\r
-                       if ("type".equals(elementName)) {\r
-                               Element parent = parents.peek();\r
-                               Res res = (Res)parent.getData();\r
-                               String uri = null;\r
-                               for (Attribute a : element.getAttributes()) {\r
-                                       if ("uri".equals(a.qName))\r
-                                               uri = a.value;\r
-                               } \r
-                               if (uri != null)\r
-                                       res.types.add(uri);\r
-                               \r
-                               return;\r
-                       }\r
-                       if ("value".equals(elementName)) {\r
-                               Element parent = parents.peek();\r
-                               Res res = (Res)parent.getData();\r
-                               String value = null;\r
-                               for (Attribute a : element.getAttributes()) {\r
-                                       if ("value".equals(a.qName))\r
-                                               value = a.value;\r
-                               } \r
-                               if (value != null)\r
-                                       res.values.add(value);\r
-                               \r
-                               return;\r
-                       }\r
-                       if ("statement".equals(elementName)) {\r
-                               int subjId = -1;\r
-                               int predId = -1;\r
-                               int objId = -1;\r
-                               for (Attribute a : element.getAttributes()) {\r
-                                       if ("subject".equals(a.qName))\r
-                                               subjId = Integer.parseInt(a.value);\r
-                                       if ("predicate".equals(a.qName))\r
-                                               predId = Integer.parseInt(a.value);\r
-                                       if ("object".equals(a.qName))\r
-                                               objId = Integer.parseInt(a.value);\r
-                               } \r
-                               \r
-                               graph.claim(idMap.get(subjId), idMap.get(predId), idMap.get(objId));\r
-                               statements++;\r
-                               if (statements % 10000 == 0) {\r
-                                       System.out.println("Imported " + statements + " Statements, " + resources + " Resources..");\r
-                                       //SessionGarbageCollection.gc(graph, 0, -1);\r
-                               }\r
-                               if (!USE_DELAYED && statements % 100000 == 0) {\r
-                                       SessionGarbageCollection.gc(graph, 0, -1);\r
-                                       System.gc();\r
-                               }\r
-                               \r
-                               return;\r
-                       }\r
-                       \r
-                       } catch (DatabaseException e) {\r
-                               throw new SAXException(e);\r
-                       }\r
-               }\r
-               \r
-               public void done() {\r
-                       \r
-               }\r
-               \r
-               public void parse(String filename) throws Exception {\r
-                       SAXParserFactory spf = SAXParserFactory.newInstance();\r
-                       SAXParser saxParser = spf.newSAXParser();\r
-                       \r
-                       XMLReader reader = saxParser.getXMLReader();\r
-                       Reader file = new BufferedReader(new FileReader(filename));\r
-                       reader.setContentHandler(this);\r
-                       reader.parse(new InputSource(file));\r
-                       done();\r
-               }\r
-               \r
-               @Override\r
-               public void startElement(String uri, String localName, String name,\r
-                               Attributes attributes) throws SAXException {\r
-                       Element e = new Element(uri,localName,name,attributes);\r
-                       current.push(e);\r
-                       //texts.push(new String());\r
-                       loadElement(e);\r
-               }\r
-               \r
-               @Override\r
-               public void endElement(String uri, String localName, String name)\r
-                               throws SAXException {\r
-                       Element e = null;\r
-                       if (!current.empty()) {\r
-                               e = current.pop();\r
-                       }\r
-                       if (e != null) {\r
-                               handleElement(current,e);\r
-                       }\r
-               }\r
-               \r
-       }\r
-       \r
-       public class Attribute {\r
-               public String localName;\r
-               public String qName;\r
-               public String uri;\r
-               public String value;\r
-               \r
-               public Attribute(String localName, String qName, String uri, String value) {\r
-                       this.localName = localName;\r
-                       this.qName = qName;\r
-                       this.uri = uri;\r
-                       this.value = value;\r
-               }\r
-       }\r
-       \r
-       public class Element implements Serializable {\r
-               private static final long serialVersionUID = -5207502156942818875L;\r
-               String uri;\r
-               String localName;\r
-               String qName;\r
-               List<Attribute> attributes = new ArrayList<Attribute>();\r
-               \r
-               public Element(String uri, String localName, String qName, Attributes attributes) {\r
-                       this.uri = uri;\r
-                       this.localName = localName;\r
-                       this.qName = qName;\r
-                       for (int i = 0; i < attributes.getLength(); i++) {\r
-                               this.attributes.add(new Attribute(attributes.getLocalName(i),attributes.getQName(i),attributes.getURI(i),attributes.getValue(i)));\r
-                       }\r
-               }\r
-\r
-               public String getUri() {\r
-                       return uri;\r
-               }\r
-\r
-               public String getLocalName() {\r
-                       return localName;\r
-               }\r
-\r
-               public String getQName() {\r
-                       return qName;\r
-               }\r
-\r
-               public List<Attribute> getAttributes() {\r
-                       return attributes;\r
-               }\r
-\r
-               private Object data;\r
-               \r
-               public void setData(Object data) {\r
-                       this.data = data;\r
-               }\r
-               \r
-               public Object getData() {\r
-                       return data;\r
-               }\r
-\r
-       }\r
-       class Res {\r
-               \r
-               List<String> types = new ArrayList<String>();\r
-               List<String> values = new ArrayList<String>();\r
-       }\r
-       \r
-       public static class Bundle {\r
-               String name;\r
-               String versionId;\r
-               public Bundle(String name, String versionId) {\r
-                       super();\r
-                       this.name = name;\r
-                       this.versionId = versionId;\r
-               }\r
-               \r
-               public String getName() {\r
-                       return name;\r
-               }\r
-               \r
-               public String getVersionId() {\r
-                       return versionId;\r
-               }\r
-       }\r
-       \r
-       \r
-}\r
+package org.simantics.interop.xmlio;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.Reader;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.DelayedWriteRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.layer0.util.SessionGarbageCollection;
+import org.simantics.layer0.Layer0;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+
+
+
+public class LoadXML {
+
+       private Session session;
+       private Resource resultRoot;
+       
+       private File file;
+       
+       
+       //private Map<Integer,Resource> idMap = new HashMap<Integer, Resource>();
+       Int2ObjectOpenHashMap<Resource> idMap = new Int2ObjectOpenHashMap<Resource>();
+       
+       //private Map<String,Resource> uriMap = new HashMap<String, Resource>();
+       
+       private WriteGraph graph;
+       private Layer0 l0;
+       private LoadRule rule;
+       
+       private int resources;
+       private int statements;
+       
+       private static final boolean USE_DELAYED = true;
+       
+       public LoadXML(Session session, File file) {
+               this.session = session;
+               this.file = file;
+               this.rule = new DefaultLoadRule();
+       }
+       
+       public void setRule(LoadRule rule) {
+               this.rule = rule;
+       }
+       
+       public void load(Resource subj, Resource pred) throws Exception {
+               resources = 0;
+               statements = 0;
+               
+               if (USE_DELAYED) {
+                       session.syncRequest(new ImportDelayedRequest(subj,pred));       
+               } else {
+                       session.syncRequest(new ImportRequest(subj,pred));      
+               }
+               //session.syncRequest(new DelayedWriteRequest() {
+               
+               
+               System.out.println("Import done.");
+       }
+       
+       private class ImportRequest extends WriteRequest {
+               Resource subj;Resource pred;
+               
+               
+               public ImportRequest(Resource subj, Resource pred) {
+                       super();
+                       this.subj = subj;
+                       this.pred = pred;
+               }
+
+               @Override
+               public void perform(WriteGraph graph) throws DatabaseException {
+                       doImport(graph, subj, pred);
+               }
+       }
+       
+       private class ImportDelayedRequest extends DelayedWriteRequest {
+               Resource subj;Resource pred;
+               
+               
+               public ImportDelayedRequest(Resource subj, Resource pred) {
+                       super();
+                       this.subj = subj;
+                       this.pred = pred;
+               }
+
+               @Override
+               public void perform(WriteGraph graph) throws DatabaseException {
+                       doImport(graph, subj, pred);
+               }
+       }
+       
+       private void doImport(WriteGraph graph, Resource subj, Resource pred) throws DatabaseException {
+               LoadXML.this.graph = graph;
+               l0 = Layer0.getInstance(graph);
+               Layer0Utils.setDependenciesIndexingDisabled(graph, true);
+               try {
+                       XMLParser parser = new XMLParser();
+                       parser.parse(file.getAbsolutePath());
+                       System.out.println("Imported " + statements + " Statements, " + resources + " Resources.");
+               } catch (Exception e) {
+                       throw new DatabaseException(e);
+               } finally {
+                       resultRoot = idMap.get(0);
+                       graph.claim(subj, pred, resultRoot);
+                       idMap.clear();
+               }
+       }
+       
+       
+//     public Resource getResult() {
+//             return resultRoot;
+//     }
+       
+       protected Resource getResource(ReadGraph graph, String uri) throws DatabaseException {
+               return rule.getResource(graph, uri);
+       }
+       
+       protected Object createValue(ReadGraph graph, List<String> value, List<String> types) throws DatabaseException {
+               return rule.createValue(graph, value, types);
+       }
+       
+       protected void initializeWithBundles(ReadGraph graph, List<Bundle> bundles) throws DatabaseException {
+               rule.initializeWithBundles(graph, bundles);
+       }
+       
+       
+       public class XMLParser  extends DefaultHandler implements Serializable {
+
+               private static final long serialVersionUID = -4995836637014958966L;
+               
+               private Stack<Element> current = new Stack<Element>();
+               
+               private void loadElement(Element element) throws SAXException{
+                       String name = element.qName;
+                       if ("graphexport".equals(name))
+                               return;
+                       if ("graphbundles".equals(name)) {
+                               element.setData(new ArrayList<Bundle>());
+                               return;
+                       }
+                       if ("bundle".equals(name))
+                               return;
+                       if ("resource".equals(name)) {
+                               element.setData(new Res());
+                               return;
+                       }
+                       if ("type".equals(name)) {
+                               return;
+                       }
+                       if ("statement".equals(name))
+                               return;
+                       
+               }
+               
+               private void handleElement(Stack<Element> parents, Element element) throws SAXException{
+                       try {
+                       String elementName = element.qName;
+                       if ("graphexport".equals(elementName))
+                               return;
+                       if ("graphbundles".equals(elementName)) {
+                               List<Bundle> list = (List<Bundle>)element.getData();
+                               initializeWithBundles(graph, list);
+                               element.setData(null);
+                               return;
+                       }
+                       if ("bundle".equals(elementName)) {
+                               List<Bundle> list = (List<Bundle>)parents.peek().getData();
+                               String name = null;
+                               String versionId = null;
+                               for (Attribute a : element.getAttributes()) {
+                                       if ("name".equals(a.qName))
+                                               name = a.value;
+                                       if ("versionid".equals(a.qName))
+                                               versionId = a.value;
+                               } 
+                               list.add(new Bundle(name,versionId));
+                               return;
+                       }
+                       if ("resource".equals(elementName)) {
+                               Res res = (Res)element.getData();
+                               boolean rel = false;
+                               String uri = null;
+                               int id = -1;
+                               Resource r = null;
+                               for (Attribute a : element.getAttributes()) {
+                                       if ("id".equals(a.qName))
+                                               id = Integer.parseInt(a.value);
+                                       if ("rel".equals(a.qName))
+                                               rel = "true".equals(a.value);
+                                       if ("uri".equals(a.qName))
+                                               uri = a.value;
+                               } 
+                               if (rel) {
+                                       r = getResource(graph, uri);
+                               } else {
+                                       
+                                       r = graph.newResource();
+                                       for (String typeUri : res.types) {
+                                               Resource type =getResource(graph, typeUri);
+                                               graph.claim(r, l0.InstanceOf, type);
+                                       }
+                                       
+                                       if (res.values.size() > 0 ) {
+                                               Object valObj = createValue(graph, res.values, res.types);
+                                               graph.claimValue(r, valObj);
+                                       }
+                               }
+                               if (id == -1)
+                                       throw new SAXException("Resource id missing");
+                               idMap.put(id, r);
+                               
+                               res.types.clear();
+                               res.values.clear();
+                               element.setData(null);
+                               resources++;
+                               return;
+                       }
+                       if ("type".equals(elementName)) {
+                               Element parent = parents.peek();
+                               Res res = (Res)parent.getData();
+                               String uri = null;
+                               for (Attribute a : element.getAttributes()) {
+                                       if ("uri".equals(a.qName))
+                                               uri = a.value;
+                               } 
+                               if (uri != null)
+                                       res.types.add(uri);
+                               
+                               return;
+                       }
+                       if ("value".equals(elementName)) {
+                               Element parent = parents.peek();
+                               Res res = (Res)parent.getData();
+                               String value = null;
+                               for (Attribute a : element.getAttributes()) {
+                                       if ("value".equals(a.qName))
+                                               value = a.value;
+                               } 
+                               if (value != null)
+                                       res.values.add(value);
+                               
+                               return;
+                       }
+                       if ("statement".equals(elementName)) {
+                               int subjId = -1;
+                               int predId = -1;
+                               int objId = -1;
+                               for (Attribute a : element.getAttributes()) {
+                                       if ("subject".equals(a.qName))
+                                               subjId = Integer.parseInt(a.value);
+                                       if ("predicate".equals(a.qName))
+                                               predId = Integer.parseInt(a.value);
+                                       if ("object".equals(a.qName))
+                                               objId = Integer.parseInt(a.value);
+                               } 
+                               
+                               graph.claim(idMap.get(subjId), idMap.get(predId), idMap.get(objId));
+                               statements++;
+                               if (statements % 10000 == 0) {
+                                       System.out.println("Imported " + statements + " Statements, " + resources + " Resources..");
+                                       //SessionGarbageCollection.gc(graph, 0, -1);
+                               }
+                               if (!USE_DELAYED && statements % 100000 == 0) {
+                                       SessionGarbageCollection.gc(graph, 0, -1);
+                                       System.gc();
+                               }
+                               
+                               return;
+                       }
+                       
+                       } catch (DatabaseException e) {
+                               throw new SAXException(e);
+                       }
+               }
+               
+               public void done() {
+                       
+               }
+               
+               public void parse(String filename) throws Exception {
+                       SAXParserFactory spf = SAXParserFactory.newInstance();
+                       SAXParser saxParser = spf.newSAXParser();
+                       
+                       XMLReader reader = saxParser.getXMLReader();
+                       Reader file = new BufferedReader(new FileReader(filename));
+                       reader.setContentHandler(this);
+                       reader.parse(new InputSource(file));
+                       done();
+               }
+               
+               @Override
+               public void startElement(String uri, String localName, String name,
+                               Attributes attributes) throws SAXException {
+                       Element e = new Element(uri,localName,name,attributes);
+                       current.push(e);
+                       //texts.push(new String());
+                       loadElement(e);
+               }
+               
+               @Override
+               public void endElement(String uri, String localName, String name)
+                               throws SAXException {
+                       Element e = null;
+                       if (!current.empty()) {
+                               e = current.pop();
+                       }
+                       if (e != null) {
+                               handleElement(current,e);
+                       }
+               }
+               
+       }
+       
+       public class Attribute {
+               public String localName;
+               public String qName;
+               public String uri;
+               public String value;
+               
+               public Attribute(String localName, String qName, String uri, String value) {
+                       this.localName = localName;
+                       this.qName = qName;
+                       this.uri = uri;
+                       this.value = value;
+               }
+       }
+       
+       public class Element implements Serializable {
+               private static final long serialVersionUID = -5207502156942818875L;
+               String uri;
+               String localName;
+               String qName;
+               List<Attribute> attributes = new ArrayList<Attribute>();
+               
+               public Element(String uri, String localName, String qName, Attributes attributes) {
+                       this.uri = uri;
+                       this.localName = localName;
+                       this.qName = qName;
+                       for (int i = 0; i < attributes.getLength(); i++) {
+                               this.attributes.add(new Attribute(attributes.getLocalName(i),attributes.getQName(i),attributes.getURI(i),attributes.getValue(i)));
+                       }
+               }
+
+               public String getUri() {
+                       return uri;
+               }
+
+               public String getLocalName() {
+                       return localName;
+               }
+
+               public String getQName() {
+                       return qName;
+               }
+
+               public List<Attribute> getAttributes() {
+                       return attributes;
+               }
+
+               private Object data;
+               
+               public void setData(Object data) {
+                       this.data = data;
+               }
+               
+               public Object getData() {
+                       return data;
+               }
+
+       }
+       class Res {
+               
+               List<String> types = new ArrayList<String>();
+               List<String> values = new ArrayList<String>();
+       }
+       
+       public static class Bundle {
+               String name;
+               String versionId;
+               public Bundle(String name, String versionId) {
+                       super();
+                       this.name = name;
+                       this.versionId = versionId;
+               }
+               
+               public String getName() {
+                       return name;
+               }
+               
+               public String getVersionId() {
+                       return versionId;
+               }
+       }
+       
+       
+}
index bcbd52728e396df77ff1ae5075a31dac483f0694..61432a1d725c967773a3b8e6436a9518042ff366 100644 (file)
-package org.simantics.interop.xmlio;\r
-\r
-import java.io.File;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.OutputStreamWriter;\r
-import java.io.PrintWriter;\r
-import java.io.Writer;\r
-import java.util.Arrays;\r
-import java.util.Calendar;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.Stack;\r
-\r
-import org.apache.xml.serialize.OutputFormat;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.Statement;\r
-import org.simantics.db.common.request.ReadRequest;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.layer0.DatabaseManagementResource;\r
-import org.simantics.layer0.Layer0;\r
-import org.xml.sax.Attributes;\r
-import org.xml.sax.Locator;\r
-import org.xml.sax.SAXException;\r
-import org.xml.sax.SAXParseException;\r
-import org.xml.sax.ext.LexicalHandler;\r
-import org.xml.sax.ext.Locator2;\r
-import org.xml.sax.helpers.AttributesImpl;\r
-import org.xml.sax.helpers.DefaultHandler;\r
-\r
-public class SaveXML extends DefaultHandler implements LexicalHandler {\r
-       \r
-       private Session session;\r
-       private Resource root;\r
-       private SaveRule saveRule;\r
-       \r
-       \r
-       private File file;\r
-       \r
-       private PrintWriter fOut;\r
-       /** Canonical output. */\r
-       protected boolean fCanonical = true;\r
-         /** Element depth. */\r
-    protected int fElementDepth;\r
-    \r
-    /** Document locator. */\r
-    protected Locator fLocator;\r
-    \r
-    /** Processing XML 1.1 document. */\r
-    protected boolean fXML11 = true;\r
-    \r
-    /** In CDATA section. */\r
-    protected boolean fInCDATA;\r
-    \r
-       \r
-       public SaveXML(Session session, Resource root, File file) {\r
-               this.session = session;\r
-               this.root = root;\r
-               this.file = file;\r
-               this.saveRule = new DependsOnSaveRule();\r
-       }\r
-       \r
-       public void setSaveRule(SaveRule saveRule) {\r
-               this.saveRule = saveRule;\r
-       }\r
-       \r
-       public void save() throws DatabaseException, IOException, SAXException {\r
-               fCanonical = false;\r
-               FileOutputStream fos = new FileOutputStream(file);\r
-           fOut = new PrintWriter(new OutputStreamWriter(fos, "UTF8"));\r
-               \r
-           startDocument();\r
-           fXML11 = true;\r
-           AttributesImpl attrs = new AttributesImpl();\r
-           addDate(attrs);\r
-           startElement("", "", "graphexport", attrs);\r
-           saveGraphBundles();\r
-           saveData();\r
-           endElement("", "", "graphexport");\r
-           endDocument();\r
-           fOut.close();\r
-       }\r
-       \r
-       private void addDate(AttributesImpl attrs) {\r
-               Calendar calendar = Calendar.getInstance();\r
-               int year = calendar.get(Calendar.YEAR);\r
-               int month = calendar.get(Calendar.MONTH) + 1;\r
-               int day = calendar.get(Calendar.DAY_OF_MONTH);\r
-               int hour = calendar.get(Calendar.HOUR_OF_DAY);\r
-               int min = calendar.get(Calendar.MINUTE);\r
-               int sec = calendar.get(Calendar.SECOND);\r
-       String date = "";\r
-       date += year;\r
-       date += "-";\r
-       if (month < 10)\r
-               date+="0";\r
-       date += month;\r
-       date += "-";\r
-       if (day < 10)\r
-               date+="0";\r
-       date += day;\r
-       date += "T";\r
-       if (hour < 10)\r
-               date+="0";\r
-       date += hour;\r
-       date += ":";\r
-       if (min < 10)\r
-               date+="0";\r
-       date += min;\r
-       date += ":";\r
-       if (sec < 10)\r
-               date+="0";\r
-       date += sec;\r
-       attrs.addAttribute("", "", "date", "CDATA", date);\r
-       }\r
-       \r
-       \r
-       Map<Resource,Integer> idMap = new HashMap<Resource, Integer>();\r
-       \r
-       Set<Resource> processed = new HashSet<Resource>();\r
-       Stack<Resource> stack = new Stack<Resource>();\r
-       Layer0 l0;\r
-       int statements = 0;\r
-       \r
-       private void saveData() throws DatabaseException {\r
-       idMap.clear();\r
-       processed.clear();\r
-       stack.clear();\r
-       statements = 0;\r
-       session.syncRequest(new ReadRequest() {\r
-               \r
-               @Override\r
-               public void run(ReadGraph graph) throws DatabaseException {\r
-                       l0 = Layer0.getInstance(graph);\r
-                       saveRule.init(graph);\r
-                       stack.push(root);\r
-               }\r
-       });\r
-       try {\r
-               while (!stack.isEmpty()) {\r
-                       session.syncRequest(new ReadRequest() {\r
-                               \r
-                               @Override\r
-                               public void run(ReadGraph graph) throws DatabaseException {\r
-                                       \r
-                                       try {\r
-                                       \r
-                                       \r
-                                       AttributesImpl attrs = new AttributesImpl();\r
-                                       \r
-                                       \r
-                                       while (!stack.isEmpty()) {\r
-                                               Resource r = stack.pop();\r
-                                               if (processed.contains(r))\r
-                                                       continue;\r
-                                               processed.add(r);\r
-                                               Collection<Statement> statement = graph.getStatements(r, l0.IsWeaklyRelatedTo);\r
-                                               boolean split = false;\r
-                                               for (Statement s : statement) { \r
-                                                       if (s.isAsserted(r))\r
-                                                               continue;\r
-                                                       if (!saveRule.save(graph, s))\r
-                                                               continue;\r
-                                                       // System.out.println("Processing " + s.getSubject() + " " + s.getPredicate() + " " + s.getObject());\r
-                                                       \r
-                                                       statements++;\r
-                                                       int sId = getId(graph, s.getSubject(),false);\r
-                                                       int pId = getId(graph, s.getPredicate(),true);\r
-                                                       int oId = getId(graph, s.getObject(),false);\r
-                                                       attrs.clear();\r
-                                                       attrs.addAttribute("", "", "subject", "CDATA", Integer.toString(sId));\r
-                                                       attrs.addAttribute("", "", "predicate", "CDATA", Integer.toString(pId));\r
-                                                       attrs.addAttribute("", "", "object", "CDATA", Integer.toString(oId));\r
-                                                       startElement("", "", "statement", attrs);\r
-                                                       endElement("", "", "statement");\r
-                                                       if (!processed.contains(s.getObject()))\r
-                                                               stack.push(s.getObject());\r
-                                                       if (statements % 10000 == 0) {\r
-                                                               System.out.println("Processed " + statements + " statements...");\r
-                                                               split = true;\r
-                                                       }\r
-                                                       \r
-                                               }\r
-                                               if (split)\r
-                                                       return;\r
-                                               \r
-                                       }\r
-                                       System.out.println("Done. Processed " + statements + " statements.");\r
-                                       } catch (SAXException e) {\r
-                                               throw new DatabaseException(e); \r
-                                       }\r
-                               \r
-                               }\r
-                       });\r
-               \r
-               }\r
-       } finally {\r
-               idMap.clear();\r
-               processed.clear();\r
-               stack.clear();\r
-       }\r
-       \r
-}\r
-       \r
-       private int getId(ReadGraph g, Resource r, boolean rel) throws SAXException, DatabaseException {\r
-               Integer id = idMap.get(r);\r
-               if (id == null) {\r
-                       id = idMap.size();\r
-                       idMap.put(r, id);\r
-                       AttributesImpl attrs = new AttributesImpl();\r
-                       attrs.addAttribute("", "", "id", "CDATA", id.toString());\r
-                       if (rel) {\r
-                               attrs.addAttribute("", "", "rel", "CDATA", Boolean.TRUE.toString());\r
-                               String uri = g.getPossibleURI(r);\r
-                               if (uri != null)\r
-                                       attrs.addAttribute("", "", "uri", "CDATA", uri);\r
-                       }\r
-                       \r
-                       startElement("", "", "resource", attrs);\r
-                       if (!rel) {\r
-                               Layer0 l0 = Layer0.getInstance(g);\r
-                               //Collection<Resource> types = g.getPrincipalTypes(r);\r
-                               Collection<Resource> types = g.getObjects(r, l0.InstanceOf);\r
-                               attrs.clear();\r
-                               for (Resource type : types) {\r
-                                       String uri = g.getPossibleURI(type);\r
-                                       if (uri != null) {\r
-                                               attrs.addAttribute("", "", "uri", "CDATA", uri);\r
-                                               startElement("", "", "type", attrs);\r
-                                               endElement("", "", "type");\r
-                                       } else {\r
-                                               // TODO : handle URIless types.\r
-                                               throw new DatabaseException("Cannot resolve URI for type " + type + ", instance " + r); \r
-                                       }\r
-                               }\r
-                       }\r
-                       if (g.hasValue(r)) {\r
-                               // FIXME: does not handle arrays.\r
-                               Object value = g.getValue(r);\r
-                               \r
-                               if (value instanceof Object[]) {\r
-                                       Object[] valuearray = (Object[])value;\r
-                                       for (Object o : valuearray) {\r
-                                               attrs.clear();\r
-                                               attrs.addAttribute("", "", "value", "CDATA", o.toString());\r
-                                               startElement("", "", "value", attrs);\r
-                                               endElement("", "", "value");\r
-                                       }\r
-                               } else {\r
-                                       attrs.clear();\r
-                                       attrs.addAttribute("", "", "value", "CDATA", value.toString());\r
-                                       startElement("", "", "value", attrs);\r
-                                       endElement("", "", "value");\r
-                               }\r
-                       }\r
-                       endElement("", "", "resource");\r
-                       \r
-               }\r
-               return id;\r
-       }\r
-       \r
-       \r
-       private void saveGraphBundles() throws DatabaseException{\r
-               final Resource rootLibrary = session.getRootLibrary();\r
-               session.syncRequest(new ReadRequest() {\r
-                       \r
-                       @Override\r
-                       public void run(ReadGraph graph) throws DatabaseException {\r
-                               Layer0 l0 = Layer0.getInstance(graph);\r
-                               DatabaseManagementResource dm = DatabaseManagementResource.getInstance(graph);\r
-                               Collection<Resource> objs = graph.getObjects(rootLibrary, l0.ConsistsOf);\r
-                               Resource graphBundles = null;\r
-                               for (Resource o : objs) {\r
-                                       if (isGraphBundleLib(graph, rootLibrary)) {\r
-                                               graphBundles = o;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               if (graphBundles == null)\r
-                                       graphBundles = dm.InstalledGraphBundles;\r
-                                       \r
-                               objs = graph.getObjects(graphBundles, l0.ConsistsOf);\r
-                               AttributesImpl attrs = new AttributesImpl();\r
-                               try {\r
-                               startElement("", "", "graphbundles", attrs);\r
-                               for (Resource graphBundle : objs) {\r
-                                       if (!graph.isInstanceOf(graphBundle, dm.GraphBundle))\r
-                                               continue;\r
-                                       String name = graph.getRelatedValue(graphBundle, l0.HasName);\r
-                                       String versionId = graph.getRelatedValue(graphBundle, dm.HasVersionedId);\r
-                                       attrs.clear();\r
-                                       attrs.addAttribute("", "", "name", "CDATA", name);\r
-                                       attrs.addAttribute("", "", "versionid", "CDATA", versionId);\r
-                                       startElement("", "", "bundle", attrs);\r
-                                       endElement("", "", "bundle");\r
-                               }\r
-                               \r
-                               endElement("", "", "graphbundles");\r
-                               } catch (SAXException e) {\r
-                                       throw new DatabaseException(e);\r
-                               }\r
-                       }\r
-               });\r
-       }\r
-       \r
-       private boolean isGraphBundleLib(ReadGraph graph, Resource o) throws DatabaseException {\r
-               Layer0 l0 = Layer0.getInstance(graph);\r
-               String name = graph.getPossibleRelatedValue(o, l0.HasName);\r
-               return "InstalledGraphBundles".equals(name);\r
-       }\r
-       \r
-       \r
-       \r
-    /** Set Document Locator. */\r
-    public void setDocumentLocator(Locator locator) {\r
-       fLocator = locator;\r
-    } // setDocumentLocator(Locator)\r
-       \r
-    /** Start document. */\r
-    public void startDocument() throws SAXException {\r
-\r
-        fElementDepth = 0;\r
-        fXML11 = false;\r
-        fInCDATA = false;\r
-        \r
-    } // startDocument()\r
-\r
-    /** Processing instruction. */\r
-    public void processingInstruction(String target, String data)\r
-        throws SAXException {\r
-\r
-        if (fElementDepth > 0) {\r
-            fOut.print("<?");\r
-            fOut.print(target);\r
-            if (data != null && data.length() > 0) {\r
-                fOut.print(' ');\r
-                fOut.print(data);\r
-            }\r
-            fOut.print("?>");\r
-            fOut.flush();\r
-        }\r
-\r
-    } // processingInstruction(String,String)\r
-\r
-    /** Start element. */\r
-    public void startElement(String uri, String local, String raw,\r
-                             Attributes attrs) throws SAXException {\r
-\r
-        // Root Element\r
-        if (fElementDepth == 0) {\r
-            String encoding = "UTF-8";\r
-            if (fLocator != null) {\r
-                if (fLocator instanceof Locator2) {\r
-                    Locator2 locator2 = (Locator2) fLocator;\r
-                    fXML11 = "1.1".equals(locator2.getXMLVersion());\r
-                    encoding = locator2.getEncoding();\r
-                    if (encoding == null) {\r
-                        encoding = "UTF-8";\r
-                    }\r
-                }\r
-                fLocator = null;\r
-            }\r
-\r
-            // The XML declaration cannot be printed in startDocument because\r
-            // the version and encoding information reported by the Locator \r
-            // cannot be relied on until the next event after startDocument.\r
-            if (!fCanonical) {\r
-                fOut.print("<?xml version=\"");\r
-                fOut.print(fXML11 ? "1.1" : "1.0");\r
-                fOut.print("\" encoding=\"");\r
-                fOut.print(encoding);\r
-                fOut.println("\"?>");\r
-                fOut.flush();\r
-            }\r
-        }\r
-        \r
-        fElementDepth++;\r
-        fOut.print('<');\r
-        fOut.print(raw);\r
-        if (attrs != null) {\r
-            attrs = sortAttributes(attrs);\r
-            int len = attrs.getLength();\r
-            for (int i = 0; i < len; i++) {\r
-                fOut.print(' ');\r
-                fOut.print(attrs.getQName(i));\r
-                fOut.print("=\"");\r
-                normalizeAndPrint(attrs.getValue(i), true);\r
-                fOut.print('"');\r
-            }\r
-        }\r
-        //fOut.print('>');\r
-        fOut.print(">\n");\r
-        fOut.flush();\r
-\r
-    } // startElement(String,String,String,Attributes)\r
-\r
-    /** Characters. */\r
-    public void characters(char ch[], int start, int length)\r
-        throws SAXException {\r
-\r
-        if (!fInCDATA) {\r
-            normalizeAndPrint(ch, start, length, false);\r
-        }\r
-        else {\r
-            for (int i = 0; i < length; ++i) {\r
-               fOut.print(ch[start+i]);\r
-            }\r
-        }\r
-        fOut.flush();\r
-\r
-    } // characters(char[],int,int);\r
-\r
-    /** Ignorable whitespace. */\r
-    public void ignorableWhitespace(char ch[], int start, int length)\r
-        throws SAXException {\r
-\r
-        characters(ch, start, length);\r
-        fOut.flush();\r
-\r
-    } // ignorableWhitespace(char[],int,int);\r
-\r
-    /** End element. */\r
-    public void endElement(String uri, String local, String raw)\r
-        throws SAXException {\r
-\r
-        fElementDepth--;\r
-        fOut.print("</");\r
-        fOut.print(raw);\r
-        //fOut.print('>');\r
-        fOut.print(">\n");\r
-        fOut.flush();\r
-\r
-    } // endElement(String)\r
-\r
-    //\r
-    // ErrorHandler methods\r
-    //\r
-\r
-    /** Warning. */\r
-    public void warning(SAXParseException ex) throws SAXException {\r
-        printError("Warning", ex);\r
-    } // warning(SAXParseException)\r
-\r
-    /** Error. */\r
-    public void error(SAXParseException ex) throws SAXException {\r
-        printError("Error", ex);\r
-    } // error(SAXParseException)\r
-\r
-    /** Fatal error. */\r
-    public void fatalError(SAXParseException ex) throws SAXException {\r
-        printError("Fatal Error", ex);\r
-        throw ex;\r
-    } // fatalError(SAXParseException)\r
-\r
-    //\r
-    // LexicalHandler methods\r
-    //\r
-\r
-    /** Start DTD. */\r
-    public void startDTD(String name, String publicId, String systemId)\r
-        throws SAXException {\r
-    } // startDTD(String,String,String)\r
-\r
-    /** End DTD. */\r
-    public void endDTD() throws SAXException {\r
-    } // endDTD()\r
-\r
-    /** Start entity. */\r
-    public void startEntity(String name) throws SAXException {\r
-    } // startEntity(String)\r
-\r
-    /** End entity. */\r
-    public void endEntity(String name) throws SAXException {\r
-    } // endEntity(String)\r
-\r
-    /** Start CDATA section. */\r
-    public void startCDATA() throws SAXException {\r
-        if (!fCanonical) {\r
-            fOut.print("<![CDATA[");\r
-            fInCDATA = true;\r
-        }\r
-    } // startCDATA()\r
-\r
-    /** End CDATA section. */\r
-    public void endCDATA() throws SAXException {\r
-        if (!fCanonical) {\r
-            fInCDATA = false;\r
-            fOut.print("]]>");\r
-        }\r
-    } // endCDATA()\r
-\r
-    /** Comment. */\r
-    public void comment(char ch[], int start, int length) throws SAXException {\r
-        if (!fCanonical && fElementDepth > 0) {\r
-            fOut.print("<!--");\r
-            for (int i = 0; i < length; ++i) {\r
-                fOut.print(ch[start+i]);\r
-            }\r
-            //fOut.print("-->");\r
-            fOut.print("-->\n");\r
-            fOut.flush();\r
-        }\r
-    } // comment(char[],int,int)\r
-\r
-    //\r
-    // Protected methods\r
-    //\r
-\r
-    /** Returns a sorted list of attributes. */\r
-    protected Attributes sortAttributes(Attributes attrs) {\r
-\r
-       return attrs;\r
-//        AttributesImpl attributes = new AttributesImpl();\r
-//\r
-//        int len = (attrs != null) ? attrs.getLength() : 0;\r
-//        for (int i = 0; i < len; i++) {\r
-//            String name = attrs.getQName(i);\r
-//            int count = attributes.getLength();\r
-//            int j = 0;\r
-//            while (j < count) {\r
-//                if (name.compareTo(attributes.getQName(j)) < 0) {\r
-//                    break;\r
-//                }\r
-//                j++;\r
-//            }\r
-//            //attributes.insertAttributeAt(j, name, attrs.getType(i),attrs.getValue(i));\r
-//            attributes.setAttribute(j, attrs.getURI(i), attrs.getLocalName(i), name, attrs.getType(i), attrs.getValue(i));\r
-//        }\r
-//\r
-//        return attributes;\r
-\r
-    } // sortAttributes(AttributeList):AttributeList\r
-\r
-    /** Normalizes and prints the given string. */\r
-    protected void normalizeAndPrint(String s, boolean isAttValue) {\r
-\r
-        int len = (s != null) ? s.length() : 0;\r
-        for (int i = 0; i < len; i++) {\r
-            char c = s.charAt(i);\r
-            normalizeAndPrint(c, isAttValue);\r
-        }\r
-\r
-    } // normalizeAndPrint(String,boolean)\r
-\r
-    /** Normalizes and prints the given array of characters. */\r
-    protected void normalizeAndPrint(char[] ch, int offset, int length, boolean isAttValue) {\r
-        for (int i = 0; i < length; i++) {\r
-            normalizeAndPrint(ch[offset + i], isAttValue);\r
-        }\r
-    } // normalizeAndPrint(char[],int,int,boolean)\r
-\r
-    /** Normalizes and print the given character. */\r
-    protected void normalizeAndPrint(char c, boolean isAttValue) {\r
-\r
-        switch (c) {\r
-            case '<': {\r
-                fOut.print("&lt;");\r
-                break;\r
-            }\r
-            case '>': {\r
-                fOut.print("&gt;");\r
-                break;\r
-            }\r
-            case '&': {\r
-                fOut.print("&amp;");\r
-                break;\r
-            }\r
-            case '"': {\r
-                // A '"' that appears in character data \r
-                // does not need to be escaped.\r
-                if (isAttValue) {\r
-                    fOut.print("&quot;");\r
-                }\r
-                else {\r
-                    fOut.print("\"");\r
-                }\r
-                break;\r
-            }\r
-            case '\r': {\r
-               // If CR is part of the document's content, it\r
-               // must not be printed as a literal otherwise\r
-               // it would be normalized to LF when the document\r
-               // is reparsed.\r
-               fOut.print("&#xD;");\r
-               break;\r
-            }\r
-            case '\n': {\r
-                if (fCanonical) {\r
-                    fOut.print("&#xA;");\r
-                    break;\r
-                }\r
-                // else, default print char\r
-            }\r
-            default: {\r
-                // In XML 1.1, control chars in the ranges [#x1-#x1F, #x7F-#x9F] must be escaped.\r
-               //\r
-               // Escape space characters that would be normalized to #x20 in attribute values\r
-               // when the document is reparsed.\r
-               //\r
-               // Escape NEL (0x85) and LSEP (0x2028) that appear in content \r
-               // if the document is XML 1.1, since they would be normalized to LF \r
-               // when the document is reparsed.\r
-               if (fXML11 && ((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) \r
-                   || (c >= 0x7F && c <= 0x9F) || c == 0x2028)\r
-                   || isAttValue && (c == 0x09 || c == 0x0A)) {\r
-                   fOut.print("&#x");\r
-                   fOut.print(Integer.toHexString(c).toUpperCase());\r
-                   fOut.print(";");\r
-                }\r
-                else {\r
-                    fOut.print(c);\r
-                }        \r
-            }\r
-        }\r
-    } // normalizeAndPrint(char,boolean)\r
-\r
-    /** Prints the error message. */\r
-    protected void printError(String type, SAXParseException ex) {\r
-\r
-        System.err.print("[");\r
-        System.err.print(type);\r
-        System.err.print("] ");\r
-        String systemId = ex.getSystemId();\r
-        if (systemId != null) {\r
-            int index = systemId.lastIndexOf('/');\r
-            if (index != -1)\r
-                systemId = systemId.substring(index + 1);\r
-            System.err.print(systemId);\r
-        }\r
-        System.err.print(':');\r
-        System.err.print(ex.getLineNumber());\r
-        System.err.print(':');\r
-        System.err.print(ex.getColumnNumber());\r
-        System.err.print(": ");\r
-        System.err.print(ex.getMessage());\r
-        System.err.println();\r
-        System.err.flush();\r
-\r
-    } // printError(String,SAXParseException)\r
-\r
-}\r
+package org.simantics.interop.xmlio;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.Statement;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.layer0.DatabaseManagementResource;
+import org.simantics.layer0.Layer0;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.ext.Locator2;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class SaveXML extends DefaultHandler implements LexicalHandler {
+       
+       private Session session;
+       private Resource root;
+       private SaveRule saveRule;
+       
+       
+       private File file;
+       
+       private PrintWriter fOut;
+       /** Canonical output. */
+       protected boolean fCanonical = true;
+         /** Element depth. */
+    protected int fElementDepth;
+    
+    /** Document locator. */
+    protected Locator fLocator;
+    
+    /** Processing XML 1.1 document. */
+    protected boolean fXML11 = true;
+    
+    /** In CDATA section. */
+    protected boolean fInCDATA;
+    
+       
+       public SaveXML(Session session, Resource root, File file) {
+               this.session = session;
+               this.root = root;
+               this.file = file;
+               this.saveRule = new DependsOnSaveRule();
+       }
+       
+       public void setSaveRule(SaveRule saveRule) {
+               this.saveRule = saveRule;
+       }
+       
+       public void save() throws DatabaseException, IOException, SAXException {
+               fCanonical = false;
+               FileOutputStream fos = new FileOutputStream(file);
+           fOut = new PrintWriter(new OutputStreamWriter(fos, "UTF8"));
+               
+           startDocument();
+           fXML11 = true;
+           AttributesImpl attrs = new AttributesImpl();
+           addDate(attrs);
+           startElement("", "", "graphexport", attrs);
+           saveGraphBundles();
+           saveData();
+           endElement("", "", "graphexport");
+           endDocument();
+           fOut.close();
+       }
+       
+       private void addDate(AttributesImpl attrs) {
+               Calendar calendar = Calendar.getInstance();
+               int year = calendar.get(Calendar.YEAR);
+               int month = calendar.get(Calendar.MONTH) + 1;
+               int day = calendar.get(Calendar.DAY_OF_MONTH);
+               int hour = calendar.get(Calendar.HOUR_OF_DAY);
+               int min = calendar.get(Calendar.MINUTE);
+               int sec = calendar.get(Calendar.SECOND);
+       String date = "";
+       date += year;
+       date += "-";
+       if (month < 10)
+               date+="0";
+       date += month;
+       date += "-";
+       if (day < 10)
+               date+="0";
+       date += day;
+       date += "T";
+       if (hour < 10)
+               date+="0";
+       date += hour;
+       date += ":";
+       if (min < 10)
+               date+="0";
+       date += min;
+       date += ":";
+       if (sec < 10)
+               date+="0";
+       date += sec;
+       attrs.addAttribute("", "", "date", "CDATA", date);
+       }
+       
+       
+       Map<Resource,Integer> idMap = new HashMap<Resource, Integer>();
+       
+       Set<Resource> processed = new HashSet<Resource>();
+       Stack<Resource> stack = new Stack<Resource>();
+       Layer0 l0;
+       int statements = 0;
+       
+       private void saveData() throws DatabaseException {
+       idMap.clear();
+       processed.clear();
+       stack.clear();
+       statements = 0;
+       session.syncRequest(new ReadRequest() {
+               
+               @Override
+               public void run(ReadGraph graph) throws DatabaseException {
+                       l0 = Layer0.getInstance(graph);
+                       saveRule.init(graph);
+                       stack.push(root);
+               }
+       });
+       try {
+               while (!stack.isEmpty()) {
+                       session.syncRequest(new ReadRequest() {
+                               
+                               @Override
+                               public void run(ReadGraph graph) throws DatabaseException {
+                                       
+                                       try {
+                                       
+                                       
+                                       AttributesImpl attrs = new AttributesImpl();
+                                       
+                                       
+                                       while (!stack.isEmpty()) {
+                                               Resource r = stack.pop();
+                                               if (processed.contains(r))
+                                                       continue;
+                                               processed.add(r);
+                                               Collection<Statement> statement = graph.getStatements(r, l0.IsWeaklyRelatedTo);
+                                               boolean split = false;
+                                               for (Statement s : statement) { 
+                                                       if (s.isAsserted(r))
+                                                               continue;
+                                                       if (!saveRule.save(graph, s))
+                                                               continue;
+                                                       // System.out.println("Processing " + s.getSubject() + " " + s.getPredicate() + " " + s.getObject());
+                                                       
+                                                       statements++;
+                                                       int sId = getId(graph, s.getSubject(),false);
+                                                       int pId = getId(graph, s.getPredicate(),true);
+                                                       int oId = getId(graph, s.getObject(),false);
+                                                       attrs.clear();
+                                                       attrs.addAttribute("", "", "subject", "CDATA", Integer.toString(sId));
+                                                       attrs.addAttribute("", "", "predicate", "CDATA", Integer.toString(pId));
+                                                       attrs.addAttribute("", "", "object", "CDATA", Integer.toString(oId));
+                                                       startElement("", "", "statement", attrs);
+                                                       endElement("", "", "statement");
+                                                       if (!processed.contains(s.getObject()))
+                                                               stack.push(s.getObject());
+                                                       if (statements % 10000 == 0) {
+                                                               System.out.println("Processed " + statements + " statements...");
+                                                               split = true;
+                                                       }
+                                                       
+                                               }
+                                               if (split)
+                                                       return;
+                                               
+                                       }
+                                       System.out.println("Done. Processed " + statements + " statements.");
+                                       } catch (SAXException e) {
+                                               throw new DatabaseException(e); 
+                                       }
+                               
+                               }
+                       });
+               
+               }
+       } finally {
+               idMap.clear();
+               processed.clear();
+               stack.clear();
+       }
+       
+}
+       
+       private int getId(ReadGraph g, Resource r, boolean rel) throws SAXException, DatabaseException {
+               Integer id = idMap.get(r);
+               if (id == null) {
+                       id = idMap.size();
+                       idMap.put(r, id);
+                       AttributesImpl attrs = new AttributesImpl();
+                       attrs.addAttribute("", "", "id", "CDATA", id.toString());
+                       if (rel) {
+                               attrs.addAttribute("", "", "rel", "CDATA", Boolean.TRUE.toString());
+                               String uri = g.getPossibleURI(r);
+                               if (uri != null)
+                                       attrs.addAttribute("", "", "uri", "CDATA", uri);
+                       }
+                       
+                       startElement("", "", "resource", attrs);
+                       if (!rel) {
+                               Layer0 l0 = Layer0.getInstance(g);
+                               //Collection<Resource> types = g.getPrincipalTypes(r);
+                               Collection<Resource> types = g.getObjects(r, l0.InstanceOf);
+                               attrs.clear();
+                               for (Resource type : types) {
+                                       String uri = g.getPossibleURI(type);
+                                       if (uri != null) {
+                                               attrs.addAttribute("", "", "uri", "CDATA", uri);
+                                               startElement("", "", "type", attrs);
+                                               endElement("", "", "type");
+                                       } else {
+                                               // TODO : handle URIless types.
+                                               throw new DatabaseException("Cannot resolve URI for type " + type + ", instance " + r); 
+                                       }
+                               }
+                       }
+                       if (g.hasValue(r)) {
+                               // FIXME: does not handle arrays.
+                               Object value = g.getValue(r);
+                               
+                               if (value instanceof Object[]) {
+                                       Object[] valuearray = (Object[])value;
+                                       for (Object o : valuearray) {
+                                               attrs.clear();
+                                               attrs.addAttribute("", "", "value", "CDATA", o.toString());
+                                               startElement("", "", "value", attrs);
+                                               endElement("", "", "value");
+                                       }
+                               } else {
+                                       attrs.clear();
+                                       attrs.addAttribute("", "", "value", "CDATA", value.toString());
+                                       startElement("", "", "value", attrs);
+                                       endElement("", "", "value");
+                               }
+                       }
+                       endElement("", "", "resource");
+                       
+               }
+               return id;
+       }
+       
+       
+       private void saveGraphBundles() throws DatabaseException{
+               final Resource rootLibrary = session.getRootLibrary();
+               session.syncRequest(new ReadRequest() {
+                       
+                       @Override
+                       public void run(ReadGraph graph) throws DatabaseException {
+                               Layer0 l0 = Layer0.getInstance(graph);
+                               DatabaseManagementResource dm = DatabaseManagementResource.getInstance(graph);
+                               Collection<Resource> objs = graph.getObjects(rootLibrary, l0.ConsistsOf);
+                               Resource graphBundles = null;
+                               for (Resource o : objs) {
+                                       if (isGraphBundleLib(graph, rootLibrary)) {
+                                               graphBundles = o;
+                                               break;
+                                       }
+                               }
+                               if (graphBundles == null)
+                                       graphBundles = dm.InstalledGraphBundles;
+                                       
+                               objs = graph.getObjects(graphBundles, l0.ConsistsOf);
+                               AttributesImpl attrs = new AttributesImpl();
+                               try {
+                               startElement("", "", "graphbundles", attrs);
+                               for (Resource graphBundle : objs) {
+                                       if (!graph.isInstanceOf(graphBundle, dm.GraphBundle))
+                                               continue;
+                                       String name = graph.getRelatedValue(graphBundle, l0.HasName);
+                                       String versionId = graph.getRelatedValue(graphBundle, dm.HasVersionedId);
+                                       attrs.clear();
+                                       attrs.addAttribute("", "", "name", "CDATA", name);
+                                       attrs.addAttribute("", "", "versionid", "CDATA", versionId);
+                                       startElement("", "", "bundle", attrs);
+                                       endElement("", "", "bundle");
+                               }
+                               
+                               endElement("", "", "graphbundles");
+                               } catch (SAXException e) {
+                                       throw new DatabaseException(e);
+                               }
+                       }
+               });
+       }
+       
+       private boolean isGraphBundleLib(ReadGraph graph, Resource o) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(graph);
+               String name = graph.getPossibleRelatedValue(o, l0.HasName);
+               return "InstalledGraphBundles".equals(name);
+       }
+       
+       
+       
+    /** Set Document Locator. */
+    public void setDocumentLocator(Locator locator) {
+       fLocator = locator;
+    } // setDocumentLocator(Locator)
+       
+    /** Start document. */
+    public void startDocument() throws SAXException {
+
+        fElementDepth = 0;
+        fXML11 = false;
+        fInCDATA = false;
+        
+    } // startDocument()
+
+    /** Processing instruction. */
+    public void processingInstruction(String target, String data)
+        throws SAXException {
+
+        if (fElementDepth > 0) {
+            fOut.print("<?");
+            fOut.print(target);
+            if (data != null && data.length() > 0) {
+                fOut.print(' ');
+                fOut.print(data);
+            }
+            fOut.print("?>");
+            fOut.flush();
+        }
+
+    } // processingInstruction(String,String)
+
+    /** Start element. */
+    public void startElement(String uri, String local, String raw,
+                             Attributes attrs) throws SAXException {
+
+        // Root Element
+        if (fElementDepth == 0) {
+            String encoding = "UTF-8";
+            if (fLocator != null) {
+                if (fLocator instanceof Locator2) {
+                    Locator2 locator2 = (Locator2) fLocator;
+                    fXML11 = "1.1".equals(locator2.getXMLVersion());
+                    encoding = locator2.getEncoding();
+                    if (encoding == null) {
+                        encoding = "UTF-8";
+                    }
+                }
+                fLocator = null;
+            }
+
+            // The XML declaration cannot be printed in startDocument because
+            // the version and encoding information reported by the Locator 
+            // cannot be relied on until the next event after startDocument.
+            if (!fCanonical) {
+                fOut.print("<?xml version=\"");
+                fOut.print(fXML11 ? "1.1" : "1.0");
+                fOut.print("\" encoding=\"");
+                fOut.print(encoding);
+                fOut.println("\"?>");
+                fOut.flush();
+            }
+        }
+        
+        fElementDepth++;
+        fOut.print('<');
+        fOut.print(raw);
+        if (attrs != null) {
+            attrs = sortAttributes(attrs);
+            int len = attrs.getLength();
+            for (int i = 0; i < len; i++) {
+                fOut.print(' ');
+                fOut.print(attrs.getQName(i));
+                fOut.print("=\"");
+                normalizeAndPrint(attrs.getValue(i), true);
+                fOut.print('"');
+            }
+        }
+        //fOut.print('>');
+        fOut.print(">\n");
+        fOut.flush();
+
+    } // startElement(String,String,String,Attributes)
+
+    /** Characters. */
+    public void characters(char ch[], int start, int length)
+        throws SAXException {
+
+        if (!fInCDATA) {
+            normalizeAndPrint(ch, start, length, false);
+        }
+        else {
+            for (int i = 0; i < length; ++i) {
+               fOut.print(ch[start+i]);
+            }
+        }
+        fOut.flush();
+
+    } // characters(char[],int,int);
+
+    /** Ignorable whitespace. */
+    public void ignorableWhitespace(char ch[], int start, int length)
+        throws SAXException {
+
+        characters(ch, start, length);
+        fOut.flush();
+
+    } // ignorableWhitespace(char[],int,int);
+
+    /** End element. */
+    public void endElement(String uri, String local, String raw)
+        throws SAXException {
+
+        fElementDepth--;
+        fOut.print("</");
+        fOut.print(raw);
+        //fOut.print('>');
+        fOut.print(">\n");
+        fOut.flush();
+
+    } // endElement(String)
+
+    //
+    // ErrorHandler methods
+    //
+
+    /** Warning. */
+    public void warning(SAXParseException ex) throws SAXException {
+        printError("Warning", ex);
+    } // warning(SAXParseException)
+
+    /** Error. */
+    public void error(SAXParseException ex) throws SAXException {
+        printError("Error", ex);
+    } // error(SAXParseException)
+
+    /** Fatal error. */
+    public void fatalError(SAXParseException ex) throws SAXException {
+        printError("Fatal Error", ex);
+        throw ex;
+    } // fatalError(SAXParseException)
+
+    //
+    // LexicalHandler methods
+    //
+
+    /** Start DTD. */
+    public void startDTD(String name, String publicId, String systemId)
+        throws SAXException {
+    } // startDTD(String,String,String)
+
+    /** End DTD. */
+    public void endDTD() throws SAXException {
+    } // endDTD()
+
+    /** Start entity. */
+    public void startEntity(String name) throws SAXException {
+    } // startEntity(String)
+
+    /** End entity. */
+    public void endEntity(String name) throws SAXException {
+    } // endEntity(String)
+
+    /** Start CDATA section. */
+    public void startCDATA() throws SAXException {
+        if (!fCanonical) {
+            fOut.print("<![CDATA[");
+            fInCDATA = true;
+        }
+    } // startCDATA()
+
+    /** End CDATA section. */
+    public void endCDATA() throws SAXException {
+        if (!fCanonical) {
+            fInCDATA = false;
+            fOut.print("]]>");
+        }
+    } // endCDATA()
+
+    /** Comment. */
+    public void comment(char ch[], int start, int length) throws SAXException {
+        if (!fCanonical && fElementDepth > 0) {
+            fOut.print("<!--");
+            for (int i = 0; i < length; ++i) {
+                fOut.print(ch[start+i]);
+            }
+            //fOut.print("-->");
+            fOut.print("-->\n");
+            fOut.flush();
+        }
+    } // comment(char[],int,int)
+
+    //
+    // Protected methods
+    //
+
+    /** Returns a sorted list of attributes. */
+    protected Attributes sortAttributes(Attributes attrs) {
+
+       return attrs;
+//        AttributesImpl attributes = new AttributesImpl();
+//
+//        int len = (attrs != null) ? attrs.getLength() : 0;
+//        for (int i = 0; i < len; i++) {
+//            String name = attrs.getQName(i);
+//            int count = attributes.getLength();
+//            int j = 0;
+//            while (j < count) {
+//                if (name.compareTo(attributes.getQName(j)) < 0) {
+//                    break;
+//                }
+//                j++;
+//            }
+//            //attributes.insertAttributeAt(j, name, attrs.getType(i),attrs.getValue(i));
+//            attributes.setAttribute(j, attrs.getURI(i), attrs.getLocalName(i), name, attrs.getType(i), attrs.getValue(i));
+//        }
+//
+//        return attributes;
+
+    } // sortAttributes(AttributeList):AttributeList
+
+    /** Normalizes and prints the given string. */
+    protected void normalizeAndPrint(String s, boolean isAttValue) {
+
+        int len = (s != null) ? s.length() : 0;
+        for (int i = 0; i < len; i++) {
+            char c = s.charAt(i);
+            normalizeAndPrint(c, isAttValue);
+        }
+
+    } // normalizeAndPrint(String,boolean)
+
+    /** Normalizes and prints the given array of characters. */
+    protected void normalizeAndPrint(char[] ch, int offset, int length, boolean isAttValue) {
+        for (int i = 0; i < length; i++) {
+            normalizeAndPrint(ch[offset + i], isAttValue);
+        }
+    } // normalizeAndPrint(char[],int,int,boolean)
+
+    /** Normalizes and print the given character. */
+    protected void normalizeAndPrint(char c, boolean isAttValue) {
+
+        switch (c) {
+            case '<': {
+                fOut.print("&lt;");
+                break;
+            }
+            case '>': {
+                fOut.print("&gt;");
+                break;
+            }
+            case '&': {
+                fOut.print("&amp;");
+                break;
+            }
+            case '"': {
+                // A '"' that appears in character data 
+                // does not need to be escaped.
+                if (isAttValue) {
+                    fOut.print("&quot;");
+                }
+                else {
+                    fOut.print("\"");
+                }
+                break;
+            }
+            case '\r': {
+               // If CR is part of the document's content, it
+               // must not be printed as a literal otherwise
+               // it would be normalized to LF when the document
+               // is reparsed.
+               fOut.print("&#xD;");
+               break;
+            }
+            case '\n': {
+                if (fCanonical) {
+                    fOut.print("&#xA;");
+                    break;
+                }
+                // else, default print char
+            }
+            default: {
+                // In XML 1.1, control chars in the ranges [#x1-#x1F, #x7F-#x9F] must be escaped.
+               //
+               // Escape space characters that would be normalized to #x20 in attribute values
+               // when the document is reparsed.
+               //
+               // Escape NEL (0x85) and LSEP (0x2028) that appear in content 
+               // if the document is XML 1.1, since they would be normalized to LF 
+               // when the document is reparsed.
+               if (fXML11 && ((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) 
+                   || (c >= 0x7F && c <= 0x9F) || c == 0x2028)
+                   || isAttValue && (c == 0x09 || c == 0x0A)) {
+                   fOut.print("&#x");
+                   fOut.print(Integer.toHexString(c).toUpperCase());
+                   fOut.print(";");
+                }
+                else {
+                    fOut.print(c);
+                }        
+            }
+        }
+    } // normalizeAndPrint(char,boolean)
+
+    /** Prints the error message. */
+    protected void printError(String type, SAXParseException ex) {
+
+        System.err.print("[");
+        System.err.print(type);
+        System.err.print("] ");
+        String systemId = ex.getSystemId();
+        if (systemId != null) {
+            int index = systemId.lastIndexOf('/');
+            if (index != -1)
+                systemId = systemId.substring(index + 1);
+            System.err.print(systemId);
+        }
+        System.err.print(':');
+        System.err.print(ex.getLineNumber());
+        System.err.print(':');
+        System.err.print(ex.getColumnNumber());
+        System.err.print(": ");
+        System.err.print(ex.getMessage());
+        System.err.println();
+        System.err.flush();
+
+    } // printError(String,SAXParseException)
+
+}