Specifications of all the interchangeable classes of AAF as Java interfaces. The root class for all interchangeable classes that can be serialized to an AAF file is {@link tv.amwa.maj.model.InterchangeObject}.

## Heritage

The interfaces in this package were derived from the COM API provided with the C++ reference implementation for AAF in file "`AAF.idl`". This COM API provides a set of public interfaces to AAF classes that map well to Java interfaces, with the benefit that the translated interfaces will have a similar names and support similar implementation patterns to those of the reference implementation. This will be an advantage in the event that any existing C-based code using the reference implementation is ported to Java.

This section describes issues that were encountered in the translation of the interfaces and methods from the COM API into Java interfaces. These include a different approach to exceptional conditions, representation of optional properties, enumerators over collections and default values.

### Table of contents

- Derivation from COM interfaces
  - Interface translation
  - Basic method translation
  - String property method translation
  - Multiple out parameters
- Object initialization
- Naming
  - COM API names and Java names
  - Naming conflicts
- Representing list, arrays and sets
  - Fixed and variable size arrays
  - Weak and strong reference sets
  - Shallow copy of a collection
- Optional properties and default values
  - Required properties
  - Omitted properties are Java null values
  - Default values
- Cardinality and collections

### Derivation from COM interfaces

The file "`AAF.idl`" in the C-based AAF reference implementation contains the specifications of a number of interfaces and their associated methods. These interfaces cover all of the classes of the AAF object specification, including meta definitions. Additional interfaces are also specified relating to file handling and, where appropriate, these have been included in the MAJ API. Where the standard Java API provides built-in features duplicated in the COM interfaces, the Java approach is chosen in preference.

In general, each interface in "`AAF.idl`" maps to a public Java interface in this package. Due to Java rules constraining one public interface to be defined in one file, this means that the single file in the existing reference implementation has mapped to 117 files in the MAJ API! An interface named `IAAFMob` becomes {@link tv.amwa.maj.model.Package} in the MAJ API. Translation of the material object (mob) interface, now called package under the SMPTE unified names for AAF and MXF, will now be used as an example of how interfaces have been translated from the COM API into the MAJ API.

#### Interface translation

For each interface in the COM API, documentation refers to a number of independent interfaces that must be additionally implemented by any implementation of the interface to achieve the AAF class hierarchy. This approach could have been adopted in the MAJ API but no automatic compiler checking would take place to ensure all the required methods were provided in any implementation. Instead, the MAJ API uses interface inheritance. For the mob example, the COM API documentation says that all all mobs must also implement `IAAFObject`. In the MAJ API, this interface is known by its specified name of {@link tv.amwa.maj.model.InterchangeObject} and the mob/package interface extends this.

        public interface Package
            extends InterchangeObject {

                ...
        }

When the COM API is extended to support new features, extra interfaces are added. In the case of a mob, new methods have been specified in interface `IAAFMob2`. These extended interfaces have been merged into one interface in the MAJ API, meaning that all the methods of interface `IAAFMob2` from the COM API are included in interface {@link tv.amwa.maj.model.Package} in the MAJ API.

#### Basic method translation

Every mob has a mob id property with get and set methods that allow that property to be set in both the COM API and MAJ API. These methods are specified in the COM API as follows:

        HRESULT GetMobID (
            [out] aafMobID_t *  pMobID);

        HRESULT SetMobID (
            [in, ref] aafMobID_constref  mobID);

In the MAJ API, the new MXF and AAF SMPTE harmonized names are used, so a MobID is now known as a PackageID. Therefore, the above methods translate to the following equivalents in the MAJ API:

        public @PackageIDType tv.amwa.maj.record.PackageID getPackageID();

        public void setPackageID(
                @PackageIDType tv.amwa.maj.record.PackageID packageID)
            throws NullPointerException;

The steps taken in the method translation illustrated by the code above are as follows:

- All method names start with a lower case letter in the MAJ API. In most cases, this is the only change made to a method name between the COM API and the MAJ API. In the example, `GetMobID` becomes `getPackageID`.
- If a method has a single out parameter in the COM API, this becomes the return value of the method in the MAJ API. In the example, the single `[out]` parameter of the `GetMobID` method is of type `aafMobID_t *`. This type is represented by the interface {@link tv.amwa.maj.record.PackageID tv.amwa.maj.record.PackageID} in the MAJ API and so a value of this type is returned from method `getPackageID`. The annotation {@link tv.amwa.maj.misctype.PackageIDType @PackageIDType} is included to show that the value returned by the method is of "PackageIDType" as specified in the AAF object specification.
- The COM API returns a value of type "`HRESULT`" from every method. This is a 4-byte integer code as defined by a set of macros in file "`AAFResult.h`". The successful completion of a COM API method returns result code "`AAFRESULT_SUCCESS`". For the MAJ API, all methods are considered to complete successfully unless they throw an {@linkplain java.lang.Exception exception}. This creates the opportunity for a MAJ API method to return a value, which is an approach more commonly adopted by the Java community.
- All in parameters of a method in the COM API are replaced by equivalent method parameters for the MAJ API, using appropriate type mappings. These type mappings can be queried through the {@linkplain tv.amwa.maj.util.LookupTable type MAJ API lookup table}. In the example COM API set method, the `mobID` method parameter of type `aafMobID_constref` is translated to parameter `mobId` of type {@link tv.amwa.maj.record.PackageID} in the MAJ API.
- The package id property of a package is a required property and so it should not be omitted, ie. set to undefined or `null`. The COM API documentation often includes a list of result codes to be returned when the method has not been successful. One of these is "`AAFRESULT_NULL_PARAM`" that indicates that a null value has been encountered unexpectedly. In the MAJ API, this translates to the standard {@link java.lang.NullPointerException}.
- Finally, the documentation of the COM API method has been used as the basis of the MAJ API documentation. However, a lot of subsequent editing has taken place so that the MAJ API documentation is often more like the AAF object specification than the COM API documentation. For an example, see {@link tv.amwa.maj.model.Package#getPackageID()} and {@link tv.amwa.maj.model.Package#setPackageID(tv.amwa.maj.record.PackageID) Mob.setPackageID()}.

#### String property method translation

String handling is different between the C-based COM API, which uses null-terminated sequences of `aafCharacter_t` values, and the MAJ API, which uses the built-in {@linkplain java.lang.String Java string} class. For the mob interface, the following methods are defined to set the name of the mob:

        HRESULT SetName (
            [in, string] aafCharacter_constptr  pName);

        HRESULT GetNameBufLen (
            [out] aafUInt32 *  pBufSize);

        HRESULT GetName (
            [out, string, size_is(bufSize)] aafCharacter *  pName,
            [in] aafUInt32  bufSize);

These three methods translate to the following methods in the {@linkplain tv.amwa.maj.model.Package package interface} of the MAJ API:

        public void setName(
            @AAFString String name);

        public @AAFString String getName()
            throws PropertyNotPresentException;

The `GetNameBufLen` method of the COM API is required so that a character buffer of the appropriate size can be passed to `GetName`. Java can return a string object without the need for a buffer to be provided, so a name buffer length method is not required.

The name property is optional for the AAF specified Mob class. If the `GetName` method of the COM API is called when the name is not present, a `AAFRESULT_PROP_NOT_PRESENT` result code is returned. In the MAJ API, this is replaced by throwing a {@link tv.amwa.maj.exception.PropertyNotPresentException} exception. Most result codes from the COM API have been translated to Java exceptions, either as standard Java exceptions or newly created, MAJ API-specific exceptions are described further in the description of the exception package. Also, see the MAJ API approach to omitted property values.

#### Multiple out parameters

Some methods in the COM API have multiple out parameters. Java only supports the return of one parameter from a method, but this can be an interface to an object with several properties, acting like a record. Where this is the case, an interface to access multi-parameter return values has been created in the union package.

As an example, consider the following method in the COM API that returns the fade values of a {@linkplain tv.amwa.maj.model.SourceClip source clip}:

        HRESULT GetFade (
            [out] aafLength_t *    pFadeInLen,
            [out] aafFadeType_t *  pFadeInType,
            [out] aafBoolean_t *   pFadeInPresent,
            [out] aafLength_t *    pFadeOutLen,
            [out] aafFadeType_t *  pFadeOutType,
            [out] aafBoolean_t *   pFadeOutPresent);

This is replaced by the following method in the MAJ API:

        public tv.amwa.maj.union.Fade getFade();

The {@linkplain tv.amwa.maj.union.Fade fade interface} of the MAJ API is specified to have the following methods:

        public interface Fade {

            public @LengthType long getFadeInLength();
            public void setFadeInLength(@LengthType long fadeInLength);

            public FadeType getFadeInType();
            public void setFadeInType(FadeType fadeInType);

            public boolean isFadeInPresent();

            public @LengthType long getFadeOutLength();
            public void setFadeOutLength(@LengthType long fadeOutLength);

            public FadeType getFadeOutType();
            public void setFadeOutType(FadeType fadeOutType);

            public boolean isFadeOutPresent();
        }

### Object initialization

In the COM API, some objects are represented as having a not initialized and initialized state. The specification of these classes may define an `initialize` method, which could return an already initialized result if the object is already in an initialized state. Also, many methods in the reference implementation are specified to return a not initialized result to indicate that the object on which they were called is in the not initialized state.

In the MAJ API interfaces, all objects are considered initialized once they are created, which greatly simplifies the resulting code and relies on Java's object state management rather than requiring an implementor to write their own. Therefore, no public mechanism is provided to create a class without setting its required parameters or accepting default values. Use the factory methods of the {@linkplain tv.amwa.maj.industry.Forge forge} to do this and take care that any default values provided are either acceptable as they are or replaced.

Direct access to underlying public constructor methods are not provided.

### Naming

#### COM API names and Java names

The COM API uses a number of abbreviations in its names for methods and classes, such as "Def" for "Definition". As many IDEs for Java offer auto-completion facilities, the approach adopted for the MAJ API is that names should be as close as possible to full-length English words. The intention is to make any Java code as readable as possible. The table below shows some of the expansions:

COM API alias | MAJ API name | COM API example | MAJ API equivalent
--- | --- | --- | ---
Def | Definition | OperationDef | OperationDefinition
Enum | Enumeration | TypeDefEnum | TypeDefinitionEnumeration
Int | Integer | TypeDefInt | TypeDefinitionInteger
Object | InterchangeObject | IAAFObject | InterchangeObject
ObjRef | ObjectReference | TypeDefWeakObjectRef | TypeDefinitionWeakObjectReference

Wherever possible, the names used in the MAJ API match those used in AAF object specification.

#### Naming conflicts

Applying the mapping of the film edge code data type in the "`AAFTypes.h`" to Java in the same way as other structures would create a Java interface in the MAJ API called Edgecode. Applying the mapping of COM API interfaces to the existing AAF reference implementation to Java interfaces would also create an interface called Edgecode. To resolve this naming conflict, the edgecode structure is mapped to an {@link tv.amwa.maj.record.EdgeCodeValue} and the AAF specified class becomes {@link tv.amwa.maj.model.EdgeCodeSegment}.

A similar naming conflict has been encountered for Timecode. The timecode structure maps to a Java interface in the MAJ API called {@link tv.amwa.maj.record.TimecodeValue} and the timecode interface for the specified AAF class is called {@link tv.amwa.maj.model.TimecodeSegment}.

Another conflict existed between the AAF specified class SourceReference and structure "`aafSourceRef_t`". The source reference structure maps to a Java interface in the MAJ API called {@link tv.amwa.maj.union.SourceReferenceValue} and the source reference interface for the specified AAF class is called {@link tv.amwa.maj.model.SourceReferenceSegment}.

To avoid conflicts with commonly used Java class names in the Java API, some classes in the MAJ API have had the letters "AAF" appended to the start of their names or reverted to their specified names. These include:

AAF ref. impl. name | MAJ API name | to avoid conflict with
--- | --- | ---
File | {@link tv.amwa.maj.model.AAFFile} | {@link java.io.File java.io.File}
FileDescriptor | {@link tv.amwa.maj.model.AAFFileDescriptor} | {@link java.io.FileDescriptor java.io.FileDescriptor}
Object | {@link tv.amwa.maj.model.InterchangeObject} | {@link java.lang.Object java.lang.Object}

### Representing lists, arrays and sets

The AAF object specification specifies three data types for the representation of collections: {@linkplain tv.amwa.maj.meta.TypeDefinitionFixedArray fixed size arrays}, {@linkplain tv.amwa.maj.meta.TypeDefinitionVariableArray variable size arrays} and {@linkplain tv.amwa.maj.meta.TypeDefinitionSet sets}. Methods of the COM API that allow access to properties of these types may return type-specific enumerators over the elements of a collection or pointers to arrays with the size of that array. The MAJ API approach is different and depends on the type defined for a property.

#### Fixed and variable sized arrays

For arrays of values that are represented in the COM API by an out parameter that is a pointer to a block of memory containing a sequence of values, such as the {@linkplain tv.amwa.maj.model.SourceReferenceSegment#getChannelIDs() channel ids property of a source reference segment}, the MAJ API returns a Java array. This is the case for arrays of values of primitive types, such as {@linkplain tv.amwa.maj.integer.UInt32}, or record values, such as {@linkplain tv.amwa.maj.record.AUID}.

The following code is the COM API method for retrieving the current value of the channel IDs property:

        HRESULT GetChannelIDs (
            [in] aafUInt32  numberElements,
            [in] aafUInt32*  pChannelIDs);

In the MAJ API, this has been translated to:

        public @UInt32Array int[] getChannelIDs();

For variable size arrays, the COM API also returns a length. This is not necessary in Java as every Java array is an object with access to its current length through its length field. For example:

        int[] channelIds = mySource.getChannelIDs();
        int channelIdsLength = channelIds.length;

#### Weak and strong reference vectors

The data types known as weak reference vectors and strong reference vectors in the AAF object specification are ordered collections of references to other AAF persistent objects or meta objects. These are not collections of elements of primitive or record types. The COM API includes a standard set of methods for manipulating any property of vector type, including append, insert at, remove at etc., as well as specifying a type-specific enumerator for ordered access to the elements. In the translation to the MAJ API, the methods are included and the type-specific enumerators are replaced by the use of the Java generic collections framework {@linkplain java.util.List list type}.

For example, the `IEnumAAFMobSlots` interface in the COM API is replaced by the Java `java.util.List<? extends Track>` generic list in the MAJ API. The following code shows the COM API methods for managing the list of {@linkplain tv.amwa.maj.model.Track tracks} of a {@linkplain tv.amwa.maj.model.Package package}:

        HRESULT AppendSlot (
            [in] IAAFMobSlot * pSlot);
        HRESULT PrependSlot (
            [in] IAAFMobSlot * pSlot);
        HRESULT InsertSlotAt (
            [in] aafUInt32  index,
            [in] IAAFMobSlot * pSlot);
        HRESULT RemoveSlotAt (
            [in] aafUInt32  index);
        HRESULT GetSlotAt (
            [in] aafUInt32  index,
            [out, retval] IAAFMobSlot ** ppSlot);
        HRESULT GetSlots (
            [out] IEnumAAFMobSlots ** ppEnum);

MAJ API supports the MXF and AAF SMPTE harmonized names, so an AAF MobSlot is known as a Track. This translates to the following methods in the MAJ API:

        public void appendPackageTrack(
                Track track);
        public void prependPackageTrack(
                Track track);
        public void insertPackageTrackAt(
                int index,
                Track track);
        public void removePackageTrackAt(
                int index);
        public Track getPackageTrackAt(
                int index);
        public java.util.List<? extends Track> getPackageTracks();

#### Weak and strong reference sets

The data types known as weak reference sets or strong reference sets in the AAF object specification are unordered collections of references to other AAF persistent objects or meta objects. These are not collections elements of primitive types or record values. The COM API includes a standard set of methods for manipulating any property of set type, including add, count and remove etc., as well as specifying a type-specific enumerator for access to the elements in no particular order. In the translation to the MAJ API, the methods are included and the type-specific enumerators are replaced by the use of the Java generic collections framework {@linkplain java.util.Set set type}.

For example, the `IEnumAAFEssenceData` interface in the COM API is replaced by the Java `java.util.Set<? extends EssenceData>` generic set in the MAJ API. The following code shows the COM API methods for managing the set of {@linkplain tv.amwa.maj.model.EssenceData essence data items} stored in a {@linkplain tv.amwa.maj.model.ContentStorage content storage}:

        HRESULT AddEssenceData (
            [in] IAAFEssenceData * pEssenceData);
        HRESULT CountEssenceData (
            [out, retval] aafUInt32 *  pResult);
        HRESULT RemoveEssenceData (
            [in] IAAFEssenceData * pEssenceData);
        HRESULT LookupEssenceData (
            [in, ref] aafMobID_constref  mobID,
            [out,retval] IAAFEssenceData ** ppEssenceData);
        HRESULT EnumEssenceData (
            [out,retval] IEnumAAFEssenceData ** ppEnum);

This translates to the following methods in the MAJ API:

        public void addEssenceData(
                EssenceData essenceData);
        public @UInt32 int countEssenceData();
        public void removeEssenceData(
                EssenceData essenceData);
        public EssenceData lookupEssenceData(
                tv.amwa.maj.record.PackageID mobId);
        public java.util.Set<? extends EssenceData> enumEssenceData();

#### Shallow copy of a collection

The collections returned by methods such as {@link tv.amwa.maj.model.Package#getPackageTracks() Package.getPackageTracks()} and {@link tv.amwa.maj.model.ContentStorage#enumEssenceDataObjects() ContentStorage.enumEssenceDataObjects()} are specified to be shallow copies. This means that the actual collection object returned by the method is not the same as the one stored in the persistent object on which the method was called. Modifications to the structures of collection returned will not cause any side effects on the stored collection. However, the elements within the returned collection are not cloned and modifications to any of the elements will have a side effect on the elements stored within the persistent object owning the collection.

All MAJ API implementations of the interfaces in this package support cloning, so creating a deep copy of a collection is possible with code similar to the following example:

        Collection<? extends InterchangeObject> group;
        ...
        for ( InterchangeObject item : group ) {
            group.remove(item);
            group.add(item.clone());
        }

Although the interfaces of this package specify shallow copies only, an implementation of the interfaces of this package may return a deep copy of all collections. For reasons of efficiency, the implementations provided with the MAJ API only return shallow copies of collections. In general, this is acceptable for the manipulation of a file whereas for the creation of a media asset management system based on these classes, care needs to be taken when sharing items between collections.

### Optional properties and default values

A property of an AAF persistent class or meta definition class may be either optional or required. Required properties shall always provide a value for any instance of their class. If a property is optional for a class, it may be either present or omitted from an instance of that class. This makes a lot of sense for efficient serialized representations of AAF objects where a sequence of bytes representing the instance of a class does not have to contain any bytes for a particular property. However, for a Java object or an entity persisted to a database in a media asset management system, it is necessary to provide get and set methods and have a column available to store all properties. This section describes the MAJ API approach to optional properties.

#### Required properties

Required properties are always considered as present and typically have a pair of get and set methods each, which work as follows:

- The get method of a required property should always return a valid and not null value for that property. Most required properties are initialized during the construction of the class.
- The set method of a required property should throw a {@linkplain java.lang.NullPointerException null pointer exception} if an attempt is made to set its value to `null`. The method may throw an {@linkplain java.lang.IllegalArgumentException illegal argument exception} if an attempt is made to set a value outside of the acceptable range for that property.

As discussed earlier, the required {@linkplain tv.amwa.maj.record.PackageID package id} property's get and set methods for the {@linkplain tv.amwa.maj.model.Package package} class in the COM API:

        HRESULT GetMobID (
            [out] aafMobID_t *  pMobID);

        HRESULT SetMobID (
            [in, ref] aafMobID_constref  mobID);

The equivalent methods in the MAJ API are:

        public @PackageIDType PackageID getPackageID();

        public void setPackageID(
                @PackageIDType PackageID packageID)
            throws NullPointerException;

#### Omitted properties are Java null values

Java provides the `null` keyword to allow the value of any object to be interpreted by an application as undefined or not present. Any optional value within the MAJ API implementation of the interfaces of this package uses `null` internally to represent an omitted property value.

The behaviour of the interface methods for optional properties without default values are as follows:

- Any get method for an optional property will return the value of that property if it is currently present, otherwise it will throw a {@linkplain tv.amwa.maj.exception.PropertyNotPresentException property not present exception}. Optional property get methods should not return `null` unless this is explicitly permitted in the documentation of the method.
- Any set method for an optional property will allow the value of the property to be set to `null` to omit it, as follows:
  - If the method is called with a `null` value: if the property is currently present it will become omitted; if the property is currently omitted then it will remain omitted.
  - Calling the method with a not null value will: modify the value of a present property to the given value; make an omitted property become present and set it to the given value. The method may throw an {@linkplain java.lang.IllegalArgumentException illegal argument exception} if an attempt is made to set a value outside of the acceptable range for the property.

Primitive types in Java, such as `int` and `char`, cannot be set to `null`. However, each of the primitive types has a corresponding object representation in the `java.lang` package, such as {@link java.lang.Integer} and {@link java.lang.Character}, that can be set to `null`. Therefore, set methods for optional properties of these types use the object representation as parameters so the property can be set to be omitted. Java provides auto-boxing and un-boxing of primitive values to/from their object-representation equivalent types, so there is no need to convert an `int` value to an {@link java.lang.Integer} value before calling the set method.

For example, the optional "AudioRefLevel" property of a {@linkplain tv.amwa.maj.model.SoundDescriptor sound descriptor} has no default value and the following get/set methods in the COM API:

        HRESULT GetAudioRefLevel (
            [out] aafInt8 *  pLevel);

        HRESULT SetAudioRefLevel (
            [in] aafInt8  level);

The get method shown above may return a result of `AAFRESULT_PROP_NOT_PRESENT`. The equivalent methods in the MAJ API are:

        public @Int8 byte getAudioRefLevel()
            throws PropertyNotPresentException;

        public void setAudioRefLevel(
                @Int8 Byte audioRefLevel);

Note that the use of {@link java.lang.Byte} as the type for the parameter for the set method is deliberate to allow the property to be omitted by setting it to `null`.

#### Default values

Some optional properties have default values specified in the AAF object specification. For these properties, the interfaces of this package are specified to return the default value if an optional property is omitted. The default values are specified as constant values in the interface specification containing the associated optional property. For an {@link tv.amwa.maj.model.RGBADescriptor}, these are:

- {@link tv.amwa.maj.model.RGBADescriptor#ALPHAMINREF_DEFAULT} - default value for the "AlphaMinRef" property;
- {@link tv.amwa.maj.model.RGBADescriptor#ALPHAMAXREF_DEFAULT} - default value for the "AlphaMaxRef" property;
- {@link tv.amwa.maj.model.RGBADescriptor#COMPONENTMINREF_DEFAULT} - default value for the "ComponentMinRef" property;
- {@link tv.amwa.maj.model.RGBADescriptor#COMPONENTMAXREF_DEFAULT} - default value for the "ComponentMaxRef" property;
- {@link tv.amwa.maj.model.RGBADescriptor#SCANNINGDIRECTION_DEFAULT} - default value for the "ScanningDirection" property.

The behaviour of the interface methods for optional properties with default values are as follows:

- Any get method for an optional property with a default value will return that default value if the property is omitted, otherwise it will return the value currently set for the property. The behaviour of this kind of method is the same for an omitted property and for a present property that happens to be set to the default value.
- Any set method for an optional property with a default value will accept a `null` value to omit the property, as follows:
  - If the method is called with a `null` value: if the property is currently present it will become omitted; if the property is currently omitted, it will remain omitted and subsequent calls to the matching get method will return the default value of the property.
  - Calling the value with a not null value will: modify the value of a present property to the given value; make an omitted property become present and set it to the given value. The method may throw an {@linkplain java.lang.IllegalArgumentException illegal argument exception} if an attempt is made to set a value outside of the acceptable range for the property.

This approach can make it difficult to find out if a property is present or omitted. Some interfaces include a is property present method, such as {@linkplain tv.amwa.maj.union.Fade#isFadeOutPresent()}. An alternative approach is to use the {@link tv.amwa.maj.industry.MediaEngine#isPropertyPresent(tv.amwa.maj.industry.MetadataObject, String) MediaEngine.isPropertyPresent()} method of every {@linkplain tv.amwa.maj.model.InterchangeObject interchange object}. For example, use the following code to find out if the "AlphaMinRef" property is present for a {@link tv.amwa.maj.model.RGBADescriptor}:

        RGBADescriptor imageInfo;
        ...
        ClassDefinition imageInfoClass = imageInfo.getDefinition();
        PropertyDefinition alphaMinRefProperty =
            imageInfoClass.lookupPropertyDefinition("AlphaMinRef");
        boolean alphaMinPresent = imageInfo.isPropertyPresent(alphaMinRefProperty);

As an example of an optional property with a default value, here are the methods to set and get the "AlphaMinRef" property in the COM API:

        HRESULT GetAlphaMinRef (
            [out] aafUInt32 *  pAlphaMinRef);

        HRESULT SetAlphaMinRef (
            [in] aafUInt32  alphaMinRef);

For the get method, the COM API does not return the default value when the property is omitted. Instead, it returns an `AAFRESULT_PROP_NOT_PRESENT` code. In contrast, the following equivalent MAJ API methods always succeed with the get method returning the default value when the property is omitted:

        public @UInt32 int getAlphaMinRef();

        public void setAlphaMinRef(
                @UInt32 Integer alphaMinRef);

The set method can be called with `null` to omit this property.

### Cardinality and collections

Some collection properties are optional, some are allowed to be empty. The MAJ API represents collections of a specified cardinality as shown in the following table:

| optional collection | required collection
0..* | Property is omitted when the collection is empty. Property is present when it contains at least one item. No representation of an empty collection. | Collection may be empty and present.
1..* | Property is either omitted or the property is present and contains at least one value. | Property should always contains at least one element.

This is problematic in the case that an AAF file deliberately represents an empty collection for a present optional property. The MAJ API makes no distinction between an empty optional collection property and an omitted optional collection property. Reading in a file with an empty present collection property will result in an internal MAJ API representation as a omitted collection property. Subsequent writing of the same data will omit the property.