package com.canoo.webtest.plugins.pdftest.htmlunit.pdfbox;
import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.commons.collections.Predicate;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import com.canoo.webtest.plugins.pdftest.htmlunit.PDFField;
/**
* Implementation of {@link PDFField} based on
* <a href="http://www.pdfbox.org/">PDFBox</a>.
* @author Etienne Studer
* @author Marc Guillemot
*/
public class PdfBoxPDFField implements PDFField {
private final PDField field_;
private PdfBoxPDFField(final PDField field)
{
field_ = field;
}
public String toString() {
final StringBuffer sb = new StringBuffer();
sb.append("name: " + getName() + ", ");
sb.append("value: " + getValue());
return sb.toString();
}
public String getValue() {
try
{
final PDField parent = field_.getParent();
final PDField field = parent != null ? parent : field_;
String value = field.getValue();
if (value == null)
value = PdfBoxPDFPage.stringValue(field.getDictionary().getDictionaryObject(COSName.DV));
return value;
}
catch (final IOException e) {
throw new RuntimeException("Can't read field value", e);
}
}
protected static int getPageNumber(final PDField nativeField)
{
int pageNumber = -1;
try
{
final COSDictionary page = (COSDictionary) nativeField.getWidget().getDictionary().getDictionaryObject(COSName.P);
final List pages = nativeField.getAcroForm().getDocument().getDocumentCatalog().getAllPages();
for (final ListIterator iter = pages.listIterator(); iter.hasNext();) {
final PDPage pageX = (PDPage) iter.next();
if (pageX.getCOSDictionary().equals(page)) {
pageNumber = iter.previousIndex();
break;
}
}
}
catch (final IOException e)
{
throw new RuntimeException("Failed accessing the page", e);
}
if (pageNumber == -1)
throw new RuntimeException("Failed retrieving page number for field " + nativeField);
return 1 + pageNumber;
}
public PDField getNativeField()
{
return field_;
}
public boolean isReadOnly()
{
return getNativeField().isReadonly();
}
/**
* Gets the field name
*/
public String getName()
{
try
{
return getNativeField().getFullyQualifiedName();
}
catch (final IOException e)
{
throw new RuntimeException("Problem extracting field name", e);
}
}
private static final Map<PDField, PDFField> wrappers_ = new WeakHashMap<PDField, PDFField>();
static public PDFField wrap(final PDField nativeField)
{
PDFField wrapperField = wrappers_.get(nativeField);
if (wrapperField == null)
{
wrapperField = new PdfBoxPDFField(nativeField);
wrappers_.put(nativeField, wrapperField);
}
return wrapperField;
}
protected abstract static class FieldPredicate implements Predicate
{
public boolean evaluate(final Object object) {
try {
return evaluateField((PDField) object);
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
protected abstract boolean evaluateField(final PDField field) throws IOException;
/**
* Builds a field predicate accepting only fields with the given name
* @param name the name to filter with
* @return a predicate
*/
static FieldPredicate buildNamePredicate(final String name)
{
return new FieldPredicate()
{
protected boolean evaluateField(final PDField field) throws IOException {
final PDField parent = field.getParent();
final String fieldName;
if (parent != null)
fieldName = parent.getFullyQualifiedName();
else
fieldName = field.getFullyQualifiedName();
return name.equals(fieldName);
}
};
}
/**
* Builds a field predicate accepting only fields located on the given page
* @param pageNumber the page on which fields should be located
* @return a predicate
*/
static FieldPredicate buildPageNumberPredicate(final int pageNumber)
{
return new FieldPredicate()
{
protected boolean evaluateField(final PDField field) throws IOException {
return pageNumber == getPageNumber(field);
}
};
}
}
}