MXFBuilder (Media Authoring with Java API)
Date: 2016-02-05

tv.amwa.maj.io.mxf

## Class MXFBuilder

- java.lang.Object
- - tv.amwa.maj.io.mxf.MXFBuilder

-     public class MXFBuilder
      extends Object

  Collection of static methods that provide the ability to build MXF files from in memory data models (e.g. AAF) and vice versa. Reading or writing an MXF file is boiled down to calling these methods in the correct order.

  In this builder, the following capability is provided for reading and writing KLV triplets:

  - The ability to read and write keys with `readKey(ByteBuffer)` and `writeKey(UL, ByteBuffer)`;
  - The ability to read and write BER encoded length values with `readBERLength(ByteBuffer)` and `writeBERLength(long, int, ByteBuffer)`;
  - Two kinds of value encoding are supported:
    - Reading and writing fixed length packs is supported with `readFixedLengthPack(AUID, ByteBuffer)`, `writeFixedLengthPack(FixedLengthPack, ByteBuffer)` and `lengthOfFixedLengthPack(FixedLengthPack)`;
    - Reading and writing local sets with 2-byte keys and 2-byte values is supported with `readLocalSet(UL, ByteBuffer, PrimerPack, Map, List)`, `writeLocalSet(MetadataObject, ByteBuffer, PrimerPack, List)` and `lengthOfLocalSet(MetadataObject)`.

  When reading an MXF file, all methods report an error on bad data and try to skip over it and move on.

  See Also:
    `MXFFile`

- - ### Method Summary

    All Methods Static Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static long` | `calculateMinimumHeaderMetadataSize(Preface preface)` Calculate the minimum number of bytes required to carry the given preface as header metadata in an MXF files.
    `static void` | `clearIgnoredProperties()` Clear the set of ignored properties, restoring the builder to the state where it will attempt to raad everything.
    `static void` | `ignoreProperty(String ignoreMe)` Add a property to the set of properties ignored by this builder.
    `static boolean` | `isKLVFill(UL key)` Determines if the given key represents KLV fill data that can be safely skipped over.
    `static long` | `lengthOfFixedLengthPack(FixedLengthPack fixedLengthPack)` Calculates the number of bytes that will be used to encode the value of the given fixed length pack, exclusive of its key and length representation in the byte stream.
    `static long` | `lengthOfLocalSet(MetadataObject toWrite)` Calculates the length in bytes of a local set value for the given metadata object, excluding the sets initial key and value.
    `static long` | `readBERLength(ByteBuffer buffer)` Reads a basic encoding rules (BER) length from the given buffer at the current position.
    `static FixedLengthPack` | `readFixedLengthPack(AUID key, ByteBuffer buffer)` Read data from a fixed length pack that starts with the provided key and is contained in the given buffer.
    `static UL` | `readKey(ByteBuffer keyData)` Read a 16-byte universal label from the specified byte buffer.
    `static MetadataObject` | `readLocalSet(UL key, ByteBuffer buffer, PrimerPack primerPack, Map<AUIDImpl,MetadataObject> referenceTable, List<ResolutionEntry> resolutions)` Create a new instance of a metadata object from the given buffer that has an encoding of the value as a local set.
    `static void` | `registerMXF()`
    `static long` | `skipKLVFill(ByteBuffer buffer)` Skip over KLV fill data at the current position for a buffer, moving the position to the first byte beyond the fill data, which may be the end of the buffer.
    `static long` | `skipKLVFill(MXFFile mxfFile)` Skips over KLV fill information at the current position for an MXF file.
    `static void` | `writeBERLength(long length, int encodedBytes, ByteBuffer buffer)` Encodes the given length value using the basic encoding rules (BER) for lengths and writes it to the given buffer.
    `static void` | `writeFixedLengthPack(FixedLengthPack fixedLengthPack, ByteBuffer buffer)` Write the value of the given fixed length pack to the given byte buffer.
    `static void` | `writeKey(UL key, ByteBuffer buffer)` Write the given universal label key to the given buffer.
    `static long` | `writeLocalSet(MetadataObject toWrite, ByteBuffer buffer, PrimerPack primerPack, List<PropertyValue> forwardReferences)` Writes the given metadata object to the given buffer encoded as a local set, excluding its key and length that will have already been written.
    `static long` | `writeLocalSet(PropertyValue referencedValue, ByteBuffer buffer, PrimerPack primerPack, List<PropertyValue> forwardReferences)` Writes the given `strongly referenced` value to the given buffer encoded as a local set, excluding its key and length that will have already been written.

    - ### Methods inherited from class java.lang.Object

      `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Method Detail

    - #### registerMXF

          public static final void registerMXF()

    - #### ignoreProperty

          public static final void ignoreProperty(String ignoreMe)
                                           throws NullPointerException

      Add a property to the set of properties ignored by this builder. When reading an MXF file containing consisting of local sets that have known issues, it is useful to be able to ignore certain properties by skipping over them and not producing an error. This method reduces noise rather than changing the ability of the builder to read a file.

      No check is made against any known metadata set to see if the property exists. The property will be ignored on the basis of its name and name only.

      Parameters:
        `ignoreMe` - Name of a property to ignore.
      Throws:
        `NullPointerException` - Cannot set a property to ignore with a `null` string.

    - #### clearIgnoredProperties

          public static final void clearIgnoredProperties()

      Clear the set of ignored properties, restoring the builder to the state where it will attempt to raad everything.

    - #### readFixedLengthPack

          public static final FixedLengthPack readFixedLengthPack(AUID key,
                                                                  ByteBuffer buffer)
                                                           throws NullPointerException,
                                                                  EndOfDataException,
                                                                  ClassCastException

      Read data from a fixed length pack that starts with the provided key and is contained in the given buffer.

      The methods reads the buffer to create a the metadata object corresponding to the key. The key is the identification of the class defining the metadata object. To be able to instantiate the metadata object, it must have been registered with the warehouse first. As the order of a fixed length pack is used to determine which property is which in the buffer, the implementation of the metadata object must also implement fixed length pack.

      The key is provided to the method separately as it must have been read from the buffer to determine that the next item in the buffer is a fixed length pack. The buffer should contain have remaining to read the correct number of bytes as has been determined by reading the length of the pack before calling this method. Although known as a fixed length pack, it is possible for the last property of the pack to have variable length, as for the essence containers of a partition pack.

      Parameters:
        `key` - Identification of the metadata object represented by the fixed length pack.
        `buffer` - Buffer containing a serialization of the value of the pack. When passed into the method, the remaining number of bytes to read is equal to the length of the pack taken from the KLV coding.
      Returns:
        Metadata object created by reading the fixed length pack.
      Throws:
        `NullPointerException` - One or both of the arguments is/are `null` or the key is not of a known type.
        `EndOfDataException` - Reached the end of the buffer before al the properties of the fixed length pack have been read.
        `ClassCastException` - The metadata object registered in the warehosue with the given key is not a fixed length pack.
      See Also:
        `writeFixedLengthPack(FixedLengthPack, ByteBuffer)`, `lengthOfFixedLengthPack(FixedLengthPack)`, `PartitionPack`, `PrimerPack`, `FixedLengthPack`, `FixedLengthPack.getPackOrder()`

    - #### writeFixedLengthPack

          public static final void writeFixedLengthPack(FixedLengthPack fixedLengthPack,
                                                        ByteBuffer buffer)
                                                 throws NullPointerException,
                                                        InsufficientSpaceException

      Write the value of the given fixed length pack to the given byte buffer. The key and length of the pack must have been written to the buffer prior to calling this method.

      The buffer is expected to have sufficient capacity remaining. To determine how much capacity this is before calling this method, call `lengthOfFixedLengthPack(FixedLengthPack)`.

      The properties of the fixed length pack are written to the buffer in the specified order.

      Parameters:
        `fixedLengthPack` - Data to write to the buffer.
        `buffer` - Buffer to be written into.
      Throws:
        `NullPointerException` - One or both of the arguments is/are `null`.
        `InsufficientSpaceException` - Not enough space is available write all the data into the buffer. Note that this exception will be thrown part way through an attempt to write to the buffer.
      See Also:
        `readFixedLengthPack(AUID, ByteBuffer)`, `lengthOfFixedLengthPack(FixedLengthPack)`, `PartitionPack`, `PrimerPack`, `FixedLengthPack`, `FixedLengthPack.getPackOrder()`

    - #### lengthOfFixedLengthPack

          public static final long lengthOfFixedLengthPack(FixedLengthPack fixedLengthPack)
                                                    throws NullPointerException

      Calculates the number of bytes that will be used to encode the value of the given fixed length pack, exclusive of its key and length representation in the byte stream. The length calculation can be used as the encoded length and to create a buffer with at least enough capacity to represent the fixed length pack ready for writing.

      Parameters:
        `fixedLengthPack` - Fixed length back to calculate the encoded length of.
      Returns:
        Number of bytes required to encode the given data.
      Throws:
        `NullPointerException` - Cannot calculate a length from a `null` value.
      See Also:
        `writeFixedLengthPack(FixedLengthPack, ByteBuffer)`, `readFixedLengthPack(AUID, ByteBuffer)`

    - #### readLocalSet

          public static final MetadataObject readLocalSet(UL key,
                                                          ByteBuffer buffer,
                                                          PrimerPack primerPack,
                                                          Map<AUIDImpl,MetadataObject> referenceTable,
                                                          List<ResolutionEntry> resolutions)
                                                   throws Exception

      Create a new instance of a metadata object from the given buffer that has an encoding of the value as a local set. Header metadata is encoded as a sequence of local sets, where each local set may have a variable length depending on its value.

      The key will have been read from the stream already and must correspond to the identification of a class registered with the warehouse. The length will have been read from the stream and used to set the number of bytes available to read from the given buffer.

      A local set encoding is a sequence of tag-length-value triplets of each property, where the tags are two bytes long. The keys are resolved to full 16-byte keys using the given primer pack that has been read from the same header metadata.

      As a local set often has references to other local sets in the same sequence that makes up header metadata, the local set must allow for the resolution of the references after the creation of all of the metadata objects. The local set will add its identification to the reference table and request any subsequent resolutions required to fully complete the value.

      This method skips over the following kinds of data, returning `null`:

      - Any local set with a key that is not known in the warehouse;
      - Any representation of a meta dictionary, such as that sometimes found in an MXF OP-Atom file;
      - A local set that is a kind of meta definition, although a warning message will be generated to say if the meta definition is now known in the warehouse;
      - Any properties on the properties to be ignored list;
      - Any properties that are not known for the class identified by the given key.
      Parameters:
        `key` - Identification of the local set.
        `buffer` - Buffer containing the encoding of the local set.
        `primerPack` - Mapping of 2-byte tags to full 16-byte property identifications.
        `referenceTable` - Mapping of local set instance identifications to values being created as header metadata is read in sequence.
        `resolutions` - Requests for subsequent resolutions required to complete the value of the returned metadata object.
      Returns:
        Metadata object of the class with the given identifier with most of its properties set according to the local set encoding in the given buffer.
      Throws:
        `Exception` - A problem occurred parsing the local set and so the value should be skipped over.
      See Also:
        `writeLocalSet(MetadataObject, ByteBuffer, PrimerPack, List)`, `writeLocalSet(PropertyValue, ByteBuffer, PrimerPack, List)`, `lengthOfLocalSet(MetadataObject)`, `HeaderMetadata.getPreface()`, `ResolutionEntry.resolve(Map)`

    - #### writeLocalSet

          public static final long writeLocalSet(MetadataObject toWrite,
                                                 ByteBuffer buffer,
                                                 PrimerPack primerPack,
                                                 List<PropertyValue> forwardReferences)
                                          throws NullPointerException,
                                                 InsufficientSpaceException

      Writes the given metadata object to the given buffer encoded as a local set, excluding its key and length that will have already been written. A new random instance ID will be created to identify the metadata object. As such, this method is suitable to write the top of a hierarchy of objects. If the object is referenced from another object in the same header metadata, write the reference and value to the local set with `writeLocalSet(PropertyValue, ByteBuffer, PrimerPack, List)`.

      The buffer must have sufficient capacity and this can be ensured by calling `lengthOfLocalSet(MetadataObject)` first.

      Any strong references made by this metadata object to another one must result in the referenced value being added to the list of forward references. The caller must ensure that all forward references get added to the list.

      Parameters:
        `toWrite` - Metadata object to write as a local set value.
        `buffer` - Buffer to write the local set data into.
        `primerPack` - Lookup table of tag-to-key mappings in use for this header metadata.
        `forwardReferences` - List of forward references that have yet to be written into the current set of header metadata.
      Returns:
        Number of local set bytes written. If the number is less than expected, this suggests that some of the properties could not be written into the set.
      Throws:
        `NullPointerException` - One or more of the arguments is/are `null`.
        `InsufficientSpaceException` - The given buffer does not have enough capacity to receive the bytes required to represent the local set.
      See Also:
        `readLocalSet(UL, ByteBuffer, PrimerPack, Map, List)`, `lengthOfLocalSet(MetadataObject)`

    - #### writeLocalSet

          public static final long writeLocalSet(PropertyValue referencedValue,
                                                 ByteBuffer buffer,
                                                 PrimerPack primerPack,
                                                 List<PropertyValue> forwardReferences)
                                          throws NullPointerException,
                                                 InsufficientSpaceException

      Writes the given `strongly referenced` value to the given buffer encoded as a local set, excluding its key and length that will have already been written. The local identifier of the strong reference will be used created to identify the metadata object that is contained in the value. As such, this method is suitable to write mid- and bottom tier objects in the object hierarchy. If the object is not referenced from another object in the same header metadata, write the the local set with `writeLocalSet(MetadataObject, ByteBuffer, PrimerPack, List)`.

      The buffer must have sufficient capacity and this can be ensured by calling `lengthOfLocalSet(MetadataObject)` first.

      Any strong references made by this metadata object to another one must result in the referenced value being added to the list of forward references. The caller must ensure that all forward references get added to the list.

      Parameters:
        `referencedValue` - Strongly referenced value to write.
        `buffer` - Buffer to write the local set data into.
        `primerPack` - Lookup table of tag-to-key mappings in use for this header metadata.
        `forwardReferences` - List of forward references that have yet to be written into the current set of header metadata.
      Returns:
        Number of local set bytes written. If the number is less than expected, this suggests that some of the properties could not be written into the set.
      Throws:
        `NullPointerException` - One or more of the arguments is/are `null`.
        `InsufficientSpaceException` - The given buffer does not have enough capacity to receive the bytes required to represent the local set.
      See Also:
        `readLocalSet(UL, ByteBuffer, PrimerPack, Map, List)`, `lengthOfLocalSet(MetadataObject)`

    - #### lengthOfLocalSet

          @UInt64
          public static final long lengthOfLocalSet(MetadataObject toWrite)
                                                     throws NullPointerException

      Calculates the length in bytes of a local set value for the given metadata object, excluding the sets initial key and value. The value returned can be used to allocate sufficient capacity in a buffer to encode the value and to write the length part of a KLV triplet representing the value.

      Parameters:
        `toWrite` - Metadata object to calculate the length of.
      Returns:
        Length of the given metadata object in bytes when encoded as a local set.
      Throws:
        `NullPointerException` - Cannot calculate a length for a `null` value.
      See Also:
        `writeBERLength(long, int, ByteBuffer)`

    - #### isKLVFill

          public static final boolean isKLVFill(UL key)

      Determines if the given key represents KLV fill data that can be safely skipped over.

      Parameters:
        `key` - Key to test.
      Returns:
        Does the given key represent KLV fill data?
      See Also:
        `skipKLVFill(ByteBuffer)`

    - #### skipKLVFill

          public static final long skipKLVFill(MXFFile mxfFile)

      Skips over KLV fill information at the current position for an MXF file.

      Parameters:
        `mxfFile` - File with KLV fill data to skip at the current position.
      Returns:
        Number of bytes skipped.
      See Also:
        `skipKLVFill(ByteBuffer)`, `isKLVFill(UL)`

    - #### skipKLVFill

          public static final long skipKLVFill(ByteBuffer buffer)

      Skip over KLV fill data at the current position for a buffer, moving the position to the first byte beyond the fill data, which may be the end of the buffer.

      Parameters:
        `buffer` - Buffer with KLV fill data to skip at the current position.
      Returns:
        Number of bytes skipped over.
      See Also:
        `skipKLVFill(MXFFile)`, `isKLVFill(UL)`

    - #### readBERLength

          public static final long readBERLength(ByteBuffer buffer)
                                          throws NullPointerException,
                                                 BufferUnderflowException

      Reads a basic encoding rules (BER) length from the given buffer at the current position. For more details on BER lengths, see the wikipedia description of KLV data encoding.

      Parameters:
        `buffer` - Buffer to read the BER length from.
      Returns:
        Decoded length value.
      Throws:
        `NullPointerException` - The given buffer is `null`.
        `BufferUnderflowException` - Insufficient bytes remaining in the buffer to read the length.
      See Also:
        `writeBERLength(long, int, ByteBuffer)`

    - #### writeBERLength

          public static final void writeBERLength(long length,
                                                  int encodedBytes,
                                                  ByteBuffer buffer)
                                           throws NullPointerException,
                                                  BufferOverflowException,
                                                  IllegalArgumentException

      Encodes the given length value using the basic encoding rules (BER) for lengths and writes it to the given buffer. For more details on BER lengths, see the wikipedia description of KLV data encoding.

      Parameters:
        `length` - Length value to encode.
        `encodedBytes` - Number of bytes to use to encode the value.
        `buffer` - Buffer to write the encoded BER value to.
      Throws:
        `NullPointerException` - The given buffer is `null`.
        `BufferOverflowException` - Insufficient bytes remaining in the buffer to write the given length value.
        `IllegalArgumentException` - The length value is negative or will not fit in the number of encoded bytes specified.

    - #### readKey

          public static final UL readKey(ByteBuffer keyData)

      Read a 16-byte universal label from the specified byte buffer.

      Parameters:
        `keyData` - Buffer containing a key at the current position.
      Returns:
        Key as a universal label or `null` if insufficient data was available or the key is invalid.
      See Also:
        `writeKey(UL, ByteBuffer)`

    - #### writeKey

          public static final void writeKey(UL key,
                                            ByteBuffer buffer)
                                     throws NullPointerException,
                                            BufferOverflowException

      Write the given universal label key to the given buffer.

      Parameters:
        `key` - Key to be written.
        `buffer` - Buffer to write the key to.
      Throws:
        `NullPointerException` - One or both of the arguments is/are `null`.
        `BufferOverflowException` - Insufficient capacity remaining in the given buffer to write a 16-byte key to.
      See Also:
        `readKey(ByteBuffer)`

    - #### calculateMinimumHeaderMetadataSize

          public static final long calculateMinimumHeaderMetadataSize(Preface preface)
                                                               throws NullPointerException

      Calculate the minimum number of bytes required to carry the given preface as header metadata in an MXF files.

      Parameters:
        `preface` - Header metadata to calculate the size for.
      Returns:
        Minimum number of bytes required to encode the header metadata and associated primer pack.
      Throws:
        `NullPointerException` - Cannot calculate the size for a `null` preface.
      See Also:
        `Partition.writeHeaderMetadata(Preface, long)`

(c)2007-2016 Richard Cartwright, all rights reserved. Licensed under Apache 2 license and subject to the AMWA IPR policy.