/**
  * This method checks the AP entry of the Annotation Dictionary. If the AP key is missing, this
  * method returns true. If the AP key exists, only the N entry is authorized and must be a Stream
  * which define the appearance of the annotation. (Currently, only the type of the N entry is
  * checked because of the Appearance stream is a Form XObject, so it will be checked by the
  * Graphics Helper)
  *
  * <p>If the AP content isn't valid, this method return false and updates the errors list.
  *
  * @param errors list of errors which is updated if validation fails
  * @return
  */
 protected boolean checkAP(List<ValidationError> errors) {
   PDAppearanceDictionary ap = this.pdAnnot.getAppearance();
   if (ap != null) {
     COSDictionary apDict = ap.getDictionary();
     // ---- Only N entry is authorized
     if (apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_D)) != null
         || apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_R)) != null) {
       errors.add(
           new ValidationResult.ValidationError(
               ValidationConstants.ERROR_ANNOT_INVALID_AP_CONTENT,
               "Only the N Appearance is authorized"));
       return false;
     } else if (apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_N)) == null) {
       // ---- N entry is required
       errors.add(
           new ValidationResult.ValidationError(
               ValidationConstants.ERROR_ANNOT_MISSING_AP_N_CONTENT,
               "The N Appearance must be present"));
       return false;
     } else {
       // ---- the N entry must be a Stream (Dictionaries are forbidden)
       COSBase apn = apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_N));
       if (!COSUtils.isStream(apn, this.cosDoc)) {
         errors.add(
             new ValidationResult.ValidationError(
                 ValidationConstants.ERROR_ANNOT_INVALID_AP_CONTENT,
                 "The N Appearance must be a Stream"));
         return false;
       }
     }
   } // else  ok, nothing to check,this field is optional
   return true;
 }
 /**
  * This method validates the Popup entry. This entry shall contain an other Annotation. This
  * annotation is validated with the right AnnotationValidator.
  *
  * @param errors
  * @return
  * @throws ValidationException
  */
 protected boolean checkPopup(List<ValidationError> errors) throws ValidationException {
   COSBase cosPopup =
       this.annotDictionary.getItem(COSName.getPDFName(ANNOT_DICTIONARY_VALUE_SUBTYPE_POPUP));
   if (cosPopup != null) {
     COSDictionary popupDict = COSUtils.getAsDictionary(cosPopup, this.cosDoc);
     if (popupDict == null) {
       errors.add(
           new ValidationError(
               ERROR_SYNTAX_DICT_INVALID,
               "An Annotation has a Popup entry, but the value is missing or isn't a dictionary"));
       return false;
     }
     AnnotationValidator popupVal =
         this.annotFact.getAnnotationValidator(popupDict, handler, errors);
     return popupVal.validate(errors);
   }
   return true;
 }