These are my notes for my GovCamp presentation in Brussels (September 21, 2006; between OSCon and DrupalCon).
I was asked to talk about the Belgian eID; the eID is the new Belgian identity card in the form of a smartcard.
I am not an eID expert, so I decided to change the focus of the presentation to a technology I know rather well: the Portable Document Format (PDF).
In this article you will learn:
The conclusion will be that you really don't need to be an eID expert to achieve all this. If I can do it, so can you ;-)
We all know the Portable Document Format (PDF) as a secure and reliable technology to distribute read-only electronic documents. Governments and enterprises around the world have adopted PDF as the de facto standard output format for publications, reports, white papers, and so forth.
But PDF is about much more than read-only text presented in a nice layout. In my book iText in Action you will find examples of all kinds of interesting interactive features that IMHO deserve more attention from a larger public. One of the first examples that comes to mind is an interactive map of a city, with different layers that can be turned on/off by the end user; however that was one of the subjects of another presentation. In this demo, I'll show some examples that didn't make the book. I saved them for an occasion like this ;-)
Some of the functionality that is needed to understand the examples can be found in chapter 15 and chapter 16 of iText in Action, but I'll try to present the principles without getting too technical.
There are two types of forms in PDF:
Figure 1.1 shows a PDF document that contains an AcroForm.
figure 1.1: an interactive form
The form in figure 1.1 isn't filled in yet and it isn't designed very well because it's hard to distinguish the fields that can be filled in unless we highlight the 'editable zones' in the document (see figure 1.2).
figure 1.2: an interactive form with high-lighted fields that were filled in
The word 'SUBMIT' is a clickable field (a button). If we push it, an XML file, more specifically an XFDF file is posted to the server (see figure 1.3).
figure 1.3: the XFDF file submitted to the server
You can see the example in action here: EIDFormSubmit.pdf. If you want to try the example on your own server, you can download the source code: EIDFormSubmit.java and show_data.jsp.
The JSP file does nothing more than returning the inputstream that was posted to the server as an outputstream sent back to the browser.
The java code draws a PdfPTable to the document and adds some text fields and a pushbutton using cell and field positioning events. There is a more complex example with JavaScript actions and the possibility to upload a file in the book. I reused the book example for an article on ECTS: learningagreement.pdf.
In the ECTS example, the PDF form is posted using the Forms Data Format (FDF). The data entered in the IDENTITY CARD example is posted as XFDF; this is the XML version of FDF. We could also have sent the data to the server as an HTML query string. Sending the file as a filled-in PDF will only work if you have Acrobat (not just Adobe Reader).
Can an end user save a (partially) filled in form on his own computer? Only if he has the full Acrobat. With the free Adobe Reader users will be able fill in the PDF form and print out a copy of the filled in form, but they cannot SAVE the filled in form on their computer unless the PDF has been SAVE enabled with the "usage rights"; those are available through the Adobe Reader Extensions. You can only create a PDF with such usage rights if you have the full Acrobat.
There are a lot of similarities and differences between PDF forms and HTML forms. In the book, I have made a table that compares the functionality. As a rule of thumb I would advise to use HTML if the form is short and simple. For example if it has only a handful of fields, or if it's easy to distribute the fields over several pages. PDF forms make more sense than HTML forms in these two cases:
Figure 1.4 shows a form without a submit button.
figure 1.4: a form without submit button
This form has the same fields as before. We could fill this form out manually, but there is little more we can do than printing. Or is there?
The form shown in figure 1.4 was created to serve as a template. Suppose we need to fill out this form in a batch process. Suppose we have a database with names and addresses and we want to create a document that has one page per database record using the form as a template (see in figure 1.5).
figure 1.5: a document with n pages, one per database record
There are different ways to achieve this. The most efficient way, would be to retrieve the coordinates of the fields in an onOpenDocument, to add the flattened form in an onEndPage event, and to add the data using a static ColumnText method; but I promised you I would keep it simple, so we are going to adapt a simple example from chapter 2 of the book. We are going to create the document in 'multiple passes'.
With PdfStamper we'll create a separate PDF document in memory for each record based on the EIDFormTemplate.pdf. We'll use PdfCopy to create the EIDForms.pdf PDF file with as many pages as there are records in our database.
Have a look at EIDFormTemplate.java to see how it's done.
String[] keys = { NAME, TWO_FIRST_FIRST_NAMES, BIRTH_DATE, SEX, BIRTH_LOCATION, NATIONALITY, ADDRESS, MUNICIPALITY, ZIP };
String[][] values = {
{ "Specimen", "Laura Aurora", "03-03-1970", "Female", "Foobar", "Foobarese", "Movie Drive 1", "Foobar", "70084" },
{ "Wayne", "Bruce", "05-05-1950", "Male", "Gotham City", "American", "Wayne Street 2", "Gotham City", "1234" },
{ "Bond", "James", "07-07-1960", "Male", "Manchester", "British", "Bond Street 007", "London", "1000" }
};
PdfReader reader;
ByteArrayOutputStream baos;
PdfStamper stamper;
AcroFields form;
Document document = new Document();
try {
PdfCopy copy = new PdfCopy(document, new FileOutputStream("EIDForms.pdf"));
document.open();
for (int i = 0; i < values.length; i++) {
// set fields
reader = new PdfReader("EIDFormTemplate.pdf");
baos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, baos);
form = stamper.getAcroFields();
form.setExtraMargin(0, 1);
for (int j = 0; j < keys.length; j++) {
form.setField(keys[j], values[i][j]);
}
stamper.setFormFlattening(true);
stamper.close();
// add page
reader = new PdfReader(baos.toByteArray());
copy.addPage(copy.getImportedPage(reader, 1));
}
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
document.close();
The more complex version of this example is used at Ghent University to create 27,000+ page documents with letters that have to be sent to every student. Although the content of these letters may change on a regular basis, the source code needed to stamp the student data on each letter remains the same as long as the fieldnames in the template don't change. It's a very powerful solution.
For the sake of completeness, I have adapted the EIDFormTemplate.java example the way I described before: using page events and ColumnText: BatchFormFill.java. We have only three records in 'database', so in both cases a PDF with 3 pages is generated, yet a PDF created using the first method (EIDForms.pdf) is 14 KB, while the PDF created using the 'batch' method (batch.pdf) is only 3KB. In order words: you can reduce the file size drastically using the second method. The same goes for performance!
But I promised you I would talk about the eID, so it is high time we turn this page and have a look at an example where the form is filled in automatically using the data from our eID.
