Writing Java Servlets to Produce XHTML Code That References External SVG Files
Java Programming Notes # 2218
- Preface
- General background information
- Preview
- Discussion and sample code
- Run the program
- Summary
- What's next?
- Resources
- Complete program listings
- Copyright
- About the author
Preface
General
This lesson is part of a series (see Resources) designed to teach you how to write servlets to produce SVG code that will be rendered in graphic form by an SVG-capable browser such as Firefox 1.5. In this lesson you will learn how to write servlets that produce XHTML output containing references to external SVG files. The SVG files may be static, or may be created on-the-fly during the execution of the servlet.
I taught you how write your own SVG graphics library to eliminate, or at least alleviate the requirement to write raw XML code or raw JAXP DOM code in earlier lessons in the series. The use of the SVG graphics library makes it possible for you to produce SVG output simply by making typical Java method calls. One of the sample programs in this lesson makes use of that SVG graphics library.
Viewing tip
I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.
Figures
- Figure 1. Graphic output for all three programs.
- Figure 2. Output XHTML produced by the program Svg09.
- Figure 3. Five steps for writing a servlet program.
Listings
- Listing 1. The beginning of the Svg09 class.
- Listing 2. Create the object element.
- Listing 3. Finish writing the file and terminate the program.
- Listing 4. Beginning of the program named Svg10.
- Listing 5. The beginning of the class and the doGet method.
- Listing 6. Abbreviated code for creating the DOM tree.
- Listing 7. Transform the DOM tree.
- Listing 8. Execute some more required servlet code.
- Listing 9. Create the XHTML document.
- Listing 10. Program code for Svg09.
- Listing 11. Program code for Svg10.
- Listing 12. Program code for Svg11.
Supplementary material
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find a consolidated index at www.DickBaldwin.com.
General background information
SVG is a language for describing two-dimensional graphics in XML. SVG allows for three types of graphic objects:
- vector graphic shapes
- images
- text
The Scalable Vector Graphics (SVG) 1.1 Specification is extensive, but it is not easy reading, particularly if your knowledge of XML is weak.
While I don't claim to be an expert in XML, I do know enough about the topic that I can usually make sense of the material provided in the SVG specification. One of my objectives for this series is to help Java programmers who lack a strong background in XML take advantage of the capabilities of SVG.
Great graphics in the browser
|
Preview
A desktop application
I will present and explain three different programs in this lesson. The first program, named Svg09 is a stand-alone desktop application that produces an output XHTML file, (which will validate at http://validator.w3.org/file-upload.html). When this XHTML file is loaded into an SVG-capable browser, (such as Firefox 1.5), it references an SVG file stored in the same directory and causes the graphic contents of the SVG file to be rendered by the browser.
This program is mainly a first step towards the writing of servlets that produce XHTML data that serves SVG files. I will present and explain this program first because it is much easier to test and debug desktop applications than it is to test and debug servlets. As I demonstrated in the earlier lesson titled "Using Java to produce SVG code in XHTML data" (see Resources), once you finish writing, testing, and debugging a desktop application, it is not a difficult task to convert it a servlet.
A servlet that serves a static SVG file
The second program named Svg10 is a Java servlet program that delivers XHTML data, which, in turn references a static SVG file stored on the server. When this servlet is accessed using Firefox 1.5, the static SVG file is accessed and the graphic contents of the file are rendered by the browser.
The XHTML output produced by this servlet will validate at http://validator.w3.org/file-upload.html.
Something a little more dynamic
|
The output produced by this servlet will also validate at http://validator.w3.org/file-upload.html.
The graphic output
|
The first two programs require the availability of a previously generated SVG file. Hopefully, by now, you know how to write your own Java programs to create SVG files. Or, you can create an SVG file by executing the program named Svg08, that I explained in the earlier lesson titled "An improved approach for creating SVG/XML code and SVG/XML DOM nodes using Java" (see Resources).
Figure 1. Graphic output for all three programs.
|
|
The graphic image shown in Figure 1 is the same image that I explained in the earlier lesson titled "Using Java to produce SVG code in XHTML data" (see Resources). I will explain later how the scrollbars and the text in Figure 1 were produced.
Discussion and sample code
The program named Svg09
Description of the program
The purpose of this program is to show you how to write a Java program that creates an XHTML file, which references a static SVG graphics file stored in the same directory on the local hard disk.
As I mentioned earlier, my main reason for showing you this desktop application first is because desktop applications are much easier to test and debug than servlets. Further, once you have the desktop application running correctly, it is not very difficult to convert it to a servlet.
Three ways to reference a static SVG file
There are at least three ways to write the XHTML code to reference an SVG file, each of which has advantages and disadvantages. (The following information was taken from the web page titled "SVG in HTML pages." (See Resources.)
<embed>
- Advantage: supported in nearly any browser, allows html2svg and svg2html scripting, is recommended by Adobe for their SVG Viewer
- Disadvantage: not clearly standardized within any HTML specification
<object>
- Advantage: HTML4 and higher standard, supported in newer browser generations
- Disadvantage: works on newer browsers but without html2svg and svg2html scripting.
<iframe>
- Advantage: works in most browsers, but not documented
- Disadvantage: generates a window-like border without specific styling
How I did it
This program embeds the reference to the SVG file in an object element. The XHTML output file produced by this program was tested and confirmed to be valid at: http://validator.w3.org/
Output XHTML produced by the program Svg09
The XML code produced by this program (with some line breaks manually inserted for compatibility with this narrow publication format) is shown in Figure 2. I will refer back to this output XML code later while explaining the program code.
Figure 2. Output XHTML produced by the program Svg09.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > <head> <meta http-equiv="content-type" content="image/svg+xml; charset=UTF-8" /> <title>Generated XHTML file</title> </head> <body style="border:1px solid black;width:220px; height:500px;" > <p>There is an image below here. <object type="image/svg+xml" width="210" height="430" data="Svg09.svg" /> There is an image above here.</p> </body></html> |
The most interesting code in Figure 2 is highlighted in boldface.
Program testing
The program was tested using J2SE 5.0 and Firefox 1.5.09, running under WinXP.
The beginning of the Svg09 class
As is my custom, I will discuss and explain this program in fragments. You can view a complete listing of the program named Svg09 in Listing 10 near the end of the lesson.
The beginning of the class named Svg09 is shown in Listing 1.
Listing 1. The beginning of the Svg09 class.
public class Svg09{
public static void main(String argv[]){
try{
//Get an output stream.
PrintWriter out = new PrintWriter(
new FileOutputStream("junk.xhtml"));
//Create the beginning text required for the XHTML
// document.
makeXhtmlText(out);
|
Get an output stream and write normal XHTML text
Listing 1 begins by getting an output stream for writing the XHTML file named junk.xhtml.
Then it calls a convenience method named makeXhtmlText for the purpose of writing the normal text that is required for the beginning of a valid XHTML document. The method named makeXhtmlText creates all of the text above the boldface text in Figure 2. There is nothing new about this text or this code. I have discussed it in several previous lessons. I broke this code out into a separate method here simply for clarity. You can view the method named makeXhtmlText in Listing 10.
Create the object element
|
Two lines of plain text
I promised earlier that I would explain how the two lines of text shown in Figure 1 are produced. Listing 2 inserts one line of plain text above and one line of plain text below the object element. You can view those two lines of text above and below the area allocated for the image by Firefox in Figure 1.
Listing 2. Create the object element.
out.println("<p>There is an image below here.");
out.println(makeElement(
true,
"object",
new String[]{"type","image/svg+xml",
"width","210",
"height","430",
"data","Svg09.svg",
})//end call to makeElement
);//end call to println
out.println("There is an image above here.</p>");
|
The scrollbars
I also promised you earlier that I would explain the presence of the scrollbars in Figure 1. Well, the time for that explanation has come.
The image in the file named Svg09.svg that is rendered in Figure 1 has an actual width of 220 pixels and an actual height of 440 pixels. As you can see, the values of the width and height attributes in the object element that is created in Listing 2 are smaller than those dimensions (210 x 430 pixels). Firefox 1.5 responds to this situation by automatically placing horizontal and vertical scrollbars on the image as shown in Figure 1. This makes it possible to view the entire image by manipulating the scroll bars.
Finish writing the file and terminate the program
Listing 3 writes the final XHTML text and flushes the output buffer.
Listing 3. Finish writing the file and terminate the program.
out.println("</body></html>");
out.flush();
}catch(Exception e){
//Note that no effort was made to provide meaningful
// information in the event of an exception or
// error.
e.printStackTrace(System.err);
}//end catch
}// end main()
|
Listing 3 also signals the end of the main method. When control returns from the flush method, there is nothing more for the main method to do, so the program terminates.
Not much effort required
As you can see, once you have access to the convenience methods that I have provided, it doesn't require much effort to write a Java program that will produce an output XHTML file that references an SVG file, which will be rendered when the XHTML file is loaded into Firefox 1.5.
Conversion to a servlet
In the Summary section of the lesson titled "Using Java to produce SVG code in XHTML data" (see Resources), I explained the list of five fairly simple steps shown in Figure 3 that are required to convert a desktop application such as Svg09 into a servlet.
Figure 3. Five steps for writing a servlet program.
|
Will convert Svg09 into a servlet program
The next program that I will explain will be a servlet program that serves a static SVG file that is stored on the server. The program named Svg10 was written by converting the program named Svg09 into a servlet. When the servlet is accessed using Firefox 1.5, the SVG file is retrieved and rendered. An example of the output using my SVG file is shown in Figure 1. If you use a different SVG file, you should get a different output.
The program named Svg10
Description of the program
The purpose of this program is to show you how to write a simple servlet that will serve a static SVG graphics file stored on a jakarta-tomcat server running as a localhost server under WinXP.
Where should the SVG file be stored on the server?
One of the more difficult aspects of writing this servlet program had nothing to do with Java programming. Rather, it had to do with figuring out where to store the SVG file on the server and how to refer to the file in the SVG/XML code so that it would be found and retrieved by the browser. In this regard, my thanks go to Marty Hall at http://www.apl.jhu.edu/~hall/ for helping me to understand:
- Where to place static files to cause them to be accessible by a servlet.
- How to reference those files within the servlet.
Must be tested as a servlet
This program can only be tested by deploying the servlet on a servlet-compatible server and then accessing it using an SVG-capable browser, such as Firefox 1.5.
For this demonstration, the static SVG file was stored in the following location on my hard drive:
C:jakarta-tomcat-5.0.27webappsROOTimages
The servlet class file was stored in:
C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses
The servlet was accessed by addressing the following URL with Firefox:
http://localhost/servlet/Svg10
The code produced by this servlet was tested and confirmed to be valid at: http://validator.w3.org/
The program was tested using J2SE 5.0, Firefox 1.5.09, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP.
Will discuss in fragments
As usual, I will discuss this program in fragments. Also as usual, the program can be viewed in its entirety in Listing 11 near the end of the lesson.
However, because of the similarity of this program to the program named Svg09, I will only discuss those parts of the program that are different from Svg09 that were required to convert it from a desktop application to a servlet as described in the previous list of steps.
Beginning of the program named Svg10
The beginning of the program is shown in Listing 4.
Listing 4. Beginning of the program named Svg10.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Svg10 extends HttpServlet{
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException,IOException{
res.setContentType("image/svg+xml");
try{
//Get an output stream.
PrintWriter out = res.getWriter();
|
The code in Listing 4 satisfies all five steps listed in the previous list of steps that were required to convert the program named Svg09 into the servlet program named Svg10. Therefore, there is nothing more for me to discuss and explain in this program.
Therefore, that ends the discussion of the program named Svg10.
The program named Svg11
Description of the program
This program is much longer than either of the previous two programs in this lesson. However, there is very little that is new in this program. Mainly, this program was written by combining sections of code that I have previously explained in this and earlier lessons. Therefore, the explanations of the code for this program will be fairly brief.
The purpose of this program is to write a servlet that will first create a static SVG file and store it on the server and then serve that file to an SVG-capable web client by way of XHTML code that is sent to the client.
The code to accomplish this is somewhat simpler than the code required to create the SVG graphic code and to send it directly to the client as in-line graphic code. This is because this approach makes better use of JAXP to process the DOM tree that represents the graphic image.
This program uses an SVG graphic library that has been discussed and explained in earlier lessons on this topic.
The beginning of the program named Svg11
The program begins by:
- Defining a servlet that: Creates a DOM tree describing the graphic image shown in Figure 1.
- Transforming that tree into corresponding SVG XML code.
- Writing the SVG code into an output file on the server named Svg11.svg.
Producing the XHTML output
Then the servlet creates the code for a short XHTML document that references the SVG file that was just written and sends that XHTML code back to the client.
The XHTML code sent to the client is valid according to:
http://validator.w3.org/file-upload.html
Must be tested as a servlet
This program can only be tested by deploying the servlet on a servlet-compatible server and then accessing it using an SVG-capable browser such as Firefox 1.5.
On my system, the SVG file was written by the servlet into the following directory:
C:jakarta-tomcat-5.0.27webappsROOTimages
The servlet was tested by first copying it into the following directory on the Tomcat server:
C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses
Then the servlet was accessed using Firefox 1.5.09 at the URL given below:
http://localhost/servlet/Svg11
The program was tested using J2SE 5.0, Firefox 1.5.09, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP.
The beginning of the class and the doGet method
As usual, I will discuss this program in fragments. Also, as usual, you can view the entire program in its entirety in Listing 12 near the end of the lesson.
Listing 5 contains some of the requisite servlet code that you saw earlier in the program named Svg10.
Listing 5. The beginning of the class and the doGet method.
public class Svg11 extends HttpServlet{
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException,IOException{
|
Abbreviated code for creating the DOM tree
Listing 6 shows an abbreviated version of essentially the same code that I explained in detail in Listing 1 through Listing 20 in the earlier lesson titled "Using Java to produce SVG code in XHTML data" (see Resources). Note that I deleted most of the code from Listing 6 for brevity, but you can view that code in its entirety in Listing 12. The code that is represented by Listing 6 creates a DOM tree that represents the graphic image shown in Figure 1.
Listing 6. Abbreviated code for creating the DOM tree.
//The following data values will be used to create
// SVG graphics.
int ellipseCenterX = 110;
//...
//Begin by creating a Document object and a root
// node named svg.
Document document = SvgGraphics.getDocument();
Element svg = SvgGraphics.makeNode(
//...
//Create a node named defs, which will be the parent
// for three gradient definitions.
Element defs = SvgGraphics.makeNode(document,
//...
//Create nodes that define three different gradient
// coloring schemes.
Element gradientA = SvgGraphics.makeLinearGradient(
//...
//Create three stop nodes that identify the colors
// used to produce the gradient and specify where
// the colors begin and end,
SvgGraphics.makeGradientStop(document,
//...
Element gradientB = SvgGraphics.makeLinearGradient(
//...
Element gradientC = SvgGraphics.makeRadialGradient(
//...
//Create a node named g, which will be the parent
// for an ellipse,a circle, a rectangle, a line,
// a polyline, and a polygon.
Element g = SvgGraphics.makeNode(document,
//...
//Create an ellipse with a blue border that is two
// pixels wide. Fill it with the yellow-red-blue
// gradient defined by gradientA.
Element theEllipse = SvgGraphics.makeEllipse(
//...
//Rotate the ellipse by 15-degrees clockwise about
// its center.
efeheEllipse.setAttribute("transform",
//...
//Position a circle so that it appears to be inside
// the ellipse.
Element theCircle = SvgGraphics.makeCircle(
//...
//Set the appearance of the circle and rotate it by
// 15-degrees clockwise about its center.
theCircle.setAttribute("fill","url(#gradientB)");
theCircle.setAttribute("transform",
//...
//Make a rounded rectangle and fill it with
// gradientC
Element theRect = SvgGraphics.makeRect(
//...
//Draw a polyline with four points.
int[] polylinePoints =
{10,235,210,235,110,275,110,225};
Element polyline = SvgGraphics.makePolyline(
//...
//Rotate the polyline by 10 degrees around the first
// point.
polyline.setAttribute("transform",
//...
//Draw a polygon with four points. Give it a red
// border and fill it with green.
int[] polygonPoints =
{10,335,210,335,110,375,110,325};
Element polygon = SvgGraphics.makePolygon(
//...
//Draw a green line 12 pixels wide. Make the line
// 60% opaque, or 40% transparent, whichever you
// prefer.
Element line = SvgGraphics.makeLine(document,
//...
|
Transform the DOM tree
Listing 7 transforms the DOM tree into SVG XML code and writes that code into an SVG file on the server.
Listing 7. Transform the DOM tree.
SvgGraphics.transformTheDom(document,
getServletContext().getRealPath("/") + "images"
+ File.separator + "Svg11.svg");
|
The code in Listing 7 is essentially the same as the code that I explained beginning with Listing 21 in the previous lesson titled "An improved approach for creating SVG/XML code and SVG/XML DOM nodes using Java" (see Resources) with one exception. That exception has to do with the code required to specify the location where the SVG file will be written. In the earlier lesson, the file was written into the current directory on the local hard disk. In Listing 7, the SVG file is written into a file on the server.
The getServletContext method
The getServletContext method is inherited into the Svg11 class by way of the superclass named HttpServlet. The method returns a reference to an object of type ServletContext. Here is part of what Sun has to say about the getServletContext method:
"Returns a ServletContext object, which contains information about the network service in which the servlet is running."
According to Sun, an object that implements the ServletContext interface is:
"A servlet engine generated object that gives servlets information about their environment."
Also according to Sun, the invocation of the getRealPath method on the ServletContext object:
"Returns a String representing the corresponding real path in the format that is appropriate for the operating system the servlet engine is running under (including the proper path separators)."
To make a long story short
To make a long story short, on my system, the execution of the getRealPath method as shown in Listing 7 returns the following string:
C:jakarta-tomcat-5.0.27webappsROOT
The code in Listing 7 then concatenates the proper material onto the end of that string to produce the following string, which is where the SVG file was written by the servlet.
C:jakarta-tomcat-5.0.27webappsROOTimages
Execute some more required servlet code
By now, you should recognize the first statement in Listing 8 as the code required to get an output stream for the XHTML text that will be sent directly from the servlet to the browser.
Listing 8. Execute some more required servlet code.
PrintWriter out = res.getWriter();
res.setContentType("image/svg+xml");
|
You should also recognize the second statement in Listing 8 as the code required to set the type of the servlet output to the correct type for SVG data.
Create the XHTML document
The code in Listing 9 is essentially the same as the code that I explained earlier in this lesson in Listing 1 through Listing 3.
Listing 9. Create the XHTML document.
//Create the beginning text required for the XHTML
// document.
makeXhtmlText(out);
//Insert an object element that references a static
// SVG file in the directory listed in the
// opening comments to this program. The servlet
// also causes plain text to be displayed above and
// below the object element.
out.println("<p>There is an image below here.");
out.println(SvgGraphics.makeElement(
true,
"object",
new String[]{"type","image/svg+xml",
"width","210",
"height","430",
"data","/images/Svg11.svg",
})//end call to makeElement
);//end call to println
out.println("There is an image above here.</p>");
//Write the final XHTML text and flush the output
// buffer.
out.println("</body></html>");
out.flush();
}catch(Exception e){
//Note that no effort was made to provide meaningful
// information in the event of an exception or
// error.
e.printStackTrace(System.err);
}//end catch
}// end doGet()
|
End of the program
That concludes the explanation of the program named Svg11.
Run the program
I encourage you to copy the code from Listing 10, Listing 11, and Listing 12 into your text editor, compile it, and execute it. Then view the results in Firefox 1.5, or some other suitable SVG rendering engine. Experiment with the code, making changes, and observing the results of your changes.
Above all, enjoy the process. Programming, particularly graphics programming, can be fun.
Summary
In this lesson I taught you how to write a Java desktop application that creates an output XHTML file containing references to an external SVG file. After that, I taught you how to write servlets that produce XHTML output containing references to external SVG files. The SVG files may be static, or may be created on-the-fly during the execution of the servlet.
What's next?
Future lessons in this series will teach you how to write servlets that:
- Deal with the following graphics elements:
- path
- text
- image (Deal with bit-mapped images in SVG.)
- use (Create and re-use graphics elements.)
- Use SVG symbols.
- Deal with stroke caps in SVG in comparison with similar caps in Java 2D.
- Use the switch element in SVG.
- Deal with other features of SVG, such as animation.
Resources
Java 2D Graphics
300 Java 2D Graphics,
Nested Top-Level Classes and Interfaces
302 Java 2D Graphics,
The Point2D Class
304 Java 2D Graphics,
The Graphics2D Class
306 Java 2D Graphics,
Simple Affine Transforms
308 Java 2D Graphics,
The Shape Interface, Part 1
310 Java 2D Graphics,
The Shape Interface, Part 2
312 Java 2D Graphics,
Solid Color Fill
314 Java 2D Graphics,
Gradient Color Fill
316 Java 2D Graphics,
Texture Fill
318 Java 2D Graphics,
The Stroke Interface
320 Java 2D Graphics,
The Composite Interface and Transparency
322 Java 2D Graphics,
The Composite Interface, GradientPaint, and Transparency
324 Java 2D Graphics,
The Color Constructors and Transparency
Java 2D API
Specification
Java 2D API
Java API for XML Processing (JAXP)
2200 Java
API for XML Processing (JAXP), Getting Started
2202 Getting
Started with Java JAXP and XSL Transformations (XSLT)
2204 Java
JAXP, Exposing a DOM Tree
2206 Java
JAXP, Implementing Default XSLT Behavior in Java
2208 Java
JAXP, Writing Java Code to Emulate an XSLT Transformation
2210 Java
JAXP, Transforming XML to XHTML
Links to numerous XML tutorials
by Richard G. Baldwin
Scalable Vector Graphics (SVG)
2212 Java JAXP, Creating graphics using Java and SVG
2214 An improved approach for creating SVG/XML code and SVG/XML DOM nodes
using Java
2216 Using Java to produce SVG code in XHTML data
Scalable Vector Graphics (SVG) 1.1
Specification
Adobe SVG Viewer plug-in
Create vector graphics in the browser with SVG by Uche Ogbuji
SVG Tutorial
SVG Basics
SVG in HTML
pages
Miscellaneous
W3C Markup Validation
Service.
Complete program listings
Listing 10. Program code for Svg09.
/*File Svg09.java
Copyright 2006 R.G.Baldwin
The purpose of this program is to show you how to write a
Java program that creates an XHTML file, which references
a static SVG graphics file stored in the same directory on
the local hard disk.
There are several ways to accomplish this. This program
embeds the reference to the SVG file in an object element.
The XHTML output file produced by this program was tested
and confirmed to be valid at:
http://validator.w3.org/
The XML code produced by this program (with some line
breaks manually inserted for compatibility with this
narrow publication format) is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD
XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<meta http-equiv="content-type" content="image/svg+xml;
charset=UTF-8" />
<title>Generated XHTML file</title>
</head>
<body style="border:1px solid black;width:220px;
height:500px;" >
<p>There is an image below here.
<object type="image/svg+xml" width="210" height="430"
data="Svg09.svg" />
There is an image above here.</p>
</body></html>
Tested using J2SE 5.0 and Firefox 1.5.09, running under
WinXP.
*********************************************************/
import java.io.*;
public class Svg09{
public static void main(String argv[]){
try{
//Get an output stream.
PrintWriter out = new PrintWriter(
new FileOutputStream("junk.xhtml"));
//Create the beginning text required for the XHTML
// document.
makeXhtmlText(out);
//Insert an object element that references an SVG
// file in the same directory, with plain text
// above and below the object element.
out.println("<p>There is an image below here.");
out.println(makeElement(
true,
"object",
new String[]{"type","image/svg+xml",
"width","210",
"height","430",
"data","Svg09.svg",
})//end call to makeElement
);//end call to println
out.println("There is an image above here.</p>");
//Write the final XHTML text and flush the output
// buffer.
out.println("</body></html>");
out.flush();
}catch(Exception e){
//Note that no effort was made to provide meaningful
// information in the event of an exception or
// error.
e.printStackTrace(System.err);
}//end catch
}// end main()
//----------------------------------------------------//
//This is a convenience method used to separate out the
// code required to write a lot of XHTML text into the
// output file.
static void makeXhtmlText(PrintWriter out){
out.println("<?xml version="1.0" "
+ "encoding="UTF-8"?>");
out.println(
"<!DOCTYPE html PUBLIC "-//W3C//DTD "
+ "XHTML 1.0 Transitional//EN" "
+ ""http://www.w3.org/TR/xhtml1/"
+ "DTD/xhtml1-transitional.dtd">");
out.println(makeElement(false,"html",
new String[]{"xmlns","http://www.w3.org/1999/xhtml",
"xml:lang","en"
})//end call to makeElement
);//end println
out.println("<head>");
out.println(makeElement(
true,
"meta",
new String[]{"http-equiv","content-type",
"content",
"image/svg+xml; charset=UTF-8"
})//end call to makeElement
);//end println
out.println("<title>Generated XHTML file</title>");
out.println("</head>");
out.println(makeElement(
false,
"body",
new String[]{"style","border:1px solid black;"
+ "width:220px;"
+ "height:500px;"
})//end call to makeElement
);//end println
}//end makeXhtmlText
//----------------------------------------------------//
/*
One of the most frustrating things about using Java
to create elements in XML, XHTML, or HTML is having
to deal with the escape characters for the many
required quotation marks. This method constructs an
element, which may or may not have attributes. Also,
the element may or may not be empty.
The user of this method does not have to deal with the
required quotation marks surrounding attribute values
and the corresponding escape characters
The first incoming parameter must be true if the
element is empty and false if the element is not
empty.
If the first parameter is true, the element is sealed
off in the required manner for an empty element. If
the first parameter is false, the method returns the
complete start tag for the element but does not
return a complete element. It is the responsibility
of the calling method to provide the content and the
end tag for the element.
The second parameter to the method must be a String
that specifies the name of the element.
The third parameter to the method must be a reference
to an array object of type String. This array must
contain an even number of elements. Each pair of
elements constitutes the name and the value of an
attribute, in the order name, value, name, value, etc.
If the reference to the array object is null and the
first parameter is false, the method returns the start
tag for an element that has no attributes and is not
empty.
If the reference is null and the first parameter is
true, the method returns a complete empty element with
no attributes (which probably doesn't make any sense).
An example of the recommended usage of the method
follows:
String newElement = SvgGraphics.makeElement(
true/false,
name,
new String[]{"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value"
});//end call to makeElement
*/
static String makeElement(
boolean empty,String elementName,String[] data){
//Begin constructing the start tag.
String element = "<" + elementName + " ";
//Deal with elements that have no attributes.
if((empty==false) && (data == null)){
//Return a complete start tag.
return element + ">";
}else if((empty==true) && (data == null)){
//Return a complete empty element.
return element + "/>";
}//end if
for(int cnt=0;cnt<data.length;cnt+=2){
String name = data[cnt];
String value = data[cnt+1];
element += name + "=" + """ + value + "" ";
}//end for loop
if(empty){
//Terminate the element appropriately for an
// empty element. A complete empty element will
// be returned.
element += "/>";
}else{
//End the start tag for an element that is not
// empty. In this case, only the start tag will
// be returned. The calling program must provide
// the content for the element as well as the end
// tag for the element.
element += ">";
}//end else
return element;
}//end makeElement
//----------------------------------------------------//
}//End class Svg09
|
Listing 11. Program code for Svg10.
/*File Svg10.java
Copyright 2007, R.G.Baldwin
The purpose of this program is to show you how to write a
simple servlet that will serve a static SVG graphics file
stored on a jakarta-tomcat server running as a localhost
server under WinXP.
Note that everything reasonable was done to keep this
servlet as small and simple as practical.
Many thanks go to Marty Hall at
http://www.apl.jhu.edu/~hall/
for helping this author understand:
A. Where to place static files to cause them to be
accessible by a servlet.
B. How to reference those files within the servlet.
C. Some other hints regarding good programming practice
using Java servlets on a jakarta-tomcat server.
This program can only be tested by deploying the servlet
on a servlet-compatible server and then accessing it
using an SVG-compatible browser, such as Firefox 1.5.
For this demonstration, the static SVG file is stored in:
C:jakarta-tomcat-5.0.27webappsROOTimages
The servlet class file is stored in:
C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses
The servlet is accessed using Firefox at the following
URL:
http://localhost/servlet/Svg10
The code produced by this servlet was tested and confirmed
to be valid at:
http://validator.w3.org/
The following XML code is produced by this servlet (with
some line breaks manually entered here for compatibility
with this narrow publication format):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<meta http-equiv="content-type" content="image/svg+xml;
charset=UTF-8" />
<title>Generated XHTML file</title>
</head>
<body style="border:1px solid black;width:220px;
height:500px;" >
<p>There is an image below here.
<object type="image/svg+xml" width="210" height="430"
data="/images/Svg10.svg" />
There is an image above here.</p>
</body></html>
Tested using J2SE 5.0, Firefox 1.5.09, and
jakarta-tomcat-5.0.27 running as a localhost server under
WinXP.
*********************************************************/
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Svg10 extends HttpServlet{
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException,IOException{
res.setContentType("image/svg+xml");
try{
//Get an output stream.
PrintWriter out = res.getWriter();
//Create the beginning text required for the XHTML
// document.
makeXhtmlText(out);
//Insert an object element that references a static
// SVG file in the directory listed in the
// opening comments to this program. The servlet
// also causes plain text to be displayed above and
// below the object element.
out.println("<p>There is an image below here.");
out.println(makeElement(
true,
"object",
new String[]{"type","image/svg+xml",
"width","210",
"height","430",
"data","/images/Svg10.svg",
})//end call to makeElement
);//end call to println
out.println("There is an image above here.</p>");
//Write the final XHTML text and flush the output
// buffer.
out.println("</body></html>");
out.flush();
}catch(Exception e){
//Note that no effort was made to provide meaningful
// information in the event of an exception or
// error.
e.printStackTrace(System.err);
}//end catch
}// end doGet()
//----------------------------------------------------//
//This is a convenience method used to separate out the
// code required to write a lot of XHTML text into the
// output file.
static void makeXhtmlText(PrintWriter out){
out.println("<?xml version="1.0" "
+ "encoding="UTF-8"?>");
out.println(
"<!DOCTYPE html PUBLIC "-//W3C//DTD "
+ "XHTML 1.0 Transitional//EN" "
+ ""http://www.w3.org/TR/xhtml1/"
+ "DTD/xhtml1-transitional.dtd">");
out.println(makeElement(false,"html",
new String[]{"xmlns","http://www.w3.org/1999/xhtml",
"xml:lang","en"
})//end call to makeElement
);//end println
out.println("<head>");
out.println(makeElement(
true,
"meta",
new String[]{"http-equiv","content-type",
"content",
"image/svg+xml; charset=UTF-8"
})//end call to makeElement
);//end println
out.println("<title>Generated XHTML file</title>");
out.println("</head>");
out.println(makeElement(
false,
"body",
new String[]{"style","border:1px solid black;"
+ "width:220px;"
+ "height:500px;"
})//end call to makeElement
);//end println
}//end makeXhtmlText
//----------------------------------------------------//
/*
One of the most frustrating things about using Java
to create elements in XML, XHTML, or HTML is having
to deal with the escape characters for the many
required quotation marks. This method constructs an
element, which may or may not have attributes. Also,
the element may or may not be empty.
The user of this method does not have to deal with the
required quotation marks surrounding attribute values
and the corresponding escape characters
The first incoming parameter must be true if the
element is empty and false if the element is not
empty.
If the first parameter is true, the element is sealed
off in the required manner for an empty element. If
the first parameter is false, the method returns the
complete start tag for the element but does not
return a complete element. It is the responsibility
of the calling method to provide the content and the
end tag for the element.
The second parameter to the method must be a String
that specifies the name of the element.
The third parameter to the method must be a reference
to an array object of type String. This array must
contain an even number of elements. Each pair of
elements constitutes the name and the value of an
attribute, in the order name, value, name, value, etc.
If the reference to the array object is null and the
first parameter is false, the method returns the start
tag for an element that has no attributes and is not
empty.
If the reference is null and the first parameter is
true, the method returns a complete empty element with
no attributes (which probably doesn't make any sense).
An example of the recommended usage of the method
follows:
String newElement = makeElement(
true/false,
name,
new String[]{"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value"
});//end call to makeElement
*/
static String makeElement(
boolean empty,String elementName,String[] data){
//Begin constructing the start tag.
String element = "<" + elementName + " ";
//Deal with elements that have no attributes.
if((empty==false) && (data == null)){
//Return a complete start tag.
return element + ">";
}else if((empty==true) && (data == null)){
//Return a complete empty element.
return element + "/>";
}//end if
for(int cnt=0;cnt<data.length;cnt+=2){
String name = data[cnt];
String value = data[cnt+1];
element += name + "=" + """ + value + "" ";
}//end for loop
if(empty){
//Terminate the element appropriately for an
// empty element. A complete empty element will
// be returned.
element += "/>";
}else{
//End the start tag for an element that is not
// empty. In this case, only the start tag will
// be returned. The calling program must provide
// the content for the element as well as the end
// tag for the element.
element += ">";
}//end else
return element;
}//end makeElement
//----------------------------------------------------//
}//End class Svg10
|
Listing 12. Program code for Svg11.
/*File Svg11.java
Copyright 2007, R.G.Baldwin
The purpose of this program is to write a servlet that
will first create a static SVG file and store it on the
server and then serve that file to an SVG-capable web
client by way of XHTML code that is sent to the client.
The code to accomplish this is somewhat simpler than the
code required to create the SVG graphic code and send it
directly to the client as in-line graphic code. This is
because this approach makes better use of JAXP to process
the DOM tree that represents the graphic image.
This program uses an SVG graphic library that has been
discussed and explained in earlier lessons on this topic.
The program defines a servlet that:
Creates a DOM tree describing a specific graphic image.
Transforms that tree into corresponding SVG XML code.
Writes the SVG code into an output file on the server.
Then the servlet creates the code for a short XHTML
document that references the SVG file just written and
sends that XHTML code back to the client.
The XHTML code sent to the client is valid according to:
http://validator.w3.org/file-upload.html
This program can only be tested by deploying the servlet
on a servlet-compatible server and then accessing it
using an SVG-compatible browser, such as Firefox 1.5.
On my system, the SVG file is written into the following
directory:
C:jakarta-tomcat-5.0.27webappsROOTimages
The servlet was tested by copying it into the following
directory on the Tomcat server:
C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses
Then the servlet was accessed using Firefox 1.5.09 at
the URL given below:
http://localhost/servlet/Svg11
Tested using J2SE 5.0, Firefox 1.5.09, and
jakarta-tomcat-5.0.27 running as a localhost server under
WinXP.
*********************************************************/
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
public class Svg11 extends HttpServlet{
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException,IOException{
//The following data values will be used to create
// SVG graphics.
int ellipseCenterX = 110;
int ellipseCenterY = 100;
int ellipseWidth = 100;
int ellipseHeight = 40;
int ellipseRotate = 15;//degrees
int circleCenterX = 110;
int circleCenterY = 100;
int circleRadius = 30;
int circleRotate = 15;
int rectCenterX = 110;
int rectCenterY = 200;
int rectWidth = 110;
int rectHeight = 80;
int rectRoundX = 26;
int rectRoundY = 25;
int rotatePolyline = 10;
try{
//Create a DOM tree that describes a particular
// graphic image.
//Begin by creating a Document object and a root
// node named svg. All of the graphic content will
// be contained in the svg element.
//At this point, the program starts using the
// SVG graphics library encapsulated in the class
// named SvgGraphics.
Document document = SvgGraphics.getDocument();
//Create the root node named svg and append it to
// the document.
//Set some attributes on the root node that are
// required for proper rendering.
Element svg = SvgGraphics.makeNode(
document,
null,//parent could be null
"svg",//node type
new String[]{"xmlns","http://www.w3.org/2000/svg",
"version","1.1",
"width","220px",
"height","440px",
"position","static",
"top","0",
"left","0"
});//end call to makeNode
//Create a node named defs, which will be the parent
// for three gradient definitions. There will be
// two linear gradients and one radial gradient.
// Pass null for the reference to the object for the
// special case where the node has no attribtes.
Element defs = SvgGraphics.makeNode(document,
svg,//parent
"defs",
null);
//Create nodes that define three different gradient
// coloring schemes.
//The definitions are identified as gradientA,
// gradientB, and gradientC. They will be referred
// to later to specify the fill colors for an
// ellipse, a circle, and a rounded rectangle.
//Define gradientA, which provides a linear
// gradient from yellow to red to blue going from
// left to right.
Element gradientA = SvgGraphics.makeLinearGradient(
document, //this document
defs, //parent
"gradientA");//id
//Create three stop nodes that identify the colors
// used to produce the gradient and specify where
// the colors begin and end,
SvgGraphics.makeGradientStop(document,
gradientA,//parent
"2%", //start here
"yellow");//color
SvgGraphics.makeGradientStop(document,
gradientA,
"50%",
"red");
SvgGraphics.makeGradientStop(document,
gradientA,
"98%",
"blue");
//Define gradientB, which provides a linear
// gradient having two stops from green to blue
// going from left to right.
Element gradientB =SvgGraphics.makeLinearGradient(
document, //this document
defs, //parent
"gradientB");//id
SvgGraphics.makeGradientStop(document,
gradientB,//parent
"0%", //start here
"green"); //color
SvgGraphics.makeGradientStop(document,
gradientB,
"100%",
"blue");
//Define gradientC, which provides a radial
// gradient from yellow to red to blue going from
// the center to the outer edge.
Element gradientC =
SvgGraphics.makeRadialGradient(
document, //this document
defs, //parent
"gradientC", //ID
"userSpaceOnUse",
rectCenterX, //cx
rectCenterY, //cy
rectWidth/2); //r
SvgGraphics.makeGradientStop(document,
gradientC,
"0%",
"yellow");
SvgGraphics.makeGradientStop(document,
gradientC,
"50%",
"red");
SvgGraphics.makeGradientStop(document,
gradientC,
"100%",
"blue");
//Create a node named g, which will be the parent
// for an ellipse,a circle, a rectangle, a line,
// a polyline, and a polygon. Pass null for the
// reference to the object for the special case
// where the node has no attribtes.
Element g = SvgGraphics.makeNode(document,
svg,//parent
"g",
null);
//Create an ellipse with a blue border that is two
// pixels wide. Fill it with the yellow-red-blue
// gradient defined by gradientA.
Element theEllipse = SvgGraphics.makeEllipse(
document,
g,//Owner
ellipseCenterX,
ellipseCenterY,
ellipseWidth,
ellipseHeight);
//Set the appearance of the ellipse.
theEllipse.setAttribute("fill","url(#gradientA)");
theEllipse.setAttribute("stroke","blue");
theEllipse.setAttribute("stroke-width","2");
//Rotate the ellipse by 15-degrees clockwise about
// its center.
theEllipse.setAttribute("transform",
"translate(" + ellipseCenterX + ","
+ ellipseCenterY + ") "
+ "rotate(" + ellipseRotate + ") "
+ "translate(" + (-ellipseCenterX) + ","
+ (-ellipseCenterY) + ") ");
//Position a circle so that it appears to be inside
// the ellipse. Fill it with the green-blue
// gradient defined by gradientB.
Element theCircle = SvgGraphics.makeCircle(
document,
g,//Owner
circleCenterX,
circleCenterY,
circleRadius);
//Set the appearance of the circle and rotate it by
// 15-degrees clockwise about its center.
theCircle.setAttribute("fill","url(#gradientB)");
theCircle.setAttribute("transform",
"translate(" + circleCenterX + ","
+ circleCenterY + ") "
+ "rotate(" + circleRotate + ") "
+ "translate(" + (-circleCenterX) + ","
+ (-circleCenterY) + ") ");
//Make a rounded rectangle and fill it with
// gradientC
Element theRect = SvgGraphics.makeRect(
document,
g,//Owner
rectCenterX - rectWidth/2,//x
rectCenterY - rectHeight/2,//y
rectWidth,
rectHeight);
theRect.setAttribute("fill","url(#gradientC)");
//Round the corners.
theRect.setAttribute("rx",""+ rectRoundX);
theRect.setAttribute("ry",""+ rectRoundY);
//Draw a polyline with four points.
int[] polylinePoints =
{10,235,210,235,110,275,110,225};
Element polyline = SvgGraphics.makePolyline(
document,
g,//owner
polylinePoints);
//Rotate the polyline by 10 degrees around the first
// point.
polyline.setAttribute("transform",
"translate(" + polylinePoints[0] + ","
+ polylinePoints[1] + ")"
+ "rotate(" + rotatePolyline + ")"
+ "translate(" + (-polylinePoints[0])
+ "," + (-polylinePoints[1]) + ")");
//Draw a polygon with four points. Give it a red
// border and fill it with green.
int[] polygonPoints =
{10,335,210,335,110,375,110,325};
Element polygon = SvgGraphics.makePolygon(
document,
g,//parent
polygonPoints);
polygon.setAttribute("fill","green");
polygon.setAttribute("stroke","red");
polygon.setAttribute("stroke-width","3");
//Draw a green line 12 pixels wide. Make the line
// 60% opaque, or 40% transparent, whichever you
// prefer.
Element line = SvgGraphics.makeLine(document,
g, //owner
0, //x1
0, //y1
220, //x2
440);//y2
line.setAttribute("stroke","green");
line.setAttribute("stroke-width","12");
line.setAttribute("stroke-opacity","0.6");
//Now transform the DOM tree into SVG XML code and
// write that code into an SVG file on the server.
SvgGraphics.transformTheDom(document,
getServletContext().getRealPath("/") + "images"
+ File.separator + "Svg11.svg");
//Get an output stream for the XHTML text that will
// be sent directly from the servlet to the browser.
PrintWriter out = res.getWriter();
res.setContentType("image/svg+xml");
//Create the beginning text required for the XHTML
// document.
makeXhtmlText(out);
//Insert an object element that references a static
// SVG file in the directory listed in the
// opening comments to this program. The servlet
// also causes plain text to be displayed above and
// below the object element.
out.println("<p>There is an image below here.");
out.println(SvgGraphics.makeElement(
true,
"object",
new String[]{"type","image/svg+xml",
"width","210",
"height","430",
"data","/images/Svg11.svg",
})//end call to makeElement
);//end call to println
out.println("There is an image above here.</p>");
//Write the final XHTML text and flush the output
// buffer.
out.println("</body></html>");
out.flush();
}catch(Exception e){
//Note that no effort was made to provide meaningful
// information in the event of an exception or
// error.
e.printStackTrace(System.err);
}//end catch
}// end doGet()
//----------------------------------------------------//
//This is a convenience method used to separate out the
// code required to write a lot of XHTML text into the
// output file.
static void makeXhtmlText(PrintWriter out){
out.println("<?xml version="1.0" "
+ "encoding="UTF-8"?>");
out.println(
"<!DOCTYPE html PUBLIC "-//W3C//DTD "
+ "XHTML 1.0 Transitional//EN" "
+ ""http://www.w3.org/TR/xhtml1/"
+ "DTD/xhtml1-transitional.dtd">");
out.println(SvgGraphics.makeElement(false,"html",
new String[]{"xmlns","http://www.w3.org/1999/xhtml",
"xml:lang","en"
})//end call to makeElement
);//end println
out.println("<head>");
out.println(SvgGraphics.makeElement(
true,
"meta",
new String[]{"http-equiv","content-type",
"content",
"image/svg+xml; charset=UTF-8"
})//end call to makeElement
);//end println
out.println("<title>Generated XHTML file</title>");
out.println("</head>");
out.println(SvgGraphics.makeElement(
false,
"body",
new String[]{"style","border:1px solid black;"
+ "width:220px;"
+ "height:500px;"
})//end call to makeElement
);//end println
}//end makeXhtmlText
//----------------------------------------------------//
}//End class Svg11
//======================================================//
//This is a proof-of-concept graphics class that
// provides method calls for the creation of the following
// DOM tree nodes:
// A general node of any type
// A linear gradient element.
// A radial gradient element.
// An ellipse.
// A circle.
// A rectangle.
// A line.
// A polyline.
// A polygon.
//Each method receives a reference to the overall document
// along with a reference to the parent for the new node.
//When the method returns, the new node has been appended
// to the parent node.
class SvgGraphics{
//----------------------------------------------------//
//This method creates a linear gradient node to which
// stop elements must be appended.
static Element makeLinearGradient(Document document,
Element parent,
String id){
Element gradient =
(Element)document.createElement("linearGradient");
parent.appendChild(gradient);
gradient.setAttribute("id",id);
return gradient;
}//End makeLinearGradient
//----------------------------------------------------//
//This method creates a radial gradient node to which
// stop elements must be appended. Note that numeric
// attributes are set as type String.
static Element makeRadialGradient(Document document,
Element parent,
String id,
String gradientUnits,
int cx,
int cy,
int r){
Element gradient =
(Element)document.createElement("radialGradient");
parent.appendChild(gradient);
gradient.setAttribute("id",id);
gradient.setAttribute("gradientUnits",gradientUnits);
gradient.setAttribute("cx",""+cx);
gradient.setAttribute("cy",""+cy);
gradient.setAttribute("r",""+r);
return gradient;
}//End makeRadialGradient
//----------------------------------------------------//
//This method creates a gradient stop node to be
// appended to a linear gradient node or a radial
// gradient node.
static Element makeGradientStop(Document document,
Element parent,
String location,
String color){
Element stopElement =
(Element)document.createElement("stop");
parent.appendChild(stopElement);
stopElement.setAttribute("offset",location);
stopElement.setAttribute("stop-color",color);
return stopElement;
}//End makeGradientStop
//----------------------------------------------------//
//This method returns a reference to an ellipse. The
// xCoor and yCoor parameters specify the center of the
// ellipse. The xRadius and yRadius parameters specify
// the width and height of the ellipse respectively
// while it is in the horizontal plane before being
// rotated. Numeric attributes are set at type String.
static Element makeEllipse(Document document,
Element parent,
int xCoor,
int yCoor,
int xRadius,
int yRadius){
Element ellipse =
(Element)document.createElement("ellipse");
parent.appendChild(ellipse);
ellipse.setAttribute("cx",""+xCoor);
ellipse.setAttribute("cy",""+yCoor);
ellipse.setAttribute("rx",""+xRadius);
ellipse.setAttribute("ry",""+yRadius);
return ellipse;
}//end makeEllipse
//----------------------------------------------------//
//This method returns a reference to a circle. The
// xCoor and yCoor parameters specify the center of the
// circle. The radius parameter specifies the radus of
// the circle. Numeric attributes are set as type
// String.
static Element makeCircle(Document document,
Element parent,
int xCoor,
int yCoor,
int radius){
Element circle =
(Element)document.createElement("circle");
parent.appendChild(circle);
circle.setAttribute("cx",""+xCoor);
circle.setAttribute("cy",""+yCoor);
circle.setAttribute("r",""+radius);
return circle;
}//end makeCircle
//----------------------------------------------------//
//This method returns a reference to a rectangle. The
// xCoor and yCoor parameters specify the location of
// the upper left corner. The width and height
// parameters specify the width and the height while
// the rectangle is in the horizontal plane before
// being rotated. Numeric attributes are set as type
// String.
static Element makeRect(Document document,
Element parent,
int xCoor,
int yCoor,
int width,
int height){
Element rect =
(Element)document.createElement("rect");
parent.appendChild(rect);
rect.setAttribute("x",""+xCoor);
rect.setAttribute("y",""+yCoor);
rect.setAttribute("width",""+width);
rect.setAttribute("height",""+height);
return rect;
}//end makeRect
//----------------------------------------------------//
//This method returns a reference to a line. x1 and y1
// specify the starting point of the line before it is
// rotated. x2 and y2 specify the end point. By
// default, the stroke is set to black one pixel wide.
// This can be overridden to speciy other colors and
// other widths if you need to do so.
static Element makeLine(Document document,
Element parent,
int x1,
int y1,
int x2,
int y2){
Element line =
(Element)document.createElement("line");
parent.appendChild(line);
line.setAttribute("x1",""+x1);
line.setAttribute("y1",""+y1);
line.setAttribute("x2",""+x2);
line.setAttribute("y2",""+y2);
line.setAttribute("stroke","black");
line.setAttribute("stroke-width","1");
return line;
}//end makeLine
//----------------------------------------------------//
//This method returns a reference to a polyline. The
// array of type int[] must contain an even number of
// values for things to work correctly.
//The values are extracted from the array and treated
// as coordinate values x1,y1, x2,y2, x3,y3 ... etc.
// By default, the stroke is set to black one pixel
// wide with no fill. This can be overridden to other
// colors and other widths if you need to do so.
static Element makePolyline(Document document,
Element parent,
int[] points){
Element polyline =
(Element)document.createElement("polyline");
parent.appendChild(polyline);
String dataPoints = "";
for(int cnt=0;cnt<points.length;cnt++){
dataPoints += "" + points[cnt] + ",";
}//end for loop
polyline.setAttribute("points",dataPoints);
polyline.setAttribute("stroke","black");
polyline.setAttribute("stroke-width","1");
polyline.setAttribute("fill","none");
return polyline;
}//end makePolyline
//----------------------------------------------------//
//This method returns a reference to a polygon. The
// array of type int[] must contain an even number of
// values for things to work correctly.
//The values are extracted from the array and treated
// as coordinate values x1,y1, x2,y2, x3,y3 ... etc.
// By default, the stroke is set to black, one pixel
// wide with no fill. This can be overridden to other
// colors and other widths if you need to do so.
//The major difference between a polygon and a polyline
// is that a polyline leaves the last point dangling.
// However, a polygon automatically draws a line from
// the last point back to the first point to close
// the polygon.
static Element makePolygon(Document document,
Element parent,
int[] points){
Element polygon =
(Element)document.createElement("polygon");
parent.appendChild(polygon);
String dataPoints = "";
for(int cnt=0;cnt<points.length;cnt++){
dataPoints += "" + points[cnt] + ",";
}//end for loop
polygon.setAttribute("points",dataPoints);
polygon.setAttribute("stroke","black");
polygon.setAttribute("stroke-width","1");
polygon.setAttribute("fill","none");
return polygon;
}//end makePolygon
//----------------------------------------------------//
/*
One of the most frustrating things about using Java
to create elements in XML, XHTML, or HTML is having
to deal with the escape characters for the many
required quotation marks. This method constructs an
element, which may or may not have attributes. Also,
the element may or may not be empty.
The user of this method does not have to deal with the
required quotation marks surrounding attribute values
and the corresponding escape characters
The first incoming parameter must be true if the
element is empty and false if the element is not
empty.
If the first parameter is true, the element is sealed
off in the required manner for an empty element. If
the first parameter is false, the method returns the
complete start tag for the element but does not
return a complete element. It is the responsibility
of the calling method to provide the content and the
end tag for the element.
The second parameter to the method must be a String
that specifies the name of the element.
The third parameter to the method must be a reference
to an array object of type String. This array must
contain an even number of elements. Each pair of
elements constitutes the name and the value of an
attribute, in the order name, value, name, value, etc.
If the reference to the array object is null and the
first parameter is false, the method returns the start
tag for an element that has no attributes and is not
empty.
If the reference is null and the first parameter is
true, the method returns a complete empty element with
no attributes (which probably doesn't make any sense).
An example of the recommended usage of the method
follows:
String newElement = SvgGraphics.makeElement(
true/false,
name,
new String[]{"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value"
});//end call to makeElement
*/
static String makeElement(
boolean empty,String elementName,String[] data){
//Begin constructing the start tag.
String element = "<" + elementName + " ";
//Deal with elements that have no attributes.
if((empty==false) && (data == null)){
//Return a complete start tag.
return element + ">";
}else if((empty==true) && (data == null)){
//Return a complete empty element.
return element + "/>";
}//end if
for(int cnt=0;cnt<data.length;cnt+=2){
String name = data[cnt];
String value = data[cnt+1];
element += name + "=" + """ + value + "" ";
}//end for loop
if(empty){
//Terminate the element appropriately for an
// empty element. A complete empty element will
// be returned.
element += "/>";
}else{
//End the start tag for an element that is not
// empty. In this case, only the start tag will
// be returned. The calling program must provide
// the content for the element as well as the end
// tag for the element.
element += ">";
}//end else
return element;
}//end makeElement
//----------------------------------------------------//
/*
The purpose of this method is to create a general node
having any name, and any number of attributes with any
attribute names and any String values for the
attributes, or no attributes at all.
The first parameter is a reference to the document to
which the new node belongs.
The second parameter is a reference to the parent node
to which this node is to be appended so as to become a
child of that node. If this parameter is null, the new
node is appended to the document. Otherwise, it is
appended to the specified parent node.
The third parameter is a String that specifies the type
of node.
The fourth parameter to the method must be a reference
to an array object of type String. This array must
contain an even number of elements. Each pair of
elements constitutes the name and the value of an
attribute, in the order name, value, name, value, etc.
An example of the recommended usage of the method
follows:
Element abc = SvgGraphics.makeNode(
document,
def,//parent could be null
"ghi",//node type
new String[]{"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value",
"name","value"
});//end call to makeNode
*/
static Element makeNode(Document document,
Element parent,
String nodeType,
String[] data){
Element element =
(Element)document.createElement(nodeType);
if(parent == null){
//For the special case of parent equal to null,
// append the new node to the document.
document.appendChild(element);
}else{
//Otherwise, append the new node to the specified
// parent.
parent.appendChild(element);
}//end else
//Deal with elements that have no attributes.
if(data == null){
return element;
}//end if
for(int cnt=0;cnt<data.length;cnt+=2){
String name = data[cnt];
String value = data[cnt+1];
element.setAttribute(name,value);
}//end for loop
return element;
}//end makeNode
//----------------------------------------------------//
//This is a utility method that is used to execute code
// that is the same regardless of the graphic image
// being produced.
static Document getDocument(){
Document document = null;
try{
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
factory.newDocumentBuilder();
document = builder.newDocument();
}catch(Exception e){
e.printStackTrace(System.err);
System.exit(0);
}//end catch
return document;
}//end getDocument
//----------------------------------------------------//
//This is a utility method that is used to execute code
// that is the same regardless of the graphic image
// being produced. This method transforms the DOM into
// raw XML code and writes that code into the output.
static void transformTheDom(Document document,
String filename){
try{
//Get a TransformerFactory object.
TransformerFactory xformFactory =
TransformerFactory.newInstance();
//Get an XSL Transformer object.
Transformer transformer =
xformFactory.newTransformer();
//Get a DOMSource object that represents the
// Document object
DOMSource source = new DOMSource(document);
//Get an output stream for the output file.
PrintWriter outStream = new PrintWriter(filename);
//Get a StreamResult object that points to the
// output file. Then transform the DOM sending XML
// code to to the file
StreamResult fileResult =
new StreamResult(outStream);
transformer.transform(source,fileResult);
}//end try block
catch(Exception e){
e.printStackTrace(System.err);
}//end catch
}//end transformTheDom
//----------------------------------------------------//
}//end class SvgGraphics
|
Copyright
Copyright 2007, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
About the author
Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.
In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP). His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments. (TI is still a world leader in DSP.) In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

