// Path: src/de/felixbruns/jotify/api/media/Link.java
// public class InvalidSpotifyURIException extends Exception {
// 	private static final long serialVersionUID = 1L;
// }
// 
// Path: src/de/felixbruns/jotify/api/util/Hex.java
// public class Hex {
// 	/**
// 	 * Convert a hexadecimal string into a byte array.
// 	 * <ul>
// 	 * 	<li>Safe with leading zeroes (unlike {@link java.math.BigInteger}).</li>
// 	 * 	<li>Safe with negative byte values (unlike {@link Byte}.parseByte).</li>
// 	 * </ul>
// 	 * 
// 	 * @param hex The hexadecimal string to convert.
// 	 * 
// 	 * @return A byte array
// 	 */
// 	public static byte[] toBytes(String hex){
// 		if(!isHex(hex)){
// 			throw new IllegalArgumentException("Input string is not a valid hexadecimal string!");
// 		}
// 		
// 		byte[] bytes = new byte[hex.length() / 2];
// 		
// 		/* Loop over two characters at a time and convert them to a byte. */
// 		for(int i = 0; i < hex.length(); i += 2){
// 			bytes[i / 2] = (byte)(
// 				(Character.digit(hex.charAt(i    ), 16) << 4) +
// 				 Character.digit(hex.charAt(i + 1), 16)
// 			);
// 		}
// 		
// 		return bytes;
// 	}
// 	
// 	/**
// 	 * Convert a byte array into a hexadecimal string.
// 	 * 
// 	 * @param bytes The byte array
// 	 * 
// 	 * @return A hexadecimal string
// 	 */
// 	public static String toHex(byte[] bytes){
// 		String hex = "";
// 		
// 		for(int i = 0; i < bytes.length; i++){
// 			hex += String.format("%02x", bytes[i]);
// 		}
// 		
// 		return hex;
// 	}
// 	
// 	/**
// 	 * Check if a string is a valid hexadecimal string.
// 	 * 
// 	 * @param hex The string to check.
// 	 * 
// 	 * @return true if it is a valid hexadecimal string, false otherwise.
// 	 */
// 	public static boolean isHex(String hex){
// 		return (hex.length() % 2 == 0) && hex.matches("[0-9A-Fa-f]+");
// 	}
// }


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.felixbruns.jotify.api.media.Link.InvalidSpotifyURIException;
import de.felixbruns.jotify.api.util.Hex;
package de.felixbruns.jotify.api.media;



/**
 * Holds basic information about media.
 * 
 * @author Felix Bruns <felixbruns@web.de>
 * 
 * @category Media
 */
public class Media {
	/**
	 * Identifier for this media object (32-character hex string).
	 */
	protected String id;
	
	/**
	 * Redirects (other identifiers) for this media (32-character hex strings).
	 */
	protected List<String> redirects;
	
	/**
	 * Popularity of this media (from 0.0 to 1.0).
	 */
	protected float popularity;
	
	/**
	 * Restrictions of this media.
	 */
	private List<Restriction> restrictions;
	
	/**
	 * External ids of this media.
	 */
	private Map<String, String> externalIds;
	
	/**
	 * Creates an empty {@link Media} object.
	 */
	protected Media(){
		this.id           = null;
		this.redirects    = new ArrayList<String>();
		this.popularity   = Float.NaN;
		this.restrictions = new ArrayList<Restriction>();
		this.externalIds  = new HashMap<String, String>();
	}
	
	/**
	 * Creates a {@link Media} object with the specified {@code id}.
	 * 
	 * @param id A 32-character hex string or a Spotify URI.
	 * 
	 * @throws IllegalArgumentException If the given id is invalid.
	 */
	protected Media(String id){
		/* Check if id is a 32-character hex string. */
		if(id.length() == 32 && Hex.isHex(id)){
			this.id = id;
		}
		/* Otherwise try to parse it as a Spotify URI. */
		else{
			try{
				this.id = Link.create(id).getId();
			}
			catch(InvalidSpotifyURIException e){
				throw new IllegalArgumentException(
					"Given id is neither a 32-character " +
					"hex string nor a valid Spotify URI.", e
				);
			}
		}
		
		/* Set other media properties. */
		this.redirects    = new ArrayList<String>();
		this.popularity   = Float.NaN;
		this.restrictions = new ArrayList<Restriction>();
		this.externalIds  = new HashMap<String, String>();
	}
	
	/**
	 * Get the media identifier.
	 * 
	 * @return A 32-character identifier.
	 */
	public String getId(){
		return this.id;
	}
	
	/**
	 * Set the media identifier.
	 * 
	 * @param id A 32-character identifier.
	 * 
	 * @throws IllegalArgumentException If the given id is invalid.
	 */
	public void setId(String id){
		/* Check if id string is valid. */
// Path: src/de/felixbruns/jotify/api/media/Link.java
// public class InvalidSpotifyURIException extends Exception {
// 	private static final long serialVersionUID = 1L;
// }
// 
// Path: src/de/felixbruns/jotify/api/util/Hex.java
// public class Hex {
// 	/**
// 	 * Convert a hexadecimal string into a byte array.
// 	 * <ul>
// 	 * 	<li>Safe with leading zeroes (unlike {@link java.math.BigInteger}).</li>
// 	 * 	<li>Safe with negative byte values (unlike {@link Byte}.parseByte).</li>
// 	 * </ul>
// 	 * 
// 	 * @param hex The hexadecimal string to convert.
// 	 * 
// 	 * @return A byte array
// 	 */
// 	public static byte[] toBytes(String hex){
// 		if(!isHex(hex)){
// 			throw new IllegalArgumentException("Input string is not a valid hexadecimal string!");
// 		}
// 		
// 		byte[] bytes = new byte[hex.length() / 2];
// 		
// 		/* Loop over two characters at a time and convert them to a byte. */
// 		for(int i = 0; i < hex.length(); i += 2){
// 			bytes[i / 2] = (byte)(
// 				(Character.digit(hex.charAt(i    ), 16) << 4) +
// 				 Character.digit(hex.charAt(i + 1), 16)
// 			);
// 		}
// 		
// 		return bytes;
// 	}
// 	
// 	/**
// 	 * Convert a byte array into a hexadecimal string.
// 	 * 
// 	 * @param bytes The byte array
// 	 * 
// 	 * @return A hexadecimal string
// 	 */
// 	public static String toHex(byte[] bytes){
// 		String hex = "";
// 		
// 		for(int i = 0; i < bytes.length; i++){
// 			hex += String.format("%02x", bytes[i]);
// 		}
// 		
// 		return hex;
// 	}
// 	
// 	/**
// 	 * Check if a string is a valid hexadecimal string.
// 	 * 
// 	 * @param hex The string to check.
// 	 * 
// 	 * @return true if it is a valid hexadecimal string, false otherwise.
// 	 */
// 	public static boolean isHex(String hex){
// 		return (hex.length() % 2 == 0) && hex.matches("[0-9A-Fa-f]+");
// 	}
// }


// Path: src/de/felixbruns/jotify/api/media/Media.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.felixbruns.jotify.api.media.Link.InvalidSpotifyURIException;
import de.felixbruns.jotify.api.util.Hex;

package de.felixbruns.jotify.api.media;



/**
 * Holds basic information about media.
 * 
 * @author Felix Bruns <felixbruns@web.de>
 * 
 * @category Media
 */
public class Media {
	/**
	 * Identifier for this media object (32-character hex string).
	 */
	protected String id;
	
	/**
	 * Redirects (other identifiers) for this media (32-character hex strings).
	 */
	protected List<String> redirects;
	
	/**
	 * Popularity of this media (from 0.0 to 1.0).
	 */
	protected float popularity;
	
	/**
	 * Restrictions of this media.
	 */
	private List<Restriction> restrictions;
	
	/**
	 * External ids of this media.
	 */
	private Map<String, String> externalIds;
	
	/**
	 * Creates an empty {@link Media} object.
	 */
	protected Media(){
		this.id           = null;
		this.redirects    = new ArrayList<String>();
		this.popularity   = Float.NaN;
		this.restrictions = new ArrayList<Restriction>();
		this.externalIds  = new HashMap<String, String>();
	}
	
	/**
	 * Creates a {@link Media} object with the specified {@code id}.
	 * 
	 * @param id A 32-character hex string or a Spotify URI.
	 * 
	 * @throws IllegalArgumentException If the given id is invalid.
	 */
	protected Media(String id){
		/* Check if id is a 32-character hex string. */
		if(id.length() == 32 && Hex.isHex(id)){
			this.id = id;
		}
		/* Otherwise try to parse it as a Spotify URI. */
		else{
			try{
				this.id = Link.create(id).getId();
			}
			catch(InvalidSpotifyURIException e){
				throw new IllegalArgumentException(
					"Given id is neither a 32-character " +
					"hex string nor a valid Spotify URI.", e
				);
			}
		}
		
		/* Set other media properties. */
		this.redirects    = new ArrayList<String>();
		this.popularity   = Float.NaN;
		this.restrictions = new ArrayList<Restriction>();
		this.externalIds  = new HashMap<String, String>();
	}
	
	/**
	 * Get the media identifier.
	 * 
	 * @return A 32-character identifier.
	 */
	public String getId(){
		return this.id;
	}
	
	/**
	 * Set the media identifier.
	 * 
	 * @param id A 32-character identifier.
	 * 
	 * @throws IllegalArgumentException If the given id is invalid.
	 */
	public void setId(String id){
		/* Check if id string is valid. */
		if(id == null || id.length() != 32 || !Hex.isHex(id)){