@@ -275,16 +275,19 @@ public void setXmpMetadata(XMPMeta xmpMeta) throws XMPException {
275
275
setXmpMetadata (xmpMeta , serializeOptions );
276
276
}
277
277
278
- public void createXmpMetadata () throws XMPException {
279
- checkClosingStatus ();
280
- XMPMeta xmpMeta = XMPMetaFactory .create ();
281
- xmpMeta .setObjectName (XMPConst .TAG_XMPMETA );
282
- xmpMeta .setObjectName ("" );
278
+ protected void updateXmpMetadata () {
283
279
try {
284
- xmpMeta .setProperty (XMPConst .NS_DC , PdfConst .Format , "application/pdf" );
285
- xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Producer , Version .getInstance ().getVersion ());
286
- } catch (XMPException ignored ) {
280
+ if (writer .properties .addXmpMetadata ) {
281
+ setXmpMetadata (createXmpMetadata ());
282
+ }
283
+ } catch (XMPException e ) {
284
+ Logger logger = LoggerFactory .getLogger (PdfDocument .class );
285
+ logger .error (LogMessageConstant .EXCEPTION_WHILE_UPDATING_XMPMETADATA , e );
287
286
}
287
+ }
288
+
289
+ protected XMPMeta createXmpMetadata () throws XMPException {
290
+ XMPMeta xmpMeta = XMPMetaFactory .parseFromBuffer (getXmpMetadata (true ));
288
291
PdfDictionary docInfo = info .getPdfObject ();
289
292
if (docInfo != null ) {
290
293
PdfName key ;
@@ -299,34 +302,73 @@ public void createXmpMetadata() throws XMPException {
299
302
continue ;
300
303
value = ((PdfString ) obj ).toUnicodeString ();
301
304
if (PdfName .Title .equals (key )) {
302
- xmpMeta .setLocalizedText (XMPConst .NS_DC , PdfConst .Title , XMPConst .X_DEFAULT , XMPConst .X_DEFAULT , value );
305
+ if (!IsXmpMetaHasLocalizedText (xmpMeta , XMPConst .NS_DC , PdfConst .Title )) {
306
+ xmpMeta .setLocalizedText (XMPConst .NS_DC , PdfConst .Title , XMPConst .X_DEFAULT , XMPConst .X_DEFAULT , value );
307
+ }
303
308
} else if (PdfName .Author .equals (key )) {
304
309
xmpMeta .appendArrayItem (XMPConst .NS_DC , PdfConst .Creator , new PropertyOptions (PropertyOptions .ARRAY_ORDERED ), value , null );
305
310
} else if (PdfName .Subject .equals (key )) {
306
- xmpMeta .setLocalizedText (XMPConst .NS_DC , PdfConst .Description , XMPConst .X_DEFAULT , XMPConst .X_DEFAULT , value );
311
+ if (!IsXmpMetaHasLocalizedText (xmpMeta , XMPConst .NS_DC , PdfConst .Description )) {
312
+ xmpMeta .setLocalizedText (XMPConst .NS_DC , PdfConst .Description , XMPConst .X_DEFAULT , XMPConst .X_DEFAULT , value );
313
+ }
307
314
} else if (PdfName .Keywords .equals (key )) {
308
- for (String v : value .split (",|;" ))
309
- if (v .trim ().length () > 0 )
315
+ for (String v : value .split (",|;" )) {
316
+ if (v .trim ().length () > 0 ) {
310
317
xmpMeta .appendArrayItem (XMPConst .NS_DC , PdfConst .Subject , new PropertyOptions (PropertyOptions .ARRAY ), v .trim (), null );
311
- xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Keywords , value );
318
+ }
319
+ }
320
+ if (!isXmpMetaHasProperty (xmpMeta , XMPConst .NS_PDF , PdfConst .Keywords )) {
321
+ xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Keywords , value );
322
+ }
312
323
} else if (PdfName .Creator .equals (key )) {
313
- xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .CreatorTool , value );
324
+ if (!isXmpMetaHasProperty (xmpMeta , XMPConst .NS_PDF , PdfConst .CreatorTool )) {
325
+ xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .CreatorTool , value );
326
+ }
314
327
} else if (PdfName .Producer .equals (key )) {
315
- xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Producer , value );
328
+ if (!isXmpMetaHasProperty (xmpMeta , XMPConst .NS_PDF , PdfConst .Producer )) {
329
+ xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Producer , value );
330
+ }
316
331
} else if (PdfName .CreationDate .equals (key )) {
317
- xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .CreateDate , PdfDate .getW3CDate (value ));
332
+ if (!isXmpMetaHasProperty (xmpMeta , XMPConst .NS_XMP , PdfConst .CreateDate )) {
333
+ xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .CreateDate , PdfDate .getW3CDate (value ));
334
+ }
318
335
} else if (PdfName .ModDate .equals (key )) {
319
- xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .ModifyDate , PdfDate .getW3CDate (value ));
336
+ if (!isXmpMetaHasProperty (xmpMeta , XMPConst .NS_XMP , PdfConst .ModifyDate )) {
337
+ xmpMeta .setProperty (XMPConst .NS_XMP , PdfConst .ModifyDate , PdfDate .getW3CDate (value ));
338
+ }
320
339
}
321
340
}
322
341
}
323
- if (isTagged ()) {
342
+ if (isTagged () && ! isXmpMetaHasProperty ( xmpMeta , XMPConst . NS_PDFUA_ID , XMPConst . PART ) ) {
324
343
xmpMeta .setPropertyInteger (XMPConst .NS_PDFUA_ID , XMPConst .PART , 1 , new PropertyOptions (PropertyOptions .SEPARATE_NODE ));
325
344
}
326
- setXmpMetadata ( xmpMeta ) ;
345
+ return xmpMeta ;
327
346
}
328
347
348
+ /**
349
+ * Gets XMPMetadata.
350
+ */
329
351
public byte [] getXmpMetadata () {
352
+ return getXmpMetadata (false );
353
+ }
354
+
355
+ /**
356
+ * Gets XMPMetadata or create a new one.
357
+ * @param createNew if true, create a new empty XMPMetadata if it did not present.
358
+ * @return existed or newly created XMPMetadata byte array.
359
+ */
360
+ public byte [] getXmpMetadata (boolean createNew ) {
361
+ if (xmpMetadata == null && createNew ) {
362
+ XMPMeta xmpMeta = XMPMetaFactory .create ();
363
+ xmpMeta .setObjectName (XMPConst .TAG_XMPMETA );
364
+ xmpMeta .setObjectName ("" );
365
+ try {
366
+ xmpMeta .setProperty (XMPConst .NS_DC , PdfConst .Format , "application/pdf" );
367
+ xmpMeta .setProperty (XMPConst .NS_PDF , PdfConst .Producer , Version .getInstance ().getVersion ());
368
+ setXmpMetadata (xmpMeta );
369
+ } catch (XMPException ignored ) {
370
+ }
371
+ }
330
372
return xmpMetadata ;
331
373
}
332
374
@@ -668,9 +710,11 @@ public void close() {
668
710
isClosing = true ;
669
711
try {
670
712
if (writer != null ) {
671
- if (catalog .isFlushed ())
713
+ if (catalog .isFlushed ()) {
672
714
throw new PdfException (PdfException .CannotCloseDocumentWithAlreadyFlushedPdfCatalog );
673
- if (xmpMetadata != null ) {
715
+ }
716
+ updateXmpMetadata ();
717
+ if (getXmpMetadata () != null ) {
674
718
PdfStream xmp = new PdfStream ().makeIndirect (this );
675
719
xmp .getOutputStream ().write (xmpMetadata );
676
720
xmp .put (PdfName .Type , PdfName .Metadata );
@@ -761,7 +805,6 @@ public void close() {
761
805
}
762
806
763
807
}
764
-
765
808
byte [] originalFileID = null ;
766
809
if (crypto == null && writer .crypto != null ) {
767
810
originalFileID = writer .crypto .getDocumentId ();
@@ -1651,6 +1694,14 @@ private void ensureTreeRootAddedToNames(PdfObject treeRoot, PdfName treeType) {
1651
1694
names .put (treeType , treeRoot );
1652
1695
}
1653
1696
1697
+ private static boolean isXmpMetaHasProperty (XMPMeta xmpMeta , String schemaNS , String propName ) throws XMPException {
1698
+ return xmpMeta .getProperty (schemaNS , propName ) != null ;
1699
+ }
1700
+
1701
+ private static boolean IsXmpMetaHasLocalizedText (XMPMeta xmpMeta , String schemaNS , String altTextName ) throws XMPException {
1702
+ return xmpMeta .getLocalizedText (schemaNS , altTextName , XMPConst .X_DEFAULT , XMPConst .X_DEFAULT ) != null ;
1703
+ }
1704
+
1654
1705
@ SuppressWarnings ("unused" )
1655
1706
private byte [] getSerializedBytes () {
1656
1707
ByteArrayOutputStream bos = null ;
0 commit comments