blob: 17a91e97ce7031e8a1c71a578b1ba48036b535af [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pdfbox.pdmodel.interactive.form;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSeedValue;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
/**
* 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);
getCOSObject().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 : getAcroForm().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
{
getCOSObject().setItem(COSName.V, value);
applyChange();
}
/**
* Sets the value of this field.
*
* <b>This will throw an UnsupportedOperationException if used as the signature fields
* value can't be set using a String</>
*
* @param value the plain text value.
*
* @throws UnsupportedOperationException in all cases!
*/
@Override
public void setValue(String value) throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Signature fields don't support setting the value as String "
+ "- use setValue(PDSignature value) instead");
}
/**
* Sets the default value of this field to be the given signature.
*
* @param value is the PDSignatureField
*/
public void setDefaultValue(PDSignature value) throws IOException
{
getCOSObject().setItem(COSName.DV, value);
}
/**
* Returns the signature contained in this field.
*
* @return A signature dictionary.
*/
public PDSignature getValue()
{
COSBase value = getCOSObject().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 = getCOSObject().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) getCOSObject().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)
{
getCOSObject().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");
}
}
}