You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2011/08/30 22:58:50 UTC

svn commit: r1163376 - /pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java

Author: leleueri
Date: Tue Aug 30 20:58:49 2011
New Revision: 1163376

URL: http://svn.apache.org/viewvc?rev=1163376&view=rev
Log:
[PDFBOX-1112] Fix outline hierarchy control

Modified:
    pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java?rev=1163376&r1=1163375&r2=1163376&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/helpers/BookmarkValidationHelper.java Tue Aug 30 20:58:49 2011
@@ -30,8 +30,10 @@ import org.apache.padaf.preflight.Valida
 import org.apache.padaf.preflight.ValidatorConfig;
 import org.apache.padaf.preflight.ValidationResult.ValidationError;
 import org.apache.padaf.preflight.actions.AbstractActionManager;
+import org.apache.padaf.preflight.utils.COSUtils;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
 import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
@@ -51,137 +53,141 @@ public class BookmarkValidationHelper ex
 		super(cfg);
 	}
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * net.awl.edoc.pdfa.validation.helpers.AbstractValidationHelper#innerValidate
-   * (net.awl.edoc.pdfa.validation.DocumentHandler)
-   */
-  @Override
-  public List<ValidationError> innerValidate(DocumentHandler handler)
-      throws ValidationException {
-    List<ValidationError> result = new ArrayList<ValidationError>(0);
-
-    PDDocumentCatalog catalog = handler.getDocument().getDocumentCatalog();
-    if (catalog != null) {
-      PDDocumentOutline outlineHierarchy = catalog.getDocumentOutline();
-      if (outlineHierarchy != null) {
-        if (outlineHierarchy.getFirstChild() == null
-            || outlineHierarchy.getLastChild() == null) {
-          result.add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
-              "Outline Hierarchy doesn't have First and/or Last entry(ies)"));
-        } else {
-          // ---- Count entry is mandatory if there are childrens
-          if (!isCountEntryPresent(outlineHierarchy.getCOSDictionary())) {
-            result.add(new ValidationError(
-                ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
-                "Outline Hierarchy doesn't have Count entry"));
-          } else {
-            exploreOutlineLevel(outlineHierarchy.getFirstChild(), handler,
-                result);
-          }
-        }
-      }
-    } else {
-      throw new ValidationException(
-          "There are no Catalog entry in the Document.");
-    }
-    return result;
-  }
-
-  /**
-   * Return true if the Count entry is present in the given dictionary.
-   * 
-   * @param outline
-   * @return
-   */
-  private boolean isCountEntryPresent(COSDictionary outline) {
-    return outline.getItem(COSName.getPDFName("Count")) != null;
-  }
-
-  /**
-   * This method explores the Outline Item Level and call a validation method on
-   * each Outline Item. If an invalid outline item is found, the result list is
-   * updated.
-   * 
-   * @param inputItem
-   *          The first outline item of the level
-   * @param handler
-   *          The document handler which provides useful data for the level
-   *          exploration (ex : access to the PDDocument)
-   * @param result
-   * @return true if all items are valid in this level.
-   * @throws ValidationException
-   */
-  protected boolean exploreOutlineLevel(PDOutlineItem inputItem,
-      DocumentHandler handler, List<ValidationError> result)
-      throws ValidationException {
-    PDOutlineItem currentItem = inputItem;
-    int oiValided = 0;
-    while (currentItem != null) {
-      if (!validateItem(currentItem, handler, result)) {
-        return false;
-      }
-      oiValided++;
-      currentItem = currentItem.getNextSibling();
-    }
-    return true;
-  }
-
-  /**
-   * This method checks the inputItem dictionary and call the
-   * exploreOutlineLevel method on the first child if it is not null.
-   * 
-   * @param inputItem
-   *          outline item to validate
-   * @param handler
-   *          The document handler which provides useful data for the level
-   *          exploration (ex : access to the PDDocument)
-   * @param result
-   * @return
-   * @throws ValidationException
-   */
-  protected boolean validateItem(PDOutlineItem inputItem,
-      DocumentHandler handler, List<ValidationError> result)
-      throws ValidationException {
-    boolean isValid = true;
-    // ---- Dest entry isn't permitted if the A entry is present
-    // A entry isn't permitted if the Dest entry is present
-    // If the A enntry is present, the referenced actions is validated
-    COSDictionary dictionary = inputItem.getCOSDictionary();
-    COSBase dest = dictionary.getItem(COSName
-        .getPDFName(DICTIONARY_KEY_DESTINATION));
-    COSBase action = dictionary.getItem(COSName
-        .getPDFName(DICTIONARY_KEY_ACTION));
-
-    if (action != null && dest != null) {
-      result.add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
-          "Dest entry isn't permitted if the A entry is present"));
-      return false;
-    } else if (action != null) {
-      List<AbstractActionManager> actions = this.actionFact.getActions(dictionary, handler
-          .getDocument().getDocument());
-      for (AbstractActionManager act : actions) {
-        isValid = isValid && act.valid(result);
-      }
-    } // else no specific validation
-
-    // ---- check children
-    PDOutlineItem fChild = inputItem.getFirstChild();
-    if (fChild != null) {
-      if (!isCountEntryPresent(inputItem.getCOSDictionary())) {
-        result
-            .add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
-                "Outline item doesn't have Count entry but has at least one descendant."));
-        isValid = false;
-      } else {
-        // ---- there are some descendants, so dictionary must have a Count
-        // entry
-        isValid = isValid && exploreOutlineLevel(fChild, handler, result);
-      }
-    }
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * net.awl.edoc.pdfa.validation.helpers.AbstractValidationHelper#innerValidate
+	 * (net.awl.edoc.pdfa.validation.DocumentHandler)
+	 */
+	@Override
+	public List<ValidationError> innerValidate(DocumentHandler handler)
+			throws ValidationException {
+		List<ValidationError> result = new ArrayList<ValidationError>(0);
+
+		PDDocumentCatalog catalog = handler.getDocument().getDocumentCatalog();
+		if (catalog != null) {
+			PDDocumentOutline outlineHierarchy = catalog.getDocumentOutline();
+			if (outlineHierarchy != null) {
+				// ---- Count entry is mandatory if there are childrens
+				if (!isCountEntryPresent(outlineHierarchy.getCOSDictionary()) && (outlineHierarchy.getFirstChild() != null || outlineHierarchy.getLastChild() != null) ) {
+					result.add(new ValidationError(
+							ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
+							"Outline Hierarchy doesn't have Count entry"));
+				} else if (isCountEntryPositive(outlineHierarchy.getCOSDictionary(), handler.getDocument().getDocument()) 
+						&& (outlineHierarchy.getFirstChild() == null || outlineHierarchy.getLastChild() == null)) {
+					result.add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
+							"Outline Hierarchy doesn't have First and/or Last entry(ies)"));
+				} else {
+					exploreOutlineLevel(outlineHierarchy.getFirstChild(), handler, result);
+				}
+			}
+		} else {
+			throw new ValidationException(
+					"There are no Catalog entry in the Document.");
+		}
+		return result;
+	}
+
+	/**
+	 * Return true if the Count entry is present in the given dictionary.
+	 * 
+	 * @param outline
+	 * @return
+	 */
+	private boolean isCountEntryPresent(COSDictionary outline) {
+		return outline.getItem(COSName.getPDFName("Count")) != null;
+	}
+	/**
+	 * return true if Count entry > 0
+	 * @param outline
+	 * @param doc
+	 * @return
+	 */
+	private boolean isCountEntryPositive(COSDictionary outline, COSDocument doc) {
+		COSBase countBase = outline.getItem(COSName.getPDFName("Count"));
+		return COSUtils.isInteger(countBase, doc) && (COSUtils.getAsInteger(countBase, doc)>0);
+	}
+	/**
+	 * This method explores the Outline Item Level and call a validation method on
+	 * each Outline Item. If an invalid outline item is found, the result list is
+	 * updated.
+	 * 
+	 * @param inputItem
+	 *          The first outline item of the level
+	 * @param handler
+	 *          The document handler which provides useful data for the level
+	 *          exploration (ex : access to the PDDocument)
+	 * @param result
+	 * @return true if all items are valid in this level.
+	 * @throws ValidationException
+	 */
+	protected boolean exploreOutlineLevel(PDOutlineItem inputItem,
+			DocumentHandler handler, List<ValidationError> result)
+					throws ValidationException {
+		PDOutlineItem currentItem = inputItem;
+		while (currentItem != null) {
+			if (!validateItem(currentItem, handler, result)) {
+				return false;
+			}
+			currentItem = currentItem.getNextSibling();
+		}
+		return true;
+	}
 
-    return isValid;
-  }
+	/**
+	 * This method checks the inputItem dictionary and call the
+	 * exploreOutlineLevel method on the first child if it is not null.
+	 * 
+	 * @param inputItem
+	 *          outline item to validate
+	 * @param handler
+	 *          The document handler which provides useful data for the level
+	 *          exploration (ex : access to the PDDocument)
+	 * @param result
+	 * @return
+	 * @throws ValidationException
+	 */
+	protected boolean validateItem(PDOutlineItem inputItem,
+			DocumentHandler handler, List<ValidationError> result)
+					throws ValidationException {
+		boolean isValid = true;
+		// ---- Dest entry isn't permitted if the A entry is present
+		// A entry isn't permitted if the Dest entry is present
+		// If the A enntry is present, the referenced actions is validated
+		COSDictionary dictionary = inputItem.getCOSDictionary();
+		COSBase dest = dictionary.getItem(COSName
+				.getPDFName(DICTIONARY_KEY_DESTINATION));
+		COSBase action = dictionary.getItem(COSName
+				.getPDFName(DICTIONARY_KEY_ACTION));
+
+		if (action != null && dest != null) {
+			result.add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
+					"Dest entry isn't permitted if the A entry is present"));
+			return false;
+		} else if (action != null) {
+			List<AbstractActionManager> actions = this.actionFact.getActions(dictionary, handler
+					.getDocument().getDocument());
+			for (AbstractActionManager act : actions) {
+				isValid = isValid && act.valid(result);
+			}
+		} // else no specific validation
+
+		// ---- check children
+		PDOutlineItem fChild = inputItem.getFirstChild();
+		if (fChild != null) {
+			if (!isCountEntryPresent(inputItem.getCOSDictionary())) {
+				result
+				.add(new ValidationError(ERROR_SYNTAX_TRAILER_OUTLINES_INVALID,
+						"Outline item doesn't have Count entry but has at least one descendant."));
+				isValid = false;
+			} else {
+				// ---- there are some descendants, so dictionary must have a Count
+				// entry
+				isValid = isValid && exploreOutlineLevel(fChild, handler, result);
+			}
+		}
+
+		return isValid;
+	}
 }