class FdfReader extends PdfReader {

    PdfName encoding;
    private Map<String, PdfDictionary> fields;
    private String fileSpec;

    /**
     * Reads an FDF form.
     *
     * @param filename the file name of the form
     * @throws IOException on error
     */
    public FdfReader(String filename) throws IOException {
        super(filename);
    }

    /**
     * Reads an FDF form.
     *
     * @param pdfIn the byte array with the form
     * @throws IOException on error
     */
    public FdfReader(byte[] pdfIn) throws IOException {
        super(pdfIn);
    }

    /**
     * Reads an FDF form.
     *
     * @param url the URL of the document
     * @throws IOException on error
     */
    public FdfReader(URL url) throws IOException {
        super(url);
    }

    /**
     * Reads an FDF form.
     *
     * @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the end but is not closed
     * @throws IOException on error
     */
    public FdfReader(InputStream is) throws IOException {
        super(is);
    }

    protected void readPdf() throws IOException {<FILL_FUNCTION_BODY>}

    protected void kidNode(PdfDictionary merged, String name) {
        PdfArray kids = merged.getAsArray(PdfName.KIDS);
        if (kids == null || kids.isEmpty()) {
            if (!name.isEmpty()) {
                name = name.substring(1);
            }
            fields.put(name, merged);
        } else {
            merged.remove(PdfName.KIDS);
            for (int k = 0; k < kids.size(); ++k) {
                PdfDictionary dic = new PdfDictionary();
                dic.merge(merged);
                PdfDictionary newDic = kids.getAsDict(k);
                PdfString t = newDic.getAsString(PdfName.T);
                String newName = name;
                if (t != null) {
                    newName += "." + t.toUnicodeString();
                }
                dic.merge(newDic);
                dic.remove(PdfName.T);
                kidNode(dic, newName);
            }
        }
    }

    protected void readFields() {
        catalog = trailer.getAsDict(PdfName.ROOT);
        PdfDictionary fdf = catalog.getAsDict(PdfName.FDF);
        if (fdf == null) {
            return;
        }
        PdfString fs = fdf.getAsString(PdfName.F);
        if (fs != null) {
            fileSpec = fs.toUnicodeString();
        }
        PdfArray fld = fdf.getAsArray(PdfName.FIELDS);
        if (fld == null) {
            return;
        }
        encoding = fdf.getAsName(PdfName.ENCODING);
        PdfDictionary merged = new PdfDictionary();
        merged.put(PdfName.KIDS, fld);
        kidNode(merged, "");
    }

    /**
     * Gets all the fields. The map is keyed by the fully qualified field name and the value is a merged
     * <CODE>PdfDictionary</CODE> with the field content.
     *
     * @return all the fields
     */
    public Map<String, PdfDictionary> getAllFields() {
        return fields;
    }

    /**
     * Gets the field dictionary.
     *
     * @param name the fully qualified field name
     * @return the field dictionary
     */
    public PdfDictionary getField(String name) {
        return fields.get(name);
    }

    /**
     * Gets the field value or <CODE>null</CODE> if the field does not exist or has no value defined.
     *
     * @param name the fully qualified field name
     * @return the field value or <CODE>null</CODE>
     */
    public String getFieldValue(String name) {
        PdfDictionary field = fields.get(name);
        if (field == null) {
            return null;
        }
        PdfObject v = getPdfObject(field.get(PdfName.V));
        if (v == null) {
            return null;
        }
        if (v.isName()) {
            return PdfName.decodeName(v.toString());
        } else if (v.isString()) {
            PdfString vs = (PdfString) v;
            if (encoding == null || vs.getEncoding() != null) {
                return vs.toUnicodeString();
            }
            byte[] b = vs.getBytes();
            if (b.length >= 2 && b[0] == (byte) 254 && b[1] == (byte) 255) {
                return vs.toUnicodeString();
            }
            try {
                if (encoding.equals(PdfName.SHIFT_JIS)) {
                    return new String(b, "SJIS");
                } else if (encoding.equals(PdfName.UHC)) {
                    return new String(b, "MS949");
                } else if (encoding.equals(PdfName.GBK)) {
                    return new String(b, "GBK");
                } else if (encoding.equals(PdfName.BIGFIVE)) {
                    return new String(b, "Big5");
                }
            } catch (Exception e) {
            }
            return vs.toUnicodeString();
        }
        return null;
    }

    /**
     * Gets the PDF file specification contained in the FDF.
     *
     * @return the PDF file specification contained in the FDF
     */
    public String getFileSpec() {
        return fileSpec;
    }
}

        fields = new HashMap<>();
        try {
            tokens.checkFdfHeader();
            rebuildXref();
            readDocObj();
        } finally {
            try {
                tokens.close();
            } catch (Exception e) {
                // empty on purpose
            }
        }
        readFields();
    
<methods>public void <init>(java.lang.String) throws java.io.IOException,public void <init>(java.lang.String, byte[]) throws java.io.IOException,public void <init>(byte[]) throws java.io.IOException,public void <init>(byte[], byte[]) throws java.io.IOException,public void <init>(java.lang.String, java.security.cert.Certificate, java.security.Key, java.lang.String) throws java.io.IOException,public void <init>(java.net.URL) throws java.io.IOException,public void <init>(java.net.URL, byte[]) throws java.io.IOException,public void <init>(java.io.InputStream, byte[]) throws java.io.IOException,public void <init>(java.io.InputStream) throws java.io.IOException,public void <init>(com.lowagie.text.pdf.RandomAccessFileOrArray, byte[]) throws java.io.IOException,public void <init>(com.lowagie.text.pdf.PdfReader) ,public static byte[] ASCII85Decode(byte[]) ,public static byte[] ASCIIHexDecode(byte[]) ,public static byte[] FlateDecode(byte[]) ,public static byte[] FlateDecode(byte[], boolean) ,public static byte[] LZWDecode(byte[]) ,public com.lowagie.text.pdf.PRIndirectReference addPdfObject(com.lowagie.text.pdf.PdfObject) ,public void addViewerPreference(com.lowagie.text.pdf.PdfName, com.lowagie.text.pdf.PdfObject) ,public void close() ,public byte[] computeUserPassword() ,public void consolidateNamedDestinations() ,public static com.lowagie.text.pdf.PdfObject convertPdfNull(com.lowagie.text.pdf.PdfObject) ,public int createFakeFontSubsets() ,public static byte[] decodePredictor(byte[], com.lowagie.text.pdf.PdfObject) ,public double dumpPerc() ,public void eliminateSharedStreams() ,public com.lowagie.text.pdf.AcroFields getAcroFields() ,public com.lowagie.text.pdf.PRAcroForm getAcroForm() ,public com.lowagie.text.Rectangle getBoxSize(int, java.lang.String) ,public com.lowagie.text.pdf.PdfDictionary getCatalog() ,public int getCertificationLevel() ,public com.lowagie.text.Rectangle getCropBox(int) ,public int getCryptoMode() ,public byte[] getDocumentId() ,public int getEofPos() ,public int getFileLength() ,public Map<java.lang.String,java.lang.String> getInfo() ,public java.lang.String getJavaScript(com.lowagie.text.pdf.RandomAccessFileOrArray) throws java.io.IOException,public java.lang.String getJavaScript() throws java.io.IOException,public int getLastXref() ,public ArrayList<com.lowagie.text.pdf.PdfAnnotation.PdfImportedLink> getLinks(int) ,public byte[] getMetadata() throws java.io.IOException,public HashMap<java.lang.Object,com.lowagie.text.pdf.PdfObject> getNamedDestination() ,public HashMap<java.lang.Object,com.lowagie.text.pdf.PdfObject> getNamedDestination(boolean) ,public HashMap#RAW getNamedDestinationFromNames() ,public HashMap<java.lang.Object,com.lowagie.text.pdf.PdfObject> getNamedDestinationFromNames(boolean) ,public HashMap#RAW getNamedDestinationFromStrings() ,public static com.lowagie.text.Rectangle getNormalizedRectangle(com.lowagie.text.pdf.PdfArray) ,public int getNumberOfPages() ,public byte[] getPageContent(int, com.lowagie.text.pdf.RandomAccessFileOrArray) throws java.io.IOException,public byte[] getPageContent(int) throws java.io.IOException,public com.lowagie.text.pdf.PdfDictionary getPageN(int) ,public com.lowagie.text.pdf.PdfDictionary getPageNRelease(int) ,public com.lowagie.text.pdf.PRIndirectReference getPageOrigRef(int) ,public int getPageRotation(int) ,public com.lowagie.text.Rectangle getPageSize(int) ,public com.lowagie.text.Rectangle getPageSize(com.lowagie.text.pdf.PdfDictionary) ,public com.lowagie.text.Rectangle getPageSizeWithRotation(int) ,public com.lowagie.text.Rectangle getPageSizeWithRotation(com.lowagie.text.pdf.PdfDictionary) ,public com.lowagie.text.Rectangle getPageSizeWithRotation(int, java.lang.String) ,public static com.lowagie.text.pdf.PdfObject getPdfObject(com.lowagie.text.pdf.PdfObject) ,public static com.lowagie.text.pdf.PdfObject getPdfObject(com.lowagie.text.pdf.PdfObject, com.lowagie.text.pdf.PdfObject) ,public com.lowagie.text.pdf.PdfObject getPdfObject(int) ,public static com.lowagie.text.pdf.PdfObject getPdfObjectNullConverting(com.lowagie.text.pdf.PdfObject, com.lowagie.text.pdf.PdfObject) ,public static com.lowagie.text.pdf.PdfObject getPdfObjectRelease(com.lowagie.text.pdf.PdfObject) ,public static com.lowagie.text.pdf.PdfObject getPdfObjectRelease(com.lowagie.text.pdf.PdfObject, com.lowagie.text.pdf.PdfObject) ,public com.lowagie.text.pdf.PdfObject getPdfObjectRelease(int) ,public static com.lowagie.text.pdf.PdfObject getPdfObjectReleaseNullConverting(com.lowagie.text.pdf.PdfObject) ,public char getPdfVersion() ,public int getPermissions() ,public com.lowagie.text.pdf.RandomAccessFileOrArray getSafeFile() ,public int getSimpleViewerPreferences() ,public static byte[] getStreamBytes(com.lowagie.text.pdf.PRStream, com.lowagie.text.pdf.RandomAccessFileOrArray) throws java.io.IOException,public static byte[] getStreamBytes(com.lowagie.text.pdf.PRStream) throws java.io.IOException,public static byte[] getStreamBytesRaw(com.lowagie.text.pdf.PRStream, com.lowagie.text.pdf.RandomAccessFileOrArray) throws java.io.IOException,public static byte[] getStreamBytesRaw(com.lowagie.text.pdf.PRStream) throws java.io.IOException,public com.lowagie.text.pdf.PdfDictionary getTrailer() ,public int getXrefSize() ,public boolean is128Key() ,public boolean isAppendable() ,public boolean isEncrypted() ,public boolean isHybridXref() ,public boolean isMetadataEncrypted() ,public boolean isModificationlowedWithoutOwnerPassword() ,public boolean isNewXrefType() ,public final boolean isOpenedWithFullPermissions() ,public boolean isOwnerPasswordUsed() ,public boolean isRebuilt() ,public boolean isTampered() ,public static com.lowagie.text.pdf.PdfObject killIndirect(com.lowagie.text.pdf.PdfObject) ,public void makeRemoteNamedDestinationsLocal() ,public static void releaseLastXrefPartial(com.lowagie.text.pdf.PdfObject) ,public void releaseLastXrefPartial() ,public void releasePage(int) ,public void removeAnnotations() ,public void removeFields() ,public int removeUnusedObjects() ,public void removeUsageRights() ,public void resetLastXrefPartial() ,public void resetReleasePage() ,public void selectPages(java.lang.String) ,public void selectPages(List<java.lang.Integer>) ,public void setAppendable(boolean) ,public void setModificationAllowedWithoutOwnerPassword(boolean) ,public void setPageContent(int, byte[]) ,public void setPageContent(int, byte[], int) ,public void setPermissions(int) ,public void setTampered(boolean) ,public void setViewerPreferences(int) ,public int shuffleSubsetNames() <variables>protected com.lowagie.text.pdf.PRAcroForm acroForm,protected boolean acroFormParsed,private boolean appendable,protected com.lowagie.text.pdf.PdfDictionary catalog,protected java.security.cert.Certificate certificate,protected java.security.Key certificateKey,protected java.lang.String certificateKeyProvider,protected boolean consolidateNamedDestinations,private com.lowagie.text.pdf.PRIndirectReference cryptoRef,protected com.lowagie.text.pdf.PdfEncryption decrypt,protected boolean encrypted,private boolean encryptionError,private static final byte[] endobj,private static final byte[] endstream,protected int eofPos,private int fileLength,protected int freeXref,private boolean hybridXref,protected int lastXref,private int lastXrefPartial,private boolean modificationAllowedWithoutOwnerPassword,protected boolean newXrefType,private int objGen,private int objNum,protected Map<java.lang.Integer,com.lowagie.text.pdf.IntHashtable> objStmMark,protected com.lowagie.text.pdf.IntHashtable objStmToOffset,private boolean ownerPasswordUsed,protected int pValue,static final com.lowagie.text.pdf.PdfName[] pageInhCandidates,protected com.lowagie.text.pdf.PdfReader.PageRefs pageRefs,private boolean partial,protected byte[] password,protected char pdfVersion,protected int rValue,private int readDepth,protected boolean rebuilt,protected boolean remoteToLocalNamedDestinations,com.lowagie.text.pdf.PdfDictionary rootPages,protected boolean sharedStreams,protected List<com.lowagie.text.pdf.PdfObject> strings,protected boolean tampered,protected com.lowagie.text.pdf.PRTokeniser tokens,protected com.lowagie.text.pdf.PdfDictionary trailer,private final com.lowagie.text.pdf.internal.PdfViewerPreferencesImp viewerPreferences,protected int[] xref,private List<com.lowagie.text.pdf.PdfObject> xrefObj