Main Page | Modules | Compound List | File List | Compound Members | File Members

# Overview XMP Toolkit Overview

## This XMP Toolkit Release

This release provides the following features:

- Improved, simpler API. If you need to port code from a previous version, see the XMP API Transition Guide (under Modules).
- Updates to make the code compatible with Adobe Acrobat 7 and Adobe Creative Suite 2.
- Improved performance, in some cases significantly improved.
- Code cleanup that makes the source more readable and easier to maintain.
- Single source with UNIX-style newlines; this version works in all operating systems
- Improved namespace handling.
- Numerous bug fixes.

## General Overview of the XMP API and Internal Architecture.

The client view of the XMP API is provided through three C++ class templates:

- `TXMPMeta` provides the fundamental methods for manipulating XMP metadata.
- `TXMPIterator` provides methods to iterate over existing XMP metadata.
- `TXMPUtils` provides additional utilities layered on top of `TXMPMeta`. Use a string class to instantiate the templates; you can use `std::string`. The string class is a template parameter, which simplifies its use for clients that have an existing string model different from `std::string`.

Developers should understand the XMP data model before working with the XMP Toolkit. The data model is documented in chapter 2 of the XMP Specification. The XMPCoverage sample provides an in-depth illustration of the use of the XMP Toolkit.

Note:
  Earlier versions of the Adobe XMP Toolkit had a different API and implementation. See the XMP API Transition Guide page for information about adapting to the new API.

The XMP Toolkit is implemented in three layers, which isolate the return of string values, synchronization for multi-threaded use, and exception propagation. While the SDK as provided from Adobe builds a static library, this layering can easily be adapted to build a DLL.

- The top layer is the implementation of the client template classes. This layer is for copying string results and releasing the threading lock if necessary.
- The middle layer consists of the three classes `WXMPMeta`, `WXMPIterator`, and `WXMPUtils`. They provide wrappers between the top client layer and the actual implementation. The middle layer is responsible for acquiring the threading lock, basic parameter checking, catching propagated exceptions, and releasing the threading lock when appropriate.
- The inner layer is the actual implementation, contained in the three classes `XMPMeta`, `XMPIterator`, and `XMPUtils`.

## Use of the XMP API

Client code obtains access to the XMP API by including a single header, XMP.hpp. You should read the template header files, TXMPMeta.hpp, and so on, for detailed information, but do not #include them. You should also read XMP_Const.h for detailed information about types and constants for namespace URIs and option flags. The client templates are instantiated by including XMP.incl_cpp in exactly one source file. The macro `TXMP_STRING_TYPE` must be defined first to provide the string class.

The string class used to instantiate the templates must have the following member functions, which match those of `std::string`:

         assign ( const char * str, size_t len )
         size_t size() const
         const char * c_str() const

The result type of `assign` does not matter, it is always ignored.

Use of the XMP Toolkit is reasonably straightforward once you understand the XMP data model. Some tips to keep in mind:

- All strings passed as parameters must be UTF-8.
- All strings returned will be UTF-8.
- Register private namespaces before use.
- Don't depend on specific namespace prefixes. Don't hardwire the prefixes for struct fields, use functions like `Get/SetStructField` or `ComposeStructFieldPath`.
- Use the path composition functions for complex paths with nested structs or arrays.
- Use `Get/SetLocalizedText` when dealing with language alternative (alt-text) arrays.

### Implementation Call Chain

The implementation of `GetProperty` provides a good illustration of the toolkit layering. The declaration below for `TXMPMeta::GetProperty` is simplified by hardwiring `std::string`. The `XMP_StringPtr` type is simply `const char *`.

         bool TXMPMeta::GetProperty ( XMP_StringPtr    schemaNS,
                                      XMP_StringPtr    propName,
                                      std::string *    propValue,
                                      XMP_OptionBits * options ) const
         {
            XMP_StringPtr resultPtr = 0;
            XMP_StringLen resultLen = 0;

            bool found = this->xmpObj.GetProperty ( schemaNS, propName,
                                                    &resultPtr, &resultLen, options );

            if ( found ) {
                if ( propValue != 0 ) propValue->assign ( resultPtr, resultLen );
                this->xmpObj.UnlockObject ( kXMP_NoOptions );
            }
            return found;

         }

The template object contains a data member pointer to the underlying `WXMPMeta` object. This is used to dispatch the call to the middle layer. The actual implementation of the XMP toolkit returns string values as a pointer and length, the pointer references private internal storage of the toolkit. The client code copies the string value to the client's string object. This minimizes the amount of string copying, and should the XMP toolkit be built as a DLL ensures that any memory allocation for the client's value is done on the client side. The call to `WXMPMeta::UnlockObject` is explained below.

         bool WXMPMeta::GetProperty ( XMP_StringPtr    schemaNS,
                                      XMP_StringPtr    propName,
                                      XMP_StringPtr *  propValue,
                                      XMP_StringLen *  valueSize,
                                      XMP_OptionBits * options ) const
         {
             XMP_Bool found;
             XMP_ENTER_WRAPPER ( "WXMPMeta::GetProperty" )

             if ( (schemaNS == 0) || (*schemaNS == 0) ) {
                 XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
             }
             if ( (propName == 0) || (*propName == 0) ) {
                 XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
             }

             if ( propValue == 0 ) propValue = &voidStringPtr;
             if ( valueSize == 0 ) valueSize = &voidStringLen;
             if ( options == 0 ) options = &voidOptionBits;

             const XMPMeta & meta = WtoXMPMeta_Ref ( *this );
             found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options );

             XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
             return found;
         }

The entry and exit macros in the `WXMPMeta` layer acquire the threading lock on entry and usually release it on exit. The lock is kept on exit whenever a string value is returned. Since a pointer to internal data is returned, the threading lock can't be released until after the template code in the client copies the string. The entry and exit macros also prevent uncontrolled exception propagation from the lower layer back to the client. This is not critical for use of the XMP Toolkit as a static library. But it is generally not safe to propagate C++ exceptions across DLL boundaries.