FileDocCategorySizeDatePackage
MetadataContainer.javaAPI DocJaudiotagger 2.0.416195Wed Mar 30 16:11:50 BST 2011org.jaudiotagger.audio.asf.data

MetadataContainer

public class MetadataContainer extends Chunk implements org.jaudiotagger.audio.asf.io.WriteableChunk
This structure represents the "Metadata Object","Metadata Library Object" and "Extended Content Description".
author
Christian Laireiter

Fields Summary
private final ContainerType
containerType
stores the represented container type.
private final Map
descriptors
Stores the descriptors.
private final DescriptorPointer
perfPoint
for performance reasons this instance is used to look up existing descriptors in {@link #descriptors}.
Constructors Summary
public MetadataContainer(ContainerType type)
Creates an instance.

param
type determines the type of the container


                                
        
        this(type, 0, BigInteger.ZERO);
    
public MetadataContainer(ContainerType type, long pos, BigInteger size)
Creates an instance.

param
type determines the type of the container
param
pos location in the ASF file
param
size size of the chunk.

        super(type.getContainerGUID(), pos, size);
        this.containerType = type;
    
public MetadataContainer(GUID containerGUID, long pos, BigInteger size)
Creates an instance.

param
containerGUID the containers GUID
param
pos location in the ASF file
param
size size of the chunk.

        this(determineType(containerGUID), pos, size);
    
Methods Summary
public final voidaddDescriptor(MetadataDescriptor toAdd)
Adds a metadata descriptor.

param
toAdd the descriptor to add.
throws
IllegalArgumentException if descriptor does not meet container requirements, or already exist.

        // check with throwing exceptions
        this.containerType.assertConstraints(toAdd.getName(), toAdd
                .getRawData(), toAdd.getType(), toAdd.getStreamNumber(), toAdd
                .getLanguageIndex());
        // validate containers capabilities
        if (!isAddSupported(toAdd)) {
            throw new IllegalArgumentException(
                    "Descriptor cannot be added, see isAddSupported(...)");
        }
        /*
         * Check for containers types capabilities.
         */
        // Search for descriptor list by name, language and stream.
        List<MetadataDescriptor> list;
        synchronized (this.perfPoint) {
            list = this.descriptors.get(this.perfPoint.setDescriptor(toAdd));
        }
        if (list == null) {
            list = new ArrayList<MetadataDescriptor>();
            this.descriptors.put(new DescriptorPointer(toAdd), list);
        } else {
            if (!list.isEmpty() && !this.containerType.isMultiValued()) {
                throw new IllegalArgumentException(
                        "Container does not allow multiple values of descriptors with same name, language index and stream number");
            }
        }
        list.add(toAdd);
    
protected final MetadataDescriptorassertDescriptor(java.lang.String key)
This method asserts that this container has a descriptor with the specified key, means returns an existing or creates a new descriptor.

param
key the descriptor name to look up (or create)
return
the/a descriptor with the specified name (and initial type of {@link MetadataDescriptor#TYPE_STRING}.

        return assertDescriptor(key, MetadataDescriptor.TYPE_STRING);
    
protected final MetadataDescriptorassertDescriptor(java.lang.String key, int type)
This method asserts that this container has a descriptor with the specified key, means returns an existing or creates a new descriptor.

param
key the descriptor name to look up (or create)
param
type if the descriptor is created, this data type is applied.
return
the/a descriptor with the specified name.

        MetadataDescriptor desc;
        final List<MetadataDescriptor> descriptorsByName = getDescriptorsByName(key);
        if (descriptorsByName == null || descriptorsByName.isEmpty()) {
            desc = new MetadataDescriptor(getContainerType(), key, type);
            addDescriptor(desc);
        } else {
            desc = descriptorsByName.get(0);
        }
        return desc;
    
public final booleancontainsDescriptor(MetadataDescriptor lookup)
Checks whether a descriptor already exists.
Name, stream number and language index are compared. Data and data type are ignored.

param
lookup descriptor to look up.
return
true if such a descriptor already exists.

        assert lookup != null;
        return this.descriptors.containsKey(this.perfPoint
                .setDescriptor(lookup));
    
private static ContainerTypedetermineType(GUID guid)
Looks up all {@linkplain ContainerType#getContainerGUID() guids} and returns the matching type.

param
guid GUID to look up
return
matching container type.
throws
IllegalArgumentException if no container type matches

        assert guid != null;
        ContainerType result = null;
        for (final ContainerType curr : ContainerType.values()) {
            if (curr.getContainerGUID().equals(guid)) {
                result = curr;
                break;
            }
        }
        if (result == null) {
            throw new IllegalArgumentException(
                    "Unknown metadata container specified by GUID ("
                            + guid.toString() + ")");
        }
        return result;
    
public final ContainerTypegetContainerType()
Returns the type of container this instance represents.

return
represented container type.

        return this.containerType;
    
public longgetCurrentAsfChunkSize()
{@inheritDoc}

        /*
         * 16 bytes GUID, 8 bytes chunk size, 2 bytes descriptor count
         */
        long result = 26;
        for (final MetadataDescriptor curr : getDescriptors()) {
            result += curr.getCurrentAsfSize(this.containerType);
        }
        return result;
    
public final intgetDescriptorCount()
Returns the number of contained descriptors.

return
number of descriptors.

        return this.getDescriptors().size();
    
public final java.util.ListgetDescriptors()
Returns all stored descriptors.

return
stored descriptors.

        final List<MetadataDescriptor> result = new ArrayList<MetadataDescriptor>();
        for (final List<MetadataDescriptor> curr : this.descriptors.values()) {
            result.addAll(curr);
        }
        return result;
    
public final java.util.ListgetDescriptorsByName(java.lang.String name)
Returns a list of descriptors with the given {@linkplain MetadataDescriptor#getName() name}.

param
name name of the descriptors to return
return
list of descriptors with given name.

        assert name != null;
        final List<MetadataDescriptor> result = new ArrayList<MetadataDescriptor>();
        final Collection<List<MetadataDescriptor>> values = this.descriptors
                .values();
        for (final List<MetadataDescriptor> currList : values) {
            if (!currList.isEmpty() && currList.get(0).getName().equals(name)) {
                result.addAll(currList);
            }
        }
        return result;
    
protected final java.lang.StringgetValueFor(java.lang.String name)
This method looks up a descriptor with given name and returns its value as string.

param
name the name of the descriptor to look up.
return
the string representation of a found descriptors value. Even an empty string if no descriptor has been found.

        String result = "";
        final List<MetadataDescriptor> descs = getDescriptorsByName(name);
        if (descs != null) {
            assert descs.size() <= 1;
            if (!descs.isEmpty()) {
                result = descs.get(0).getString();
            }
        }
        return result;
    
public final booleanhasDescriptor(java.lang.String name)
Determines if this container contains a descriptor with given {@linkplain MetadataDescriptor#getName() name}.

param
name Name of the descriptor to look for.
return
true if descriptor has been found.

        return !getDescriptorsByName(name).isEmpty();
    
public booleanisAddSupported(MetadataDescriptor descriptor)
Determines/checks if the given descriptor may be added to the container.
This implies a check for the capabilities of the container specified by its {@linkplain #getContainerType() container type}.

param
descriptor the descriptor to test.
return
true if {@link #addDescriptor(MetadataDescriptor)} can be called with given descriptor.

        boolean result = getContainerType().checkConstraints(
                descriptor.getName(), descriptor.getRawData(),
                descriptor.getType(), descriptor.getStreamNumber(),
                descriptor.getLanguageIndex()) == null;
        // Now check if there is already a value contained.
        if (result && !getContainerType().isMultiValued()) {
            synchronized (this.perfPoint) {
                final List<MetadataDescriptor> list = this.descriptors
                        .get(this.perfPoint.setDescriptor(descriptor));
                if (list != null) {
                    result = list.isEmpty();
                }
            }
        }
        return result;
    
public final booleanisEmpty()
{@inheritDoc}

        boolean result = true;
        if (getDescriptorCount() != 0) {
            final Iterator<MetadataDescriptor> iterator = getDescriptors()
                    .iterator();
            while (result && iterator.hasNext()) {
                result &= iterator.next().isEmpty();
            }
        }
        return result;
    
public java.lang.StringprettyPrint(java.lang.String prefix)
{@inheritDoc}

        final StringBuilder result = new StringBuilder(super.prettyPrint(prefix));
        for (final MetadataDescriptor curr : getDescriptors()) {
            result.append(prefix).append("  |-> ");
            result.append(curr);
            result.append(Utils.LINE_SEPARATOR);
        }
        return result.toString();
    
public final voidremoveDescriptorsByName(java.lang.String name)
Removes all stored descriptors with the given {@linkplain MetadataDescriptor#getName() name}.

param
name the name to remove.

        assert name != null;
        final Iterator<List<MetadataDescriptor>> iterator = this.descriptors
                .values().iterator();
        while (iterator.hasNext()) {
            final List<MetadataDescriptor> curr = iterator.next();
            if (!curr.isEmpty() && curr.get(0).getName().equals(name)) {
                iterator.remove();
            }
        }
    
protected final voidsetStringValue(java.lang.String name, java.lang.String value)
{@linkplain #assertDescriptor(String) asserts} the existence of a descriptor with given name and {@linkplain MetadataDescriptor#setStringValue(String) assings} the string value.

param
name the name of the descriptor to set the value for.
param
value the string value.

        assertDescriptor(name).setStringValue(value);
    
public longwriteInto(java.io.OutputStream out)
{@inheritDoc}

        final long chunkSize = getCurrentAsfChunkSize();
        final List<MetadataDescriptor> descriptorList = getDescriptors();
        out.write(getGuid().getBytes());
        Utils.writeUINT64(chunkSize, out);
        Utils.writeUINT16(descriptorList.size(), out);
        for (final MetadataDescriptor curr : descriptorList) {
            curr.writeInto(out, this.containerType);
        }
        return chunkSize;