XML Java

/*
   This program is a part of the companion code for Core Java 8th ed.
   (http://horstmann.com/corejava)
   This program 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.
   This program 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 this program.  If not, see .
*/
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
 * This program shows how to write an XML file. It saves a file describing a modern drawing in SVG
 * format.
 * @version 1.10 2004-09-04
 * @author Cay Horstmann
 */
public class XMLWriteTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               XMLWriteFrame frame = new XMLWriteFrame();
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.setVisible(true);
            }
         });
   }
}
/**
 * A frame with a component for showing a modern drawing.
 */
class XMLWriteFrame extends JFrame
{
   public XMLWriteFrame()
   {
      setTitle("XMLWriteTest");
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
      chooser = new JFileChooser();
      // add component to frame
      comp = new RectangleComponent();
      add(comp);
      // set up menu bar
      JMenuBar menuBar = new JMenuBar();
      setJMenuBar(menuBar);
      JMenu menu = new JMenu("File");
      menuBar.add(menu);
      JMenuItem newItem = new JMenuItem("New");
      menu.add(newItem);
      newItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               comp.newDrawing();
            }
         });
      JMenuItem saveItem = new JMenuItem("Save with DOM/XSLT");
      menu.add(saveItem);
      saveItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               try
               {
                  saveDocument();
               }
               catch (Exception e)
               {
                  JOptionPane.showMessageDialog(XMLWriteFrame.this, e.toString());
               }
            }
         });
      JMenuItem saveStAXItem = new JMenuItem("Save with StAX");
      menu.add(saveStAXItem);
      saveStAXItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               try
               {
                  saveStAX();
               }
               catch (Exception e)
               {
                  JOptionPane.showMessageDialog(XMLWriteFrame.this, e.toString());
               }
            }
         });
      JMenuItem exitItem = new JMenuItem("Exit");
      menu.add(exitItem);
      exitItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               System.exit(0);
            }
         });
   }
   /**
    * Saves the drawing in SVG format, using DOM/XSLT
    */
   public void saveDocument() throws TransformerException, IOException
   {
      if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return;
      File f = chooser.getSelectedFile();
      Document doc = comp.buildDocument();
      Transformer t = TransformerFactory.newInstance().newTransformer();
      t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
            "http://www.w3.org/TR/2000/CR-SVG-20000802/DTD/svg-20000802.dtd");
      t.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD SVG 20000802//EN");
      t.setOutputProperty(OutputKeys.INDENT, "yes");
      t.setOutputProperty(OutputKeys.METHOD, "xml");
      t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
      t.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(f)));
   }
   
   /**
    * Saves the drawing in SVG format, using StAX
    */
   public void saveStAX() throws FileNotFoundException, XMLStreamException
   {
      if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return;
      File f = chooser.getSelectedFile();
      XMLOutputFactory factory = XMLOutputFactory.newInstance();
      XMLStreamWriter writer = factory.createXMLStreamWriter(new FileOutputStream(f));
      comp.writeDocument(writer);
      writer.close();
   }
   public static final int DEFAULT_WIDTH = 300;
   public static final int DEFAULT_HEIGHT = 200;
   private RectangleComponent comp;
   private JFileChooser chooser;
}
/**
 * A component that shows a set of colored rectangles
 */
class RectangleComponent extends JComponent
{
   public RectangleComponent()
   {
      rects = new ArrayList();
      colors = new ArrayList();
      generator = new Random();
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      try
      {
         builder = factory.newDocumentBuilder();
      }
      catch (ParserConfigurationException e)
      {
         e.printStackTrace();
      }
   }
   /**
    * Create a new random drawing.
    */
   public void newDrawing()
   {
      int n = 10 + generator.nextInt(20);
      rects.clear();
      colors.clear();
      for (int i = 1; i <= n; i++)
      {
         int x = generator.nextInt(getWidth());
         int y = generator.nextInt(getHeight());
         int width = generator.nextInt(getWidth() - x);
         int height = generator.nextInt(getHeight() - y);
         rects.add(new Rectangle(x, y, width, height));
         int r = generator.nextInt(256);
         int g = generator.nextInt(256);
         int b = generator.nextInt(256);
         colors.add(new Color(r, g, b));
      }
      repaint();
   }
   public void paintComponent(Graphics g)
   {
      if (rects.size() == 0) newDrawing();
      Graphics2D g2 = (Graphics2D) g;
      // draw all rectangles
      for (int i = 0; i < rects.size(); i++)
      {
         g2.setPaint(colors.get(i));
         g2.fill(rects.get(i));
      }
   }
   /**
    * Creates an SVG document of the current drawing.
    * @return the DOM tree of the SVG document
    */
   public Document buildDocument()
   {
      Document doc = builder.newDocument();
      Element svgElement = doc.createElement("svg");
      doc.appendChild(svgElement);
      svgElement.setAttribute("width", "" + getWidth());
      svgElement.setAttribute("height", "" + getHeight());
      for (int i = 0; i < rects.size(); i++)
      {
         Color c = colors.get(i);
         Rectangle2D r = rects.get(i);
         Element rectElement = doc.createElement("rect");
         rectElement.setAttribute("x", "" + r.getX());
         rectElement.setAttribute("y", "" + r.getY());
         rectElement.setAttribute("width", "" + r.getWidth());
         rectElement.setAttribute("height", "" + r.getHeight());
         rectElement.setAttribute("fill", colorToString(c));
         svgElement.appendChild(rectElement);
      }
      return doc;
   }
   /**
    * Writers an SVG document of the current drawing.
    * @param writer the document destination
    */
   public void writeDocument(XMLStreamWriter writer) throws XMLStreamException
   {
      writer.writeStartDocument();
      writer.writeDTD("            + "\"http://www.w3.org/TR/2000/CR-SVG-20000802/DTD/svg-20000802.dtd\">");
      writer.writeStartElement("svg");
      writer.writeAttribute("width", "" + getWidth());
      writer.writeAttribute("height", "" + getHeight());
      for (int i = 0; i < rects.size(); i++)
      {
         Color c = colors.get(i);
         Rectangle2D r = rects.get(i);
         writer.writeEmptyElement("rect");
         writer.writeAttribute("x", "" + r.getX());
         writer.writeAttribute("y", "" + r.getY());
         writer.writeAttribute("width", "" + r.getWidth());
         writer.writeAttribute("height", "" + r.getHeight());
         writer.writeAttribute("fill", colorToString(c));         
      }
      writer.writeEndDocument(); // closes svg element
   }  
   
   /**
    * Converts a color to a hex value.
    * @param c a color
    * @return a string of the form #rrggbb
    */
   private static String colorToString(Color c)
   {
      StringBuffer buffer = new StringBuffer();
      buffer.append(Integer.toHexString(c.getRGB() & 0xFFFFFF));
      while (buffer.length() < 6)
         buffer.insert(0, '0');
      buffer.insert(0, '#');
      return buffer.toString();
   }
   private ArrayList rects;
   private ArrayList colors;
   private Random generator;
   private DocumentBuilder builder;
}