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 idMap = new HashMap(); Int2ObjectOpenHashMap idMap = new Int2ObjectOpenHashMap(); //private Map uriMap = new HashMap(); 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 value, List types) throws DatabaseException { return rule.createValue(graph, value, types); } protected void initializeWithBundles(ReadGraph graph, List bundles) throws DatabaseException { rule.initializeWithBundles(graph, bundles); } public class XMLParser extends DefaultHandler implements Serializable { private static final long serialVersionUID = -4995836637014958966L; private Stack current = new Stack(); private void loadElement(Element element) throws SAXException{ String name = element.qName; if ("graphexport".equals(name)) return; if ("graphbundles".equals(name)) { element.setData(new ArrayList()); 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 parents, Element element) throws SAXException{ try { String elementName = element.qName; if ("graphexport".equals(elementName)) return; if ("graphbundles".equals(elementName)) { List list = (List)element.getData(); initializeWithBundles(graph, list); element.setData(null); return; } if ("bundle".equals(elementName)) { List list = (List)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 attributes = new ArrayList(); 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 getAttributes() { return attributes; } private Object data; public void setData(Object data) { this.data = data; } public Object getData() { return data; } } class Res { List types = new ArrayList(); List values = new ArrayList(); } 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; } } }