// Copyright FreeHEP, 2007 package hep.aida.ref.xml; import hep.aida.IAnalysisFactory; import hep.aida.ICloud1D; import hep.aida.ICloud2D; import hep.aida.ICloud3D; import hep.aida.IDataPointSet; import hep.aida.IHistogram1D; import hep.aida.IHistogram2D; import hep.aida.IHistogram3D; import hep.aida.IManagedObject; import hep.aida.IProfile1D; import hep.aida.IProfile2D; import hep.aida.ITree; import hep.aida.ITreeFactory; import hep.aida.ITuple; import hep.aida.ref.AidaUtils; import hep.aida.test.AidaTestCase; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.freehep.util.argv.ArgumentFormatException; import org.freehep.util.argv.ArgumentParser; import org.freehep.util.argv.BooleanOption; import org.freehep.util.argv.MissingArgumentException; import org.freehep.util.argv.StringOption; import org.freehep.util.argv.StringParameter; import de.schlichtherle.io.File; import de.schlichtherle.io.FileOutputStream; import de.schlichtherle.io.FileWriter; /** * Writes AIDA Tree to zip archive. * * @author serbo * @author Mark Donszelmann * @version $Id: AidaZipXMLWriter.java 13360 2007-10-02 23:13:06Z serbo $ */ public class AidaZipXMLWriter { private static String dirType = "dir"; protected String[] skip; protected boolean binary; protected List list; protected File root; public static void main(String[] args) throws Exception { BooleanOption helpOpt = new BooleanOption("-help", "-h", "Show this help page", true); BooleanOption verboseOpt = new BooleanOption("-verbose", "-v", "Set verbose output", false); BooleanOption overWriteOpt = new BooleanOption("-overwrite", "-o", "Overwrite existing output file", false); BooleanOption binaryOpt = new BooleanOption("-binary", "-b", "Write in binary format (if available)", false); BooleanOption zipOpt = new BooleanOption("-zip", "-z", "Write in zip format (.zip)", false); BooleanOption compressOpt = new BooleanOption("-compress", "-c", "Write in compressed format (.gz or .zip)", false); BooleanOption verifyOpt = new BooleanOption("-verify", "-d", "Check for diffs between input and output", false); StringOption storeType = new StringOption("-type", "-t", "Store_Type", "xml", "Type of the file: xml, hbook, root, etc."); StringOption skipTypes = new StringOption("-skip", "-s", "ITuple,ICloud2D", null, "AIDA Object Types to skip during conversion: comma-separated list, no spaces"); StringParameter sourceFile = new StringParameter("inputFile", "Path to the input file (aida, hbook, root)"); StringParameter dstFile = new StringParameter("outputFile", "Path to the output file"); String originalFileType = "xml"; String[] skip = null; boolean overWrite = false; boolean verbose = false; boolean binary = false; boolean zip = false; boolean compress = false; boolean verify = false; ArgumentParser cl = new ArgumentParser("AidaZipXMLWriter "); cl.add(helpOpt); cl.add(verboseOpt); cl.add(overWriteOpt); cl.add(binaryOpt); cl.add(zipOpt); cl.add(compressOpt); cl.add(verifyOpt); cl.add(storeType); cl.add(skipTypes); cl.add(sourceFile); cl.add(dstFile); try { List extra = cl.parse(args); if (!extra.isEmpty() || helpOpt.getValue()) { cl.printUsage(System.out); return; } verbose = verboseOpt.getValue(); if (storeType.getValue() != null && !storeType.getValue().trim().equals("")) originalFileType = storeType.getValue(); String skipString = skipTypes.getValue(); if (skipString != null && !skipString.trim().equals("")) { Map map = AidaUtils.parseOptions(skipString); if (map.size() > 0) { skip = new String[map.size()]; skip = (String[]) map.keySet().toArray(skip); } } overWrite = overWriteOpt.getValue(); binary = binaryOpt.getValue(); compress = compressOpt.getValue(); zip = zipOpt.getValue(); verify = verboseOpt.getValue(); // End of argument parsing File inFile = new File(sourceFile.getValue()); if (!inFile.exists()) { throw new IOException("Input file does not exist: " + sourceFile.getValue()); } File outFile = new File(dstFile.getValue()); if (!overWrite && outFile.exists()) { throw new IOException("Output file already exists: " + dstFile.getValue()); } if (verbose) { System.out.println("Will convert: " + originalFileType + " file into AIDA " + (binary ? "(Binary) " : "") + "XML"); System.out.println("\tInput File: " + inFile.getPath()); System.out.println("\tInput File Type: " + originalFileType); System.out.println("\tOutput File: " + outFile.getPath()); String tmpSkip = null; if (skip != null && skip.length > 0) { tmpSkip = "\n"; for (int i = 0; i < skip.length; i++) tmpSkip += "\t\t\t " + skip[i] + "\n"; } System.out.println("\tSkip AIDA types: " + tmpSkip); } long t0 = System.currentTimeMillis(); IAnalysisFactory af = IAnalysisFactory.create(); ITreeFactory tf = af.createTreeFactory(); ITree srcTree = tf.create(sourceFile.getValue(), originalFileType, true, false); int srcLength = srcTree.listObjectTypes("/", true).length; System.err.println("Reading "+srcLength+" records."); System.err.println("Total time to read: " + ((System.currentTimeMillis() - t0) / 1000) + " s."); t0 = System.currentTimeMillis(); AidaXMLStore store = new AidaXMLStore(); store.commit(srcTree, outFile, skip, zip, compress, binary); System.err.println("Total time to write: " + ((System.currentTimeMillis() - t0) / 1000) + " s."); if (verify) { t0 = System.currentTimeMillis(); ITree dstTree = tf.create(dstFile.getValue(), originalFileType); System.err.println("Verifying "+dstTree.listObjectNames("/", true).length+" records."); // System.err.println("And again "+dstTree.listObjectNames("/", true).length+" records."); // assertEquals(srcTree, dstTree); System.err.println("Total time to verify: " + ((System.currentTimeMillis() - t0) / 1000) + " s."); } } catch (MissingArgumentException mae) { System.out.println(mae.getMessage()); System.exit(1); } catch (ArgumentFormatException afe) { System.out.println(afe.getMessage()); System.exit(1); } catch (Exception e) { if (verbose) { System.out.println("ERROR: " + e.getMessage()); e.printStackTrace(); } else throw e; } } // FIXME, move to aida-test private static void assertEquals(ITree dstTree, ITree srcTree) { String[] names = srcTree.listObjectNames("/", true); // same number of objects ? TestCase.assertEquals(dstTree.listObjectNames("/", true).length, names.length); // objects the same ? for (int i = 0; i < names.length; i++) { if (!names[i].endsWith("/")) { IManagedObject dstObject = dstTree.find(names[i]); IManagedObject srcObject = srcTree.find(names[i]); AidaTestCase.assertEquals(dstObject.getClass(), srcObject .getClass()); AidaTestCase.assertEquals(dstObject, srcObject); if (dstObject instanceof ITuple) { AidaTestCase.assertEquals((ITuple) dstObject, (ITuple) srcObject); } else if (dstObject instanceof IDataPointSet) { AidaTestCase.assertEquals((IDataPointSet) dstObject, (IDataPointSet) srcObject); } else if (dstObject instanceof IHistogram1D) { AidaTestCase.assertEquals((IHistogram1D) dstObject, (IHistogram1D) srcObject); } else if (dstObject instanceof IHistogram2D) { AidaTestCase.assertEquals((IHistogram2D) dstObject, (IHistogram2D) srcObject); } else if (dstObject instanceof IHistogram3D) { AidaTestCase.assertEquals((IHistogram3D) dstObject, (IHistogram3D) srcObject); } else if (dstObject instanceof ICloud1D) { AidaTestCase.assertEquals((ICloud1D) dstObject, (ICloud1D) srcObject); } else if (dstObject instanceof ICloud2D) { AidaTestCase.assertEquals((ICloud2D) dstObject, (ICloud2D) srcObject); } else if (dstObject instanceof ICloud3D) { AidaTestCase.assertEquals((ICloud3D) dstObject, (ICloud3D) srcObject); } else if (dstObject instanceof IProfile1D) { AidaTestCase.assertEquals((IProfile1D) dstObject, (IProfile1D) srcObject); } else if (dstObject instanceof IProfile2D) { AidaTestCase.assertEquals((IProfile2D) dstObject, (IProfile2D) srcObject); } else { AidaTestCase.fail("IManagedObject of unknown class: " + dstObject.getClass()); } } } } AidaZipXMLWriter(File file) throws IOException { this(file, null); } AidaZipXMLWriter(File file, String[] skip) throws IOException { this(file, true, skip); } AidaZipXMLWriter(File file, boolean binary, String[] skip) throws IOException { this.root = file; this.binary = binary; this.skip = skip; list = new ArrayList(); } void toXML(ITree tree) { String[] objNames = tree.listObjectNames("/", true); String[] objTypes = null; if (skip != null && skip.length > 0) objTypes = tree.listObjectTypes("/", true); for (int i = 0; i < objNames.length; i++) { // Skip writing some types to file if (skip != null && skip.length > 0 && AidaUtils.findInArray(objTypes[i], skip) >= 0) continue; int pos = objNames[i].lastIndexOf('/'); String objPath = null; IManagedObject mo = null; // For directories if ((pos + 1) == objNames[i].length()) { String tmp = objNames[i].substring(0, pos); int pos2 = tmp.lastIndexOf('/'); objPath = tmp.substring(0, pos2 + 1); String objName = objNames[i].substring(pos2 + 1); mo = new DirectoryObject(objName); // For other objects } else { objPath = objNames[i].substring(0, pos + 1); mo = tree.find(objNames[i]); } toXML(mo, objPath); } } // "path" is the directory where to put this IManagedObject, must end with // "/" void toXML(IManagedObject mo, String path) { // Skip writing some types to file if (mo != null && skip != null && skip.length > 0 && AidaUtils.findInArray(mo.type(), skip) >= 0) return; String fullPath = path + mo.name(); boolean isDirectory = mo.type().equalsIgnoreCase(dirType); // handle types if (isDirectory) { if (fullPath.endsWith("/")) { fullPath = fullPath.substring(0, fullPath.length()-1); } } else { fullPath = fullPath + "." + mo.type(); } String zipPath = fullPath; if (zipPath.startsWith("/")) zipPath = zipPath.substring(1); // System.err.println(zipPath); // write data try { File file = new File(root, zipPath); if (isDirectory) { file.mkdirs(); } else { AidaXMLWriter axw = null; try { if (binary) { OutputStream os = new BufferedOutputStream( new FileOutputStream(file)); list.add(os); axw = new AidaXMLWriter(new DataOutputStream(os)); } else { Writer writer = new BufferedWriter(new FileWriter(file)); list.add(writer); axw = new AidaXMLWriter(writer); } axw.toXML(mo, path); } catch (Exception e) { System.out.println("Error writing element: " + fullPath + ", " + mo.type()); e.printStackTrace(); } if (axw != null) { axw.close(); } } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void close() throws IOException { root = null; for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); if (obj instanceof Writer) ((Writer) obj).close(); else if (obj instanceof OutputStream) ((OutputStream) obj).close(); } list.clear(); } class DirectoryObject extends hep.aida.ref.ManagedObject { DirectoryObject(String name) { super(name); } public String type() { return dirType; } } }