CODEFETCH™
            Examples
Cache of Code/Ch23/Sketcher with XML/Element.java from
http://media.wiley.com/product_ancillary/44/07645687/DOWNLOAD/Beg_Java_Code.zip
Source code below from:
Ivor Horton's Beginning Java 2, JDK 5 Edition
By Ivor Horton
Published 31 December, 2004
Average rating

      Powells     Alibris


import java.awt.Color;
import java.awt.Shape;
import java.awt.Point;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.GeneralPath; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.PathIterator;

import java.util.Vector;

import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import org.w3c.dom.Document;
import org.w3c.dom.Attr;

public abstract class Element implements Serializable {
  public Element(Color color) {
    this.color = color;  
  }

  // Constrcutor to initialize fields from XML document
  protected Element(org.w3c.dom.Element xmlElement) {
    // Get the <color> element
    org.w3c.dom.NodeList list = xmlElement.getElementsByTagName("color");
    setElementColor((org.w3c.dom.Element)list.item(0));        // Set the color

    list = xmlElement.getElementsByTagName("position");        // Get <position>
    setElementPosition((org.w3c.dom.Element)list.item(0));     // Set the position

    angle = Double.parseDouble(xmlElement.getAttribute("angle")); // Set the angle
  }

  public Color getColor() {
    return color;  
  }

  // Set or reset highlight color
  public void setHighlighted(boolean highlighted) {
    this.highlighted = highlighted;
  }

  // Get the current position of the element
  public Point getPosition() {  
    return position;  
  }

  // Draw an element in a given graphics context
  protected void draw(Graphics2D g2D, Shape element) {
    g2D.setPaint(highlighted ? Color.MAGENTA : color);  // Set the element color
    AffineTransform old = g2D.getTransform();           // Save the current transform
    g2D.translate(position.x, position.y);              // Translate to position
    g2D.rotate(angle);                                  // Rotate about position
    g2D.draw(element);                                  // Draw the element
    g2D.setTransform(old);                              // Restore original transform
  }

  protected java.awt.Rectangle getBounds(java.awt.Rectangle bounds) { 
    AffineTransform at = AffineTransform.getTranslateInstance(position.x, position.y);
    at.rotate(angle);
    return at.createTransformedShape(bounds).getBounds();
  }

  // Move an element
  public void move(int deltax, int deltay) {
    position.x += deltax;
    position.y += deltay;
  } 

  // Increment the element rotation angle
  public void rotate(double angle) {  
    this.angle += angle;
  }

  // Create XML <color> element
  protected org.w3c.dom.Element createColorElement(Document doc) {
    org.w3c.dom.Element colorElement = doc.createElement("color");
 
    Attr attr = doc.createAttribute("R");
    attr.setValue(String.valueOf(color.getRed()));
    colorElement.setAttributeNode(attr);  

    attr = doc.createAttribute("G");
    attr.setValue(String.valueOf(color.getGreen()));
    colorElement.setAttributeNode(attr);  

    attr = doc.createAttribute("B");
    attr.setValue(String.valueOf(color.getBlue()));
    colorElement.setAttributeNode(attr);
    return colorElement;      
  }

  // Create XML point-type element
  protected org.w3c.dom.Element createPointTypeElement(Document doc,
                                                       String name,
                                                       String xValue,
                                                       String yValue) { 
    org.w3c.dom.Element element = doc.createElement(name);

    Attr attr = doc.createAttribute("x");         // Create attribute x
    attr.setValue(xValue);                        // and set its value
    element.setAttributeNode(attr);               // Insert the x attribute   

    attr = doc.createAttribute("y");              // Create attribute y
    attr.setValue(yValue);                        // and set its value
    element.setAttributeNode(attr);               // Insert the y attribute   
    return element;              
  }

  // Create XML <position> element
  protected org.w3c.dom.Element createPositionElement(Document doc) {
    return createPointTypeElement(doc, "position",
                                  String.valueOf(position.getX()),
                                  String.valueOf(position.getY()));
  }

  // Set element color from XML <color> element
  protected void setElementColor(org.w3c.dom.Element colorElement) {
      color = new Color(Integer.parseInt(colorElement.getAttribute("R")),
                        Integer.parseInt(colorElement.getAttribute("G")),
                        Integer.parseInt(colorElement.getAttribute("B")));
  }

  // Set element position from XML <position> element
  protected void setElementPosition(org.w3c.dom.Element posElement) {
      position = new Point(); 
      position.setLocation(Double.parseDouble(posElement.getAttribute("x")),
                           Double.parseDouble(posElement.getAttribute("y")));
  }

  public abstract java.awt.Rectangle getBounds();
  public abstract void modify(Point start, Point last);
  public abstract void draw(Graphics2D g2D);
  public abstract void addElementNode(Document document);
  
  protected Color color;                         // Color of a shape
  protected boolean highlighted = false;         // Highlight flag
  final static Point origin = new Point();       // Point 0,0
  protected Point position;                      // Element position
  protected double angle = 0.0;                  // Rotation angle
  
  // Nested class defining a line
  public static class Line extends Element {
    public Line(Point start, Point end, Color color) {
      super(color);
      position = start;
      line = new Line2D.Double(origin, new Point(end.x - position.x, end.y - position.y));
    }

  // Content is <color>, <position>, <endpoint> elements. Attribute is angle.
  public Line(org.w3c.dom.Element xmlElement) {
    super(xmlElement);

    org.w3c.dom.NodeList list = xmlElement.getElementsByTagName("endpoint");
    org.w3c.dom.Element endpoint = (org.w3c.dom.Element)list.item(0);
    line = new Line2D.Double(origin.x, origin.y,
                Double.parseDouble(endpoint.getAttribute("x"))-position.getX(), 
                Double.parseDouble(endpoint.getAttribute("y"))-position.getY());
  } 

    // Method to serialize a line
    private void writeObject(ObjectOutputStream out) throws IOException {
      out.writeDouble(line.x2);
      out.writeDouble(line.y2);
    }

    // Method to deserialize a line
    private void readObject(java.io.ObjectInputStream in)
                               throws IOException, ClassNotFoundException {
      double x2 = in.readDouble();
      double y2 = in.readDouble();
      line = new Line2D.Double(0,0,x2,y2);
    }

    public void draw(Graphics2D g2D) {
      draw(g2D, line);                           // Call base draw method
    }

    // Obtain the rectangle bounding the line
    public java.awt.Rectangle getBounds() {
      return getBounds(line.getBounds());
    }

    // Change the end point for the line
    public void modify(Point start, Point last) {
      line.x2 = last.x - position.x;
      line.y2 = last.y - position.y;
    }

    // Add XML <line> element
    public void addElementNode(Document doc) {
      org.w3c.dom.Element lineElement = doc.createElement("line");
 
      // Create the angle attribute and attach it to the <line> node
      Attr attr = doc.createAttribute("angle");
      attr.setValue(String.valueOf(angle));
      lineElement.setAttributeNode(attr);
  
      // Append the <color>, <position>, and <endpoint> nodes as children
      lineElement.appendChild(createColorElement(doc));
      lineElement.appendChild(createPositionElement(doc));
      lineElement.appendChild(createEndpointElement(doc));
  
      // Append the <line> node to the document root node
      doc.getDocumentElement().appendChild(lineElement); 
    } 

    // Create XML <endpoint> element
    private org.w3c.dom.Element createEndpointElement(Document doc) {
      return createPointTypeElement(doc, "endpoint",
                                    String.valueOf(line.x2+position.x),
                                    String.valueOf(line.y2+position.y));
    }

    private Line2D.Double line;
  }

  // Nested class defining a rectangle
  public static class Rectangle extends Element {
    public Rectangle(Point start, Point end, Color color) {
      super(color);
    position = new Point(Math.min(start.x, end.x),
                         Math.min(start.y, end.y));
    rectangle = new Rectangle2D.Double(origin.x,
                                       origin.y,
                                       Math.abs(start.x - end.x),     // Width
                                       Math.abs(start.y - end.y));    // & height 
    }

    // Rectangle has angle attribute. Content is <color>,<position>,<bottomright>
    public Rectangle(org.w3c.dom.Element xmlElement) {
      super(xmlElement);

      org.w3c.dom.NodeList list = xmlElement.getElementsByTagName("bottomright");
      org.w3c.dom.Element bottomright = (org.w3c.dom.Element)list.item(0);
      rectangle = new Rectangle2D.Double(origin.x, origin.y, 
             Double.parseDouble(bottomright.getAttribute("x"))-position.getX(), 
             Double.parseDouble(bottomright.getAttribute("y"))-position.getY());
    }

    // Method to serialize a rectangle
    private void writeObject(ObjectOutputStream out) throws IOException {
      out.writeDouble(rectangle.width);
      out.writeDouble(rectangle.height);
    }

    // Method to deserialize a rectangle
    private void readObject(ObjectInputStream in)
                 throws IOException, ClassNotFoundException {
      double width = in.readDouble();
      double height = in.readDouble();
      rectangle = new Rectangle2D.Double(0,0,width,height);
    }

    public void draw(Graphics2D g2D) {
      draw(g2D, rectangle);                      // Call base draw method
    }

    // Method to return the rectangle enclosing this rectangle
    public java.awt.Rectangle getBounds() { 
      return getBounds(rectangle.getBounds());
    }

    // Method to redefine the rectangle
    public void modify(Point start, Point last) {
      position.x = Math.min(start.x, last.x);
      position.y = Math.min(start.y, last.y);
      rectangle.width = Math.abs(start.x - last.x);
      rectangle.height = Math.abs(start.y - last.y);
    }

    // Add an XML <rectangle> element
    public void addElementNode(Document doc) {
      org.w3c.dom.Element rectElement = doc.createElement("rectangle");
 
      // Create the angle attribute and attach it to the <rectangle> node
      Attr attr = doc.createAttribute("angle");
      attr.setValue(String.valueOf(angle));
      rectElement.setAttributeNode(attr);
 
      // Append the <color>, <position>, and <bottomright> nodes as children
      rectElement.appendChild(createColorElement(doc));
      rectElement.appendChild(createPositionElement(doc));
      rectElement.appendChild(createBottomrightElement(doc));
 
      doc.getDocumentElement().appendChild(rectElement);
    }

    // Create XML <bottomright> element
    private org.w3c.dom.Element createBottomrightElement(Document doc) {
      return createPointTypeElement(doc, "bottomright",
                                    String.valueOf(rectangle.width+position.x),
                                    String.valueOf(rectangle.height+position.y));
    }

    private Rectangle2D.Double rectangle;
  }

  // Nested class defining a circle
  public static class Circle extends Element {
    public Circle(Point center, Point circum, Color color) {
      super(color);
  
      // Radius is distance from center to circumference
      double radius = center.distance(circum);
      position = new Point(center.x - (int)radius,
                           center.y - (int)radius);
      
      circle = new Ellipse2D.Double(origin.x, origin.y,     // Position - top-left
                                    2.*radius, 2.*radius ); // Width & height
    }

    // Circle has radius, angle attributes. Content is <color>, <position>
    public Circle(org.w3c.dom.Element xmlElement) {
      super(xmlElement);
      
      double radius = Double.parseDouble(xmlElement.getAttribute("radius")); 
      circle = new Ellipse2D.Double(origin.x, origin.y,     // Position - top-left
                                    2.*radius, 2.*radius);  // Width & height
    }

    // Method to serialze a circle
    private void writeObject(ObjectOutputStream out) throws IOException {
      out.writeDouble(circle.width);
    }

    // Method to deserialize a circle
    private void readObject(ObjectInputStream in)
                               throws IOException, ClassNotFoundException {
      double width = in.readDouble();
      circle = new Ellipse2D.Double(0,0,width,width);
    }

    public void draw(Graphics2D g2D) {
      draw(g2D, circle);                         // Call base draw method
    }

    // Return the rectangle bounding this circle
    public java.awt.Rectangle getBounds() { 
      return getBounds(circle.getBounds());
    }

    // Recreate this circle
    public void modify(Point center, Point circum) {
      double radius = center.distance(circum);
      position.x = center.x - (int)radius;
      position.y = center.y - (int)radius;
      circle.width = circle.height = 2*radius;
    }

    // Add XML <circle> element
    public void addElementNode(Document doc) {
      org.w3c.dom.Element circleElement = doc.createElement("circle");
 
      // Create the radius attribute and attach it to the <circle> node
      Attr attr = doc.createAttribute("radius");
      attr.setValue(String.valueOf(circle.width/2.0));
      circleElement.setAttributeNode(attr);
  
      // Create the angle attribute and attach it to the <circle> node
      attr = doc.createAttribute("angle");
      attr.setValue(String.valueOf(angle));
      circleElement.setAttributeNode(attr);

      // Append the <color> and <position> nodes as children
      circleElement.appendChild(createColorElement(doc));
      circleElement.appendChild(createPositionElement(doc));
 
      doc.getDocumentElement().appendChild(circleElement);
    }

    private Ellipse2D.Double circle;
  }

  // Nested class defining a curve
  public static class Curve extends Element {
    public Curve(Point start, Point next, Color color) {
      super(color);
      curve = new GeneralPath();
      position = start;
      curve.moveTo(origin.x, origin.y);
      curve.lineTo(next.x - position.x,
                   next.y - position.y);
    }

    // Curve has angle attribute. Content is <color>, <position>, <point>+
    public Curve(org.w3c.dom.Element xmlElement) {
      super(xmlElement);

      curve = new GeneralPath();
      curve.moveTo(origin.x, origin.y);
      org.w3c.dom.NodeList nodes = xmlElement.getElementsByTagName("point");
      for(int i = 0 ; i<nodes.getLength() ; i++) {
        curve.lineTo(
                     (float)(Double.parseDouble(
           ((org.w3c.dom.Element)nodes.item(i)).getAttribute("x")) - position.x),
                     (float)(Double.parseDouble(
           ((org.w3c.dom.Element)nodes.item(i)).getAttribute("y")) - position.y));
      }
    }

    // Method to serialize a curve
    private void writeObject(ObjectOutputStream out) throws IOException {
      PathIterator iterator = curve.getPathIterator(new AffineTransform());
      Vector<Float> coords = new Vector<Float>();
      int maxCoordCount = 6;
      float[] temp = new float[maxCoordCount];   // Stores segment data

      int result = iterator.currentSegment(temp); // Get first segment
      assert(result == iterator.SEG_MOVETO);
      iterator.next();                           // Next segment
      while(!iterator.isDone()) {                // While there are segments
        result = iterator.currentSegment(temp);  // Get the segment data
        assert(result == iterator.SEG_LINETO);

        coords.add(temp[0]);                     // Add x coordinate to Vector
        coords.add(temp[1]);                     // Add y coordinate
        iterator.next();                         // Go to next segment
      }

      out.writeObject(coords);                   // Save the Vector
}

    // Method to deserialize a curve
    private void readObject(ObjectInputStream in)
                        throws IOException, ClassNotFoundException {
      Vector<Float> coords = (Vector<Float>)in.readObject(); // Read vector
      curve = new GeneralPath();                       // Create a path
      curve.moveTo(0,0);                               // Move to the origin

      for(int i = 0 ; i<coords.size() ; i += 2 ) {     // For each pair of elements
        curve.lineTo(coords.get(i), coords.get(i+1));  // Create a line segment
      }
    }

    // Add another segment
    public void modify(Point start, Point next) {
      curve.lineTo(next.x - start.x,
                   next.y - start.y);
    }

    public void draw(Graphics2D g2D) {
      draw(g2D, curve);                          // Call base draw method
    }

    // Return the rectangle bounding the path
    public java.awt.Rectangle getBounds() { 
      return getBounds(curve.getBounds());
    }

    // Add XML <curve> element
    public void addElementNode(Document doc) {
      org.w3c.dom.Element curveElement = doc.createElement("curve");
  
      // Create the angle attribute and attach it to the <curve> node
      Attr attr = doc.createAttribute("angle");
      attr.setValue(String.valueOf(angle));
      curveElement.setAttributeNode(attr);
   
      // Append the <color> and <position> nodes as children
      curveElement.appendChild(createColorElement(doc));
      curveElement.appendChild(createPositionElement(doc));
  
      // Get the defining points via a path iterator
      PathIterator iterator = curve.getPathIterator(new AffineTransform());
      int maxCoordCount = 6;                  // Maximum coordinates for a segment
      float[] temp = new float[maxCoordCount];           // Stores segment data
  
      int result = iterator.currentSegment(temp);        // Get first segment
      assert result == iterator.SEG_MOVETO;              // ... should be move to
  
      iterator.next();                                   // Next segment
      while(!iterator.isDone())   {                      // While you have segments
        result = iterator.currentSegment(temp);          // Get the segment data
        assert result == iterator.SEG_LINETO;            // Should all be lines
   
        // Create a <point> node and add it to the list of children
        curveElement.appendChild(createPointTypeElement(doc, "point",
                                      String.valueOf(temp[0]+position.x),
                                      String.valueOf(temp[1]+position.y)));
        iterator.next();                                   // Go to next segment
      }
  
      doc.getDocumentElement().appendChild(curveElement);
    }

    private GeneralPath curve;
  }

  // Nested class defining text elements
  public static class Text extends Element  {
    public Text(Font font, String text, Point position, Color color,
                                        java.awt.Rectangle bounds) {
      super(color);
      this.font = font;
      this.position = position;
      this.position.y -= (int)bounds.getHeight();
      this.text = text;
      this.bounds = new java.awt.Rectangle(origin.x, origin.y,
                                            bounds.width, bounds.height);
    }

    // Text has angle attribute. Content is <color>, <position>, <font>, <string>
    // <font> has attributes fontname, fontstyle, pointsize
    // fontstyle is "plain", "bold", "italic", or "bold-italic"
    // <string> content is text plus <bounds>
    public Text(org.w3c.dom.Element xmlElement) {
      super(xmlElement);

      // Get the font details
      org.w3c.dom.NodeList list = xmlElement.getElementsByTagName("font");
      org.w3c.dom.Element fontElement = (org.w3c.dom.Element)list.item(0);
      String styleStr = fontElement.getAttribute("fontstyle");
      int style = 0;
      if(styleStr.equals("plain")) {
        style = Font.PLAIN;
      } else if(styleStr.equals("bold")) {
        style = Font.BOLD;
      } else if(styleStr.equals("italic")) {
        style = Font.ITALIC;
      } else if(styleStr.equals("bold-italic")) {
        style = Font.BOLD + Font.ITALIC;
      } else {
        assert false;
      } 
      font = new Font(fontElement.getAttribute("fontname"), style,
                      Integer.parseInt(fontElement.getAttribute("pointsize")));    

      // Get string bounds
      list = xmlElement.getElementsByTagName("bounds");
      org.w3c.dom.Element boundsElement = (org.w3c.dom.Element)list.item(0);
      
      this.bounds = new java.awt.Rectangle(origin.x, origin.y,
                          Integer.parseInt(boundsElement.getAttribute("width")),
                          Integer.parseInt(boundsElement.getAttribute("height")));
      
      // Get the string
      list = xmlElement.getElementsByTagName("string");
      org.w3c.dom.Element string = (org.w3c.dom.Element)list.item(0);
      list = string.getChildNodes();

     StringBuffer textStr = new StringBuffer();
     for(int i = 0 ; i<list.getLength() ; i++) {
        if(list.item(i).getNodeType()==org.w3c.dom.Node.TEXT_NODE) {
          textStr.append(((org.w3c.dom.Text)list.item(i)).getData());
        }
     }
     text = textStr.toString().trim();
   }  

    public java.awt.Rectangle getBounds() {
      return getBounds(bounds);
    }

    public void draw(Graphics2D g2D)  {
      g2D.setPaint(highlighted ? Color.MAGENTA : color);
      Font oldFont = g2D.getFont();                   // Save the old font
      g2D.setFont(font);                              // Set the new font

      AffineTransform old = g2D.getTransform();       // Save the current transform
      g2D.translate(position.x, position.y);          // Translate to position
      g2D.rotate(angle);                              // Rotate about position
      g2D.drawString(text, origin.x, origin.y+(int)bounds.getHeight());
      g2D.setTransform(old);                          // Restore original transform
      g2D.setFont(oldFont);                           // Restore the old font
    }

    public void modify(Point start, Point last) {
      // No code is required here, but we must supply a definition
    }

    // Add XML <text> element
    public void addElementNode(Document doc) {
      org.w3c.dom.Element textElement = doc.createElement("text");
 
      // Create the angle attribute and attach it to the <text> node
      Attr attr = doc.createAttribute("angle");
      attr.setValue(String.valueOf(angle));
      textElement.setAttributeNode(attr);
     
      // Append the <color> and <position> nodes as children
      textElement.appendChild(createColorElement(doc));
      textElement.appendChild(createPositionElement(doc));
   
      // Create and apppend the <font> node 
      org.w3c.dom.Element fontElement = doc.createElement("font");
      attr = doc.createAttribute("fontname");
      attr.setValue(font.getName());
      fontElement.setAttributeNode(attr);
  
      attr = doc.createAttribute("fontstyle");
      String style = null;
      int styleCode = font.getStyle();
      if(styleCode == Font.PLAIN) {
        style = "plain";
      } else if(styleCode == Font.BOLD) {
        style = "bold";
      } else if(styleCode == Font.ITALIC) {
        style = "italic";
      } else if(styleCode == Font.ITALIC+Font.BOLD) {
          style = "bold-italic";
      }
      assert style != null;
      attr.setValue(style);
      fontElement.setAttributeNode(attr);
 
      attr = doc.createAttribute("pointsize");
      attr.setValue(String.valueOf(font.getSize()));
      fontElement.setAttributeNode(attr);
      textElement.appendChild(fontElement);
 
      // Create the <string> node
      org.w3c.dom.Element string = doc.createElement("string");
 
      // Create the <bounds> node and its attributes
      org.w3c.dom.Element bounds = doc.createElement("bounds");
      attr = doc.createAttribute("width");
      attr.setValue(String.valueOf(this.bounds.width));
      bounds.setAttributeNode(attr);
      attr = doc.createAttribute("height");
      attr.setValue(String.valueOf(this.bounds.height));
      bounds.setAttributeNode(attr);
      string.appendChild(bounds);      // Set <bounds> element as <string> content

      string.appendChild(doc.createTextNode(text));
      textElement.appendChild(string);// Set <text> as <string> content
      doc.getDocumentElement().appendChild(textElement);
    }

    private Font font;                           // The font to be used
    private String text;                         // Text to be displayed
    private java.awt.Rectangle bounds;           // The bounding rectangle
  }
}