Using version 2.0 of the BFO Graph Library with BFO Report Generator
BFO Report Generator by default includes the BFO Graph Library, but the older version 1.0 library. While this is adequate for many users, people may want to use the new graphs and features available in version 2.0 of the Graph library. This article will show how to achieve this.
Web Application Usage
If you're generating PDFs from XML or JSP files and returning PDFs to the client browser then it's fairly straightforward to include version 2.0 graphs by just using a JSP page that includes the version 2.0 tag library, and then using the version 2.0 graphs as normal, as shown below. Note Line #2, which sets up the tag library to allow us to use a funnel chart, one of the new charts available in Graph Library 2.1.4.
<?xml version="1.0"?>
<%@ taglib uri="http://big.faceless.org/products/graph" prefix="bfg" %>
<%@ page language="java" contentType="text/xml; charset=UTF-8"%>
<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body>
<p font-size="14">Integrating Version 2.0 Graphs into Report Generator</p>
<bfg:axesgraph width="600" height="600"
backgroundcolor="#FFFFFF"
yrotation="10" zrotation="180" xrotation="45">
<bfg:stackedbarseries name="Funnel Example"
topbarwidth="0.9" bottombarwidth="0"
bargap="1.2">
<bfg:barseries name="2001"
color="#F7953A" bordercolor="#000000">
<bfg:data x="Data" y="7"/>
<bfg:label x="Data" y="3"
textcolor="#FFFFFF">35 percent</bfg:label>
</bfg:barseries>
<bfg:barseries name="2002"
color="#79847E" bordercolor="#000000">
<bfg:data x="Data" y="3" />
<bfg:label x="Data" y="2"
textcolor="#FFFFFF">8.75 percent</bfg:label>
</bfg:barseries>
<bfg:barseries name="2003"
color="#F6CB9E" bordercolor="#000000">
<bfg:data x="Data" y="5" />
<bfg:label x="Data" y="3"
textcolor="#FFFFFF">18.5 percent</bfg:label>
</bfg:barseries>
<bfg:barseries name="2004"
color="#ACA3B3" bordercolor="#000000">
<bfg:data x="Data" y="4" />
<bfg:label x="Data" y="3"
textcolor="#FFFFFF">12.5 percent</bfg:label>
</bfg:barseries>
<bfg:barseries name="2005"
color="#ED6032" bordercolor="#000000">
<bfg:data x="Data" y="5"/>
<bfg:label x="Data" y="3"
textcolor="#FFFFFF">25 percent</bfg:label>
</bfg:barseries>
</bfg:stackedbarseries>
<bfg:axis pos="left" type="null"
bordercolor="#FFFFFF" color="none"/>
<bfg:axis pos="bottom"
type="null" color="none"/>
</bfg:axesgraph>
</body>
</pdf>
Application Usage
If you're generating PDFs from a Java application then it's slightly more complicated - you need to generate the version 2.0 chart and then embed a link to it in your PDF, as shown below:
// Create the graph image
String graphxml = "<axesgraph>...</axesgraph>"
XMLGraph xmlgraph = new XMLGraph();
xmlgraph.parse(new InputSource(new StringReader(graphxml)));
Graph graph = xmlgraph.getGraph();
PNGOutput image = new PNGOutput();
FileOutputStream out = new FileOutputStream("mygraph.png");
image.writePNG(new FileOutputStream(out, 0);
out.close();
// Create the PDF with a link to the graph image inside
String reportxml = "<pdf>....<img src='mygraph.png' />...</pdf>"
ReportParser parser = ReportParser.getInstance();
InputSource sorce = new InputSource(new StringReader(reportxml));
source.setSystemId(new File(".").toString());
parser.parse(source);
The drawback with this approach is that it relies on writing a file out to the local filesystem and linking to it, which may not be appropriate in some use cases, such as when used in a Servlet.
The alternative to writing local files is to use a data URL to reference the graph image. Data URLs (http://en.wikipedia.org/wiki/Data_URI_scheme) can be used to embed data directly into an image URL, so by using the BFO org.faceless.util.DataStreamHandler class you can embed the image into a URL and reference that from the PDF. The code them becomes:
String graphxml = "<axesgraph>...</axesgraph>"
XMLGraph xmlgraph = new XMLGraph();
xmlgraph.parse(new InputSource(new StringReader(graphxml)));
Graph graph = xmlgraph.getGraph();
PNGOutput image = new PNGOutput();
ByteArrayOutputStream out = new ByteArrayOutputStream();
image.writePNG(new FileOutputStream(out, 0);
out.close();
String urlstring =
DataStreamHandler.encode(out.toByteArray(), "image/png");
URL.setURLStreamHandlerFactory(DataStreamHandler.createFactory());
String reportxml = "<pdf>....<img src=\""+urlstring+"\" />...</pdf>"
ReportParser parser = ReportParser.getInstance();
InputSource sorce = new InputSource(new StringReader(reportxml));
source.setSystemId(new File(".").toString());
parser.parse(source);