/*****************************************************************************
*
* 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.
*
****************************************************************************/
package org.apache.pdfbox.preflight.font.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
import org.apache.pdfbox.preflight.PreflightConstants;
import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
import org.apache.pdfbox.preflight.exception.ValidationException;
import org.apache.pdfbox.preflight.font.descriptor.FontDescriptorHelper;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.DublinCoreSchema;
import org.apache.xmpbox.schema.XMPRightsManagementSchema;
import org.apache.xmpbox.type.AbstractField;
import org.apache.xmpbox.type.ArrayProperty;
import org.apache.xmpbox.type.BooleanType;
import org.apache.xmpbox.type.TextType;
/**
* Class used to validate the MetaData entry of the Font File Stream dictionary.
*/
public class FontMetaDataValidation
{
public List<ValidationError> validatePDFAIdentifer(XMPMetadata metadata, PDFontDescriptor fontDesc)
throws ValidationException
{
List<ValidationError> ve = new ArrayList<>();
analyseFontName(metadata, fontDesc, ve);
analyseRights(metadata, fontDesc, ve);
return ve;
}
/**
* Value of the dc:title must be the same as the FontName in the font descriptor.
*
* @param metadata
* XMPMetaData of the Font File Stream
* @param fontDesc
* The FontDescriptor dictionary
* @param ve
* the list of validation error to update if the validation fails
*/
public boolean analyseFontName(XMPMetadata metadata, PDFontDescriptor fontDesc, List<ValidationError> ve)
{
String fontName = fontDesc.getFontName();
String noSubSetName = fontName;
if (FontDescriptorHelper.isSubSet(fontName))
{
noSubSetName = fontName.split("\\+")[1];
}
DublinCoreSchema dc = metadata.getDublinCoreSchema();
if (dc != null && dc.getTitleProperty() != null)
{
String defaultTitle = dc.getTitle("x-default");
if (defaultTitle != null)
{
if (!defaultTitle.equals(fontName) && (noSubSetName != null && !defaultTitle.equals(noSubSetName)))
{
StringBuilder sb = new StringBuilder(80);
sb.append("FontName")
.append(" present in the FontDescriptor dictionary doesn't match with XMP information dc:title of the Font File Stream.");
ve.add(new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb.toString()));
return false;
}
// --- default value is the right one
return true;
}
else
{
Iterator<AbstractField> it = dc.getTitleProperty().getContainer().getAllProperties().iterator();
boolean empty = true;
while (it.hasNext())
{
empty = false;
AbstractField tmp = it.next();
if (tmp instanceof TextType)
{
String val = ((TextType) tmp).getStringValue();
if (val.equals(fontName) || val.equals(noSubSetName))
{
// value found, return
return true;
}
}
}
// title doesn't match, it is an error.
StringBuilder sb = new StringBuilder(80);
sb.append("FontName");
if (empty)
{
sb.append(" present in the FontDescriptor dictionary can't be found in XMP information the Font File Stream.");
ve.add(new ValidationError(PreflightConstants.ERROR_METADATA_PROPERTY_MISSING, sb.toString()));
}
else
{
sb.append(" present in the FontDescriptor dictionary doesn't match with XMP information dc:title of the Font File Stream.");
ve.add(new ValidationError(PreflightConstants.ERROR_METADATA_MISMATCH, sb.toString()));
}
return false;
}
}
return true;
}
/**
* If XMP MetaData are present, they must have followings information :
* <UL>
* <li>dc:rights
* <li>Marked (with the value true)
* <li>Owner
* <li>UsageTerms
* </UL>
*
* @param metadata
* XMPMetaData of the Font File Stream
* @param fontDesc
* The FontDescriptor dictionary
* @param ve
* the list of validation error to update if the validation fails
* @return true if the analysis found no problems, false if it did.
*/
public boolean analyseRights(XMPMetadata metadata, PDFontDescriptor fontDesc, List<ValidationError> ve)
{
DublinCoreSchema dc = metadata.getDublinCoreSchema();
if (dc != null)
{
ArrayProperty copyrights = dc.getRightsProperty();
if (copyrights == null || copyrights.getContainer() == null
|| copyrights.getContainer().getAllProperties().isEmpty())
{
ve.add(new ValidationError(PreflightConstants.ERROR_METADATA_PROPERTY_MISSING,
"CopyRights is missing from the XMP information (dc:rights) of the Font File Stream."));
return false;
}
}
XMPRightsManagementSchema rights = metadata.getXMPRightsManagementSchema();
if (rights != null)
{
BooleanType marked = rights.getMarkedProperty();
if (marked != null && !marked.getValue())
{
ve.add(new ValidationError(PreflightConstants.ERROR_METADATA_PROPERTY_MISSING,
"the XMP information (xmpRights:Marked) is invalid for the Font File Stream."));
return false;
}
/*
* rights.getUsageTerms() & rights.getOwnerValue() should be present but it is only a recommendation : may
* be it should be useful to append a Warning if these entries are missing.
*/
}
return true;
}
}