Author: tilman
Date: Tue Dec 2 12:40:26 2025
New Revision: 1930193
Log:
PDFBOX-6114: improve PDF/A extension schema validation with missing fields
names, by Andrea Vacondio
Modified:
pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/PdfaExtensionHelper.java
Modified:
pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/PdfaExtensionHelper.java
==============================================================================
---
pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/PdfaExtensionHelper.java
Tue Dec 2 12:40:22 2025 (r1930192)
+++
pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/PdfaExtensionHelper.java
Tue Dec 2 12:40:26 2025 (r1930193)
@@ -1,318 +1,313 @@
-/*****************************************************************************
- *
- * 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.xmpbox.xml;
-
-import java.util.List;
-
-import org.apache.xmpbox.XMPMetadata;
-import org.apache.xmpbox.schema.PDFAExtensionSchema;
-import org.apache.xmpbox.schema.XMPSchema;
-import org.apache.xmpbox.schema.XMPSchemaFactory;
-import org.apache.xmpbox.type.AbstractField;
-import org.apache.xmpbox.type.AbstractStructuredType;
-import org.apache.xmpbox.type.ArrayProperty;
-import org.apache.xmpbox.type.Cardinality;
-import org.apache.xmpbox.type.DefinedStructuredType;
-import org.apache.xmpbox.type.PDFAFieldType;
-import org.apache.xmpbox.type.PDFAPropertyType;
-import org.apache.xmpbox.type.PDFASchemaType;
-import org.apache.xmpbox.type.PDFATypeType;
-import org.apache.xmpbox.type.PropertiesDescription;
-import org.apache.xmpbox.type.PropertyType;
-import org.apache.xmpbox.type.StructuredType;
-import org.apache.xmpbox.type.TypeMapping;
-import org.apache.xmpbox.type.Types;
-import org.apache.xmpbox.xml.XmpParsingException.ErrorType;
-
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-
-public final class PdfaExtensionHelper
-{
-
- public static final String CLOSED_CHOICE = "closed Choice of ";
-
- public static final String OPEN_CHOICE = "open Choice of ";
-
- private PdfaExtensionHelper()
- {
- }
-
- public static void validateNaming(XMPMetadata meta, Element description)
throws XmpParsingException
- {
- NamedNodeMap nnm = description.getAttributes();
- for (int i = 0; i < nnm.getLength(); i++)
- {
- Attr attr = (Attr) nnm.item(i);
- checkNamespaceDeclaration(attr, PDFAExtensionSchema.class);
- checkNamespaceDeclaration(attr, PDFAFieldType.class);
- checkNamespaceDeclaration(attr, PDFAPropertyType.class);
- checkNamespaceDeclaration(attr, PDFASchemaType.class);
- checkNamespaceDeclaration(attr, PDFATypeType.class);
- }
- }
-
- private static void checkNamespaceDeclaration(Attr attr, Class<? extends
AbstractStructuredType> clz)
- throws XmpParsingException
- {
- String prefix = attr.getLocalName();
- String namespace = attr.getValue();
- String cprefix =
clz.getAnnotation(StructuredType.class).preferedPrefix();
- String cnamespace =
clz.getAnnotation(StructuredType.class).namespace();
- // check extension
- if (cprefix.equals(prefix) && !cnamespace.equals(namespace))
- {
- throw new XmpParsingException(ErrorType.InvalidPdfaSchema,
- "Invalid PDF/A namespace definition, "
- + "prefix: " + prefix + ", namespace: " +
namespace);
- }
- if (cnamespace.equals(namespace) && !cprefix.equals(prefix))
- {
- throw new XmpParsingException(ErrorType.InvalidPdfaSchema,
- "Invalid PDF/A namespace definition, "
- + "prefix: " + prefix + ", namespace: " +
namespace);
- }
- }
-
- public static void populateSchemaMapping(XMPMetadata meta) throws
XmpParsingException
- {
- List<XMPSchema> schems = meta.getAllSchemas();
- TypeMapping tm = meta.getTypeMapping();
- StructuredType stPdfaExt =
PDFAExtensionSchema.class.getAnnotation(StructuredType.class);
- for (XMPSchema xmpSchema : schems)
- {
- if (xmpSchema.getNamespace().equals(stPdfaExt.namespace()))
- {
- // ensure the prefix is the preferred one (cannot use other
definition)
- if (!xmpSchema.getPrefix().equals(stPdfaExt.preferedPrefix()))
- {
- throw new XmpParsingException(ErrorType.InvalidPrefix,
- "Found invalid prefix for PDF/A extension, found
'" + xmpSchema.getPrefix()
- + "', should be '" +
stPdfaExt.preferedPrefix() + "'");
- }
- // create schema and types
- PDFAExtensionSchema pes = (PDFAExtensionSchema) xmpSchema;
- ArrayProperty sp = pes.getSchemasProperty();
- for (AbstractField af : sp.getAllProperties())
- {
- if (af instanceof PDFASchemaType)
- {
- populatePDFASchemaType(meta, (PDFASchemaType) af, tm);
- } // TODO unmanaged ?
- }
- }
- }
- }
-
- private static void populatePDFASchemaType(XMPMetadata meta,
PDFASchemaType st, TypeMapping tm)
- throws XmpParsingException
- {
- String namespaceUri = st.getNamespaceURI();
- if (namespaceUri == null)
- {
- // PDFBOX-5525
- throw new XmpParsingException(ErrorType.RequiredProperty,
- "Missing pdfaSchema:namespaceURI in type definition");
- }
- namespaceUri = namespaceUri.trim();
- String prefix = st.getPrefixValue();
- ArrayProperty properties = st.getProperty();
- ArrayProperty valueTypes = st.getValueType();
- XMPSchemaFactory xsf = tm.getSchemaFactory(namespaceUri);
- // retrieve namespaces
- if (xsf == null)
- {
- // create namespace with no field
- tm.addNewNameSpace(namespaceUri, prefix);
- xsf = tm.getSchemaFactory(namespaceUri);
- }
- // populate value type
- if (valueTypes != null)
- {
- for (AbstractField af2 : valueTypes.getAllProperties())
- {
- if (af2 instanceof PDFATypeType)
- {
- populatePDFAType(meta, (PDFATypeType) af2, tm);
- }
- }
- }
- // populate properties
- if (properties == null)
- {
- throw new XmpParsingException(ErrorType.RequiredProperty,
- "Missing pdfaSchema:property in type definition");
- }
- for (AbstractField af2 : properties.getAllProperties())
- {
- if (af2 instanceof PDFAPropertyType)
- {
- populatePDFAPropertyType((PDFAPropertyType) af2, tm, xsf);
- } // TODO unmanaged ?
- }
- }
-
- private static void populatePDFAPropertyType(PDFAPropertyType property,
TypeMapping tm, XMPSchemaFactory xsf)
- throws XmpParsingException
- {
- String pname = property.getName();
- String ptype = property.getValueType();
- String pdescription = property.getDescription();
- String pCategory = property.getCategory();
- // check all mandatory fields are OK
- if (pname == null || ptype == null || pdescription == null ||
pCategory == null)
- {
- // all fields are mandatory
- throw new XmpParsingException(ErrorType.RequiredProperty,
- "Missing field in property definition");
- }
- // check ptype existence
- PropertyType pt = transformValueType(tm, ptype);
- if (pt == null)
- {
- throw new XmpParsingException(ErrorType.NoValueType, "Unknown
property value type : " + ptype);
- }
- if (pt.type() == null)
- {
- throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + ptype);
- }
- else if (pt.type().isSimple() || pt.type().isStructured()
- || pt.type() == Types.DefinedType)
- {
- xsf.getPropertyDefinition().addNewProperty(pname, pt);
- }
- else
- {
- throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + ptype);
- }
- }
-
- private static void populatePDFAType(XMPMetadata meta, PDFATypeType type,
TypeMapping tm)
- throws XmpParsingException
- {
- String ttype = type.getType();
- String tns = type.getNamespaceURI();
- String tprefix = type.getPrefixValue();
- String tdescription = type.getDescription();
- ArrayProperty fields = type.getFields();
- if (ttype == null || tns == null || tprefix == null || tdescription ==
null)
- {
- // all fields are mandatory
- throw new XmpParsingException(ErrorType.RequiredProperty,
- "Missing field in type definition");
- }
- // create the structured type
- DefinedStructuredType structuredType = new DefinedStructuredType(meta,
tns, tprefix, null); // TODO
- // maybe a name exists
- if (fields != null)
- {
- List<AbstractField> definedFields = fields.getAllProperties();
- for (AbstractField af3 : definedFields)
- {
- if (af3 instanceof PDFAFieldType)
- {
- populatePDFAFieldType((PDFAFieldType) af3, structuredType);
- }
- // else TODO
- }
- }
- // add the structured type to list
- PropertiesDescription pm = new PropertiesDescription();
- structuredType.getDefinedProperties().forEach(pm::addNewProperty);
- tm.addToDefinedStructuredTypes(ttype, tns, pm);
- }
-
- private static void populatePDFAFieldType(PDFAFieldType field,
DefinedStructuredType structuredType)
- throws XmpParsingException
- {
- String fName = field.getName();
- String fDescription = field.getDescription();
- String fValueType = field.getValueType();
- if (fName == null || fDescription == null || fValueType == null)
- {
- throw new XmpParsingException(ErrorType.RequiredProperty, "Missing
field in field definition");
- }
- try
- {
- Types fValue = Types.valueOf(fValueType);
- structuredType.addProperty(fName,
TypeMapping.createPropertyType(fValue, Cardinality.Simple));
- }
- catch (IllegalArgumentException e)
- {
- throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + fValueType, e);
- // TODO could fValueType be a structured type ?
- }
- }
-
- private static PropertyType transformValueType(TypeMapping tm, String
valueType)
- {
- if ("Lang Alt".equals(valueType))
- {
- return TypeMapping.createPropertyType(Types.LangAlt,
Cardinality.Simple);
- }
- // else all other cases
- if (valueType.startsWith(CLOSED_CHOICE))
- {
- valueType = valueType.substring(CLOSED_CHOICE.length());
- }
- else if (valueType.startsWith(OPEN_CHOICE))
- {
- valueType = valueType.substring(OPEN_CHOICE.length());
- }
- int pos = valueType.indexOf(' ');
- Cardinality card = Cardinality.Simple;
- if (pos > 0)
- {
- String scard = valueType.substring(0, pos);
- switch (scard)
- {
- case "seq":
- card = Cardinality.Seq;
- break;
- case "bag":
- card = Cardinality.Bag;
- break;
- case "alt":
- card = Cardinality.Alt;
- break;
- default:
- return null;
- }
- }
- String vt = valueType.substring(pos + 1);
- Types type = null;
- try
- {
- type = pos < 0 ? Types.valueOf(valueType) : Types.valueOf(vt);
- }
- catch (IllegalArgumentException e)
- {
- if (tm.isDefinedType(vt))
- {
- type = Types.DefinedType;
- }
- }
- return TypeMapping.createPropertyType(type, card);
- }
-
-}
+/*****************************************************************************
+ *
+ * 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.xmpbox.xml;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.apache.xmpbox.XMPMetadata;
+import org.apache.xmpbox.schema.PDFAExtensionSchema;
+import org.apache.xmpbox.schema.XMPSchema;
+import org.apache.xmpbox.schema.XMPSchemaFactory;
+import org.apache.xmpbox.type.AbstractField;
+import org.apache.xmpbox.type.AbstractStructuredType;
+import org.apache.xmpbox.type.ArrayProperty;
+import org.apache.xmpbox.type.Cardinality;
+import org.apache.xmpbox.type.DefinedStructuredType;
+import org.apache.xmpbox.type.PDFAFieldType;
+import org.apache.xmpbox.type.PDFAPropertyType;
+import org.apache.xmpbox.type.PDFASchemaType;
+import org.apache.xmpbox.type.PDFATypeType;
+import org.apache.xmpbox.type.PropertiesDescription;
+import org.apache.xmpbox.type.PropertyType;
+import org.apache.xmpbox.type.StructuredType;
+import org.apache.xmpbox.type.TypeMapping;
+import org.apache.xmpbox.type.Types;
+import org.apache.xmpbox.xml.XmpParsingException.ErrorType;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+public final class PdfaExtensionHelper
+{
+
+ public static final String CLOSED_CHOICE = "closed Choice of ";
+
+ public static final String OPEN_CHOICE = "open Choice of ";
+
+ private PdfaExtensionHelper()
+ {
+ }
+
+ public static void validateNaming(XMPMetadata meta, Element description)
throws XmpParsingException
+ {
+ NamedNodeMap nnm = description.getAttributes();
+ for (int i = 0; i < nnm.getLength(); i++)
+ {
+ Attr attr = (Attr) nnm.item(i);
+ checkNamespaceDeclaration(attr, PDFAExtensionSchema.class);
+ checkNamespaceDeclaration(attr, PDFAFieldType.class);
+ checkNamespaceDeclaration(attr, PDFAPropertyType.class);
+ checkNamespaceDeclaration(attr, PDFASchemaType.class);
+ checkNamespaceDeclaration(attr, PDFATypeType.class);
+ }
+ }
+
+ private static void checkNamespaceDeclaration(Attr attr, Class<? extends
AbstractStructuredType> clz)
+ throws XmpParsingException
+ {
+ String prefix = attr.getLocalName();
+ String namespace = attr.getValue();
+ String cprefix =
clz.getAnnotation(StructuredType.class).preferedPrefix();
+ String cnamespace =
clz.getAnnotation(StructuredType.class).namespace();
+ // check extension
+ if (cprefix.equals(prefix) && !cnamespace.equals(namespace))
+ {
+ throw new XmpParsingException(ErrorType.InvalidPdfaSchema,
+ "Invalid PDF/A namespace definition, "
+ + "prefix: " + prefix + ", namespace: " +
namespace);
+ }
+ if (cnamespace.equals(namespace) && !cprefix.equals(prefix))
+ {
+ throw new XmpParsingException(ErrorType.InvalidPdfaSchema,
+ "Invalid PDF/A namespace definition, "
+ + "prefix: " + prefix + ", namespace: " +
namespace);
+ }
+ }
+
+ public static void populateSchemaMapping(XMPMetadata meta) throws
XmpParsingException
+ {
+ List<XMPSchema> schems = meta.getAllSchemas();
+ TypeMapping tm = meta.getTypeMapping();
+ StructuredType stPdfaExt =
PDFAExtensionSchema.class.getAnnotation(StructuredType.class);
+ for (XMPSchema xmpSchema : schems)
+ {
+ if (xmpSchema.getNamespace().equals(stPdfaExt.namespace()))
+ {
+ // ensure the prefix is the preferred one (cannot use other
definition)
+ if (!xmpSchema.getPrefix().equals(stPdfaExt.preferedPrefix()))
+ {
+ throw new XmpParsingException(ErrorType.InvalidPrefix,
+ "Found invalid prefix for PDF/A extension, found
'" + xmpSchema.getPrefix()
+ + "', should be '" +
stPdfaExt.preferedPrefix() + "'");
+ }
+ // create schema and types
+ PDFAExtensionSchema pes = (PDFAExtensionSchema) xmpSchema;
+ ArrayProperty sp = pes.getSchemasProperty();
+ for (AbstractField af : sp.getAllProperties())
+ {
+ if (af instanceof PDFASchemaType)
+ {
+ populatePDFASchemaType(meta, (PDFASchemaType) af, tm);
+ } // TODO unmanaged ?
+ }
+ }
+ }
+ }
+
+ private static void populatePDFASchemaType(XMPMetadata meta,
PDFASchemaType st, TypeMapping tm)
+ throws XmpParsingException
+ {
+ String namespaceUri = st.getNamespaceURI();
+ // PDFBOX-5525
+ requireNonNull(namespaceUri, () -> "Missing pdfaSchema:namespaceURI in
type definition");
+ namespaceUri = namespaceUri.trim();
+ String prefix = st.getPrefixValue();
+ ArrayProperty properties = st.getProperty();
+ ArrayProperty valueTypes = st.getValueType();
+ XMPSchemaFactory xsf = tm.getSchemaFactory(namespaceUri);
+ // retrieve namespaces
+ if (xsf == null)
+ {
+ // create namespace with no field
+ tm.addNewNameSpace(namespaceUri, prefix);
+ xsf = tm.getSchemaFactory(namespaceUri);
+ }
+ // populate value type
+ if (valueTypes != null)
+ {
+ for (AbstractField af2 : valueTypes.getAllProperties())
+ {
+ if (af2 instanceof PDFATypeType)
+ {
+ populatePDFAType(meta, (PDFATypeType) af2, tm);
+ }
+ }
+ }
+ // populate properties
+ requireNonNull(properties, () -> "Missing pdfaSchema:property in type
definition");
+ for (AbstractField af2 : properties.getAllProperties())
+ {
+ if (af2 instanceof PDFAPropertyType)
+ {
+ populatePDFAPropertyType((PDFAPropertyType) af2, tm, xsf);
+ } // TODO unmanaged ?
+ }
+ }
+
+ private static void populatePDFAPropertyType(PDFAPropertyType property,
TypeMapping tm, XMPSchemaFactory xsf)
+ throws XmpParsingException
+ {
+ String pname = property.getName();
+ String ptype = property.getValueType();
+ // check all mandatory fields are OK
+ requireNonNull(pname, () -> String.format("Missing field '%s' in
property definition", PDFAPropertyType.NAME));
+ requireNonNull(ptype, () -> String.format("Missing field '%s' in
property definition", PDFAPropertyType.VALUETYPE));
+ requireNonNull(property.getDescription(), () -> String.format("Missing
field '%s' in property definition", PDFAPropertyType.DESCRIPTION));
+ requireNonNull(property.getCategory(), () -> String.format("Missing
field '%s' in property definition", PDFAPropertyType.CATEGORY));
+
+ // check ptype existence
+ PropertyType pt = transformValueType(tm, ptype);
+ if (pt == null)
+ {
+ throw new XmpParsingException(ErrorType.NoValueType, "Unknown
property value type : " + ptype);
+ }
+ if (pt.type() == null)
+ {
+ throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + ptype);
+ }
+ else if (pt.type().isSimple() || pt.type().isStructured()
+ || pt.type() == Types.DefinedType)
+ {
+ xsf.getPropertyDefinition().addNewProperty(pname, pt);
+ }
+ else
+ {
+ throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + ptype);
+ }
+ }
+
+ private static void populatePDFAType(XMPMetadata meta, PDFATypeType type,
TypeMapping tm)
+ throws XmpParsingException
+ {
+ String ttype = type.getType();
+ String tns = type.getNamespaceURI();
+ String tprefix = type.getPrefixValue();
+ // all fields are mandatory
+ requireNonNull(ttype, () -> String.format("Missing field '%s' in type
definition", PDFATypeType.TYPE));
+ requireNonNull(tns, () -> String.format("Missing field '%s' in type
definition", PDFATypeType.NS_URI));
+ requireNonNull(tprefix, () -> String.format("Missing field '%s' in
type definition", PDFATypeType.PREFIX));
+ requireNonNull(type.getDescription(), () -> String.format("Missing
field '%s' in type definition", PDFATypeType.DESCRIPTION));
+
+ // create the structured type
+ DefinedStructuredType structuredType = new DefinedStructuredType(meta,
tns, tprefix, null); // TODO
+ // maybe a name exists
+ ArrayProperty fields = type.getFields();
+ if (fields != null)
+ {
+ List<AbstractField> definedFields = fields.getAllProperties();
+ for (AbstractField af3 : definedFields)
+ {
+ if (af3 instanceof PDFAFieldType)
+ {
+ populatePDFAFieldType((PDFAFieldType) af3, structuredType);
+ }
+ // else TODO
+ }
+ }
+ // add the structured type to list
+ PropertiesDescription pm = new PropertiesDescription();
+ structuredType.getDefinedProperties().forEach(pm::addNewProperty);
+ tm.addToDefinedStructuredTypes(ttype, tns, pm);
+ }
+
+ private static void populatePDFAFieldType(PDFAFieldType field,
DefinedStructuredType structuredType)
+ throws XmpParsingException
+ {
+ String fName = field.getName();
+ String fValueType = field.getValueType();
+ requireNonNull(fName, () -> String.format("Missing field '%s' in field
definition", PDFAFieldType.NAME));
+ requireNonNull(field.getDescription(), () -> String.format("Missing
field '%s' in field definition", PDFAFieldType.DESCRIPTION));
+ requireNonNull(fValueType, () -> String.format("Missing field '%s' in
field definition", PDFAFieldType.VALUETYPE));
+
+ try
+ {
+ Types fValue = Types.valueOf(fValueType);
+ structuredType.addProperty(fName,
TypeMapping.createPropertyType(fValue, Cardinality.Simple));
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new XmpParsingException(ErrorType.NoValueType, "Type not
defined : " + fValueType, e);
+ // TODO could fValueType be a structured type ?
+ }
+ }
+
+ private static PropertyType transformValueType(TypeMapping tm, String
valueType)
+ {
+ if ("Lang Alt".equals(valueType))
+ {
+ return TypeMapping.createPropertyType(Types.LangAlt,
Cardinality.Simple);
+ }
+ // else all other cases
+ if (valueType.startsWith(CLOSED_CHOICE))
+ {
+ valueType = valueType.substring(CLOSED_CHOICE.length());
+ }
+ else if (valueType.startsWith(OPEN_CHOICE))
+ {
+ valueType = valueType.substring(OPEN_CHOICE.length());
+ }
+ int pos = valueType.indexOf(' ');
+ Cardinality card = Cardinality.Simple;
+ if (pos > 0)
+ {
+ String scard = valueType.substring(0, pos);
+ switch (scard)
+ {
+ case "seq":
+ card = Cardinality.Seq;
+ break;
+ case "bag":
+ card = Cardinality.Bag;
+ break;
+ case "alt":
+ card = Cardinality.Alt;
+ break;
+ default:
+ return null;
+ }
+ }
+ String vt = valueType.substring(pos + 1);
+ Types type = null;
+ try
+ {
+ type = pos < 0 ? Types.valueOf(valueType) : Types.valueOf(vt);
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (tm.isDefinedType(vt))
+ {
+ type = Types.DefinedType;
+ }
+ }
+ return TypeMapping.createPropertyType(type, card);
+ }
+
+ private static void requireNonNull(Object value, Supplier<String> message)
throws XmpParsingException
+ {
+ if (value == null)
+ {
+ throw new XmpParsingException(ErrorType.RequiredProperty,
message.get());
+ }
+ }
+}