0001: /*
0002: * Copyright (c) 2007, intarsys consulting GmbH
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * - Redistributions of source code must retain the above copyright notice,
0008: * this list of conditions and the following disclaimer.
0009: *
0010: * - Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * - Neither the name of intarsys nor the names of its contributors may be used
0015: * to endorse or promote products derived from this software without specific
0016: * prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028: * POSSIBILITY OF SUCH DAMAGE.
0029: */
0030: package de.intarsys.pdf.pd;
0031:
0032: import java.util.Collections;
0033: import java.util.HashSet;
0034: import java.util.Iterator;
0035: import java.util.List;
0036: import java.util.Set;
0037:
0038: import de.intarsys.pdf.cos.COSArray;
0039: import de.intarsys.pdf.cos.COSBasedObject;
0040: import de.intarsys.pdf.cos.COSDictionary;
0041: import de.intarsys.pdf.cos.COSInteger;
0042: import de.intarsys.pdf.cos.COSName;
0043: import de.intarsys.pdf.cos.COSObject;
0044: import de.intarsys.pdf.cos.COSString;
0045:
0046: /**
0047: * Abstract superclass for the different field types in an AcroForm.
0048: *
0049: */
0050: abstract public class PDAcroFormField extends PDAcroFormNode implements
0051: IAdditionalActionSupport {
0052: /**
0053: * The meta class implementation
0054: */
0055: static public class MetaClass extends PDAcroFormNode.MetaClass {
0056: protected MetaClass(Class instanceClass) {
0057: super (instanceClass);
0058: }
0059:
0060: protected COSName cosGetFieldType(COSDictionary dict) {
0061: COSName type = dict.get(DK_FT).asName();
0062: if (type == null) {
0063: COSDictionary parent = dict.get(DK_Parent)
0064: .asDictionary();
0065: if (parent != null) {
0066: return cosGetFieldType(parent);
0067: }
0068: }
0069: return type;
0070: }
0071:
0072: protected COSBasedObject.MetaClass doDetermineClass(
0073: COSObject object) {
0074: if (!(object instanceof COSDictionary)) {
0075: return null;
0076: }
0077: COSObject fieldType = cosGetFieldType((COSDictionary) object);
0078: if (CN_FT_Tx.equals(fieldType)) {
0079: return PDAFTextField.META;
0080: } else if (CN_FT_Btn.equals(fieldType)) {
0081: return PDAFButtonField.META;
0082: } else if (CN_FT_Ch.equals(fieldType)) {
0083: return PDAFChoiceField.META;
0084: } else if (CN_FT_Sig.equals(fieldType)) {
0085: return PDAFSignatureField.META;
0086: } else {
0087: return PDAFIntermediateNode.META;
0088: }
0089: }
0090: }
0091:
0092: /** The name for field types entry. */
0093: static public final COSName DK_FT = COSName.constant("FT"); //$NON-NLS-1$
0094:
0095: /** Field type Button */
0096: static public final COSName CN_FT_Btn = COSName.constant("Btn"); //$NON-NLS-1$
0097:
0098: /** Field type Text */
0099: static public final COSName CN_FT_Tx = COSName.constant("Tx"); //$NON-NLS-1$
0100:
0101: /** Field type Choice */
0102: static public final COSName CN_FT_Ch = COSName.constant("Ch"); //$NON-NLS-1$
0103:
0104: /** Field type Signature */
0105: static public final COSName CN_FT_Sig = COSName.constant("Sig"); //$NON-NLS-1$
0106:
0107: /** The name for the parent entry. */
0108: static public final COSName DK_Parent = COSName.constant("Parent"); //$NON-NLS-1$
0109:
0110: /** The name for the childrens entry. */
0111: static public final COSName DK_Kids = COSName.constant("Kids"); //$NON-NLS-1$
0112:
0113: /** The name for the partial field name entry, also called the local name. */
0114: static public final COSName DK_T = COSName.constant("T"); //$NON-NLS-1$
0115:
0116: /** The name for the AlternateFieldName entry. */
0117: static public final COSName DK_TU = COSName.constant("TU"); //$NON-NLS-1$
0118:
0119: /** The name for the mapping entry. */
0120: static public final COSName DK_TM = COSName.constant("TM"); //$NON-NLS-1$
0121:
0122: /**
0123: * The name of the FieldFlags entry.
0124: * <p>
0125: * For a list of possible flags:
0126: * </p>
0127: *
0128: * @see de.intarsys.pdf.pd.AcroFormFieldFlags
0129: */
0130: static public final COSName DK_Ff = COSName.constant("Ff"); //$NON-NLS-1$
0131:
0132: /** The name for the fields value entry. */
0133: static public final COSName DK_V = COSName.constant("V"); //$NON-NLS-1$
0134:
0135: /** The key for the DefaultValue entry. */
0136: static public final COSName DK_DV = COSName.constant("DV"); //$NON-NLS-1$
0137:
0138: /** alignment constant: 0: Left-justified */
0139: final static public int ALIGNMENT_LEFT = 0;
0140:
0141: /** alignment constant: 1: Centered */
0142: final static public int ALIGNMENT_CENTER = 1;
0143:
0144: /** alignment constant: 2: Right-justified */
0145: final static public int ALIGNMENT_RIGHT = 2;
0146:
0147: /** The name for the DefaultStyle entry. */
0148: static public final COSName DK_DS = COSName.constant("DS"); //$NON-NLS-1$
0149:
0150: /** The name for RichTextString value entry. */
0151: static public final COSName DK_RV = COSName.constant("RV"); //$NON-NLS-1$
0152:
0153: /** supported additional action triggers */
0154: static public final Set ACROFORMFIELD_ACTION_TRIGGERS;
0155:
0156: /** The meta class instance */
0157: static public final MetaClass META = new MetaClass(MetaClass.class
0158: .getDeclaringClass());
0159:
0160: /** The name for the MaximumLength entry. */
0161: static public final COSName DK_MaxLen = COSName.constant("MaxLen"); // //$NON-NLS-1$
0162:
0163: static {
0164: ACROFORMFIELD_ACTION_TRIGGERS = new HashSet(5);
0165: ACROFORMFIELD_ACTION_TRIGGERS.add("K"); //$NON-NLS-1$
0166: ACROFORMFIELD_ACTION_TRIGGERS.add("F"); //$NON-NLS-1$
0167: ACROFORMFIELD_ACTION_TRIGGERS.add("V"); //$NON-NLS-1$
0168: ACROFORMFIELD_ACTION_TRIGGERS.add("C"); //$NON-NLS-1$
0169: }
0170:
0171: private AcroFormFieldFlags fieldFlags;
0172:
0173: private List cachedKids;
0174:
0175: protected PDAcroFormField(COSObject object) {
0176: super (object);
0177: }
0178:
0179: /**
0180: * Insert a new {@link PDAnnotation} object for the form field. The
0181: * annotation represents the visual component displaying the logical form
0182: * field. A form field can be represented by more than one annotation.
0183: *
0184: * @param annot
0185: * The {@link PDAnnotation} to add to the field.
0186: */
0187: public void addAnnotation(PDWidgetAnnotation annot) {
0188: cosAddKid(annot.cosGetDict());
0189: }
0190:
0191: /*
0192: * (non-Javadoc)
0193: *
0194: * @see de.intarsys.pdf.pd.PDAcroFormNode#addField(de.intarsys.pdf.pd.PDAcroFormField)
0195: */
0196: public void addField(PDAcroFormField field) {
0197: cosAddKid(field.cosGetDict());
0198: if (field.isTypeSig()) {
0199: getAcroForm().getSigFlags().setSignatureExists(true);
0200: }
0201: }
0202:
0203: /**
0204: * Get the integer representing the field flags.
0205: *
0206: * @return Get the integer representing the field flags.
0207: */
0208: public int basicGetFieldFlags() {
0209: COSInteger flags = cosGetFieldInheritable(DK_Ff).asInteger();
0210: if (flags != null) {
0211: return flags.intValue();
0212: }
0213: return 0; // default
0214: }
0215:
0216: /**
0217: * Assign the integer representing the field flags.
0218: *
0219: * @param newFlags
0220: * The new flags
0221: */
0222: public void basicSetFieldFlags(int newFlags) {
0223: if (getParent() != null) {
0224: COSInteger parentFlag = getParent().cosGetFieldInheritable(
0225: DK_Ff).asInteger();
0226: if ((parentFlag != null)
0227: && (parentFlag.intValue() == newFlags)) {
0228: cosRemoveField(DK_Ff); // clear own flag
0229: return;
0230: }
0231: }
0232: cosSetField(DK_Ff, COSInteger.create(newFlags));
0233: }
0234:
0235: protected boolean checkFieldType(COSName checkType) {
0236: return checkType.equals(cosGetFieldType());
0237: }
0238:
0239: /*
0240: * (non-Javadoc)
0241: *
0242: * @see de.intarsys.pdf.pd.PDAcroFormNode#collectLeafFields(java.util.List)
0243: */
0244: protected List collectLeafFields(List result) {
0245: result.add(this );
0246: return result;
0247: }
0248:
0249: /**
0250: * Copy the receiver.
0251: *
0252: * <p>
0253: * The copy made does NOT contain any children information.
0254: * </p>
0255: *
0256: * @return A copy of the receiver.
0257: */
0258: public PDAcroFormField copy() {
0259: // TODO 2 define good copy semantics
0260: COSDictionary dict = COSDictionary.create();
0261: dict.beIndirect();
0262:
0263: dict.put(DK_FT, cosGetField(DK_FT).copyShallow());
0264: PDAcroFormField copy = (PDAcroFormField) PDAcroFormField.META
0265: .createFromCos(dict);
0266:
0267: // copy the important parameters
0268: copy.cosSetField(DK_T, cosGetField(DK_T).copyShallow());
0269: copy.cosSetField(DK_V, cosGetField(DK_V).copyShallow());
0270: copy.cosSetField(DK_TU, cosGetField(DK_TU).copyShallow());
0271: copy.cosSetField(DK_TM, cosGetField(DK_TM).copyShallow());
0272: copy.cosSetField(DK_Ff, cosGetField(DK_Ff).copyShallow());
0273: copy.cosSetField(DK_DV, cosGetField(DK_DV).copyShallow());
0274: copy.cosSetField(DK_DA, cosGetField(DK_DA).copyShallow());
0275: copy.cosSetField(DK_Q, cosGetField(DK_Q).copyShallow());
0276: copy.cosSetField(PDAFChoiceField.DK_Opt, cosGetField(
0277: PDAFChoiceField.DK_Opt).copyShallow());
0278: copy.cosSetField(DK_MaxLen, cosGetField(DK_MaxLen)
0279: .copyShallow());
0280: copy.cosSetField(PDAFChoiceField.DK_TI, cosGetField(
0281: PDAFChoiceField.DK_TI).copyShallow());
0282: copy.cosSetField(PDAFChoiceField.DK_I, cosGetField(
0283: PDAFChoiceField.DK_I).copyShallow());
0284: return copy;
0285: }
0286:
0287: protected void cosAddKid(COSDictionary dict) {
0288: COSArray cosKids = cosGetField(DK_Kids).asArray();
0289: if (cosKids == null) {
0290: cosKids = COSArray.create();
0291: cosSetField(DK_Kids, cosKids);
0292: }
0293: cosKids.add(dict);
0294: dict.put(DK_Parent, cosGetDict());
0295: }
0296:
0297: /**
0298: * Tries to return a valid /DV entry:
0299: * <ol>
0300: * <li>returns its own /DV entry, if it is not null</li>
0301: * <li>returns the /DV entry of its logical root, if it is not null</li>
0302: * <li>returns the first /DV entry found of the logical roots kids</li>
0303: * <li>null if nothing was found</li>
0304: * </ol>
0305: *
0306: * @return see description
0307: */
0308: public COSObject cosGetDefaultValue() {
0309: return cosGetValueEntry(DK_DV);
0310: }
0311:
0312: /**
0313: * The AcroForm field type expected for this.
0314: *
0315: * @return The AcroForm field type expected for this.
0316: */
0317: abstract public COSName cosGetExpectedFieldType();
0318:
0319: /**
0320: * The real AcroForm field type of this.
0321: *
0322: * @return The real AcroForm field type of this.
0323: */
0324: public COSName cosGetFieldType() {
0325: return cosGetFieldInheritable(DK_FT).asName();
0326: }
0327:
0328: /**
0329: * Tries to return a valid /V entry:
0330: * <ol>
0331: * <li>returns its own /V entry, if it is not null</li>
0332: * <li>returns the /V entry of its logical root, if it is not null</li>
0333: * <li>returns the first /V entry found of the logical roots kids</li>
0334: * <li>null if nothing was found</li>
0335: * </ol>
0336: *
0337: * @return see description
0338: */
0339: public COSObject cosGetValue() {
0340: return cosGetValueEntry(DK_V);
0341: }
0342:
0343: /**
0344: * Tries to return a valid value entry (/DV or /V):
0345: * <ol>
0346: * <li>returns its own value entry, if it is not null</li>
0347: * <li>returns the value entry of its logical root, if it is not null</li>
0348: * <li>returns the first value entry found of the logical roots kids</li>
0349: * <li>null if nothing was found</li>
0350: * </ol>
0351: *
0352: * @return see description
0353: */
0354: protected COSObject cosGetValueEntry(COSName key) {
0355: COSObject cosValue = cosGetField(key);
0356: if (cosValue.isNull()) {
0357: cosValue = getLogicalRoot().cosGetFieldDescendant(key);
0358: }
0359: return cosValue;
0360: }
0361:
0362: protected boolean cosRemoveKid(COSDictionary dict) {
0363: COSArray cosKids = cosGetField(DK_Kids).asArray();
0364: if (cosKids == null) {
0365: return false;
0366: }
0367: if (cosKids.remove(dict)) {
0368: dict.remove(DK_Parent);
0369: return true;
0370: }
0371: return false;
0372: }
0373:
0374: protected COSObject cosSetDefaultValue(COSObject newDefaultValue) {
0375: return cosSetFieldInheritable(DK_DV, newDefaultValue);
0376: }
0377:
0378: protected COSObject cosSetFieldType(COSName newFieldType) {
0379: return cosSetFieldInheritable(DK_FT, newFieldType);
0380: }
0381:
0382: protected void cosSetMappingName(String newMappingName) {
0383: setFieldName(DK_TM, newMappingName);
0384: }
0385:
0386: protected void cosSetRichTextString(String newRichTextString) {
0387: setFieldName(DK_RV, newRichTextString);
0388: }
0389:
0390: /**
0391: * Sets the /V entry in this node and removes all /V entries in child nodes.
0392: *
0393: * @param newValue
0394: *
0395: * @return The /V entry previously associated with this.
0396: */
0397: public COSObject cosSetValue(COSObject newValue) {
0398: return cosSetFieldInheritable(DK_V, newValue);
0399: }
0400:
0401: /**
0402: * @deprecated
0403: * @param disposeEmptyAncestors
0404: */
0405: public void dispose(boolean disposeEmptyAncestors) {
0406: PDAcroFormField removeTarget = null;
0407: if (getLogicalRoot().cosGetDict() == cosGetDict()) {
0408: // I am the logical root
0409: removeTarget = getParent();
0410: } else {
0411: // just an anonymous leaf
0412: removeTarget = getLogicalRoot();
0413: }
0414:
0415: //
0416: if (removeTarget == null) {
0417: // remove from acro form
0418: getAcroForm().removeField(this );
0419: } else {
0420: removeTarget.removeField(this );
0421: if (disposeEmptyAncestors
0422: && (removeTarget.getKids().size() == 0)) {
0423: // target has no more kids, dispose it
0424: removeTarget.dispose(disposeEmptyAncestors);
0425: }
0426: }
0427: }
0428:
0429: /*
0430: * (non-Javadoc)
0431: *
0432: * @see de.intarsys.pdf.pd.PDAcroFormNode#getAcroForm()
0433: */
0434: public PDAcroForm getAcroForm() {
0435: PDDocument doc = getDoc();
0436: if (doc == null) {
0437: return null;
0438: }
0439: return doc.getAcroForm();
0440: }
0441:
0442: /*
0443: * (non-Javadoc)
0444: *
0445: * @see de.intarsys.pdf.pd.IAdditionalActionSupport#getAdditionalActions()
0446: */
0447: public PDAdditionalActions getAdditionalActions() {
0448: COSDictionary field = cosGetField(DK_AA).asDictionary();
0449: return (PDAdditionalActions) PDAdditionalActions.META
0450: .createFromCos(field);
0451: }
0452:
0453: /**
0454: * The fields alternate name.
0455: *
0456: * @return The fields alternate name.
0457: */
0458: public String getAlternateFieldName() {
0459: return getFieldString(DK_TU, null);
0460: }
0461:
0462: protected List getAnnotations(List annotations) {
0463: if (isAnnotation()) {
0464: annotations.add(PDAnnotation.META
0465: .createFromCos(cosGetDict()));
0466: }
0467: return super .getAnnotations(annotations);
0468: }
0469:
0470: /**
0471: * a acro form field may be associated with a widget annotation. somewhere
0472: * down in the hierarchy there MUST be an annotation. this method returns
0473: * the first annotation available.
0474: *
0475: * @return the first associated annotation object if available (or null)
0476: *
0477: * @deprecated
0478: */
0479: public PDAnnotation getAnyAnnotation() {
0480: // todo 1 why not PDWIdgetAnnotation
0481: if (isAnnotation()) {
0482: return (PDAnnotation) PDAnnotation.META
0483: .createFromCos(cosGetDict());
0484: }
0485: for (Iterator i = getGenericChildren().iterator(); i.hasNext();) {
0486: PDAcroFormField kid = (PDAcroFormField) i.next();
0487: PDAnnotation result = kid.getAnyAnnotation();
0488: if (result != null) {
0489: return result;
0490: }
0491: }
0492: return null;
0493: }
0494:
0495: protected String getDefaultStyle() {
0496: return getFieldString(DK_DS, null);
0497: }
0498:
0499: /**
0500: * The flags associated with the form field.
0501: *
0502: * @return The flags associated with the form field.
0503: */
0504: public AcroFormFieldFlags getFieldFlags() {
0505: if (fieldFlags == null) {
0506: fieldFlags = new AcroFormFieldFlags(this );
0507: }
0508: return fieldFlags;
0509: }
0510:
0511: /*
0512: * (non-Javadoc)
0513: *
0514: * @see de.intarsys.pdf.pd.PDObject#getGenericChildren()
0515: */
0516: public List getGenericChildren() {
0517: return getKids();
0518: }
0519:
0520: /*
0521: * (non-Javadoc)
0522: *
0523: * @see de.intarsys.pdf.pd.PDObject#getGenericParent()
0524: */
0525: public PDObject getGenericParent() {
0526: PDObject parent = getParent();
0527: if (parent == null) {
0528: return getAcroForm();
0529: }
0530: return parent;
0531: }
0532:
0533: /**
0534: * The child nodes of this (named after the /Kids key in the defining
0535: * {@link COSDictionary});
0536: *
0537: * @return The child nodes of this.
0538: */
0539: public List getKids() {
0540: if (cachedKids == null) {
0541: cachedKids = getPDObjects(DK_Kids, PDAcroFormField.META,
0542: true);
0543: if (cachedKids == null) {
0544: // do not cache!
0545: return Collections.EMPTY_LIST;
0546: }
0547: }
0548: return cachedKids;
0549: }
0550:
0551: /**
0552: * The local name for this node. This method returns null for an non
0553: * existing or empty /T entry in the defining {@link COSDictionary}.
0554: *
0555: * @return The local name for this node.
0556: */
0557: public String getLocalName() {
0558: return getLocalName(false);
0559: }
0560:
0561: /**
0562: * The local name for this node. This method returns null for an non
0563: * existing or empty /T entry in the base {@link COSDictionary}. The name
0564: * is transformed to canonical form if <code>canonical</code> is true.
0565: *
0566: * @param canonical
0567: * Flag if the name shoul be in canonical form.
0568: * @return The local name for this node.
0569: */
0570: public String getLocalName(boolean canonical) {
0571: String name = getFieldString(DK_T, null);
0572: if ((name != null) && (!name.trim().equals(""))) { //$NON-NLS-1$
0573: return canonical ? canonicalize(name) : name;
0574: }
0575: return null;
0576: }
0577:
0578: /**
0579: * The logical parent node of this PDAcroFormField.
0580: *
0581: * <p>
0582: * The logical parent is the next node up the parent hierarchy that has a
0583: * different qualified name, this means it is a node that does not designate
0584: * the same logical field as the receiver.
0585: * </p>
0586: *
0587: * @return the logical parent, or the form itself.
0588: */
0589: public PDAcroFormNode getLogicalParent() {
0590: PDAcroFormField root = getLogicalRoot();
0591: if (root == null) {
0592: return getAcroForm();
0593: }
0594: PDAcroFormField p = root.getParent();
0595: if (p == null) {
0596: return getAcroForm();
0597: }
0598: return p;
0599: }
0600:
0601: /**
0602: * The logical root node of this PDAcroFormField.
0603: *
0604: * <p>
0605: * The logical root is the last node up the parent hierarchy that has the
0606: * name qualified name, this means the topmost node that designates the same
0607: * logical field as the receiver.
0608: * </p>
0609: *
0610: * @return the root field, or this.
0611: */
0612: public PDAcroFormField getLogicalRoot() {
0613: if (getLocalName(false) == null) {
0614: PDAcroFormField p = getParent();
0615: if (p == null) {
0616: return this ;
0617: }
0618: return p.getLogicalRoot();
0619: }
0620: return this ;
0621: }
0622:
0623: protected String getMappingName() {
0624: return getFieldString(DK_TM, null);
0625: }
0626:
0627: /**
0628: * The maximum length for this field or <code>null</code> if not defined.
0629: *
0630: * @return The maximum length for this field or <code>null</code> if not
0631: * defined.
0632: */
0633: public Integer getMaxLen() {
0634: COSInteger cosBase = cosGetFieldInheritable(DK_MaxLen)
0635: .asInteger();
0636: if (cosBase != null) {
0637: return Integer.valueOf(cosBase.intValue());
0638: }
0639: cosBase = cosGetFieldDescendant(DK_MaxLen).asInteger();
0640: if (cosBase != null) {
0641: return Integer.valueOf(cosBase.intValue());
0642: }
0643: return null;
0644: }
0645:
0646: /**
0647: * The parent node of this.
0648: * <p>
0649: * AcroForm fields are arranged in a hierarchical structure, beginning with
0650: * the root AcroForm. Fields under the AcroForm return <code>null</code>
0651: * as their parent.
0652: *
0653: * @return The parent node of this.
0654: */
0655: public PDAcroFormField getParent() {
0656: COSDictionary dict = cosGetField(DK_Parent).asDictionary();
0657: if (dict != null) {
0658: return (PDAcroFormField) PDAcroFormField.META
0659: .createFromCos(dict);
0660: }
0661: return null;
0662: }
0663:
0664: /**
0665: * Returns the parent name, if any, or null.
0666: *
0667: * @param canonical
0668: * True if the name should be canonical.
0669: *
0670: * @return the name of the direct parent PDAcroFormField
0671: */
0672: protected String getParentName(boolean canonical) {
0673: if (getParent() == null) {
0674: return null;
0675: }
0676: return getParent().getQualifiedName(canonical);
0677: }
0678:
0679: /**
0680: * A fully qualified name for this.
0681: *
0682: * <p>
0683: * The name of a acro form field is the concatenation of every node's name
0684: * in the hierarchy, separated with '.'.
0685: * </p>
0686: *
0687: * @return A fully qualified name for this.
0688: */
0689: public String getQualifiedName() {
0690: return getQualifiedName(false);
0691: }
0692:
0693: /**
0694: * A fully qualified name for this. If requested, the name is in canonical
0695: * format.
0696: *
0697: * <p>
0698: * The name of a acro form field is the concatenation of every node's name
0699: * in the hierarchy, separated with '.'.
0700: * </p>
0701: *
0702: * @param canonical
0703: * Flag if the name is in canonical format
0704: * @return A fully qualified name for this.
0705: */
0706: public String getQualifiedName(boolean canonical) {
0707: String partialName = getLocalName(canonical);
0708: String parentName = getParentName(canonical);
0709:
0710: String qualifiedName = parentName;
0711: if (partialName != null) {
0712: if (parentName == null) {
0713: qualifiedName = partialName;
0714: } else {
0715: qualifiedName = parentName + "." + partialName; //$NON-NLS-1$
0716: }
0717: }
0718: return qualifiedName;
0719: }
0720:
0721: protected String getRichTextString() {
0722: return getFieldString(DK_RV, null);
0723: }
0724:
0725: /*
0726: * (non-Javadoc)
0727: *
0728: * @see de.intarsys.pdf.pd.IAdditionalActionSupport#getSupportedTriggerEvents()
0729: */
0730: public Set getSupportedTriggerEvents() {
0731: return ACROFORMFIELD_ACTION_TRIGGERS;
0732: }
0733:
0734: /**
0735: * The value from cosGetValue() converted to a String
0736: *
0737: * @return The value from cosGetValue() converted to a String
0738: */
0739: public String getValueString() {
0740: COSObject value = cosGetValue();
0741: if (value.isNull()) {
0742: return null;
0743: }
0744: return value.stringValue();
0745: }
0746:
0747: /**
0748: * The value from cosGetDefaultValue() converted to a String
0749: *
0750: * @return The value from cosGetDefaultValue() converted to a String
0751: */
0752: public String getDefaultValueString() {
0753: COSObject value = cosGetDefaultValue();
0754: if (value.isNull()) {
0755: return null;
0756: }
0757: return value.stringValue();
0758: }
0759:
0760: protected void initializeFromScratch() {
0761: super .initializeFromScratch();
0762: cosSetFieldType(cosGetExpectedFieldType());
0763: cosSetField(DK_T, COSString.create("")); //$NON-NLS-1$
0764: }
0765:
0766: /*
0767: * (non-Javadoc)
0768: *
0769: * @see de.intarsys.pdf.pd.PDAcroFormNode#invalidateCaches()
0770: */
0771: public void invalidateCaches() {
0772: super .invalidateCaches();
0773: COSArray cosKids = cosGetField(DK_Kids).asArray();
0774: if (cosKids != null) {
0775: cosKids.removeObjectListener(this );
0776: }
0777: if (cachedKids != null) {
0778: // name may have changed
0779: for (Iterator i = cachedKids.iterator(); i.hasNext();) {
0780: PDAcroFormField field = (PDAcroFormField) i.next();
0781: field.invalidateCaches();
0782: }
0783: cachedKids = null;
0784: }
0785: }
0786:
0787: /**
0788: * <code>true</code> if variable text in this is centered.
0789: *
0790: * @return <code>true</code> if variable text in this is centered.
0791: */
0792: public boolean isAlignmentCenter() {
0793: return getQuadding() == ALIGNMENT_CENTER;
0794: }
0795:
0796: /**
0797: * <code>true</code> if variable text in this is left aligned.
0798: *
0799: * @return <code>true</code> if variable text in this is left aligned.
0800: */
0801: public boolean isAlignmentLeft() {
0802: return getQuadding() == ALIGNMENT_LEFT;
0803: }
0804:
0805: /**
0806: * <code>true</code> if variable text in this is right aligned.
0807: *
0808: * @return <code>true</code> if variable text in this is right aligned.
0809: */
0810: public boolean isAlignmentRight() {
0811: return getQuadding() == ALIGNMENT_RIGHT;
0812: }
0813:
0814: /**
0815: * Returns true when the field is an annotation
0816: *
0817: * @return true when the field is an annotation
0818: */
0819: public boolean isAnnotation() {
0820: // checking subtype because "/Type Annot" is optional
0821: return !cosGetDict().get(PDObject.DK_Subtype).isNull();
0822: }
0823:
0824: /**
0825: * Convenience to access "comb" flag.
0826: */
0827: public boolean isComb() {
0828: return getFieldFlags().isComb();
0829: }
0830:
0831: /**
0832: * Convenience to access "DoNotScroll" flag.
0833: */
0834: public boolean isDoNotScroll() {
0835: return getFieldFlags().isDoNotScroll();
0836: }
0837:
0838: /**
0839: * Convenience to access "Multiline" flag.
0840: */
0841: public boolean isMultiline() {
0842: return getFieldFlags().isMultiline();
0843: }
0844:
0845: /**
0846: * Convenience to access "NoExport" flag.
0847: */
0848: public boolean isNoExport() {
0849: return getFieldFlags().isNoExport();
0850: }
0851:
0852: /**
0853: * Convenience to access "ReadOnly" flag.
0854: */
0855: public boolean isReadOnly() {
0856: return getFieldFlags().isReadOnly();
0857: }
0858:
0859: /**
0860: * Return true if this is a field of type "Btn".
0861: *
0862: * <p>
0863: * "Btn" means this is a button style object.
0864: * </p>
0865: *
0866: * @return Return true if this is a field of type "Btn".
0867: */
0868: public boolean isTypeBtn() {
0869: return false;
0870: }
0871:
0872: /**
0873: * Return true if this is a field of type "Ch".
0874: *
0875: * <p>
0876: * "Ch" means this is a choice object.
0877: * </p>
0878: *
0879: * @return Return true if this is a field of type "Ch".
0880: */
0881: public boolean isTypeCh() {
0882: return false;
0883: }
0884:
0885: /**
0886: * Return true if this is a field of type "Sig".
0887: *
0888: * <p>
0889: * "Sig" means this is a text style object.
0890: * </p>
0891: *
0892: * @return Return true if this is a field of type "Sig".
0893: */
0894: public boolean isTypeSig() {
0895: return false;
0896: }
0897:
0898: /**
0899: * Return true if this is a text field.
0900: *
0901: * <p>
0902: * "Tx" means this is a text style object.
0903: * </p>
0904: *
0905: * @return Return true if this is a field of type "Tx".
0906: */
0907: public boolean isTypeTx() {
0908: return false;
0909: }
0910:
0911: /*
0912: * (non-Javadoc)
0913: *
0914: * @see de.intarsys.pdf.pd.PDAcroFormNode#removeField(de.intarsys.pdf.pd.PDAcroFormField)
0915: */
0916: public boolean removeField(PDAcroFormField field) {
0917: boolean removed = cosRemoveKid(field.cosGetDict());
0918: getAcroForm().getSigFlags().setSignatureExists(
0919: getAcroForm().isSignatureExists());
0920: return removed;
0921: }
0922:
0923: /**
0924: * Reset this to its default value.
0925: */
0926: public void reset() {
0927: //
0928: COSObject value = cosGetDefaultValue();
0929: if (value != null) {
0930: value = value.copyOptional();
0931: }
0932: cosSetValue(value);
0933: }
0934:
0935: /*
0936: * (non-Javadoc)
0937: *
0938: * @see de.intarsys.pdf.pd.IAdditionalActionSupport#setActions(de.intarsys.pdf.pd.PDAdditionalActions)
0939: */
0940: public void setAdditionalActions(PDAdditionalActions actions) {
0941: setFieldObject(DK_AA, actions);
0942: }
0943:
0944: /**
0945: * Make variable text centered.
0946: */
0947: public void setAlignmentCenter() {
0948: setQuadding(ALIGNMENT_CENTER);
0949: }
0950:
0951: /**
0952: * Make variable text left aligned.
0953: */
0954: public void setAlignmentLeft() {
0955: setQuadding(ALIGNMENT_LEFT);
0956: }
0957:
0958: /**
0959: * Make variable text right aligned.
0960: */
0961: public void setAlignmentRight() {
0962: setQuadding(ALIGNMENT_RIGHT);
0963: }
0964:
0965: /**
0966: * Asssign a alternate field name.
0967: *
0968: * @param newAlternateFieldName
0969: * The new alternate field name
0970: */
0971: public void setAlternateFieldName(String newAlternateFieldName) {
0972: setFieldString(DK_TU, newAlternateFieldName);
0973: }
0974:
0975: /**
0976: * Convenience method to access "Comb" flag.
0977: */
0978: public void setComb(boolean f) {
0979: getFieldFlags().setComb(f);
0980: }
0981:
0982: /**
0983: * Assign new default style
0984: *
0985: * @param newDefaultStyle
0986: * The new default style.
0987: */
0988: protected void setDefaultStyle(String newDefaultStyle) {
0989: setFieldName(DK_DS, newDefaultStyle);
0990: }
0991:
0992: /**
0993: * Assign a new default value. The default value is used if no value (/V) is
0994: * available.
0995: *
0996: * @param value
0997: * The new default value.
0998: */
0999: public void setDefaultValue(String value) {
1000: if (value == null) {
1001: cosSetDefaultValue(null);
1002: } else {
1003: cosSetDefaultValue(COSString.create(value));
1004: }
1005: }
1006:
1007: /**
1008: * Convenience method to access "DoNotScroll" flag.
1009: */
1010: public void setDoNotScroll(boolean f) {
1011: getFieldFlags().setDoNotScroll(f);
1012: }
1013:
1014: protected void setKids(List newKids) {
1015: setPDObjects(DK_Kids, newKids);
1016: }
1017:
1018: /**
1019: * Assign a new local name.
1020: *
1021: * @param newLocalName
1022: * The new local name
1023: */
1024: public void setLocalName(String newLocalName) {
1025: setFieldString(DK_T, newLocalName);
1026: }
1027:
1028: /**
1029: * Set the maximum length for this field.
1030: *
1031: * @param newMaxLength
1032: * The new maximum length
1033: */
1034: public void setMaxLength(Integer newMaxLength) {
1035: if (newMaxLength != null) {
1036: setFieldInt(DK_MaxLen, newMaxLength.intValue());
1037: } else {
1038: cosRemoveField(DK_MaxLen);
1039: }
1040: }
1041:
1042: /**
1043: * Convenience method to access "Multiline" flag.
1044: */
1045: public void setMultiline(boolean f) {
1046: getFieldFlags().setMultiline(f);
1047: }
1048:
1049: /**
1050: * Convenience method to access "NoExport" flag.
1051: */
1052: public void setNoExport(boolean f) {
1053: getFieldFlags().setNoExport(f);
1054: }
1055:
1056: protected void setParent(PDAcroFormField newParent) {
1057: setFieldObject(DK_Parent, newParent);
1058: }
1059:
1060: /**
1061: * Convenience method to access "ReadOnly" flag.
1062: */
1063: public void setReadOnly(boolean f) {
1064: getFieldFlags().setReadOnly(f);
1065: }
1066:
1067: /**
1068: * Set the value of this.
1069: *
1070: * @param value
1071: * The new value of this, represented by a {@link String}.
1072: */
1073: public void setValueString(String value) {
1074: if (value == null) {
1075: cosSetValue(null);
1076: } else {
1077: cosSetValue(COSString.create(value));
1078: }
1079: }
1080:
1081: /**
1082: * Set the value of this to a {@link List} of {@link String} objects.
1083: *
1084: * @param values
1085: * The new value.
1086: */
1087: public void setValueStrings(List values) {
1088: if ((values == null) || values.isEmpty()) {
1089: cosSetValue(null);
1090: } else {
1091: cosSetValue(COSString.create((String) values.get(0)));
1092: }
1093: }
1094:
1095: /*
1096: * (non-Javadoc)
1097: *
1098: * @see de.intarsys.pdf.pd.PDObject#toString()
1099: */
1100: public String toString() {
1101: String qName = getQualifiedName();
1102: if (qName == null) {
1103: return "unnamed AcroFormField " + super .toString(); //$NON-NLS-1$
1104: }
1105: return "AcroFormField " + qName + " " + super .toString(); //$NON-NLS-1$ //$NON-NLS-2$
1106: }
1107:
1108: /**
1109: * This is called from one of the field's annotation to set the field's
1110: * value to the appropriate state (along with keeping all other children in
1111: * synch).
1112: *
1113: * @param annotation
1114: */
1115: protected void triggerAnnotation(PDWidgetAnnotation annotation) {
1116: // this will make sense only for buttons...
1117: }
1118: }
|