package com.tom_roush.pdfbox.pdmodel.interactive.form;
import com.tom_roush.pdfbox.cos.COSBase;
import com.tom_roush.pdfbox.cos.COSDictionary;
import com.tom_roush.pdfbox.cos.COSName;
import com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import com.tom_roush.pdfbox.pdmodel.interactive.digitalsignature.PDSeedValue;
import com.tom_roush.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* A signature field is a form field that contains a digital signature.
*
* @author Ben Litchfield
* @author Thomas Chojecki
*/
public class PDSignatureField extends PDTerminalField
{
/**
* @see PDTerminalField#PDTerminalField(PDAcroForm)
*
* @param acroForm The acroForm for this field.
* @throws IOException If there is an error while resolving partial name for the signature field
* or getting the widget object.
*/
public PDSignatureField(PDAcroForm acroForm) throws IOException
{
super(acroForm);
dictionary.setItem(COSName.FT, COSName.SIG);
getWidgets().get(0).setLocked(true);
getWidgets().get(0).setPrinted(true);
setPartialName(generatePartialName());
}
/**
* Constructor.
*
* @param acroForm The form that this field is part of.
* @param field the PDF object to represent as a field.
* @param parent the parent node of the node to be created
*/
PDSignatureField(PDAcroForm acroForm, COSDictionary field, PDNonTerminalField parent)
{
super(acroForm, field, parent);
}
/**
* Generate a unique name for the signature.
*
* @return the signature's unique name
*/
private String generatePartialName()
{
String fieldName = "Signature";
Set<String> sigNames = new HashSet<String>();
// fixme: this ignores non-terminal fields, so will miss any descendant signatures
for (PDField field : acroForm.getFields())
{
if (field instanceof PDSignatureField)
{
sigNames.add(field.getPartialName());
}
}
int i = 1;
while (sigNames.contains(fieldName + i))
{
++i;
}
return fieldName + i;
}
/**
* Add a signature dictionary to the signature field.
*
* @param value is the PDSignatureField
* @deprecated Use {@link #setValue(PDSignature)} instead.
*/
@Deprecated
public void setSignature(PDSignature value) throws IOException
{
setValue(value);
}
/**
* Get the signature dictionary.
*
* @return the signature dictionary
*/
public PDSignature getSignature()
{
return getValue();
}
/**
* Sets the value of this field to be the given signature.
*
* @param value is the PDSignatureField
*/
public void setValue(PDSignature value) throws IOException
{
dictionary.setItem(COSName.V, value);
applyChange();
}
/**
* Sets the default value of this field to be the given signature.
*
* @param value is the PDSignatureField
*/
public void setDefaultValue(PDSignature value) throws IOException
{
dictionary.setItem(COSName.DV, value);
}
/**
* Returns the signature contained in this field.
*
* @return A signature dictionary.
*/
public PDSignature getValue()
{
COSBase value = dictionary.getDictionaryObject(COSName.V);
if (value == null)
{
return null;
}
return new PDSignature((COSDictionary) value);
}
/**
* Returns the default value, if any.
*
* @return A signature dictionary.
*/
public PDSignature getDefaultValue()
{
COSBase value = dictionary.getDictionaryObject(COSName.DV);
if (value == null)
{
return null;
}
return new PDSignature((COSDictionary) value);
}
@Override
public String getValueAsString()
{
PDSignature signature = getValue();
return signature != null ? signature.toString() : "";
}
/**
* <p>(Optional; PDF 1.5) A seed value dictionary containing information
* that constrains the properties of a signature that is applied to the
* field.</p>
*
* @return the seed value dictionary as PDSeedValue
*/
public PDSeedValue getSeedValue()
{
COSDictionary dict = (COSDictionary) dictionary.getDictionaryObject(COSName.SV);
PDSeedValue sv = null;
if (dict != null)
{
sv = new PDSeedValue(dict);
}
return sv;
}
/**
* <p>(Optional; PDF 1.) A seed value dictionary containing information
* that constrains the properties of a signature that is applied to the
* field.</p>
*
* @param sv is the seed value dictionary as PDSeedValue
*/
public void setSeedValue(PDSeedValue sv)
{
if (sv != null)
{
dictionary.setItem(COSName.SV, sv);
}
}
@Override
void constructAppearances() throws IOException
{
PDAnnotationWidget widget = this.getWidgets().get(0);
if (widget != null)
{
// check if the signature is visible
if (widget.getRectangle() == null || widget.getRectangle().getHeight() == 0 &&
widget.getRectangle().getWidth() == 0 || widget.isNoView() || widget.isHidden())
{
return;
}
// TODO: implement appearance generation for signatures
throw new UnsupportedOperationException("not implemented");
}
}
}