/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.tools; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Scanner; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import org.zoodb.internal.Session; import org.zoodb.internal.ZooClassProxy; import org.zoodb.jdo.ZooJdoHelper; import org.zoodb.jdo.ZooJdoProperties; import org.zoodb.jdo.impl.PersistenceManagerImpl; import org.zoodb.schema.ZooClass; import org.zoodb.tools.internal.DataDeSerializer; import org.zoodb.tools.internal.ObjectCache; import org.zoodb.tools.internal.ObjectCache.GOProxy; import org.zoodb.tools.internal.SerializerTools; import org.zoodb.tools.internal.XmlReader; /** * Export a database to xml. * * @author ztilmann * */ public class ZooXmlImport { private final Scanner scanner; public ZooXmlImport(Scanner sc) { this.scanner = sc; } public static void main(String[] args) { if (args.length != 2) { System.out.println("Error: invalid number of arguments."); System.out.println("Usage: "); System.out.println(" XmlExport <dbName> <xmlFileName>"); return; } String dbName = args[0]; String xmlName = args[1]; Scanner sc = openFile(xmlName); if (sc == null) { return; } try { new ZooXmlImport(sc).readDB(dbName); } finally { sc.close(); } sc.close(); } public void readDB(String dbName) { ZooJdoProperties props = new ZooJdoProperties(dbName); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); try { pm.currentTransaction().begin(); readFromXML(pm); } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException(t); } finally { pm.currentTransaction().commit(); pm.close(); pmf.close(); } } private static class ClsDef { long oid; String name; long superOid; ArrayList<FldDef> fields = new ArrayList<FldDef>(); public boolean needsFieldDeclarations = false; public ClsDef(String name, long oid, long superOid) { this.oid = oid; this.name = name; this.superOid = superOid; } } private static class FldDef { // int id; String name; String typeName; int arrayDim; public FldDef(int id, String name, String typeName, int arrayDim) { // this.id = id; this.name = name; this.typeName = typeName; this.arrayDim = arrayDim; } } private void readFromXML(PersistenceManager pm) { Session session = ((PersistenceManagerImpl)pm).getSession(); ObjectCache cache = new ObjectCache(session); readlnM("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); readln1("<database>"); readln1("<schema>"); HashMap<Long, ClsDef> classes = new HashMap<Long, ClsDef>(); HashMap<String, ClsDef> classNames = new HashMap<String, ClsDef>(); while (readln1("<class", "</schema>")) { String name = readValue1("name"); String oidStr = readValue1("oid"); long sOid = Long.parseLong(oidStr); long superOid = Long.parseLong(readValue1("super")); //define schema ClsDef cd = new ClsDef(name, sOid, superOid); classes.put(sOid, cd); classNames.put(name, cd); // //TODO remove // try { // Class<?> cls = Class.forName(name); // ZooClass schema = ZooSchema.locateClass(pm, cls); // if (schema == null) { // schema = ZooSchema.defineClass(pm, cls); // } // schemata.put(sOid, schema); // cache.addSchema(sOid, ((ZooClassProxy) schema).getSchemaDef()); // } catch (ClassNotFoundException e) { // throw new RuntimeException(e); // } // //TODO --- int prevId = -1; while (readln1("<attr", "</class>")) { int id = Integer.parseInt(readValue1("id")); String attrName = readValue1("name"); String typeName = readValue1("type"); int arrayDim = Integer.parseInt(readValue1("arrayDim")); readln1("/>"); //verify correct order off fields prevId++; if (prevId != id) { throw new IllegalStateException("Illegal field ordering: " + id); } FldDef f = new FldDef(id, attrName, typeName, arrayDim); cd.fields.add(f); } //readln("</class>"); } //insert schema in database HashMap<Long, ZooClass> definedClasses = new HashMap<Long, ZooClass>(); while (!classes.isEmpty()) { Iterator<ClsDef> itCD = classes.values().iterator(); ClsDef cd = itCD.next(); //50/51 are ZooPC and PersistenceCapableImpl while (!definedClasses.containsKey(cd.superOid) && cd.superOid != 50) { //declare super-class first cd = classes.get(cd.superOid); } //Some schemata are predefined ... ZooClass schema = ZooJdoHelper.schema(pm).getClass(cd.name); if (schema == null) { ZooClass scd = definedClasses.get(cd.superOid); schema = ZooJdoHelper.schema(pm).defineEmptyClass(cd.name, scd); cd.needsFieldDeclarations = true; } classes.remove(cd.oid); definedClasses.put(cd.oid, schema); cache.addSchema(cd.oid, ((ZooClassProxy)schema).getSchemaDef()); } //add attributes for (ClsDef cd: classNames.values()) { if (!cd.needsFieldDeclarations) { continue; } ZooClass schema = cache.getSchema(cd.oid).getVersionProxy(); for (FldDef f: cd.fields) { if (classNames.containsKey(f.name)) { ClsDef cdType = classNames.get(f.name); ZooClass type = cache.getSchema(cdType.oid).getVersionProxy(); schema.addField(f.name, type, f.arrayDim); System.out.println("class found for: " + f.typeName + " : " + type.getName()); } else { Class<?> cls = createArrayClass(f.arrayDim, f.typeName); schema.addField(f.name, cls); } } } XmlReader r = new XmlReader(scanner); DataDeSerializer ser = new DataDeSerializer(r, cache); readln1("<data>"); while (readln1("<class", "</data>")) { long sOid = Long.parseLong(readValue1("oid")); readValue1("name"); ZooClass cls = definedClasses.get(sOid); while (readln1("<object", "</class>")) { String oidStr = readValue1("oid"); long oid = Long.parseLong(oidStr); GOProxy hdl = cache.findOrCreateGo(oid, cls); ser.readGenericObject(sOid, hdl); readln1("</object>"); } //readln("</class>"); } //readln("</data>"); readln1("</database>"); } private static Class<?> createArrayClass(int dims, String innerType) { try { // char[] ca = new char[dims]; // Arrays.fill(ca, '['); // Class<?> compClass = Class.forName(String.valueOf(ca) + innerType); Class<?> compClass = Class.forName(innerType); return compClass; } catch (ClassNotFoundException e) { //throw new RuntimeException(e); //uhh, exceptions in normal code-flow, nice :-) } Class<?> c = SerializerTools.getPrimitiveType(innerType); if (c == null) { throw new IllegalArgumentException("Type not found: " + innerType); } // if (dims > 0) { // int[] dimDummy = new int[dims]; // Arrays.fill(dimDummy, 1); // c = Array.newInstance(c, dimDummy).getClass(); // } return c; } private static Scanner openFile(String xmlName) { File file = new File(xmlName); if (!file.exists()) { System.out.println("File not found: " + file); return null; } try { FileInputStream fis = new FileInputStream(file); return new Scanner(fis, "UTF-8"); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } /** * Read a value, e.g. class="x.y" return "x.y" for read("class"). * @param name * @return value. */ private String readValue1(String name) { String in = scanner.next(); if (!in.startsWith(name)) { throw new IllegalStateException("Expected " + name + " but got " + in); } if (in.endsWith(">")) { return in.substring(name.length() + 2, in.length()-2); } else { return in.substring(name.length() + 2, in.length()-1); } } // private String readValueM(String name) { // // //TODO // //TODO read multi! // //TODO // //TODO // String in = scanner.next(); // if (!in.startsWith(name)) { // throw new IllegalStateException("Expected " + name + " but got " + in); // } // if (in.endsWith(">")) { // return in.substring(name.length() + 2, in.length()-2); // } else { // return in.substring(name.length() + 2, in.length()-1); // } // } private void readln1(String str) { String s2 = scanner.next(); if (!s2.equals(str)) { throw new IllegalStateException("Expected: " + str + " but got: " + s2); } } private void readlnM(String str) { Scanner scStr = new Scanner(str); while (scStr.hasNext()) { String s1 = scStr.next(); String s2 = scanner.next(); if (!s2.equals(s1)) { scStr.close(); throw new IllegalStateException("Expected: " + str + " but got: " + s2); } } scStr.close(); } /** * Reads '1' token. * @param strExpected * @param strAlternative * @return true if 1st string matches, or false if second matches * @throws IllegalStateException if neither String matches */ private boolean readln1(String strExpected, String strAlternative) { String sX = scanner.next(); if (sX.equals(strExpected)) { return true; } if (sX.equals(strAlternative)) { return false; } throw new IllegalStateException("Expected: " + strAlternative + " but got: " + sX); } /** * Reads multiple tokens. * @param strExpected * @param strAlternative * @return true if 1st string matches, or false if second matches * @throws IllegalStateException if neither String matches */ // private boolean readlnM(String strExpected, String strAlternative) { // Scanner scStr1 = new Scanner(strExpected); // Scanner scStr2 = new Scanner(strAlternative); // while (scStr1.hasNext()) { // String s1 = scStr1.next(); // String s2 = null; // if (scStr2.hasNext()) { // s2 = scStr2.next(); // } // String sX = scanner.next(); // if (!sX.equals(s1)) { // if (sX.equals(s2)) { // while (scStr2.hasNext()) { // s2 = scStr2.next(); // sX = scanner.next(); // if (!sX.equals(s2)) { // scStr1.close(); // scStr2.close(); // throw new IllegalStateException( // "Expected: " + strAlternative + " but got: " + sX); // } // } // scStr1.close(); // scStr2.close(); // return false; // } else { // scStr1.close(); // scStr2.close(); // throw new IllegalStateException("Expected: " + strExpected + " but got: " + sX); // } // } // } // scStr1.close(); // scStr2.close(); // return true; // } }