package er.pdf.builder;
import java.util.Enumeration;
import java.util.Properties;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xhtmlrenderer.pdf.DefaultPDFCreationListener;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.pdf.PDFCreationListener;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.PdfWriter;
/**
* <p>
* Implements {@link PDFCreationListener} to extract metadata values from the
* input XHTML, and inserts those values into the resulting PDF. Specifically,
* XHTML {@code meta} tags with the following {@code name} attributes will have
* their {@code content} attributes inserted as the corresponding PDF metadata
* keys:
* </p>
*
* <ul>
* <li>title</li>
* <li>author</li>
* <li>subject</li>
* <li>creator</li>
* <li>descriptions</li>
* <li>keywords</li>
* </ul>
*
* <p>
* For example, the following XHTML fragment would set the {@code title},
* {@code author} and {@code subject} metadata keys in the PDF output:
* </p>
*
* <pre>
* <code>
* <meta name="title" content="Foo Sales" />
* <meta name="author" content="John Doe" />
* <meta name="subject" content="Monthly sales of Foo" />
* </code>
* </pre>
*
* <p>
* Further, in the absence of a "title" {@code meta} element, the content of the
* {@code title} element will be used instead. That is, the following fragment
* would produce the same output:
* </p>
*
* <pre>
* <code>
* <title>Foo Sales</title>
* <meta name="author" content="John Doe" />
* <meta name="subject" content="Monthly sales of Foo" />
* </code>
* </pre>
*
* <p>
* This class is based on code posted to the <a href=
* "http://code.google.com/p/flying-saucer/wiki/HowTo_PDF_metadata_from_xhtml_meta_tags"
* >Flying Saucer project wiki</a>, and is assumed to be in the public domain.
* </p>
*
* @author paulhoadley
*/
public class FlyingSaucerMetadataCreationListener extends DefaultPDFCreationListener {
/**
* Collection of XHTML {@code meta} tag keys and their values
*/
Properties headMetaTags = new Properties();
/**
* Parses the XHTML {@code meta} tags into a property list.
*
* @param sourceXHTML
* XHTML source
*/
public void parseMetaTags(Document sourceXHTML) {
Element headTag =
(Element) sourceXHTML.getDocumentElement()
.getElementsByTagName("head").item(0);
NodeList metaTags = headTag.getElementsByTagName("meta");
for (int i = 0; i < metaTags.getLength(); ++i) {
Element thisNode = (Element) metaTags.item(i);
String name = thisNode.getAttribute("name");
String content = thisNode.getAttribute("content");
if (name.length() != 0 && content.length() != 0) {
headMetaTags.setProperty(name, content);
}
}
// No title meta tag given --> take it from title tag
if (headMetaTags.getProperty("title") == null) {
Element titleTag =
(Element) headTag.getElementsByTagName("title").item(0);
if (titleTag != null) {
headMetaTags.setProperty("title", titleTag.getTextContent());
}
}
return;
}
@Override
public void preOpen(ITextRenderer iTextRenderer) {
@SuppressWarnings("unchecked")
Enumeration<String> e =
(Enumeration<String>) headMetaTags.propertyNames();
while (e.hasMoreElements()) {
String key = e.nextElement();
PdfString val =
new PdfString(headMetaTags.getProperty(key),
PdfObject.TEXT_UNICODE);
iTextRenderer.getWriter().setViewerPreferences(
PdfWriter.DisplayDocTitle);
if (key == null ? "title" == null : key.equals("title")) {
iTextRenderer.getWriter().getInfo().put(PdfName.TITLE, val);
} else if (key == null ? "author" == null : key.equals("author")) {
iTextRenderer.getWriter().getInfo().put(PdfName.AUTHOR, val);
} else if (key == null ? "subject" == null : key.equals("subject")) {
iTextRenderer.getWriter().getInfo().put(PdfName.SUBJECT, val);
} else if (key == null ? "creator" == null : key.equals("creator")) {
iTextRenderer.getWriter().getInfo().put(PdfName.CREATOR, val);
} else if (key == null ? "description" == null : key
.equals("description")) {
iTextRenderer.getWriter().getInfo().put(PdfName.DESC, val);
} else if (key == null ? "keywords" == null : key
.equals("keywords")) {
iTextRenderer.getWriter().getInfo().put(PdfName.KEYWORDS, val);
}
}
}
}