You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2013/03/06 17:46:37 UTC
svn commit: r1453416 [10/16] - in /pdfbox/trunk/preflight: ./
src/main/java/org/apache/pdfbox/preflight/
src/main/java/org/apache/pdfbox/preflight/action/
src/main/java/org/apache/pdfbox/preflight/annotation/
src/main/java/org/apache/pdfbox/preflight/a...
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ICCProfileWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ICCProfileWrapper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ICCProfileWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ICCProfileWrapper.java Wed Mar 6 16:46:35 2013
@@ -40,109 +40,128 @@ import org.apache.pdfbox.preflight.excep
import org.apache.pdfbox.preflight.utils.COSUtils;
/**
- * This class embeds an instance of java.awt.color.ICC_Profile which represent
- * the ICCProfile defined by the DestOutputItents key of the OutputIntents of
- * the PDF.
+ * This class embeds an instance of java.awt.color.ICC_Profile which represent the ICCProfile defined by the
+ * DestOutputItents key of the OutputIntents of the PDF.
*/
-public class ICCProfileWrapper {
- /**
- * The ICCProfile extracted from DestOutputItents
- */
- private final ICC_Profile profile;
-
- /**
- * The ICC ColorSpace created using the ICCProfile
- */
- private final ICC_ColorSpace colorSpace;
-
- public ICCProfileWrapper(final ICC_Profile _profile) {
- this.profile = _profile;
- this.colorSpace = new ICC_ColorSpace(_profile);
- }
-
- /**
- * Call the ICC_ColorSpace.getType method and return the value.
- *
- * @return
- */
- public int getColorSpaceType() {
- return colorSpace.getType();
- }
-
- /**
- * @return the profile
- */
- public ICC_Profile getProfile() {
- return profile;
- }
-
- /**
- * Return true if the ColourSpace is RGB
- *
- * @return
- */
- public boolean isRGBColorSpace() {
- return ICC_ColorSpace.TYPE_RGB == colorSpace.getType();
- }
-
- /**
- * Return true if the ColourSpace is CMYK
- *
- * @return
- */
- public boolean isCMYKColorSpace() {
- return ICC_ColorSpace.TYPE_CMYK == colorSpace.getType();
- }
-
- /**
- * Return true if the ColourSpace is Gray scale
- *
- * @return
- */
- public boolean isGrayColorSpace() {
- return ICC_ColorSpace.TYPE_GRAY == colorSpace.getType();
- }
-
- /**
- * This method read all outputIntent dictionary until on of them have a destOutputProfile stream.
- * This stream is parsed and is used to create a IccProfileWrapper.
- *
- * @param context
- * @return an instance of ICCProfileWrapper or null if there are no DestOutputProfile
- * @throws ValidationException if an IOException occurs during the DestOutputProfile parsing
- */
- private static ICCProfileWrapper searchFirstICCProfile(PreflightContext context) throws ValidationException {
- PreflightDocument document = context.getDocument();
- PDDocumentCatalog catalog = document.getDocumentCatalog();
- COSBase cBase = catalog.getCOSDictionary().getItem(COSName.getPDFName(DOCUMENT_DICTIONARY_KEY_OUTPUT_INTENTS));
- COSArray outputIntents = COSUtils.getAsArray(cBase, document.getDocument());
-
- for (int i = 0; outputIntents != null && i < outputIntents.size(); ++i) {
- COSDictionary outputIntentDict = COSUtils.getAsDictionary(outputIntents.get(i), document.getDocument());
- COSBase destOutputProfile = outputIntentDict.getItem(OUTPUT_INTENT_DICTIONARY_KEY_DEST_OUTPUT_PROFILE);
- if (destOutputProfile != null) {
- try {
- PDStream stream = PDStream.createFromCOS(COSUtils.getAsStream(destOutputProfile, document.getDocument()));
- if (stream != null) {
- ICC_Profile iccp = ICC_Profile.getInstance(stream.getByteArray());
- return new ICCProfileWrapper(iccp);
- }
- } catch (IllegalArgumentException e) {
- throw new ValidationException("DestOutputProfile isn't a ICCProfile", e);
- } catch (IOException e) {
- throw new ValidationException("Unable to parse the ICCProfile", e);
- }
- }
- }
- return null;
- }
-
- public static ICCProfileWrapper getOrSearchICCProfile(PreflightContext context) throws ValidationException {
- ICCProfileWrapper profileWrapper = context.getIccProfileWrapper();
- if (profileWrapper == null && !context.isIccProfileAlreadySearched()) {
- profileWrapper = searchFirstICCProfile(context);
- context.setIccProfileAlreadySearched(true);
- }
- return profileWrapper;
- }
+public class ICCProfileWrapper
+{
+ /**
+ * The ICCProfile extracted from DestOutputItents
+ */
+ private final ICC_Profile profile;
+
+ /**
+ * The ICC ColorSpace created using the ICCProfile
+ */
+ private final ICC_ColorSpace colorSpace;
+
+ public ICCProfileWrapper(final ICC_Profile _profile)
+ {
+ this.profile = _profile;
+ this.colorSpace = new ICC_ColorSpace(_profile);
+ }
+
+ /**
+ * Call the ICC_ColorSpace.getType method and return the value.
+ *
+ * @return
+ */
+ public int getColorSpaceType()
+ {
+ return colorSpace.getType();
+ }
+
+ /**
+ * @return the profile
+ */
+ public ICC_Profile getProfile()
+ {
+ return profile;
+ }
+
+ /**
+ * Return true if the ColourSpace is RGB
+ *
+ * @return
+ */
+ public boolean isRGBColorSpace()
+ {
+ return ICC_ColorSpace.TYPE_RGB == colorSpace.getType();
+ }
+
+ /**
+ * Return true if the ColourSpace is CMYK
+ *
+ * @return
+ */
+ public boolean isCMYKColorSpace()
+ {
+ return ICC_ColorSpace.TYPE_CMYK == colorSpace.getType();
+ }
+
+ /**
+ * Return true if the ColourSpace is Gray scale
+ *
+ * @return
+ */
+ public boolean isGrayColorSpace()
+ {
+ return ICC_ColorSpace.TYPE_GRAY == colorSpace.getType();
+ }
+
+ /**
+ * This method read all outputIntent dictionary until on of them have a destOutputProfile stream. This stream is
+ * parsed and is used to create a IccProfileWrapper.
+ *
+ * @param context
+ * @return an instance of ICCProfileWrapper or null if there are no DestOutputProfile
+ * @throws ValidationException
+ * if an IOException occurs during the DestOutputProfile parsing
+ */
+ private static ICCProfileWrapper searchFirstICCProfile(PreflightContext context) throws ValidationException
+ {
+ PreflightDocument document = context.getDocument();
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ COSBase cBase = catalog.getCOSDictionary().getItem(COSName.getPDFName(DOCUMENT_DICTIONARY_KEY_OUTPUT_INTENTS));
+ COSArray outputIntents = COSUtils.getAsArray(cBase, document.getDocument());
+
+ for (int i = 0; outputIntents != null && i < outputIntents.size(); ++i)
+ {
+ COSDictionary outputIntentDict = COSUtils.getAsDictionary(outputIntents.get(i), document.getDocument());
+ COSBase destOutputProfile = outputIntentDict.getItem(OUTPUT_INTENT_DICTIONARY_KEY_DEST_OUTPUT_PROFILE);
+ if (destOutputProfile != null)
+ {
+ try
+ {
+ PDStream stream = PDStream.createFromCOS(COSUtils.getAsStream(destOutputProfile,
+ document.getDocument()));
+ if (stream != null)
+ {
+ ICC_Profile iccp = ICC_Profile.getInstance(stream.getByteArray());
+ return new ICCProfileWrapper(iccp);
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ValidationException("DestOutputProfile isn't a ICCProfile", e);
+ }
+ catch (IOException e)
+ {
+ throw new ValidationException("Unable to parse the ICCProfile", e);
+ }
+ }
+ }
+ return null;
+ }
+
+ public static ICCProfileWrapper getOrSearchICCProfile(PreflightContext context) throws ValidationException
+ {
+ ICCProfileWrapper profileWrapper = context.getIccProfileWrapper();
+ if (profileWrapper == null && !context.isIccProfileAlreadySearched())
+ {
+ profileWrapper = searchFirstICCProfile(context);
+ context.setIccProfileAlreadySearched(true);
+ }
+ return profileWrapper;
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/NoPatternColorSpaceHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/NoPatternColorSpaceHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/NoPatternColorSpaceHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/NoPatternColorSpaceHelper.java Wed Mar 6 16:46:35 2013
@@ -28,22 +28,24 @@ import org.apache.pdfbox.preflight.Prefl
import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
/**
- * This class defines restrictions on Pattern ColorSpace. It checks the
- * consistency of the Color space with the DestOutputIntent, if the color space
- * is a Pattern the validation will fail.
+ * This class defines restrictions on Pattern ColorSpace. It checks the consistency of the Color space with the
+ * DestOutputIntent, if the color space is a Pattern the validation will fail.
*/
-public class NoPatternColorSpaceHelper extends StandardColorSpaceHelper {
+public class NoPatternColorSpaceHelper extends StandardColorSpaceHelper
+{
-
- public NoPatternColorSpaceHelper(PreflightContext _context, PDColorSpace _cs) {
- super(_context, _cs);
- }
+ public NoPatternColorSpaceHelper(PreflightContext _context, PDColorSpace _cs)
+ {
+ super(_context, _cs);
+ }
-/**
- * This method updates the given list with a ValidationError
- * (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN) and returns false.
- */
- protected void processPatternColorSpace(PDColorSpace pdcs) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN, "Pattern color space is forbidden"));
- }
+ /**
+ * This method updates the given list with a ValidationError (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN)
+ * and returns false.
+ */
+ protected void processPatternColorSpace(PDColorSpace pdcs)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN,
+ "Pattern color space is forbidden"));
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java Wed Mar 6 16:46:35 2013
@@ -21,7 +21,6 @@
package org.apache.pdfbox.preflight.graphic;
-
import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE;
import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE;
import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK;
@@ -52,341 +51,406 @@ import org.apache.pdfbox.preflight.Valid
import org.apache.pdfbox.preflight.exception.ValidationException;
/**
- * This class doesn't define restrictions on ColorSpace. It checks only the
- * consistency of the Color space with the DestOutputIntent.
+ * This class doesn't define restrictions on ColorSpace. It checks only the consistency of the Color space with the
+ * DestOutputIntent.
*/
-public class StandardColorSpaceHelper implements ColorSpaceHelper {
- /**
- * The context which contains useful information to process the
- * validation.
- */
- protected PreflightContext context = null;
- /**
- * The ICCProfile contained in the DestOutputIntent
- */
- protected ICCProfileWrapper iccpw = null;
- /**
- * High level object which represents the colors space to check.
- */
- protected PDColorSpace pdcs = null;
-
- protected StandardColorSpaceHelper(PreflightContext _context, PDColorSpace _cs) {
- this.context = _context;
- this.pdcs = _cs;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * net.awl.edoc.pdfa.validation.graphics.color.ColorSpaceHelper#validate(java
- * .util.List)
- */
- public final void validate() throws ValidationException {
- if ( pdcs == null ) {
- throw new ValidationException("Unable to create a PDColorSpace with the value null");
- }
-
- this.iccpw = ICCProfileWrapper.getOrSearchICCProfile(context);
- processAllColorSpace(pdcs);
- }
-
- /**
- * Method called by the validate method. According to the ColorSpace, a
- * specific ColorSpace method is called.
- *
- * @param pdcs
- * the color space object to check.
- * @param result
- * the list of error to update if the validation fails.
- * @return true if the validation succeed, false otherwise.
- */
- protected final void processAllColorSpace(PDColorSpace pdcs) {
- ColorSpaces cs = ColorSpaces.valueOf(pdcs.getName());
-
- switch (cs) {
- case DeviceRGB:
- case DeviceRGB_SHORT:
- processRGBColorSpace(pdcs);
- break;
- case DeviceCMYK:
- case DeviceCMYK_SHORT:
- processCYMKColorSpace(pdcs);
- break;
- case CalRGB:
- case CalGray:
- case Lab:
- processCalibratedColorSpace(pdcs);
- break;
- case DeviceGray:
- case DeviceGray_SHORT:
- processGrayColorSpace(pdcs);
- break;
- case ICCBased:
- processICCBasedColorSpace(pdcs);
- break;
- case DeviceN:
- processDeviceNColorSpace(pdcs);
- break;
- case Indexed:
- case Indexed_SHORT:
- processIndexedColorSpace(pdcs);
- break;
- case Separation:
- processSeparationColorSpace(pdcs);
- break;
- case Pattern:
- processPatternColorSpace(pdcs);
- break;
- default:
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE, cs.getLabel() + " is unknown as ColorSpace"));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * DeviceRGB.
- *
- */
- protected void processRGBColorSpace(PDColorSpace pdcs) {
- if (!processDefaultColorSpace(pdcs)) {
- if (iccpw == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
- } else if (!iccpw.isRGBColorSpace()) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB, "DestOutputProfile isn't RGB ColorSpace"));
- }
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * DeviceCYMK.
- *
- */
- protected void processCYMKColorSpace(PDColorSpace pdcs) {
- if (!processDefaultColorSpace(pdcs)) {
- if (iccpw == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
- } else if (!iccpw.isCMYKColorSpace()) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK, "DestOutputProfile isn't CMYK ColorSpace"));
- }
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is a
- * Pattern.
- */
- protected void processPatternColorSpace(PDColorSpace pdcs) {
- if (iccpw == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * DeviceGray.
- *
- */
- protected void processGrayColorSpace(PDColorSpace pdcs) {
- if (!processDefaultColorSpace(pdcs) && iccpw == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is a
- * Clibrated Color (CalGary, CalRGB, Lab).
- *
- */
- protected void processCalibratedColorSpace(PDColorSpace pdcs) {
- // ---- OutputIntent isn't mandatory
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is a
- * ICCBased color space. Because this kind of ColorSpace can have alternate
- * color space, the processAllColorSpace is called to check this alternate
- * color space. (Pattern is forbidden as Alternate Color Space)
- *
- * @param pdcs
- * the color space object to check.
- */
- protected void processICCBasedColorSpace(PDColorSpace pdcs) {
- PDICCBased iccBased = (PDICCBased) pdcs;
- try {
- ICC_Profile iccp = ICC_Profile.getInstance(iccBased.getPDStream().getByteArray());
- if (iccp == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED, "Unable to read ICCBase color space "));
- return ;
- }
- List<PDColorSpace> altCs = iccBased.getAlternateColorSpaces();
- for (PDColorSpace altpdcs : altCs) {
- if (altpdcs != null) {
-
- ColorSpaces altCsId = ColorSpaces.valueOf(altpdcs.getName());
- if (altCsId == ColorSpaces.Pattern) {
- context.addValidationError(new ValidationError(
- ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN, "Pattern is forbidden as AlternateColorSpace of a ICCBased"));
- return;
- }
-
- /*
- * According to the ISO-19005-1:2005
- *
- * A conforming reader shall render ICCBased colour spaces as specified
- * by the ICC specification, and shall not use the Alternate colour space
- * specified in an ICC profile stream dictionary
- *
- * We don't check the alternate ColorSpaces
- */
- }
- }
- } catch (IOException e) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read ICCBase color space : " + e.getMessage()));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * DeviceN. Because this kind of ColorSpace can have alternate color space,
- * the processAllColorSpace is called to check this alternate color space.
- * (There are no restrictions on the Alternate Color space)
- *
- * @param pdcs
- * the color space object to check.
- */
- protected void processDeviceNColorSpace(PDColorSpace pdcs) {
- PDDeviceN deviceN = (PDDeviceN) pdcs;
- try {
- if (iccpw == null) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
- return;
- }
-
- PDColorSpace altColor = deviceN.getAlternateColorSpace();
- if (altColor != null) {
- processAllColorSpace(altColor);
- }
-
- int numberOfColorants = 0;
- PDDeviceNAttributes attr = deviceN.getAttributes();
- if ( attr != null ) {
- Map colorants = attr.getColorants();
- if (colorants != null) {
- numberOfColorants = colorants.size();
- for (Object col : colorants.values()) {
- if (col != null) {
- processAllColorSpace((PDColorSpace) col);
- }
- }
- }
- }
- int numberOfComponents = deviceN.getNumberOfComponents();
- if (numberOfColorants > MAX_DEVICE_N_LIMIT || numberOfComponents > MAX_DEVICE_N_LIMIT ) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN, "DeviceN has too many tint components or colorants"));
- }
- } catch (IOException e) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read DeviceN color space : " + e.getMessage()));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * Indexed. Because this kind of ColorSpace can have a Base color space, the
- * processAllColorSpace is called to check this base color space. (Indexed and
- * Pattern can't be a Base color space)
- *
- * @param pdcs
- * the color space object to check.
- */
- protected void processIndexedColorSpace(PDColorSpace pdcs) {
- PDIndexed indexed = (PDIndexed) pdcs;
- try {
- PDColorSpace based = indexed.getBaseColorSpace();
- ColorSpaces cs = ColorSpaces.valueOf(based.getName());
- if (cs == ColorSpaces.Indexed || cs == ColorSpaces.Indexed_SHORT) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,"Indexed color space can't be used as Base color space"));
- return;
- }
- if (cs == ColorSpaces.Pattern) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,"Pattern color space can't be used as Base color space"));
- return ;
- }
- processAllColorSpace(based);
- } catch (IOException e) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Indexed color space : " + e.getMessage()));
- }
- }
-
- /**
- * Method called by the processAllColorSpace if the ColorSpace to check is
- * Separation. Because this kind of ColorSpace can have an alternate color
- * space, the processAllColorSpace is called to check this alternate color
- * space. (Indexed, Separation, DeviceN and Pattern can't be a Base color
- * space)
- *
- * @param pdcs
- * the color space object to check.
- */
- protected void processSeparationColorSpace(PDColorSpace pdcs) {
- PDSeparation separation = (PDSeparation) pdcs;
- try {
-
- PDColorSpace altCol = separation.getAlternateColorSpace();
- if (altCol != null) {
- ColorSpaces acs = ColorSpaces.valueOf(altCol.getName());
- switch (acs) {
- case Separation:
- case DeviceN:
- case Pattern:
- case Indexed:
- case Indexed_SHORT:
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE, acs.getLabel() + " color space can't be used as alternate color space"));
- break;
- default:
- processAllColorSpace(altCol);
- }
- }
- } catch (IOException e) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Separation color space : " + e.getMessage()));
- }
- }
-
- /**
- * Look up in the closest PDResources objects if there are a default ColorSpace.
- * If there are, check that is a authorized ColorSpace.
- * @param pdcs
- * @return true if the default colorspace is a right one, false otherwise.
- */
- protected boolean processDefaultColorSpace(PDColorSpace pdcs) {
- boolean result = false;
-
- // get default color space
- PreflightPath vPath = context.getValidationPath();
- PDResources resources = vPath.getClosestPathElement(PDResources.class);
- if (resources != null && resources.getColorSpaces() != null) {
- PDColorSpace defaultCS = null;
-
- Map<String, PDColorSpace> colorsSpaces = resources.getColorSpaces();
- if (pdcs.getName().equals(ColorSpaces.DeviceCMYK.getLabel())) {
- defaultCS = colorsSpaces.get("DefaultCMYK");
- } else if (pdcs.getName().equals(ColorSpaces.DeviceRGB.getLabel())) {
- defaultCS = colorsSpaces.get("DefaultRGB");
- } else if (pdcs.getName().equals(ColorSpaces.DeviceGray.getLabel())) {
- defaultCS = colorsSpaces.get("DefaultGray");
- }
-
- if (defaultCS != null) {
- // defaultCS is valid if the number of errors hasn't changed
- int nbOfErrors = context.getDocument().getResult().getErrorsList().size();
- processAllColorSpace(defaultCS);
- int newNbOfErrors = context.getDocument().getResult().getErrorsList().size();
- result = (nbOfErrors == newNbOfErrors);
- }
-
- }
-
- return result;
- }
-}
\ No newline at end of file
+public class StandardColorSpaceHelper implements ColorSpaceHelper
+{
+ /**
+ * The context which contains useful information to process the validation.
+ */
+ protected PreflightContext context = null;
+ /**
+ * The ICCProfile contained in the DestOutputIntent
+ */
+ protected ICCProfileWrapper iccpw = null;
+ /**
+ * High level object which represents the colors space to check.
+ */
+ protected PDColorSpace pdcs = null;
+
+ protected StandardColorSpaceHelper(PreflightContext _context, PDColorSpace _cs)
+ {
+ this.context = _context;
+ this.pdcs = _cs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.graphics.color.ColorSpaceHelper#validate(java .util.List)
+ */
+ public final void validate() throws ValidationException
+ {
+ if (pdcs == null)
+ {
+ throw new ValidationException("Unable to create a PDColorSpace with the value null");
+ }
+
+ this.iccpw = ICCProfileWrapper.getOrSearchICCProfile(context);
+ processAllColorSpace(pdcs);
+ }
+
+ /**
+ * Method called by the validate method. According to the ColorSpace, a specific ColorSpace method is called.
+ *
+ * @param pdcs
+ * the color space object to check.
+ * @param result
+ * the list of error to update if the validation fails.
+ * @return true if the validation succeed, false otherwise.
+ */
+ protected final void processAllColorSpace(PDColorSpace pdcs)
+ {
+ ColorSpaces cs = ColorSpaces.valueOf(pdcs.getName());
+
+ switch (cs)
+ {
+ case DeviceRGB:
+ case DeviceRGB_SHORT:
+ processRGBColorSpace(pdcs);
+ break;
+ case DeviceCMYK:
+ case DeviceCMYK_SHORT:
+ processCYMKColorSpace(pdcs);
+ break;
+ case CalRGB:
+ case CalGray:
+ case Lab:
+ processCalibratedColorSpace(pdcs);
+ break;
+ case DeviceGray:
+ case DeviceGray_SHORT:
+ processGrayColorSpace(pdcs);
+ break;
+ case ICCBased:
+ processICCBasedColorSpace(pdcs);
+ break;
+ case DeviceN:
+ processDeviceNColorSpace(pdcs);
+ break;
+ case Indexed:
+ case Indexed_SHORT:
+ processIndexedColorSpace(pdcs);
+ break;
+ case Separation:
+ processSeparationColorSpace(pdcs);
+ break;
+ case Pattern:
+ processPatternColorSpace(pdcs);
+ break;
+ default:
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE, cs.getLabel()
+ + " is unknown as ColorSpace"));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is DeviceRGB.
+ *
+ */
+ protected void processRGBColorSpace(PDColorSpace pdcs)
+ {
+ if (!processDefaultColorSpace(pdcs))
+ {
+ if (iccpw == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING,
+ "DestOutputProfile is missing"));
+ }
+ else if (!iccpw.isRGBColorSpace())
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB,
+ "DestOutputProfile isn't RGB ColorSpace"));
+ }
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is DeviceCYMK.
+ *
+ */
+ protected void processCYMKColorSpace(PDColorSpace pdcs)
+ {
+ if (!processDefaultColorSpace(pdcs))
+ {
+ if (iccpw == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING,
+ "DestOutputProfile is missing"));
+ }
+ else if (!iccpw.isCMYKColorSpace())
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK,
+ "DestOutputProfile isn't CMYK ColorSpace"));
+ }
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is a Pattern.
+ */
+ protected void processPatternColorSpace(PDColorSpace pdcs)
+ {
+ if (iccpw == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING,
+ "DestOutputProfile is missing"));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is DeviceGray.
+ *
+ */
+ protected void processGrayColorSpace(PDColorSpace pdcs)
+ {
+ if (!processDefaultColorSpace(pdcs) && iccpw == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING,
+ "DestOutputProfile is missing"));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is a Clibrated Color (CalGary, CalRGB, Lab).
+ *
+ */
+ protected void processCalibratedColorSpace(PDColorSpace pdcs)
+ {
+ // ---- OutputIntent isn't mandatory
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is a ICCBased color space. Because this kind
+ * of ColorSpace can have alternate color space, the processAllColorSpace is called to check this alternate color
+ * space. (Pattern is forbidden as Alternate Color Space)
+ *
+ * @param pdcs
+ * the color space object to check.
+ */
+ protected void processICCBasedColorSpace(PDColorSpace pdcs)
+ {
+ PDICCBased iccBased = (PDICCBased) pdcs;
+ try
+ {
+ ICC_Profile iccp = ICC_Profile.getInstance(iccBased.getPDStream().getByteArray());
+ if (iccp == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED,
+ "Unable to read ICCBase color space "));
+ return;
+ }
+ List<PDColorSpace> altCs = iccBased.getAlternateColorSpaces();
+ for (PDColorSpace altpdcs : altCs)
+ {
+ if (altpdcs != null)
+ {
+
+ ColorSpaces altCsId = ColorSpaces.valueOf(altpdcs.getName());
+ if (altCsId == ColorSpaces.Pattern)
+ {
+ context.addValidationError(new ValidationError(
+ ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN,
+ "Pattern is forbidden as AlternateColorSpace of a ICCBased"));
+ return;
+ }
+
+ /*
+ * According to the ISO-19005-1:2005
+ *
+ * A conforming reader shall render ICCBased colour spaces as specified by the ICC specification,
+ * and shall not use the Alternate colour space specified in an ICC profile stream dictionary
+ *
+ * We don't check the alternate ColorSpaces
+ */
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE,
+ "Unable to read ICCBase color space : " + e.getMessage()));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is DeviceN. Because this kind of ColorSpace
+ * can have alternate color space, the processAllColorSpace is called to check this alternate color space. (There
+ * are no restrictions on the Alternate Color space)
+ *
+ * @param pdcs
+ * the color space object to check.
+ */
+ protected void processDeviceNColorSpace(PDColorSpace pdcs)
+ {
+ PDDeviceN deviceN = (PDDeviceN) pdcs;
+ try
+ {
+ if (iccpw == null)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING,
+ "DestOutputProfile is missing"));
+ return;
+ }
+
+ PDColorSpace altColor = deviceN.getAlternateColorSpace();
+ if (altColor != null)
+ {
+ processAllColorSpace(altColor);
+ }
+
+ int numberOfColorants = 0;
+ PDDeviceNAttributes attr = deviceN.getAttributes();
+ if (attr != null)
+ {
+ Map colorants = attr.getColorants();
+ if (colorants != null)
+ {
+ numberOfColorants = colorants.size();
+ for (Object col : colorants.values())
+ {
+ if (col != null)
+ {
+ processAllColorSpace((PDColorSpace) col);
+ }
+ }
+ }
+ }
+ int numberOfComponents = deviceN.getNumberOfComponents();
+ if (numberOfColorants > MAX_DEVICE_N_LIMIT || numberOfComponents > MAX_DEVICE_N_LIMIT)
+ {
+ context.addValidationError(new ValidationError(
+ ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN,
+ "DeviceN has too many tint components or colorants"));
+ }
+ }
+ catch (IOException e)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE,
+ "Unable to read DeviceN color space : " + e.getMessage()));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is Indexed. Because this kind of ColorSpace
+ * can have a Base color space, the processAllColorSpace is called to check this base color space. (Indexed and
+ * Pattern can't be a Base color space)
+ *
+ * @param pdcs
+ * the color space object to check.
+ */
+ protected void processIndexedColorSpace(PDColorSpace pdcs)
+ {
+ PDIndexed indexed = (PDIndexed) pdcs;
+ try
+ {
+ PDColorSpace based = indexed.getBaseColorSpace();
+ ColorSpaces cs = ColorSpaces.valueOf(based.getName());
+ if (cs == ColorSpaces.Indexed || cs == ColorSpaces.Indexed_SHORT)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,
+ "Indexed color space can't be used as Base color space"));
+ return;
+ }
+ if (cs == ColorSpaces.Pattern)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,
+ "Pattern color space can't be used as Base color space"));
+ return;
+ }
+ processAllColorSpace(based);
+ }
+ catch (IOException e)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE,
+ "Unable to read Indexed color space : " + e.getMessage()));
+ }
+ }
+
+ /**
+ * Method called by the processAllColorSpace if the ColorSpace to check is Separation. Because this kind of
+ * ColorSpace can have an alternate color space, the processAllColorSpace is called to check this alternate color
+ * space. (Indexed, Separation, DeviceN and Pattern can't be a Base color space)
+ *
+ * @param pdcs
+ * the color space object to check.
+ */
+ protected void processSeparationColorSpace(PDColorSpace pdcs)
+ {
+ PDSeparation separation = (PDSeparation) pdcs;
+ try
+ {
+
+ PDColorSpace altCol = separation.getAlternateColorSpace();
+ if (altCol != null)
+ {
+ ColorSpaces acs = ColorSpaces.valueOf(altCol.getName());
+ switch (acs)
+ {
+ case Separation:
+ case DeviceN:
+ case Pattern:
+ case Indexed:
+ case Indexed_SHORT:
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE, acs
+ .getLabel() + " color space can't be used as alternate color space"));
+ break;
+ default:
+ processAllColorSpace(altCol);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE,
+ "Unable to read Separation color space : " + e.getMessage()));
+ }
+ }
+
+ /**
+ * Look up in the closest PDResources objects if there are a default ColorSpace. If there are, check that is a
+ * authorized ColorSpace.
+ *
+ * @param pdcs
+ * @return true if the default colorspace is a right one, false otherwise.
+ */
+ protected boolean processDefaultColorSpace(PDColorSpace pdcs)
+ {
+ boolean result = false;
+
+ // get default color space
+ PreflightPath vPath = context.getValidationPath();
+ PDResources resources = vPath.getClosestPathElement(PDResources.class);
+ if (resources != null && resources.getColorSpaces() != null)
+ {
+ PDColorSpace defaultCS = null;
+
+ Map<String, PDColorSpace> colorsSpaces = resources.getColorSpaces();
+ if (pdcs.getName().equals(ColorSpaces.DeviceCMYK.getLabel()))
+ {
+ defaultCS = colorsSpaces.get("DefaultCMYK");
+ }
+ else if (pdcs.getName().equals(ColorSpaces.DeviceRGB.getLabel()))
+ {
+ defaultCS = colorsSpaces.get("DefaultRGB");
+ }
+ else if (pdcs.getName().equals(ColorSpaces.DeviceGray.getLabel()))
+ {
+ defaultCS = colorsSpaces.get("DefaultGray");
+ }
+
+ if (defaultCS != null)
+ {
+ // defaultCS is valid if the number of errors hasn't changed
+ int nbOfErrors = context.getDocument().getResult().getErrorsList().size();
+ processAllColorSpace(defaultCS);
+ int newNbOfErrors = context.getDocument().getResult().getErrorsList().size();
+ result = (nbOfErrors == newNbOfErrors);
+ }
+
+ }
+
+ return result;
+ }
+}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/PDFAIdentificationValidation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/PDFAIdentificationValidation.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/PDFAIdentificationValidation.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/PDFAIdentificationValidation.java Wed Mar 6 16:46:35 2013
@@ -42,69 +42,80 @@ import org.apache.xmpbox.type.Structured
* @author Germain Costenobel
*
*/
-public class PDFAIdentificationValidation {
+public class PDFAIdentificationValidation
+{
- /**
- * Check if PDFAIdentification is valid
- *
- * @param document
- * the PDF Document
- * @param metadata
- * the XMP MetaData
- * @return List of validation errors
- * @throws ValidationException
- */
- public List<ValidationError> validatePDFAIdentifer(XMPMetadata metadata) throws ValidationException {
- List<ValidationError> ve = new ArrayList<ValidationError>();
- PDFAIdentificationSchema id = metadata.getPDFIdentificationSchema();
- if (id == null) {
- ve.add(new ValidationError(ERROR_METADATA_PDFA_ID_MISSING));
- return ve;
+ /**
+ * Check if PDFAIdentification is valid
+ *
+ * @param document
+ * the PDF Document
+ * @param metadata
+ * the XMP MetaData
+ * @return List of validation errors
+ * @throws ValidationException
+ */
+ public List<ValidationError> validatePDFAIdentifer(XMPMetadata metadata) throws ValidationException
+ {
+ List<ValidationError> ve = new ArrayList<ValidationError>();
+ PDFAIdentificationSchema id = metadata.getPDFIdentificationSchema();
+ if (id == null)
+ {
+ ve.add(new ValidationError(ERROR_METADATA_PDFA_ID_MISSING));
+ return ve;
+ }
+
+ // According to the PDF/A specification, the prefix must be pdfaid for this schema.
+ StructuredType stBasic = XMPBasicSchema.class.getAnnotation(StructuredType.class);
+ StructuredType stPdfaIdent = PDFAIdentificationSchema.class.getAnnotation(StructuredType.class);
+ if (!id.getPrefix().equals(stPdfaIdent.preferedPrefix()))
+ {
+ if (metadata.getSchema(stPdfaIdent.preferedPrefix(), stBasic.namespace()) == null)
+ {
+ ve.add(unexpectedPrefixFoundError(id.getPrefix(), stPdfaIdent.preferedPrefix(),
+ PDFAIdentificationSchema.class.getName()));
+ }
+ else
+ {
+ id = (PDFAIdentificationSchema) metadata.getSchema(stPdfaIdent.preferedPrefix(),
+ stPdfaIdent.namespace());
+ }
+ }
+ checkConformanceLevel(ve, id.getConformance());
+ checkPartNumber(ve, id.getPart());
+ return ve;
}
- // According to the PDF/A specification, the prefix must be pdfaid for this schema.
- StructuredType stBasic = XMPBasicSchema.class.getAnnotation(StructuredType.class);
- StructuredType stPdfaIdent = PDFAIdentificationSchema.class.getAnnotation(StructuredType.class);
- if (!id.getPrefix().equals(stPdfaIdent.preferedPrefix())) {
- if (metadata.getSchema(stPdfaIdent.preferedPrefix(), stBasic.namespace()) == null) {
- ve.add(unexpectedPrefixFoundError(id.getPrefix(),
- stPdfaIdent.preferedPrefix(), PDFAIdentificationSchema.class.getName()));
- } else {
- id = (PDFAIdentificationSchema) metadata.getSchema(
- stPdfaIdent.preferedPrefix(), stPdfaIdent.namespace());
- }
+ /**
+ * Return a validationError formatted when a schema has not the expected prefix
+ *
+ * @param prefFound
+ * @param prefExpected
+ * @param schema
+ * @return
+ */
+ protected ValidationError unexpectedPrefixFoundError(String prefFound, String prefExpected, String schema)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append(schema).append(" found but prefix used is '").append(prefFound).append("', prefix '")
+ .append(prefExpected).append("' is expected.");
+
+ return new ValidationError(ERROR_METADATA_WRONG_NS_PREFIX, sb.toString());
}
- checkConformanceLevel(ve, id.getConformance());
- checkPartNumber(ve, id.getPart());
- return ve;
- }
-
- /**
- * Return a validationError formatted when a schema has not the expected
- * prefix
- *
- * @param prefFound
- * @param prefExpected
- * @param schema
- * @return
- */
- protected ValidationError unexpectedPrefixFoundError(String prefFound, String prefExpected, String schema) {
- StringBuilder sb = new StringBuilder(80);
- sb.append(schema).append(" found but prefix used is '").append(prefFound)
- .append("', prefix '").append(prefExpected).append("' is expected.");
-
- return new ValidationError(ERROR_METADATA_WRONG_NS_PREFIX, sb.toString());
- }
-
- protected void checkConformanceLevel(List<ValidationError> ve, String value) {
- if (!(value.equals("A") || value.equals("B"))) {
- ve.add(new ValidationError(ERROR_METADATA_INVALID_PDFA_CONFORMANCE));
+
+ protected void checkConformanceLevel(List<ValidationError> ve, String value)
+ {
+ if (!(value.equals("A") || value.equals("B")))
+ {
+ ve.add(new ValidationError(ERROR_METADATA_INVALID_PDFA_CONFORMANCE));
+ }
}
- }
- protected void checkPartNumber(List<ValidationError> ve, int value) {
- if (value != 1) {
- ve.add(new ValidationError(ERROR_METADATA_INVALID_PDFA_VERSION_ID));
+ protected void checkPartNumber(List<ValidationError> ve, int value)
+ {
+ if (value != 1)
+ {
+ ve.add(new ValidationError(ERROR_METADATA_INVALID_PDFA_VERSION_ID));
+ }
}
- }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/RDFAboutAttributeConcordanceValidation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/RDFAboutAttributeConcordanceValidation.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/RDFAboutAttributeConcordanceValidation.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/RDFAboutAttributeConcordanceValidation.java Wed Mar 6 16:46:35 2013
@@ -23,56 +23,59 @@ package org.apache.pdfbox.preflight.meta
import java.util.List;
-
import org.apache.pdfbox.preflight.exception.ValidationException;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.XMPSchema;
/**
- * Class which all elements within an rdf:RDF have the same value for their
- * rdf:about attributes
+ * Class which all elements within an rdf:RDF have the same value for their rdf:about attributes
*
* @author Germain Costenobel
*
*/
-public class RDFAboutAttributeConcordanceValidation {
+public class RDFAboutAttributeConcordanceValidation
+{
- /**
- *
- * @param metadata
- * @return
- * @throws DifferentRDFAboutException
- * @throws ValidationException
- */
- public void validateRDFAboutAttributes(XMPMetadata metadata)
- throws ValidationException, DifferentRDFAboutException {
-
- List<XMPSchema> schemas = metadata.getAllSchemas();
- if (schemas.size() == 0) {
- throw new ValidationException(
- "Schemas not found in the given metadata representation");
- }
- String about = schemas.get(0).getAboutValue();
- // rdf:description must have an rdf:about attribute
- for (XMPSchema xmpSchema : schemas) {
- checkRdfAbout(about, xmpSchema);
- }
+ /**
+ *
+ * @param metadata
+ * @return
+ * @throws DifferentRDFAboutException
+ * @throws ValidationException
+ */
+ public void validateRDFAboutAttributes(XMPMetadata metadata) throws ValidationException, DifferentRDFAboutException
+ {
+
+ List<XMPSchema> schemas = metadata.getAllSchemas();
+ if (schemas.size() == 0)
+ {
+ throw new ValidationException("Schemas not found in the given metadata representation");
+ }
+ String about = schemas.get(0).getAboutValue();
+ // rdf:description must have an rdf:about attribute
+ for (XMPSchema xmpSchema : schemas)
+ {
+ checkRdfAbout(about, xmpSchema);
+ }
- }
+ }
- private void checkRdfAbout(String about, XMPSchema xmpSchema)
- throws DifferentRDFAboutException {
- if (!about.equals(xmpSchema.getAboutValue())) {
- throw new DifferentRDFAboutException();
+ private void checkRdfAbout(String about, XMPSchema xmpSchema) throws DifferentRDFAboutException
+ {
+ if (!about.equals(xmpSchema.getAboutValue()))
+ {
+ throw new DifferentRDFAboutException();
+ }
}
- }
- public static class DifferentRDFAboutException extends Exception {
+ public static class DifferentRDFAboutException extends Exception
+ {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- public DifferentRDFAboutException() {
- super("all rdf:about in RDF:rdf must have the same value");
+ public DifferentRDFAboutException()
+ {
+ super("all rdf:about in RDF:rdf must have the same value");
+ }
}
- }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/SynchronizedMetaDataValidation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/SynchronizedMetaDataValidation.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/SynchronizedMetaDataValidation.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/SynchronizedMetaDataValidation.java Wed Mar 6 16:46:35 2013
@@ -27,7 +27,6 @@ import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
-
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.preflight.PreflightConstants;
@@ -42,492 +41,551 @@ import org.apache.xmpbox.type.AbstractFi
import org.apache.xmpbox.type.TextType;
/**
- * Class which check if document information available in a document are
- * synchronized with XMP
+ * Class which check if document information available in a document are synchronized with XMP
*
* @author Germain Costenobel
*
*/
-public class SynchronizedMetaDataValidation {
+public class SynchronizedMetaDataValidation
+{
+
+ /**
+ * Analyze if Title embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param dc
+ * Dublin Core Schema
+ * @param ve
+ * The list of validation errors
+ */
+ protected void analyzeTitleProperty(PDDocumentInformation dico, DublinCoreSchema dc, List<ValidationError> ve)
+ {
+ String title = dico.getTitle();
+ if (title != null)
+ {
+ if (dc != null)
+ {
+ // Check the x-default value, if not found, check with the first value
+ // found
+ if (dc.getTitle() != null)
+ {
+ if (dc.getTitle("x-default") != null)
+ {
+ if (!dc.getTitle("x-default").equals(title))
+ {
+ ve.add(unsynchronizedMetaDataError("Title"));
+ }
+ }
+ else
+ {
+ // This search of first value is made just to keep compatibility
+ // with lot of PDF documents
+ // which use title without lang definition
+ // REM : MAY we have to delete this option in the future
+ Iterator<AbstractField> it = dc.getTitleProperty().getContainer().getAllProperties().iterator();
+ if (it.hasNext())
+ {
+ AbstractField tmp = it.next();
+ if (tmp instanceof TextType)
+ {
+ if (!((TextType) tmp).getStringValue().equals(title))
+ {
+ ve.add(unsynchronizedMetaDataError("Title"));
+ }
+ }
+ else
+ {
+ ve.add(AbsentXMPPropertyError("Title", "Property is badly defined"));
+ }
+ }
+ else
+ {
+ ve.add(AbsentXMPPropertyError("Title", "Property is not defined"));
+ }
+ }
+
+ }
+ else
+ {
+ ve.add(AbsentXMPPropertyError("Title", "Property is not defined"));
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("Title", "Dublin Core"));
+ }
+ }
+ }
+
+ /**
+ * Analyze if Author(s) embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param dc
+ * Dublin Core Schema
+ * @param ve
+ * The list of validation errors
+ */
+ protected void analyzeAuthorProperty(PDDocumentInformation dico, DublinCoreSchema dc, List<ValidationError> ve)
+ {
+ String author = dico.getAuthor();
+ if (author != null)
+ {
+ if (dc != null)
+ {
+ if (dc.getCreatorsProperty() != null)
+ {
+ if (dc.getCreators().size() != 1)
+ {
+ ve.add(AbsentXMPPropertyError("Author",
+ "In XMP metadata, Author(s) must be represented by a single entry in a text array (dc:creator) "));
+ }
+ else
+ {
+ if (dc.getCreators().get(0) == null)
+ {
+ ve.add(AbsentXMPPropertyError("Author", "Property is defined as null"));
+ }
+ else
+ {
+ if (!dc.getCreators().get(0).equals(author))
+ {
+ ve.add(unsynchronizedMetaDataError("Author"));
+ }
+ }
+ }
+ }
+ else
+ {
+ ve.add(AbsentXMPPropertyError("Author", "Property is not defined in XMP Metadata"));
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("Author", "Dublin Core"));
+ }
+ }
+ }
+
+ /**
+ * Analyze if Subject(s) embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param dc
+ * Dublin Core Schema
+ * @param ve
+ * The list of validation errors
+ */
+ protected void analyzeSubjectProperty(PDDocumentInformation dico, DublinCoreSchema dc, List<ValidationError> ve)
+ {
+ String subject = dico.getSubject();
+ if (subject != null)
+ {
+ if (dc != null)
+ {
+ // PDF/A Conformance Erratum (2007) specifies XMP Subject
+ // as a Text type embedded in the dc:description["x-default"].
+ if (dc.getDescriptionProperty() != null)
+ {
+ if (dc.getDescription("x-default") == null)
+ {
+ ve.add(AbsentXMPPropertyError("Subject",
+ "Subject not found in XMP (dc:description[\"x-default\"] not found)"));
+ }
+ else
+ {
+ if (!dc.getDescription("x-default").equals(subject))
+ {
+ ve.add(unsynchronizedMetaDataError("Subject"));
+
+ }
+ }
+ }
+ else
+ {
+ ve.add(AbsentXMPPropertyError("Subject", "Property is defined as null"));
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("Subject", "Dublin Core"));
+ }
+ }
+ }
+
+ /**
+ * Analyze if Keyword(s) embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param pdf
+ * PDF Schema
+ * @param ve
+ * The list of validation errors
+ */
+ protected void analyzeKeywordsProperty(PDDocumentInformation dico, AdobePDFSchema pdf, List<ValidationError> ve)
+ {
+ String keyword = dico.getKeywords();
+ if (keyword != null)
+ {
+ if (pdf != null)
+ {
+ if (pdf.getKeywordsProperty() == null)
+ {
+ ve.add(AbsentXMPPropertyError("Keywords", "Property is not defined"));
+ }
+ else
+ {
+ if (!pdf.getKeywords().equals(keyword))
+ {
+ ve.add(unsynchronizedMetaDataError("Keywords"));
+ }
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("Keywords", "PDF"));
+ }
+ }
+ }
+
+ /**
+ * Analyze if Producer embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param pdf
+ * PDF Schema
+ * @param ve
+ * The list of validation errors
+ */
+ protected void analyzeProducerProperty(PDDocumentInformation dico, AdobePDFSchema pdf, List<ValidationError> ve)
+ {
+ String producer = dico.getProducer();
+ if (producer != null)
+ {
+ if (pdf != null)
+ {
+ if (pdf.getProducerProperty() == null)
+ {
+ ve.add(AbsentXMPPropertyError("Producer", "Property is not defined"));
+ }
+ else
+ {
+ if (!pdf.getProducer().equals(producer))
+ {
+ ve.add(unsynchronizedMetaDataError("Producer"));
+ }
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("Producer", "PDF"));
+ }
+ }
+
+ }
+
+ /**
+ * Analyze if the creator tool embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param xmp
+ * XMP Basic Schema
+ * @param ve
+ * The list of validation errors
+ *
+ */
+ protected void analyzeCreatorToolProperty(PDDocumentInformation dico, XMPBasicSchema xmp, List<ValidationError> ve)
+ {
+ String creatorTool = dico.getCreator();
+ if (creatorTool != null)
+ {
+ if (xmp != null)
+ {
+ if (xmp.getCreatorToolProperty() == null)
+ {
+ ve.add(AbsentXMPPropertyError("CreatorTool", "Property is not defined"));
+ }
+ else
+ {
+ if (!xmp.getCreatorTool().equals(creatorTool))
+ {
+ ve.add(unsynchronizedMetaDataError("CreatorTool"));
+ }
+ }
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("CreatorTool", "PDF"));
+ }
+ }
- /**
- * Analyze if Title embedded in Document Information dictionary and in XMP
- * properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param dc
- * Dublin Core Schema
- * @param ve
- * The list of validation errors
- */
- protected void analyzeTitleProperty(PDDocumentInformation dico,
- DublinCoreSchema dc, List<ValidationError> ve) {
- String title = dico.getTitle();
- if (title != null) {
- if (dc != null) {
- // Check the x-default value, if not found, check with the first value
- // found
- if (dc.getTitle() != null) {
- if (dc.getTitle("x-default") != null) {
- if (!dc.getTitle("x-default").equals(title)) {
- ve.add(unsynchronizedMetaDataError("Title"));
- }
- } else {
- // This search of first value is made just to keep compatibility
- // with lot of PDF documents
- // which use title without lang definition
- // REM : MAY we have to delete this option in the future
- Iterator<AbstractField> it = dc.getTitleProperty().getContainer()
- .getAllProperties().iterator();
- if (it.hasNext()) {
- AbstractField tmp = it.next();
- if (tmp instanceof TextType) {
- if (!((TextType) tmp).getStringValue().equals(title)) {
- ve.add(unsynchronizedMetaDataError("Title"));
- }
- } else {
- ve.add(AbsentXMPPropertyError("Title",
- "Property is badly defined"));
- }
- } else {
- ve
- .add(AbsentXMPPropertyError("Title",
- "Property is not defined"));
- }
- }
-
- } else {
- ve.add(AbsentXMPPropertyError("Title", "Property is not defined"));
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("Title", "Dublin Core"));
- }
- }
- }
-
- /**
- * Analyze if Author(s) embedded in Document Information dictionary and in XMP
- * properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param dc
- * Dublin Core Schema
- * @param ve
- * The list of validation errors
- */
- protected void analyzeAuthorProperty(PDDocumentInformation dico,
- DublinCoreSchema dc, List<ValidationError> ve) {
- String author = dico.getAuthor();
- if (author != null) {
- if (dc != null) {
- if (dc.getCreatorsProperty() != null) {
- if (dc.getCreators().size() != 1) {
- ve
- .add(AbsentXMPPropertyError(
- "Author",
- "In XMP metadata, Author(s) must be represented by a single entry in a text array (dc:creator) "));
- } else {
- if (dc.getCreators().get(0) == null) {
- ve.add(AbsentXMPPropertyError("Author",
- "Property is defined as null"));
- } else {
- if (!dc.getCreators().get(0).equals(author)) {
- ve.add(unsynchronizedMetaDataError("Author"));
- }
- }
- }
- } else {
- ve.add(AbsentXMPPropertyError("Author",
- "Property is not defined in XMP Metadata"));
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("Author", "Dublin Core"));
- }
- }
- }
-
- /**
- * Analyze if Subject(s) embedded in Document Information dictionary and in
- * XMP properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param dc
- * Dublin Core Schema
- * @param ve
- * The list of validation errors
- */
- protected void analyzeSubjectProperty(PDDocumentInformation dico,
- DublinCoreSchema dc, List<ValidationError> ve) {
- String subject = dico.getSubject();
- if (subject != null) {
- if (dc != null) {
- // PDF/A Conformance Erratum (2007) specifies XMP Subject
- // as a Text type embedded in the dc:description["x-default"].
- if (dc.getDescriptionProperty() != null) {
- if (dc.getDescription("x-default") == null) {
- ve
- .add(AbsentXMPPropertyError("Subject",
- "Subject not found in XMP (dc:description[\"x-default\"] not found)"));
- } else {
- if (!dc.getDescription("x-default").equals(subject)) {
- ve.add(unsynchronizedMetaDataError("Subject"));
-
- }
- }
- } else {
- ve.add(AbsentXMPPropertyError("Subject",
- "Property is defined as null"));
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("Subject", "Dublin Core"));
- }
- }
- }
-
- /**
- * Analyze if Keyword(s) embedded in Document Information dictionary and in
- * XMP properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param pdf
- * PDF Schema
- * @param ve
- * The list of validation errors
- */
- protected void analyzeKeywordsProperty(PDDocumentInformation dico,
- AdobePDFSchema pdf, List<ValidationError> ve) {
- String keyword = dico.getKeywords();
- if (keyword != null) {
- if (pdf != null) {
- if (pdf.getKeywordsProperty() == null) {
- ve.add(AbsentXMPPropertyError("Keywords", "Property is not defined"));
- } else {
- if (!pdf.getKeywords().equals(keyword)) {
- ve.add(unsynchronizedMetaDataError("Keywords"));
- }
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("Keywords", "PDF"));
- }
- }
- }
-
- /**
- * Analyze if Producer embedded in Document Information dictionary and in XMP
- * properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param pdf
- * PDF Schema
- * @param ve
- * The list of validation errors
- */
- protected void analyzeProducerProperty(PDDocumentInformation dico,
- AdobePDFSchema pdf, List<ValidationError> ve) {
- String producer = dico.getProducer();
- if (producer != null) {
- if (pdf != null) {
- if (pdf.getProducerProperty() == null) {
- ve.add(AbsentXMPPropertyError("Producer", "Property is not defined"));
- } else {
- if (!pdf.getProducer().equals(producer)) {
- ve.add(unsynchronizedMetaDataError("Producer"));
- }
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("Producer", "PDF"));
- }
- }
-
- }
-
- /**
- * Analyze if the creator tool embedded in Document Information dictionary and
- * in XMP properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param xmp
- * XMP Basic Schema
- * @param ve
- * The list of validation errors
- *
- */
- protected void analyzeCreatorToolProperty(PDDocumentInformation dico,
- XMPBasicSchema xmp, List<ValidationError> ve) {
- String creatorTool = dico.getCreator();
- if (creatorTool != null) {
- if (xmp != null) {
- if (xmp.getCreatorToolProperty() == null) {
- ve.add(AbsentXMPPropertyError("CreatorTool",
- "Property is not defined"));
- } else {
- if (!xmp.getCreatorTool().equals(creatorTool)) {
- ve.add(unsynchronizedMetaDataError("CreatorTool"));
- }
- }
- } else {
- ve.add(AbsentSchemaMetaDataError("CreatorTool", "PDF"));
- }
- }
-
- }
-
- /**
- * Analyze if the CreationDate embedded in Document Information dictionary and
- * in XMP properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param xmp
- * XMP Basic Schema
- * @param ve
- * The list of validation errors
- * @throws ValidationException
- */
- protected void analyzeCreationDateProperty(PDDocumentInformation dico,
- XMPBasicSchema xmp, List<ValidationError> ve) throws ValidationException {
- Calendar creationDate;
- try {
- creationDate = dico.getCreationDate();
- } catch (IOException e) {
- // If there is an error while converting this property to a date
- throw formatAccessException("Document Information", "CreationDate", e);
- }
- if (creationDate != null) {
- if (xmp != null) {
- Calendar xmpCreationDate = xmp.getCreateDate();
-
- if (xmpCreationDate == null) {
- ve.add(AbsentXMPPropertyError("CreationDate",
- "Property is not defined"));
- } else {
- if (!DateConverter.toISO8601(xmpCreationDate).equals(
- DateConverter.toISO8601(creationDate))) {
- ve.add(unsynchronizedMetaDataError("CreationDate"));
- }
- }
-
- } else {
- ve.add(AbsentSchemaMetaDataError("CreationDate", "Basic XMP"));
- }
- }
- }
-
- /**
- * Analyze if the ModifyDate embedded in Document Information dictionary and
- * in XMP properties are synchronized
- *
- * @param dico
- * Document Information Dictionary
- * @param xmp
- * XMP Basic Schema
- * @param ve
- * The list of validation errors
- * @throws ValidationException
- */
- protected void analyzeModifyDateProperty(PDDocumentInformation dico,
- XMPBasicSchema xmp, List<ValidationError> ve) throws ValidationException {
- Calendar modifyDate;
- try {
- modifyDate = dico.getModificationDate();
- if (modifyDate != null) {
- if (xmp != null) {
-
- Calendar xmpModifyDate = xmp.getModifyDate();
- if (xmpModifyDate == null) {
- ve.add(AbsentXMPPropertyError("ModifyDate",
- "Property is not defined"));
- } else {
- if (!DateConverter.toISO8601(xmpModifyDate).equals(
- DateConverter.toISO8601(modifyDate))) {
-
- ve.add(unsynchronizedMetaDataError("ModificationDate"));
- }
- }
-
- } else {
- ve.add(AbsentSchemaMetaDataError("ModifyDate", "Basic XMP"));
- }
- }
- } catch (IOException e) {
- // If there is an error while converting this property to a date
- throw formatAccessException("Document Information", "ModifyDate", e);
- }
-
- }
-
- /**
- * Check if document information entries and XMP information are synchronized
- *
- * @param document
- * the PDF Document
- * @param metadata
- * the XMP MetaData
- * @return List of validation errors
- * @throws ValidationException
- */
- public List<ValidationError> validateMetadataSynchronization(PDDocument document, XMPMetadata metadata)
- throws ValidationException {
- List<ValidationError> ve = new ArrayList<ValidationError>();
-
- if (document == null) {
- throw new ValidationException("Document provided is null");
- } else {
- PDDocumentInformation dico = document.getDocumentInformation();
- if (metadata == null) {
- throw new ValidationException("Metadata provided are null");
- } else {
- DublinCoreSchema dc = metadata.getDublinCoreSchema();
-
- // TITLE
- analyzeTitleProperty(dico, dc, ve);
- // AUTHOR
- analyzeAuthorProperty(dico, dc, ve);
- // SUBJECT
- analyzeSubjectProperty(dico, dc, ve);
-
- AdobePDFSchema pdf = metadata.getAdobePDFSchema();
-
- // KEYWORDS
- analyzeKeywordsProperty(dico, pdf, ve);
- // PRODUCER
- analyzeProducerProperty(dico, pdf, ve);
-
- XMPBasicSchema xmp = metadata.getXMPBasicSchema();
-
- // CREATOR TOOL
- analyzeCreatorToolProperty(dico, xmp, ve);
-
- // CREATION DATE
- analyzeCreationDateProperty(dico, xmp, ve);
-
- // MODIFY DATE
- analyzeModifyDateProperty(dico, xmp, ve);
-
- }
-
- }
- return ve;
- }
-
- /**
- * Return a validationError formatted when a schema has not the expected
- * prefix
- *
- * @param prefFound
- * @param prefExpected
- * @param schema
- * @return
- */
- protected ValidationError unexpectedPrefixFoundError(String prefFound,
- String prefExpected, String schema) {
- StringBuilder sb = new StringBuilder(80);
- sb.append(schema).append(" found but prefix used is '").append(prefFound)
- .append("', prefix '").append(prefExpected).append("' is expected.");
-
- return new ValidationError(
- PreflightConstants.ERROR_METADATA_WRONG_NS_PREFIX, sb.toString());
- }
-
- /**
- * Return an exception formatted on IOException when accessing metadata
- *
- * @param type
- * type of property (Document Info or XMP)
- * @param target
- * the name of the metadata
- * @param cause
- * the raised IOException
- * @return the generated exception
- */
- protected ValidationException formatAccessException(String type,
- String target, Throwable cause) {
- StringBuilder sb = new StringBuilder(80);
- sb.append("Cannot treat ").append(type).append(" ").append(target).append(
- " property");
- return new ValidationException(sb.toString(), cause);
- }
-
- /**
- * Return an exception formatted on IOException when accessing on metadata
- * schema
- *
- * @param target
- * the name of the schema
- * @param cause
- * the raised IOException
- * @return the generated exception
- */
- protected ValidationException SchemaAccessException(String target,
- Throwable cause) {
- StringBuilder sb = new StringBuilder(80);
- sb.append("Cannot access to the ").append(target).append(" schema");
- return new ValidationException(sb.toString(), cause);
- }
-
- /**
- * Return a formatted validation error when metadata are not synchronized
- *
- * @param target
- * the concerned property
- * @return the generated validation error
- */
- protected ValidationError unsynchronizedMetaDataError(String target) {
- StringBuilder sb = new StringBuilder(80);
- sb
- .append(target)
- .append(
- " present in the document catalog dictionary doesn't match with XMP information");
- return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb
- .toString());
- }
-
- /**
- * Return a formatted validation error when a specific metadata schema can't
- * be found
- *
- * @param target
- * the concerned property
- * @param schema
- * the XMP schema which can't be found
- * @return the generated validation error
- */
- protected ValidationError AbsentSchemaMetaDataError(String target,
- String schema) {
- StringBuilder sb = new StringBuilder(80);
- sb
- .append(target)
- .append(
- " present in the document catalog dictionary can't be found in XMP information (")
- .append(schema).append(" schema not declared)");
- return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb
- .toString());
- }
-
- /**
- * Return a formatted validation error when a specific XMP property can't be
- * found
- *
- * @param target
- * the concerned property
- * @param details
- * comments about the XMP property
- * @return the generated validation error
- */
- protected ValidationError AbsentXMPPropertyError(String target, String details) {
- StringBuilder sb = new StringBuilder(80);
- sb
- .append(target)
- .append(
- " present in the document catalog dictionary can't be found in XMP information (")
- .append(details).append(")");
- return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb
- .toString());
- }
+ }
+
+ /**
+ * Analyze if the CreationDate embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param xmp
+ * XMP Basic Schema
+ * @param ve
+ * The list of validation errors
+ * @throws ValidationException
+ */
+ protected void analyzeCreationDateProperty(PDDocumentInformation dico, XMPBasicSchema xmp, List<ValidationError> ve)
+ throws ValidationException
+ {
+ Calendar creationDate;
+ try
+ {
+ creationDate = dico.getCreationDate();
+ }
+ catch (IOException e)
+ {
+ // If there is an error while converting this property to a date
+ throw formatAccessException("Document Information", "CreationDate", e);
+ }
+ if (creationDate != null)
+ {
+ if (xmp != null)
+ {
+ Calendar xmpCreationDate = xmp.getCreateDate();
+
+ if (xmpCreationDate == null)
+ {
+ ve.add(AbsentXMPPropertyError("CreationDate", "Property is not defined"));
+ }
+ else
+ {
+ if (!DateConverter.toISO8601(xmpCreationDate).equals(DateConverter.toISO8601(creationDate)))
+ {
+ ve.add(unsynchronizedMetaDataError("CreationDate"));
+ }
+ }
+
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("CreationDate", "Basic XMP"));
+ }
+ }
+ }
+
+ /**
+ * Analyze if the ModifyDate embedded in Document Information dictionary and in XMP properties are synchronized
+ *
+ * @param dico
+ * Document Information Dictionary
+ * @param xmp
+ * XMP Basic Schema
+ * @param ve
+ * The list of validation errors
+ * @throws ValidationException
+ */
+ protected void analyzeModifyDateProperty(PDDocumentInformation dico, XMPBasicSchema xmp, List<ValidationError> ve)
+ throws ValidationException
+ {
+ Calendar modifyDate;
+ try
+ {
+ modifyDate = dico.getModificationDate();
+ if (modifyDate != null)
+ {
+ if (xmp != null)
+ {
+
+ Calendar xmpModifyDate = xmp.getModifyDate();
+ if (xmpModifyDate == null)
+ {
+ ve.add(AbsentXMPPropertyError("ModifyDate", "Property is not defined"));
+ }
+ else
+ {
+ if (!DateConverter.toISO8601(xmpModifyDate).equals(DateConverter.toISO8601(modifyDate)))
+ {
+
+ ve.add(unsynchronizedMetaDataError("ModificationDate"));
+ }
+ }
+
+ }
+ else
+ {
+ ve.add(AbsentSchemaMetaDataError("ModifyDate", "Basic XMP"));
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ // If there is an error while converting this property to a date
+ throw formatAccessException("Document Information", "ModifyDate", e);
+ }
+
+ }
+
+ /**
+ * Check if document information entries and XMP information are synchronized
+ *
+ * @param document
+ * the PDF Document
+ * @param metadata
+ * the XMP MetaData
+ * @return List of validation errors
+ * @throws ValidationException
+ */
+ public List<ValidationError> validateMetadataSynchronization(PDDocument document, XMPMetadata metadata)
+ throws ValidationException
+ {
+ List<ValidationError> ve = new ArrayList<ValidationError>();
+
+ if (document == null)
+ {
+ throw new ValidationException("Document provided is null");
+ }
+ else
+ {
+ PDDocumentInformation dico = document.getDocumentInformation();
+ if (metadata == null)
+ {
+ throw new ValidationException("Metadata provided are null");
+ }
+ else
+ {
+ DublinCoreSchema dc = metadata.getDublinCoreSchema();
+
+ // TITLE
+ analyzeTitleProperty(dico, dc, ve);
+ // AUTHOR
+ analyzeAuthorProperty(dico, dc, ve);
+ // SUBJECT
+ analyzeSubjectProperty(dico, dc, ve);
+
+ AdobePDFSchema pdf = metadata.getAdobePDFSchema();
+
+ // KEYWORDS
+ analyzeKeywordsProperty(dico, pdf, ve);
+ // PRODUCER
+ analyzeProducerProperty(dico, pdf, ve);
+
+ XMPBasicSchema xmp = metadata.getXMPBasicSchema();
+
+ // CREATOR TOOL
+ analyzeCreatorToolProperty(dico, xmp, ve);
+
+ // CREATION DATE
+ analyzeCreationDateProperty(dico, xmp, ve);
+
+ // MODIFY DATE
+ analyzeModifyDateProperty(dico, xmp, ve);
+
+ }
+
+ }
+ return ve;
+ }
+
+ /**
+ * Return a validationError formatted when a schema has not the expected prefix
+ *
+ * @param prefFound
+ * @param prefExpected
+ * @param schema
+ * @return
+ */
+ protected ValidationError unexpectedPrefixFoundError(String prefFound, String prefExpected, String schema)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append(schema).append(" found but prefix used is '").append(prefFound).append("', prefix '")
+ .append(prefExpected).append("' is expected.");
+
+ return new ValidationError(PreflightConstants.ERROR_METADATA_WRONG_NS_PREFIX, sb.toString());
+ }
+
+ /**
+ * Return an exception formatted on IOException when accessing metadata
+ *
+ * @param type
+ * type of property (Document Info or XMP)
+ * @param target
+ * the name of the metadata
+ * @param cause
+ * the raised IOException
+ * @return the generated exception
+ */
+ protected ValidationException formatAccessException(String type, String target, Throwable cause)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append("Cannot treat ").append(type).append(" ").append(target).append(" property");
+ return new ValidationException(sb.toString(), cause);
+ }
+
+ /**
+ * Return an exception formatted on IOException when accessing on metadata schema
+ *
+ * @param target
+ * the name of the schema
+ * @param cause
+ * the raised IOException
+ * @return the generated exception
+ */
+ protected ValidationException SchemaAccessException(String target, Throwable cause)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append("Cannot access to the ").append(target).append(" schema");
+ return new ValidationException(sb.toString(), cause);
+ }
+
+ /**
+ * Return a formatted validation error when metadata are not synchronized
+ *
+ * @param target
+ * the concerned property
+ * @return the generated validation error
+ */
+ protected ValidationError unsynchronizedMetaDataError(String target)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append(target).append(" present in the document catalog dictionary doesn't match with XMP information");
+ return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb.toString());
+ }
+
+ /**
+ * Return a formatted validation error when a specific metadata schema can't be found
+ *
+ * @param target
+ * the concerned property
+ * @param schema
+ * the XMP schema which can't be found
+ * @return the generated validation error
+ */
+ protected ValidationError AbsentSchemaMetaDataError(String target, String schema)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append(target).append(" present in the document catalog dictionary can't be found in XMP information (")
+ .append(schema).append(" schema not declared)");
+ return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb.toString());
+ }
+
+ /**
+ * Return a formatted validation error when a specific XMP property can't be found
+ *
+ * @param target
+ * the concerned property
+ * @param details
+ * comments about the XMP property
+ * @return the generated validation error
+ */
+ protected ValidationError AbsentXMPPropertyError(String target, String details)
+ {
+ StringBuilder sb = new StringBuilder(80);
+ sb.append(target).append(" present in the document catalog dictionary can't be found in XMP information (")
+ .append(details).append(")");
+ return new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb.toString());
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/XpacketParsingException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/XpacketParsingException.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/XpacketParsingException.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/metadata/XpacketParsingException.java Wed Mar 6 16:46:35 2013
@@ -27,44 +27,49 @@ import org.apache.pdfbox.preflight.Valid
* This exception is raised when the parsing of the xpacket fails
*
*/
-public class XpacketParsingException extends Exception {
+public class XpacketParsingException extends Exception
+{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- protected ValidationError error;
-
- /**
- * Constructor
- *
- * @param message
- * the message
- * @param cause
- * the cause
- */
- public XpacketParsingException(String message, Throwable cause) {
- super(message, cause);
- }
-
- /**
- * Constructor
- *
- * @param message
- * the message
- */
- public XpacketParsingException(String message) {
- super(message);
- }
-
- public XpacketParsingException(String message, ValidationError error) {
- super(message);
- this.error = error;
- }
-
- public ValidationError getError() {
- return error;
- }
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ protected ValidationError error;
+
+ /**
+ * Constructor
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public XpacketParsingException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param message
+ * the message
+ */
+ public XpacketParsingException(String message)
+ {
+ super(message);
+ }
+
+ public XpacketParsingException(String message, ValidationError error)
+ {
+ super(message);
+ this.error = error;
+ }
+
+ public ValidationError getError()
+ {
+ return error;
+ }
}