import java.util.Vector;
import java.util.Enumeration;
import java.io.PrintWriter;
import java.io.OutputStream;

import java.io.ByteArrayInputStream;

import java.io.IOException;
import java.io.File;
import java.net.URL;
import java.net.URLConnection;

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xpath.XPathAPI;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.DOMBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;

import org.w3c.dom.Attr;

// Imported JAVA API for XML Parsing 1.0 classes
import javax.xml.parsers.DocumentBuilder;
import org.apache.xml.utils.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; 

import  org.apache.xml.serialize.OutputFormat;
import  org.apache.xml.serialize.Serializer;
import  org.apache.xml.serialize.SerializerFactory;
import  org.apache.xml.serialize.XMLSerializer;
import  java.io.StringWriter;
import  org.apache.xml.serialize.EncodingInfo;

import  java.io.BufferedOutputStream;
import  java.io.ObjectOutputStream;

import  java.io.BufferedInputStream;
import  java.io.ObjectInputStream;
import  java.io.File;
import  java.util.StringTokenizer;

public class Main
{
	public static void main(String[] args)
	{
		String inputfilename	=	args[0];
		long	m_Before	=	System.currentTimeMillis();
		
		File	f	=	new File(inputfilename);
		try{
			System.out.println(f.getName());
			StringTokenizer	st	=	new StringTokenizer(f.getName(), ".");
			String Basename		=	st.nextToken();
			String outputfilename	=	Basename+".bin";
			Document doc	=	loadDocument(f.toURL(), true);
			System.out.println("Read XML DOM in " +(System.currentTimeMillis()-m_Before)+" ms");
			
			//System.out.println(xmlString(doc));
			
			m_Before	=	System.currentTimeMillis();
			// Open file to serialize to
			FileOutputStream file = new FileOutputStream(outputfilename);
			BufferedOutputStream bout = new BufferedOutputStream(file);
			ObjectOutputStream out = new ObjectOutputStream(bout);
			out.writeObject(doc);
			out.flush();
			out.close();
			System.out.println("Written binary DOM in " +(System.currentTimeMillis()-m_Before)+" ms");
		
			m_Before	=	System.currentTimeMillis();
			// Open file to serialize to
			FileInputStream infile = new FileInputStream(outputfilename);
			BufferedInputStream bin = new BufferedInputStream(infile);
			ObjectInputStream in = new ObjectInputStream(bin);
			Object obj	=	in.readObject();
			doc	=	(Document)obj;
			System.out.println("Read binary DOM in " + (System.currentTimeMillis()-m_Before)+" ms");

			//System.out.println(xmlString(doc));
			m_Before	=	System.currentTimeMillis();
			outputfilename	=	Basename+".bak";
			saveDocument(doc, outputfilename);
			System.out.println("Written XML DOM in " + (System.currentTimeMillis()-m_Before)+" ms");
		}
		catch(Exception e)
		{
			System.out.println(e.toString());
			e.printStackTrace();
		}
	}
	
	public static String xmlString(Document doc) throws IOException
	{
		OutputFormat    format  =	new OutputFormat(doc);	//Serialize DOM
		format.setEncoding("UTF-8");
		format.setIndent(3);
		format.setIndenting(true);
		format.setLineWidth(80);
		format.setLineSeparator("\r\n");
		StringWriter  stringOut =	new StringWriter();		//Writer will be a String
		XMLSerializer    serial =	new XMLSerializer(stringOut, format);
		serial.asDOMSerializer();							// As a DOM Serializer
		serial.serialize(doc.getDocumentElement());
		return stringOut.toString();						//Spit out DOM as a String
	}
	
    public static synchronized boolean saveDocument(Document document, String filename)
        throws Exception
    {
        if (document == null || filename == null) 
		{
			System.out.println("No filename or document");
            return false;
        }
		PrintWriter	writer = new PrintWriter(new FileOutputStream(filename));
		writer.println(xmlString(document));
        writer.flush();
        return true;
    } 

    public static synchronized Document loadDocument(URL url, boolean Validate)
        throws Exception
    {
		/** Namespaces feature id (http://xml.org/sax/features/namespaces). */
		String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
		    
		/** Validation feature id (http://xml.org/sax/features/validation). */
		String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";

		/** Schema validation feature id (http://apache.org/xml/features/validation/schema). */
		String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema";

		// property ids

		/** Lexical handler property id (http://xml.org/sax/properties/lexical-handler). */
		String LEXICAL_HANDLER_PROPERTY_ID = "http://xml.org/sax/properties/lexical-handler";

		// default settings

		/** Default parser name. */
		String DEFAULT_PARSER_NAME = "Xerces";

		/** Default namespaces support (true). */
		boolean DEFAULT_NAMESPACES = true;

		/** Default validation support (false). */
		boolean DEFAULT_VALIDATION = false;
		    
		/** Default Schema validation support (true). */
		boolean DEFAULT_SCHEMA_VALIDATION = true;

		/** Default canonical output (false). */
		boolean DEFAULT_CANONICAL = false;

		ParserWrapper parser	=	null;//new Xerces();
        // create parser
        try {
            parser = (ParserWrapper)Class.forName(DEFAULT_PARSER_NAME).newInstance();
        }
        catch (Exception e) {
            System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
            return null;
        }
		try {
            parser.setFeature(NAMESPACES_FEATURE_ID, true);
		}
		catch (SAXException e) {
			System.err.println("warning: Parser does not support feature ("+VALIDATION_FEATURE_ID+")");
		}

		try {
			parser.setFeature(VALIDATION_FEATURE_ID, Validate);
		}
		catch (SAXException e) {
			System.err.println("warning: Parser does not support feature ("+VALIDATION_FEATURE_ID+")");
		}

		try {
			parser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
		}
		catch (SAXException e) {
			System.err.println("warning: Parser does not support feature ("+SCHEMA_VALIDATION_FEATURE_ID+")");
		}
		
		return parser.parse(url.toString());
    }
}
