FileDocCategorySizeDatePackage
AsfFieldKey.javaAPI DocJaudiotagger 2.0.411759Mon Sep 26 14:07:10 BST 2011org.jaudiotagger.tag.asf

AsfFieldKey.java

package org.jaudiotagger.tag.asf;

import org.jaudiotagger.audio.asf.data.ContainerType;
import org.jaudiotagger.audio.asf.data.ContentBranding;
import org.jaudiotagger.audio.asf.data.ContentDescription;
import org.jaudiotagger.tag.reference.Tagger;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * Field keys which need to be mapped for ASF files, or only specified for ASF.
 *
 * TODO These attributes and their v23 mapping that havent been added to enum yet
 *
 * WMA                 ID3v1   ID3v22  ID3v2324
 *
 * CopyrightURL 	  	       WCP 	WCOP
 * Duration 	  	           TLE 	TLEN
 * FileSize 	  	  	            TSIZ
 * WM/AudioFileURL 	  	WAF 	WOAF
 * WM/AudioSourceURL 	  	WAS 	WOAS
 * WM/Binary 	  	GEO 	GEOB
 * WM/EncodingSettings 	  	TSS 	TSSE
 * WM/EncodingTime 	  	  	TDEN
 * WM/MCDI 	  	  	MCDI
 * WM/ModifiedBy 	  	  	TPE4
 * WM/OriginalFilename 	  	TOF 	TOFN
 * WM/PlaylistDelay 	  	  	TDLY
 * WM/RadioStationName 	  	TRN 	TRSN
 * WM/RadioStationOwner 	  	TRO 	TRSO
 * WM/SetSubTitle 	  	  	TSST
 * WM/Text 	  	TXX 	TXXX
 * WM/UniqueFileIdentifier 	  	UFI 	UFID
 * WM/UserWebURL 	  	WXX 	WXXX
 *
 * @author Christian Laireiter
 */
public enum AsfFieldKey
{
    /*
     * Keys are arbitrary because these fields don't have 'keys' internally because they are stored in preset contents descriptor
     */
    
    // Content Description Object keys
    AUTHOR(ContentDescription.KEY_AUTHOR, false, ContainerType.CONTENT_DESCRIPTION),
    TITLE(ContentDescription.KEY_TITLE, false, ContainerType.CONTENT_DESCRIPTION),
    RATING(ContentDescription.KEY_RATING, false, ContainerType.CONTENT_DESCRIPTION),
    COPYRIGHT(ContentDescription.KEY_COPYRIGHT, false, ContainerType.CONTENT_DESCRIPTION),
    DESCRIPTION(ContentDescription.KEY_DESCRIPTION, false, ContainerType.CONTENT_DESCRIPTION),
    
    // Content Branding Object keys
    BANNER_IMAGE(ContentBranding.KEY_BANNER_IMAGE,false, ContainerType.CONTENT_BRANDING),
    BANNER_IMAGE_TYPE(ContentBranding.KEY_BANNER_TYPE,false, ContainerType.CONTENT_BRANDING),
    BANNER_IMAGE_URL(ContentBranding.KEY_BANNER_URL, false, ContainerType.CONTENT_BRANDING),
    COPYRIGHT_URL(ContentBranding.KEY_COPYRIGHT_URL, false, ContainerType.CONTENT_BRANDING),
    
    /*
     * keys are important because this is how values will be looked up by other applications
     */
    ALBUM("WM/AlbumTitle", false),
    ALBUM_ARTIST("WM/AlbumArtist", true),
    ALBUM_ARTIST_SORT("WM/AlbumArtistSortOrder", false),
    ALBUM_SORT("WM/AlbumSortOrder", false),
    AMAZON_ID("ASIN", false),
    ARTIST_SORT("WM/ArtistSortOrder", false),
    ARTISTS("WM/ARTISTS", true),
    BARCODE("WM/Barcode", false),
    BPM("WM/BeatsPerMinute", false),
    CATALOG_NO("WM/CatalogNo", false),
    CATEGORY("WM/Category", true),      
    COMPOSER("WM/Composer", true),
    COMPOSER_SORT("WM/ComposerSort", false),
    CONDUCTOR("WM/Conductor", true),
    COVER_ART("WM/Picture", true),
    COVER_ART_URL("WM/AlbumCoverURL", true),
    CUSTOM1("CUSTOM1", true),
    CUSTOM2("CUSTOM2", true),
    CUSTOM3("CUSTOM3", true),
    CUSTOM4("CUSTOM4", true),
    CUSTOM5("CUSTOM5", true),
    DIRECTOR("WM/Director", true),
    DISC_NO("WM/PartOfSet", false),
    DISC_TOTAL("WM/DiscTotal", false),
    ENCODER("WM/ToolName", false),
    ENCODED_BY("WM/EncodedBy", false),
    FBPM("FBPM", true),
    GENRE("WM/Genre", true),
    GENRE_ID("WM/GenreID", true),
    GROUPING("WM/ContentGroupDescription", false),
    INITIAL_KEY("WM/InitialKey", false),
    IS_COMPILATION("WM/IsCompilation", false),
    ISRC("WM/ISRC", false),
    ISVBR("IsVBR", true),
    LANGUAGE("WM/Language", true),
    LYRICIST("WM/Writer", true),
    LYRICS("WM/Lyrics", false),
    LYRICS_SYNCHRONISED("WM/Lyrics_Synchronised", true),
    MEDIA("WM/Media", false),
    MOOD("WM/Mood", true),
    MUSICBRAINZ_ARTISTID("MusicBrainz/Artist Id", false),
    MUSICBRAINZ_DISC_ID("MusicBrainz/Disc Id", false),
    MUSICBRAINZ_ORIGINAL_RELEASEID("MusicBrainz/Original Album Id", false),
    MUSICBRAINZ_RELEASE_COUNTRY("MusicBrainz/Album Release Country", false),
    MUSICBRAINZ_RELEASE_STATUS("MusicBrainz/Album Status", false),
    MUSICBRAINZ_RELEASE_TYPE("MusicBrainz/Album Type", false),
    MUSICBRAINZ_RELEASEARTISTID("MusicBrainz/Album Artist Id", false),
    MUSICBRAINZ_RELEASEID("MusicBrainz/Album Id", false),
    MUSICBRAINZ_RELEASEGROUPID("MusicBrainz/Release Group Id", false),
    MUSICBRAINZ_TRACK_ID("MusicBrainz/Track Id", false),
    MUSICBRAINZ_WORKID("MusicBrainz/Work Id", false),
    MUSICIP_ID("MusicIP/PUID", false),
    ACOUSTID_FINGERPRINT("Acoustid/Fingerprint", false),
    ACOUSTID_FINGERPRINT_OLD("AcoustId/Fingerprint", false),
    ACOUSTID_ID("Acoustid/Id", false),
    OCCASION("Occasion", true),
    ORIGINAL_ALBUM("WM/OriginalAlbumTitle", true),
    ORIGINAL_ARTIST("WM/OriginalArtist", true),
    ORIGINAL_LYRICIST("WM/OriginalLyricist", true),
    ORIGINAL_YEAR("WM/OriginalReleaseYear", true),
    PRODUCER("WM/Producer", false),
    QUALITY("Quality", true),
    USER_RATING("WM/SharedUserRating", true),
    MM_RATING("SDB/Rating", true),
    RECORD_LABEL("WM/Publisher", false),
    REMIXER("WM/ModifiedBy", false),
    SCRIPT("WM/Script", false),
    SUBTITLE("WM/SubTitle", false),
    TAGS("WM/Tags", false),
    TEMPO("Tempo", true),
    TITLE_SORT("WM/TitleSortOrder", false),
    TRACK("WM/TrackNumber", false),
    TRACK_TOTAL("WM/TrackTotal", false),
    URL_DISCOGS_ARTIST_SITE("WM/DiscogsArtistUrl", false),
    URL_DISCOGS_RELEASE_SITE("WM/DiscogsReleaseUrl", false),
    URL_OFFICIAL_ARTIST_SITE("WM/AuthorURL", false),
    URL_OFFICIAL_RELEASE_SITE("WM/OfficialReleaseUrl", false),
    URL_PROMOTIONAL_SITE("WM/PromotionURL", true),
    URL_WIKIPEDIA_ARTIST_SITE("WM/WikipediaArtistUrl", false),
    URL_WIKIPEDIA_RELEASE_SITE("WM/WikipediaReleaseUrl", false),
    URL_LYRICS_SITE("WM/LyricsUrl", false),
    YEAR("WM/Year", false),

    ENGINEER("WM/Engineer",false),    
    DJMIXER("WM/DJMixer",false),
    MIXER("WM/Mixer",false),
    ARRANGER("WM/Arranger",false),
    COUNTRY("WM/Country", false),

    // Special field for all unknown field names, which will getFields maximum support
    CUSTOM ("___CUSTOM___", true);

    /**
     * Stores the {@link AsfFieldKey#fieldName} to the field key.
     */
    private final static Map<String, AsfFieldKey> FIELD_ID_MAP;

    static
    {
        FIELD_ID_MAP = new HashMap<String, AsfFieldKey>(AsfFieldKey.values().length);
        for (AsfFieldKey curr : AsfFieldKey.values())
        {
            if (curr != CUSTOM) {
                assert !FIELD_ID_MAP.containsKey(curr.getFieldName()) : "duplicate field entry: "+curr.getFieldName();
                FIELD_ID_MAP.put(curr.getFieldName(), curr);
            }
        }
    }


    /**
     * Searches for an ASF field key which represents the given id string.<br>
     *
     * @param fieldName the field name used for this key
     * @return the Enum that represents this field
     */
    public static AsfFieldKey getAsfFieldKey(final String fieldName)
    {
        AsfFieldKey result = FIELD_ID_MAP.get(fieldName);
        if (result == null) {
            result = CUSTOM;
        }
        return result;
    }

    /**
     * Tests whether the field is enabled for multiple values.<br>
     *
     * @param fieldName field id to test.
     * @return <code>true</code> if ASF implementation supports multiple values for the field.
     */
    public static boolean isMultiValued(final String fieldName)
    {
        final AsfFieldKey fieldKey = getAsfFieldKey(fieldName);
        return fieldKey != null && fieldKey.isMultiValued();
    }


    /**
     * If set, the field has a standard id assigned.
     */
    private final String fieldName;

    /**
     * If <code>true</code>, the field will be stored repeatedly if occurs so in tags.
     */
    private final boolean multiValued;

    /**
     * The lowest possible container type, such a field can be stored into.<br>
     * Low means, container with least capabilities.
     */
    private final ContainerType lowestContainer;
    
    /**
     * The highest possible container type, such a field can be stored into.<br>
     * High means, most capabilities, for example string length exceeds that of
     * the extended content description, it will be stored one level up (metadata library).
     */
    private final ContainerType highestContainer;
    
    /**
     * Creates an instance<br>
     * Lowest/Highest will be {@link ContainerType#EXTENDED_CONTENT} /
     * {@link ContainerType#METADATA_LIBRARY_OBJECT}
     * 
     * @param asfFieldName
     *            standard field identifier.
     * @param multiValue
     *            <code>true</code> if the this ASF field can have multiple
     *            values.
     */
    private AsfFieldKey(final String asfFieldName, final boolean multiValue) {
        this(asfFieldName, multiValue, ContainerType.EXTENDED_CONTENT,
                ContainerType.METADATA_LIBRARY_OBJECT);
    }
    
    /**
     * Creates an instance.<br>
     * 
     * @param asfFieldName
     *              standard field identifier.
     * @param multiValue           
     *              <code>true</code> if the this ASF field can have multiple
     *              values.
     * @param restrictedTo
     *              fields must be stored in this container.
     */
    private AsfFieldKey(final String asfFieldName, final boolean multiValue,
            final ContainerType restrictedTo) {
        this(asfFieldName, multiValue, restrictedTo, restrictedTo);
    }

    /**
     * Creates an instance.<br>
     * 
     * @param asfFieldName
     *              standard field identifier.
     * @param multiValue           
     *              <code>true</code> if the this ASF field can have multiple
     *              values.
     * @param lowest
     *              fields must be stored at least in this container.
     * @param highest
     *              fields aren't allowed to be stored in better containers than
     *              this.
     */
    private AsfFieldKey(final String asfFieldName, final boolean multiValue,
            final ContainerType lowest, final ContainerType highest) {
        this.fieldName = asfFieldName;
        assert !multiValue || highest.isMultiValued() : "Definition error";
        this.multiValued = multiValue && highest.isMultiValued();
        this.lowestContainer = lowest;
        this.highestContainer = highest;
        assert ContainerType.areInCorrectOrder(lowest, highest);
    }


    /**
     * Returns the standard field id.
     *
     * @return the standard field id. (may be <code>null</code>)
     */
    public String getFieldName()
    {
        return this.fieldName;
    }

    /**
     * @return the highestContainer
     */
    public ContainerType getHighestContainer() {
        return this.highestContainer;
    }
    
    /**
     * @return the lowestContainer
     */
    public ContainerType getLowestContainer() {
        return this.lowestContainer;
    }
    
    /**
     * Returns <code>true</code> if this field can store multiple values.
     *
     * @return <code>true</code> if multiple values are supported for this field.
     */
    public boolean isMultiValued()
    {
        return this.multiValued;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        return getFieldName();
    }
}