package com.alethis.xml;

import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import org.xml.sax.ErrorHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;

public class GenerateUsingXMLReader {
    
    private final static String OUTPUT_FILE = "C:\\project\\xml\\out.xml";
    
    public final static void main(String[] args) {   
        try {
            XMLReader generator = new GeneratorUsingXMLReader();
            SAXSource source = new SAXSource(generator, new InputSource());

            File f = new File(OUTPUT_FILE);
            FileWriter fw = new FileWriter(f);
            BufferedWriter bw = new BufferedWriter(fw);
            StreamResult result = new StreamResult(bw);

            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();      
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.transform(source, result);
            
            System.out.println("DONE");
        }
        catch (TransformerConfigurationException e) {
            System.out.println("Transformer Configuration Exception: " + e.getMessage());
        }
        catch (TransformerException e) {
            System.out.println("Transformer Exception: " + e.getMessage());
        }
        catch (IOException e) {
            System.out.println("IO Exception: " + e.getMessage());
        }           
    }    
}

abstract class XMLReaderImpl implements XMLReader {

    protected ContentHandler handler;
    
    protected abstract void generate() throws SAXException;
    
    public void parse(InputSource input) throws IOException, SAXException {
        generate();
    }
    
    public void parse(String systemId) throws IOException, SAXException {
    }
    
    public void setContentHandler(ContentHandler handler) {
        this.handler = handler;
    } 

    public ContentHandler getContentHandler() {
        return this.handler;
    } 

    public void setErrorHandler(ErrorHandler handler) { 
    }
    
    public ErrorHandler getErrorHandler() { 
        return null; 
    }
    
    public void setDTDHandler(DTDHandler handler) { 
    }
    
    public DTDHandler getDTDHandler() { 
        return null;
    }
    
    public void setEntityResolver(EntityResolver resolver) { 
    }
    
    public EntityResolver getEntityResolver() { 
        return null; 
    }
    
    public void setProperty(java.lang.String name, java.lang.Object value) { 
    }
    
    public Object getProperty(java.lang.String name) { 
        return null; 
    }
    
    public void setFeature(java.lang.String name, boolean value) { 
    }
    
    public boolean getFeature(java.lang.String name) { 
        return false; 
    }
}
    
class GeneratorUsingXMLReader extends XMLReaderImpl {
    
    private final static Attributes EMPTY_ATTRS = new AttributesImpl();
    
    private final static String FAMILY = "family";
    private final static String FATHER = "father";
    private final static String MOTHER = "mother";
    private final static String CHILDREN = "children";
    private final static String CHILD = "child";
    
    private final static String AGE = "age";
    
    protected void generate() throws SAXException {
        handler.startDocument();
        
        handler.startElement("", FAMILY, FAMILY, EMPTY_ATTRS);
        
        addElement(FATHER, "Michael Boyle", "49");
        addElement(MOTHER, "Margaret Maclure", "46");
        
        handler.startElement("", CHILDREN, CHILDREN, EMPTY_ATTRS);
        addElement(CHILD, "Chloe Boyle", "12");
        addElement(CHILD, "Adrian Boyle", "10");
        handler.endElement("", CHILDREN, CHILDREN);
        
        handler.endElement("", FAMILY, FAMILY);

        handler.endDocument();
    }
    
    private void addElement(String element, String name, String age) throws SAXException {
        AttributesImpl ageAttrs = new AttributesImpl();
        ageAttrs.addAttribute("", AGE, AGE, "CDATA", age);
        handler.startElement("", element, element, ageAttrs);
        handler.characters(name.toCharArray(), 0, name.length());
        handler.endElement("", element, element);
    }
}