package de.kompf.javaxml;

import java.io.*;

import javax.xml.stream.*;

/**
 * This program demonstrates the production of XML files using XMLStreamWriter
 * from the StAX API. It writes an Atom feed with some news.
 * 
 * @author Kompf
 * 
 */
public class AtomFeedStreamWriter {

  private static final String URI_NS_ATOM = "http://www.w3.org/2005/Atom";
  private static final String URI_NS_XHTML = "http://www.w3.org/1999/xhtml";

  private XMLStreamWriter writer;

  private String updated;

  /**
   * Open the writer.
   * 
   * @param file The file to write.
   */
  public void openWriter(File file) throws FileNotFoundException,
      XMLStreamException, FactoryConfigurationError {
    // create a XMLStreamWriter
    FileOutputStream fos = new FileOutputStream(file);
    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    // not needed in this example:
    //outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
    writer = outputFactory.createXMLStreamWriter(fos, "UTF-8");
  }

  /**
   * Close the writer.
   */
  public void closeWriter() throws XMLStreamException {
    writer.close();
  }

  /**
   * Write the start of the feed.
   */
  public void writeFeedStart(String title, String link, String author,
      String updated) throws XMLStreamException {
    this.updated = updated;

    writer.setDefaultNamespace(URI_NS_ATOM);
    writer.writeStartDocument("UTF-8", "1.0");
    writer.writeCharacters("\n");
    writer.writeStartElement(URI_NS_ATOM, "feed");
    writer.writeDefaultNamespace(URI_NS_ATOM);
    writer.writeCharacters("\n");

    writeElementWithText("title", title);
    writer.writeEmptyElement(URI_NS_ATOM, "link");
    writer.writeAttribute("href", link);
    writer.writeCharacters("\n");
    writeElementWithText("updated", updated);
    writer.writeStartElement(URI_NS_ATOM, "author");
    writer.writeCharacters("\n");
    writeElementWithText("name", author);
    writer.writeEndElement(); // author
    writer.writeCharacters("\n");
    writeElementWithText("id", link);
  }

  /**
   * Write the end of the feed.
   */
  public void writeFeedEnd() throws XMLStreamException {
    writer.writeEndElement(); // feed
    writer.writeCharacters("\n");
    writer.writeEndDocument();
  }

  /**
   * Write one entry.
   */
  public void writeEntry(String title, String link) throws XMLStreamException {
    writeEntry(title, link, null);
  }

  /**
   * Write one entry with content.
   */
  public void writeEntry(String title, String link, String content)
      throws XMLStreamException {
    writer.writeStartElement(URI_NS_ATOM, "entry");
    writer.writeCharacters("\n");
    writeElementWithText("title", title);
    writer.writeEmptyElement(URI_NS_ATOM, "link");
    writer.writeAttribute("href", link);
    writer.writeCharacters("\n");
    writeElementWithText("id", link);
    writeElementWithText("updated", updated);
    if (content != null && content.length() > 0) {
      writeXHTMLContent(title, content);
    }
    writer.writeEndElement(); // entry
    writer.writeCharacters("\n");
  }

  /**
   * Output an element that contains a text node.
   * 
   * @param elName The name of the element.
   * @param text The text.
   * @throws XMLStreamException
   */
  private void writeElementWithText(String elName, String text)
      throws XMLStreamException {
    writer.writeStartElement(URI_NS_ATOM, elName);
    writer.writeCharacters(text);
    writer.writeEndElement();
    writer.writeCharacters("\n");
  }

  /**
   * Write title and content using XHTML format.
   * 
   * @throws XMLStreamException
   */
  private void writeXHTMLContent(String title, String content)
      throws XMLStreamException {
    writer.writeStartElement(URI_NS_ATOM, "content");
    writer.writeAttribute("type", "xhtml");
    writer.writeCharacters("\n");
    writer.setPrefix("xh", URI_NS_XHTML);
    writer.writeStartElement(URI_NS_XHTML, "div");
    writer.writeNamespace("xh", URI_NS_XHTML);
    writer.writeCharacters("\n");
    writer.writeStartElement(URI_NS_XHTML, "h1");
    writer.writeCharacters(title);
    writer.writeEndElement(); // h1
    writer.writeCharacters("\n");
    writer.writeCharacters(content);
    writer.writeCharacters("\n");
    writer.writeEndElement(); // div
    writer.writeCharacters("\n");
    writer.writeEndElement(); // content
    writer.writeCharacters("\n");
  }

  /**
   * MAIN.
   * 
   * @param args ignored
   */
  public static void main(String[] args) throws Exception {
    File atomFile = new File("mynews.xml");
    AtomFeedStreamWriter aw = new AtomFeedStreamWriter();

    aw.openWriter(atomFile);
    try {
      aw.writeFeedStart("kompf.de News", "http://www.kompf.de", "Martin Kompf",
          "2010-05-06T18:30:00+02:00");

      aw.writeEntry("Neue Version des << GPX Track Viewers >>",
          "http://www.kompf.de/trekka/");
      aw
          .writeEntry(
              "Neuer Artikel AtomFeedStreamWriter",
              "http://www.kompf.de/java/jaxpstreamwriter.html",
              "Die Java Streaming API für XML (StAX) eignet sich nicht nur zum Parsen, sondern auch zum Schreiben von XML Dokumenten.");

      aw.writeFeedEnd();
    } finally {
      aw.closeWriter();
    }

    System.out.println("Atom file created: " + atomFile.getAbsolutePath());
  }

}

