// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
// The following copyright from the original authors applies.
//
// 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.

// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name
// ignore_for_file: use_super_parameters

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

import "PDDocumentInformation.dart" as pddocumentinformation_;
import "../../../../_init.dart";

/// from: org.apache.pdfbox.pdmodel.PDDocument
///
/// This is the in-memory representation of the PDF document.
/// The \#close() method must be called once the document is no longer needed.
///@author Ben Litchfield
class PDDocument extends jni.JObject {
  @override
  late final jni.JObjType<PDDocument> $type = type;

  PDDocument.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $PDDocumentType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "PDDocument__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Creates an empty PDF document.
  /// You need to add at least one page for the document to be valid.
  factory PDDocument() {
    return PDDocument.fromReference(_new0().reference);
  }

  static final _new1 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "PDDocument__new1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Creates an empty PDF document.
  /// You need to add at least one page for the document to be valid.
  ///@param memUsageSetting defines how memory is used for buffering PDF streams
  factory PDDocument.new1(
    jni.JObject memUsageSetting,
  ) {
    return PDDocument.fromReference(
        _new1(memUsageSetting.reference.pointer).reference);
  }

  static final _new2 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "PDDocument__new2")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
  ///@param doc The COSDocument that this document wraps.
  factory PDDocument.new2(
    jni.JObject doc,
  ) {
    return PDDocument.fromReference(_new2(doc.reference.pointer).reference);
  }

  static final _new3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__new3")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
  ///@param doc The COSDocument that this document wraps.
  ///@param source the parser which is used to read the pdf
  factory PDDocument.new3(
    jni.JObject doc,
    jni.JObject source,
  ) {
    return PDDocument.fromReference(
        _new3(doc.reference.pointer, source.reference.pointer).reference);
  }

  static final _new4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__new4")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source, org.apache.pdfbox.pdmodel.encryption.AccessPermission permission)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
  ///@param doc The COSDocument that this document wraps.
  ///@param source the parser which is used to read the pdf
  ///@param permission he access permissions of the pdf
  factory PDDocument.new4(
    jni.JObject doc,
    jni.JObject source,
    jni.JObject permission,
  ) {
    return PDDocument.fromReference(_new4(doc.reference.pointer,
            source.reference.pointer, permission.reference.pointer)
        .reference);
  }

  static final _addPage = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addPage")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void addPage(org.apache.pdfbox.pdmodel.PDPage page)
  ///
  /// This will add a page to the document. This is a convenience method, that will add the page to the root of the
  /// hierarchy and set the parent of the page to the root.
  ///@param page The page to add to the document.
  void addPage(
    jni.JObject page,
  ) {
    _addPage(reference.pointer, page.reference.pointer).check();
  }

  static final _addSignature = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject)
  ///
  /// Add parameters of signature to be created externally using default signature options. See
  /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
  /// signature creation scenario details.
  ///
  /// Only one signature may be added in a document. To sign several times,
  /// load document, add signature, save incremental and close again.
  ///@param sigObject is the PDSignatureField model
  ///@throws IOException if there is an error creating required fields
  ///@throws IllegalStateException if one attempts to add several signature
  /// fields.
  void addSignature(
    jni.JObject sigObject,
  ) {
    _addSignature(reference.pointer, sigObject.reference.pointer).check();
  }

  static final _addSignature1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
  ///
  /// Add parameters of signature to be created externally. See
  /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
  /// signature creation scenario details.
  ///
  /// Only one signature may be added in a document. To sign several times,
  /// load document, add signature, save incremental and close again.
  ///@param sigObject is the PDSignatureField model
  ///@param options signature options
  ///@throws IOException if there is an error creating required fields
  ///@throws IllegalStateException if one attempts to add several signature
  /// fields.
  void addSignature1(
    jni.JObject sigObject,
    jni.JObject options,
  ) {
    _addSignature1(reference.pointer, sigObject.reference.pointer,
            options.reference.pointer)
        .check();
  }

  static final _addSignature2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature2")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface)
  ///
  /// Add a signature to be created using the instance of given interface.
  ///
  /// Only one signature may be added in a document. To sign several times,
  /// load document, add signature, save incremental and close again.
  ///@param sigObject is the PDSignatureField model
  ///@param signatureInterface is an interface whose implementation provides
  /// signing capabilities. Can be null if external signing if used.
  ///@throws IOException if there is an error creating required fields
  ///@throws IllegalStateException if one attempts to add several signature
  /// fields.
  void addSignature2(
    jni.JObject sigObject,
    jni.JObject signatureInterface,
  ) {
    _addSignature2(reference.pointer, sigObject.reference.pointer,
            signatureInterface.reference.pointer)
        .check();
  }

  static final _addSignature3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature3")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
  ///
  /// This will add a signature to the document. If the 0-based page number in the options
  /// parameter is smaller than 0 or larger than max, the nearest valid page number will be used
  /// (i.e. 0 or max) and no exception will be thrown.
  ///
  /// Only one signature may be added in a document. To sign several times,
  /// load document, add signature, save incremental and close again.
  ///@param sigObject is the PDSignatureField model
  ///@param signatureInterface is an interface whose implementation provides
  /// signing capabilities. Can be null if external signing if used.
  ///@param options signature options
  ///@throws IOException if there is an error creating required fields
  ///@throws IllegalStateException if one attempts to add several signature
  /// fields.
  void addSignature3(
    jni.JObject sigObject,
    jni.JObject signatureInterface,
    jni.JObject options,
  ) {
    _addSignature3(reference.pointer, sigObject.reference.pointer,
            signatureInterface.reference.pointer, options.reference.pointer)
        .check();
  }

  static final _addSignatureField = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__addSignatureField")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void addSignatureField(java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> sigFields, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
  ///
  /// This will add a list of signature fields to the document.
  ///@param sigFields are the PDSignatureFields that should be added to the document
  ///@param signatureInterface is an interface whose implementation provides
  /// signing capabilities. Can be null if external signing if used.
  ///@param options signature options
  ///@throws IOException if there is an error creating required fields
  ///@deprecated The method is misleading, because only one signature may be
  /// added in a document. The method will be removed in the future.
  void addSignatureField(
    jni.JList<jni.JObject> sigFields,
    jni.JObject signatureInterface,
    jni.JObject options,
  ) {
    _addSignatureField(reference.pointer, sigFields.reference.pointer,
            signatureInterface.reference.pointer, options.reference.pointer)
        .check();
  }

  static final _removePage = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__removePage")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void removePage(org.apache.pdfbox.pdmodel.PDPage page)
  ///
  /// Remove the page from the document.
  ///@param page The page to remove from the document.
  void removePage(
    jni.JObject page,
  ) {
    _removePage(reference.pointer, page.reference.pointer).check();
  }

  static final _removePage1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("PDDocument__removePage1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void removePage(int pageNumber)
  ///
  /// Remove the page from the document.
  ///@param pageNumber 0 based index to page number.
  void removePage1(
    int pageNumber,
  ) {
    _removePage1(reference.pointer, pageNumber).check();
  }

  static final _importPage = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__importPage")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public org.apache.pdfbox.pdmodel.PDPage importPage(org.apache.pdfbox.pdmodel.PDPage page)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will import and copy the contents from another location. Currently the content stream is
  /// stored in a scratch file. The scratch file is associated with the document. If you are adding
  /// a page to this document from another document and want to copy the contents to this
  /// document's scratch file then use this method otherwise just use the \#addPage addPage()
  /// method.
  ///
  /// Unlike \#addPage addPage(), this method creates a new PDPage object. If your page has
  /// annotations, and if these link to pages not in the target document, then the target document
  /// might become huge. What you need to do is to delete page references of such annotations. See
  /// <a href="http://stackoverflow.com/a/35477351/535646">here</a> for how to do this.
  ///
  /// Inherited (global) resources are ignored because these can contain resources not needed for
  /// this page which could bloat your document, see
  /// <a href="https://issues.apache.org/jira/browse/PDFBOX-28">PDFBOX-28</a> and related issues.
  /// If you need them, call <code>importedPage.setResources(page.getResources());</code>
  ///
  /// This method should only be used to import a page from a loaded document, not from a generated
  /// document because these can contain unfinished parts, e.g. font subsetting information.
  ///@param page The page to import.
  ///@return The page that was imported.
  ///@throws IOException If there is an error copying the page.
  jni.JObject importPage(
    jni.JObject page,
  ) {
    return _importPage(reference.pointer, page.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getDocument = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getDocument")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.cos.COSDocument getDocument()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will get the low level document.
  ///@return The document that this layer sits on top of.
  jni.JObject getDocument() {
    return _getDocument(reference.pointer).object(const jni.JObjectType());
  }

  static final _getDocumentInformation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getDocumentInformation")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.PDDocumentInformation getDocumentInformation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will get the document info dictionary. If it doesn't exist, an empty document info
  /// dictionary is created in the document trailer.
  ///
  /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
  /// document level metadata, a metadata stream should be used instead, see
  /// PDDocumentCatalog\#getMetadata().
  ///@return The documents /Info dictionary, never null.
  pddocumentinformation_.PDDocumentInformation getDocumentInformation() {
    return _getDocumentInformation(reference.pointer)
        .object(const pddocumentinformation_.$PDDocumentInformationType());
  }

  static final _setDocumentInformation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__setDocumentInformation")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setDocumentInformation(org.apache.pdfbox.pdmodel.PDDocumentInformation info)
  ///
  /// This will set the document information for this document.
  ///
  /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
  /// document level metadata, a metadata stream should be used instead, see
  /// PDDocumentCatalog\#setMetadata(org.apache.pdfbox.pdmodel.common.PDMetadata) PDDocumentCatalog\#setMetadata(PDMetadata).
  ///@param info The updated document information.
  void setDocumentInformation(
    pddocumentinformation_.PDDocumentInformation info,
  ) {
    _setDocumentInformation(reference.pointer, info.reference.pointer).check();
  }

  static final _getDocumentCatalog = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getDocumentCatalog")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.PDDocumentCatalog getDocumentCatalog()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will get the document CATALOG. This is guaranteed to not return null.
  ///@return The documents /Root dictionary
  jni.JObject getDocumentCatalog() {
    return _getDocumentCatalog(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _isEncrypted = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__isEncrypted")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isEncrypted()
  ///
  /// This will tell if this document is encrypted or not.
  ///@return true If this document is encrypted.
  bool isEncrypted() {
    return _isEncrypted(reference.pointer).boolean;
  }

  static final _getEncryption = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getEncryption")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.encryption.PDEncryption getEncryption()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will get the encryption dictionary for this document. This will still return the parameters if the document
  /// was decrypted. As the encryption architecture in PDF documents is pluggable this returns an abstract class,
  /// but the only supported subclass at this time is a
  /// PDStandardEncryption object.
  ///@return The encryption dictionary(most likely a PDStandardEncryption object)
  jni.JObject getEncryption() {
    return _getEncryption(reference.pointer).object(const jni.JObjectType());
  }

  static final _setEncryptionDictionary = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "PDDocument__setEncryptionDictionary")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setEncryptionDictionary(org.apache.pdfbox.pdmodel.encryption.PDEncryption encryption)
  ///
  /// This will set the encryption dictionary for this document.
  ///@param encryption The encryption dictionary(most likely a PDStandardEncryption object)
  ///@throws IOException If there is an error determining which security handler to use.
  void setEncryptionDictionary(
    jni.JObject encryption,
  ) {
    _setEncryptionDictionary(reference.pointer, encryption.reference.pointer)
        .check();
  }

  static final _getLastSignatureDictionary = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getLastSignatureDictionary")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature getLastSignatureDictionary()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// This will return the last signature from the field tree. Note that this may not be the
  /// last in time when empty signature fields are created first but signed after other fields.
  ///@return the last signature as <code>PDSignatureField</code>.
  ///@throws IOException if no document catalog can be found.
  jni.JObject getLastSignatureDictionary() {
    return _getLastSignatureDictionary(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getSignatureFields = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getSignatureFields")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> getSignatureFields()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Retrieve all signature fields from the document.
  ///@return a <code>List</code> of <code>PDSignatureField</code>s
  ///@throws IOException if no document catalog can be found.
  jni.JList<jni.JObject> getSignatureFields() {
    return _getSignatureFields(reference.pointer)
        .object(const jni.JListType(jni.JObjectType()));
  }

  static final _getSignatureDictionaries = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getSignatureDictionaries")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature> getSignatureDictionaries()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Retrieve all signature dictionaries from the document.
  ///@return a <code>List</code> of <code>PDSignatureField</code>s
  ///@throws IOException if no document catalog can be found.
  jni.JList<jni.JObject> getSignatureDictionaries() {
    return _getSignatureDictionaries(reference.pointer)
        .object(const jni.JListType(jni.JObjectType()));
  }

  static final _registerTrueTypeFontForClosing = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "PDDocument__registerTrueTypeFontForClosing")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void registerTrueTypeFontForClosing(org.apache.fontbox.ttf.TrueTypeFont ttf)
  ///
  /// For internal PDFBox use when creating PDF documents: register a TrueTypeFont to make sure it
  /// is closed when the PDDocument is closed to avoid memory leaks. Users don't have to call this
  /// method, it is done by the appropriate PDFont classes.
  ///@param ttf
  void registerTrueTypeFontForClosing(
    jni.JObject ttf,
  ) {
    _registerTrueTypeFontForClosing(reference.pointer, ttf.reference.pointer)
        .check();
  }

  static final _load = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "PDDocument__load")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param file file to be loaded
  ///@return loaded document
  ///@throws InvalidPasswordException If the file required a non-empty password.
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load(
    jni.JObject file,
  ) {
    return _load(file.reference.pointer).object(const $PDDocumentType());
  }

  static final _load1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF.
  ///@param file file to be loaded
  ///@param memUsageSetting defines how memory is used for buffering PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the file required a non-empty password.
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load1(
    jni.JObject file,
    jni.JObject memUsageSetting,
  ) {
    return _load1(file.reference.pointer, memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param file file to be loaded
  ///@param password password to be used for decryption
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load2(
    jni.JObject file,
    jni.JString password,
  ) {
    return _load2(file.reference.pointer, password.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load3")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF.
  ///@param file file to be loaded
  ///@param password password to be used for decryption
  ///@param memUsageSetting defines how memory is used for buffering PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load3(
    jni.JObject file,
    jni.JString password,
    jni.JObject memUsageSetting,
  ) {
    return _load3(file.reference.pointer, password.reference.pointer,
            memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load4")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param file file to be loaded
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@return loaded document
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load4(
    jni.JObject file,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
  ) {
    return _load4(file.reference.pointer, password.reference.pointer,
            keyStore.reference.pointer, alias.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load5 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load5")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF.
  ///@param file file to be loaded
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@param memUsageSetting defines how memory is used for buffering PDF streams
  ///@return loaded document
  ///@throws IOException in case of a file reading or parsing error
  static PDDocument load5(
    jni.JObject file,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
    jni.JObject memUsageSetting,
  ) {
    return _load5(
            file.reference.pointer,
            password.reference.pointer,
            keyStore.reference.pointer,
            alias.reference.pointer,
            memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load6 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "PDDocument__load6")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@return loaded document
  ///@throws InvalidPasswordException If the PDF required a non-empty password.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load6(
    jni.JObject input,
  ) {
    return _load6(input.reference.pointer).object(const $PDDocumentType());
  }

  static final _load7 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load7")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
  /// copied to main memory or to a temporary file to enable random access to the pdf.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the PDF required a non-empty password.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load7(
    jni.JObject input,
    jni.JObject memUsageSetting,
  ) {
    return _load7(input.reference.pointer, memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load8 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load8")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@param password password to be used for decryption
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load8(
    jni.JObject input,
    jni.JString password,
  ) {
    return _load8(input.reference.pointer, password.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load9 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load9")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@return loaded document
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load9(
    jni.JObject input,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
  ) {
    return _load9(input.reference.pointer, password.reference.pointer,
            keyStore.reference.pointer, alias.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load10 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load10")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
  /// copied to main memory or to a temporary file to enable random access to the pdf.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@param password password to be used for decryption
  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load10(
    jni.JObject input,
    jni.JString password,
    jni.JObject memUsageSetting,
  ) {
    return _load10(input.reference.pointer, password.reference.pointer,
            memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load11 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load11")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
  /// copied to memory or to a temporary file to enable random access to the pdf.
  ///@param input stream that contains the document. Don't forget to close it after loading.
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load11(
    jni.JObject input,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
    jni.JObject memUsageSetting,
  ) {
    return _load11(
            input.reference.pointer,
            password.reference.pointer,
            keyStore.reference.pointer,
            alias.reference.pointer,
            memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load12 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "PDDocument__load12")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input byte array that contains the document.
  ///@return loaded document
  ///@throws InvalidPasswordException If the PDF required a non-empty password.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load12(
    jni.JArray<jni.jbyte> input,
  ) {
    return _load12(input.reference.pointer).object(const $PDDocumentType());
  }

  static final _load13 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load13")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input byte array that contains the document.
  ///@param password password to be used for decryption
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load13(
    jni.JArray<jni.jbyte> input,
    jni.JString password,
  ) {
    return _load13(input.reference.pointer, password.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load14 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load14")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
  ///@param input byte array that contains the document.
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load14(
    jni.JArray<jni.jbyte> input,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
  ) {
    return _load14(input.reference.pointer, password.reference.pointer,
            keyStore.reference.pointer, alias.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _load15 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__load15")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Parses a PDF.
  ///@param input byte array that contains the document.
  ///@param password password to be used for decryption
  ///@param keyStore key store to be used for decryption when using public key security
  ///@param alias alias to be used for decryption when using public key security
  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
  ///@return loaded document
  ///@throws InvalidPasswordException If the password is incorrect.
  ///@throws IOException In case of a reading or parsing error.
  static PDDocument load15(
    jni.JArray<jni.jbyte> input,
    jni.JString password,
    jni.JObject keyStore,
    jni.JString alias,
    jni.JObject memUsageSetting,
  ) {
    return _load15(
            input.reference.pointer,
            password.reference.pointer,
            keyStore.reference.pointer,
            alias.reference.pointer,
            memUsageSetting.reference.pointer)
        .object(const $PDDocumentType());
  }

  static final _save = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__save")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void save(java.lang.String fileName)
  ///
  /// Save the document to a file.
  ///
  /// If encryption has been activated (with
  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
  /// do not use the document after saving because the contents are now encrypted.
  ///@param fileName The file to save as.
  ///@throws IOException if the output could not be written
  void save(
    jni.JString fileName,
  ) {
    _save(reference.pointer, fileName.reference.pointer).check();
  }

  static final _save1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__save1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void save(java.io.File file)
  ///
  /// Save the document to a file.
  ///
  /// If encryption has been activated (with
  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
  /// do not use the document after saving because the contents are now encrypted.
  ///@param file The file to save as.
  ///@throws IOException if the output could not be written
  void save1(
    jni.JObject file,
  ) {
    _save1(reference.pointer, file.reference.pointer).check();
  }

  static final _save2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__save2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void save(java.io.OutputStream output)
  ///
  /// This will save the document to an output stream.
  ///
  /// If encryption has been activated (with
  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
  /// do not use the document after saving because the contents are now encrypted.
  ///@param output The stream to write to. It will be closed when done. It is recommended to wrap
  /// it in a java.io.BufferedOutputStream, unless it is already buffered.
  ///@throws IOException if the output could not be written
  void save2(
    jni.JObject output,
  ) {
    _save2(reference.pointer, output.reference.pointer).check();
  }

  static final _saveIncremental = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__saveIncremental")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void saveIncremental(java.io.OutputStream output)
  ///
  /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
  /// file or a stream, not if the document was created in PDFBox itself. There must be a path of
  /// objects that have COSUpdateInfo\#isNeedToBeUpdated() set, starting from the document
  /// catalog. For signatures this is taken care by PDFBox itself.
  ///
  /// Other usages of this method are for experienced users only. You will usually never need it.
  /// It is useful only if you are required to keep the current revision and append the changes. A
  /// typical use case is changing a signed file without invalidating the signature.
  ///@param output stream to write to. It will be closed when done. It
  /// <i>__must never__</i> point to the source file or that one will be
  /// harmed!
  ///@throws IOException if the output could not be written
  ///@throws IllegalStateException if the document was not loaded from a file or a stream.
  void saveIncremental(
    jni.JObject output,
  ) {
    _saveIncremental(reference.pointer, output.reference.pointer).check();
  }

  static final _saveIncremental1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__saveIncremental1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void saveIncremental(java.io.OutputStream output, java.util.Set<org.apache.pdfbox.cos.COSDictionary> objectsToWrite)
  ///
  /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
  /// file or a stream, not if the document was created in PDFBox itself. This allows to include
  /// objects even if there is no path of objects that have
  /// COSUpdateInfo\#isNeedToBeUpdated() set so the incremental update gets smaller. Only
  /// dictionaries are supported; if you need to update other objects classes, then add their
  /// parent dictionary.
  ///
  /// This method is for experienced users only. You will usually never need it. It is useful only
  /// if you are required to keep the current revision and append the changes. A typical use case
  /// is changing a signed file without invalidating the signature. To know which objects are
  /// getting changed, you need to have some understanding of the PDF specification, and look at
  /// the saved file with an editor to verify that you are updating the correct objects. You should
  /// also inspect the page and document structures of the file with PDFDebugger.
  ///@param output stream to write to. It will be closed when done. It
  /// <i>__must never__</i> point to the source file or that one will be harmed!
  ///@param objectsToWrite objects that __must__ be part of the incremental saving.
  ///@throws IOException if the output could not be written
  ///@throws IllegalStateException if the document was not loaded from a file or a stream.
  void saveIncremental1(
    jni.JObject output,
    jni.JSet<jni.JObject> objectsToWrite,
  ) {
    _saveIncremental1(reference.pointer, output.reference.pointer,
            objectsToWrite.reference.pointer)
        .check();
  }

  static final _saveIncrementalForExternalSigning = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "PDDocument__saveIncrementalForExternalSigning")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport saveIncrementalForExternalSigning(java.io.OutputStream output)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  ///
  /// __(This is a new feature for 2.0.3. The API for external signing might change based on feedback after release!)__
  ///
  /// Save PDF incrementally without closing for external signature creation scenario. The general
  /// sequence is:
  /// <pre>
  ///    PDDocument pdDocument = ...;
  ///    OutputStream outputStream = ...;
  ///    SignatureOptions signatureOptions = ...; // options to specify fine tuned signature options or null for defaults
  ///    PDSignature pdSignature = ...;
  ///
  ///    // add signature parameters to be used when creating signature dictionary
  ///    pdDocument.addSignature(pdSignature, signatureOptions);
  ///    // prepare PDF for signing and obtain helper class to be used
  ///    ExternalSigningSupport externalSigningSupport = pdDocument.saveIncrementalForExternalSigning(outputStream);
  ///    // get data to be signed
  ///    InputStream dataToBeSigned = externalSigningSupport.getContent();
  ///    // invoke signature service
  ///    byte[] signature = sign(dataToBeSigned);
  ///    // set resulted CMS signature
  ///    externalSigningSupport.setSignature(signature);
  ///
  ///    // last step is to close the document
  ///    pdDocument.close();
  /// </pre>
  ///
  /// Note that after calling this method, only {@code close()} method may invoked for
  /// {@code PDDocument} instance and only AFTER ExternalSigningSupport instance is used.
  ///
  ///
  ///@param output stream to write the final PDF. It will be closed when the
  /// document is closed. It <i>__must never__</i> point to the source file
  /// or that one will be harmed!
  ///@return instance to be used for external signing and setting CMS signature
  ///@throws IOException if the output could not be written
  ///@throws IllegalStateException if the document was not loaded from a file or a stream or
  /// signature options were not set.
  jni.JObject saveIncrementalForExternalSigning(
    jni.JObject output,
  ) {
    return _saveIncrementalForExternalSigning(
            reference.pointer, output.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getPage = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("PDDocument__getPage")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public org.apache.pdfbox.pdmodel.PDPage getPage(int pageIndex)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns the page at the given 0-based index.
  ///
  /// This method is too slow to get all the pages from a large PDF document
  /// (1000 pages or more). For such documents, use the iterator of
  /// PDDocument\#getPages() instead.
  ///@param pageIndex the 0-based page index
  ///@return the page at the given index.
  jni.JObject getPage(
    int pageIndex,
  ) {
    return _getPage(reference.pointer, pageIndex)
        .object(const jni.JObjectType());
  }

  static final _getPages = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getPages")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.PDPageTree getPages()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns the page tree.
  ///@return the page tree
  jni.JObject getPages() {
    return _getPages(reference.pointer).object(const jni.JObjectType());
  }

  static final _getNumberOfPages = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getNumberOfPages")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getNumberOfPages()
  ///
  /// This will return the total page count of the PDF document.
  ///@return The total number of pages in the PDF document.
  int getNumberOfPages() {
    return _getNumberOfPages(reference.pointer).integer;
  }

  static final _close = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__close")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void close()
  ///
  /// This will close the underlying COSDocument object.
  ///@throws IOException If there is an error releasing resources.
  void close() {
    _close(reference.pointer).check();
  }

  static final _protect = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__protect")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy policy)
  ///
  /// Protects the document with a protection policy. The document content will be really
  /// encrypted when it will be saved. This method only marks the document for encryption. It also
  /// calls \#setAllSecurityToBeRemoved(boolean) with a false argument if it was set to true
  /// previously and logs a warning.
  ///
  /// Do not use the document after saving, because the structures are encrypted.
  ///@see org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy
  ///@see org.apache.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy
  ///@param policy The protection policy.
  ///@throws IOException if there isn't any suitable security handler.
  void protect(
    jni.JObject policy,
  ) {
    _protect(reference.pointer, policy.reference.pointer).check();
  }

  static final _getCurrentAccessPermission = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getCurrentAccessPermission")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.encryption.AccessPermission getCurrentAccessPermission()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns the access permissions granted when the document was decrypted. If the document was not decrypted this
  /// method returns the access permission for a document owner (ie can do everything). The returned object is in read
  /// only mode so that permissions cannot be changed. Methods providing access to content should rely on this object
  /// to verify if the current user is allowed to proceed.
  ///@return the access permissions for the current user on the document.
  jni.JObject getCurrentAccessPermission() {
    return _getCurrentAccessPermission(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _isAllSecurityToBeRemoved = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__isAllSecurityToBeRemoved")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isAllSecurityToBeRemoved()
  ///
  /// Indicates if all security is removed or not when writing the pdf.
  ///@return returns true if all security shall be removed otherwise false
  bool isAllSecurityToBeRemoved() {
    return _isAllSecurityToBeRemoved(reference.pointer).boolean;
  }

  static final _setAllSecurityToBeRemoved = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Uint8)>>("PDDocument__setAllSecurityToBeRemoved")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void setAllSecurityToBeRemoved(boolean removeAllSecurity)
  ///
  /// Activates/Deactivates the removal of all security when writing the pdf.
  ///@param removeAllSecurity remove all security if set to true
  void setAllSecurityToBeRemoved(
    bool removeAllSecurity,
  ) {
    _setAllSecurityToBeRemoved(reference.pointer, removeAllSecurity ? 1 : 0)
        .check();
  }

  static final _getDocumentId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getDocumentId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Long getDocumentId()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Provides the document ID.
  ///@return the document ID
  jni.JLong getDocumentId() {
    return _getDocumentId(reference.pointer).object(const jni.JLongType());
  }

  static final _setDocumentId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__setDocumentId")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setDocumentId(java.lang.Long docId)
  ///
  /// Sets the document ID to the given value.
  ///@param docId the new document ID
  void setDocumentId(
    jni.JLong docId,
  ) {
    _setDocumentId(reference.pointer, docId.reference.pointer).check();
  }

  static final _getVersion = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getVersion")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public float getVersion()
  ///
  /// Returns the PDF specification version this document conforms to.
  ///@return the PDF version (e.g. 1.4f)
  double getVersion() {
    return _getVersion(reference.pointer).float;
  }

  static final _setVersion = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Float)>>("PDDocument__setVersion")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();

  /// from: public void setVersion(float newVersion)
  ///
  /// Sets the PDF specification version for this document.
  ///@param newVersion the new PDF version (e.g. 1.4f)
  void setVersion(
    double newVersion,
  ) {
    _setVersion(reference.pointer, newVersion).check();
  }

  static final _getResourceCache = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("PDDocument__getResourceCache")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public org.apache.pdfbox.pdmodel.ResourceCache getResourceCache()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Returns the resource cache associated with this document, or null if there is none.
  ///@return the resource cache or null.
  jni.JObject getResourceCache() {
    return _getResourceCache(reference.pointer).object(const jni.JObjectType());
  }

  static final _setResourceCache = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("PDDocument__setResourceCache")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setResourceCache(org.apache.pdfbox.pdmodel.ResourceCache resourceCache)
  ///
  /// Sets the resource cache associated with this document.
  ///@param resourceCache A resource cache, or null.
  void setResourceCache(
    jni.JObject resourceCache,
  ) {
    _setResourceCache(reference.pointer, resourceCache.reference.pointer)
        .check();
  }
}

final class $PDDocumentType extends jni.JObjType<PDDocument> {
  const $PDDocumentType();

  @override
  String get signature => r"Lorg/apache/pdfbox/pdmodel/PDDocument;";

  @override
  PDDocument fromReference(jni.JReference reference) =>
      PDDocument.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($PDDocumentType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($PDDocumentType) && other is $PDDocumentType;
  }
}
