com.danielme.muspyforandroid.services.MusicBrainzClient.java Source code

Java tutorial

Introduction

Here is the source code for com.danielme.muspyforandroid.services.MusicBrainzClient.java

Source

/*
 * Copyright (C) 2012-2013 Daniel Medina <http://danielme.com>
 * 
 * This file is part of "Muspy for Android".
 * 
 * "Muspy for Android" is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 *
 * "Muspy for Android" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-3.0.html/>
 */
package com.danielme.muspyforandroid.services;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.danielme.muspyforandroid.Constants;
import com.danielme.muspyforandroid.cache.BoundedLruCache;
import com.danielme.muspyforandroid.exc.MBGatewayTimeOutException;
import com.danielme.muspyforandroid.model.Artist;
import com.danielme.muspyforandroid.model.Release;

/**
 * A  client for MusicBrainz (only artists). Singleton.
 * @author Daniel Medina (danielme.com)
 * @since 1.0
 *
 */
public final class MusicBrainzClient {

    private static final MusicBrainzClient musicBrainzClient = new MusicBrainzClient();

    private final HttpClient httpClient = new DefaultHttpClient();

    //cache for links
    private HashMap<String, String> links = new HashMap<String, String>();

    //cache for releases
    private BoundedLruCache<String, Release> releases = new BoundedLruCache<String, Release>(
            Constants.CACHE_COVER_MIN, Constants.CACHE_COVER_MAX, 0.75F);

    private MusicBrainzClient() {
        //not implemented
    }

    public static MusicBrainzClient getInstance() {
        return musicBrainzClient;
    }

    public List<Artist> searchArtists(String name, int offset, StringBuilder count, int size) throws Exception {
        List<Artist> artists = new ArrayList<Artist>();

        String url = String.format(Constants.MBRAINZ.URL_ARTISTSEARCH, URLEncoder.encode(name), size, offset);

        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader(Constants.CONTENT_TYPE, Constants.TYPE_JSON);

        HttpResponse response = httpClient.execute(httpGet);
        StatusLine statusLine = response.getStatusLine();
        //sometimes we receive HTTP 504
        if (statusLine != null && statusLine.getStatusCode() == MBGatewayTimeOutException.STATUS_CODE) {
            throw new MBGatewayTimeOutException();
        }

        String responseString = EntityUtils.toString(response.getEntity());
        JSONObject responseJSON = new JSONObject(responseString);
        JSONObject list = new JSONObject(responseJSON.getString(Constants.MBRAINZ.ARTISTLIST));
        count.delete(0, count.length());
        count.append(list.getString(Constants.MBRAINZ.COUNT));

        if (list.has(Constants.MBRAINZ.ARTIST)) {
            JSONArray jsonArray = new JSONArray(list.getString(Constants.MBRAINZ.ARTIST));

            for (int i = 0; i < jsonArray.length(); i++) {
                artists.add(populateArtist(jsonArray.getJSONObject(i)));
            }
        }

        return artists;
    }

    /**
     * @since 1.2
     * @param mbid artist
     * @return url, or null if it doesn't exist
     */
    public String getUrlWikipedia(String mbid) throws Exception {
        String link = links.get(mbid);
        if (link == null) {
            String url = String.format(Constants.MBRAINZ.URL_ARTISTDATA, URLEncoder.encode(mbid));

            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader(Constants.CONTENT_TYPE, Constants.TYPE_JSON);

            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            //sometimes we receive HTTP 504
            if (statusLine != null && statusLine.getStatusCode() == MBGatewayTimeOutException.STATUS_CODE) {
                throw new MBGatewayTimeOutException();
            }
            String responseString = EntityUtils.toString(response.getEntity());
            JSONObject responseJSON = new JSONObject(responseString);
            JSONArray jsonArray = responseJSON.getJSONArray(Constants.MBRAINZ.RELATIONS);
            if (jsonArray != null) {
                String type = null;
                int i = 0;
                while (i < jsonArray.length() && link == null) {
                    type = jsonArray.getJSONObject(i).getString(Constants.MBRAINZ.TYPE);
                    if (Constants.MBRAINZ.WIKIPEDIA.equals(type)) {
                        type = jsonArray.getJSONObject(i).getString(Constants.MBRAINZ.TYPE);
                        if (Constants.MBRAINZ.WIKIPEDIA.equals(type)) {
                            JSONObject linkObject = jsonArray.getJSONObject(i).getJSONObject(Constants.MBRAINZ.URL);
                            link = linkObject.getString(Constants.MBRAINZ.RESOURCE);
                            //only english
                            if (link.contains(Constants.MBRAINZ.WIKIPEDIA_EN)) {
                                links.put(mbid, link);
                            } else {
                                link = null;
                            }
                        }
                    }
                    i++;
                }
            }
        }
        return link;
    }

    /**
     *  Label, country, format and mbid of the concrete release
     * @since 1.2
     */
    public void loadReleaseConcrete(Release release) {
        if (releases.get(release.getMbid()) != null) {
            Release temp = releases.get(release.getMbid());
            release.setCountry(temp.getCountry());
            release.setFormat(temp.getFormat());
            release.setLabel(temp.getLabel());
            release.setTrackCount(temp.getTrackCount());
            release.setMbidConcreteRelease(temp.getMbidConcreteRelease());
        } else {
            String url = String.format(Constants.MBRAINZ.URL_RELEASES, URLEncoder.encode(release.getMbid()));

            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader(Constants.CONTENT_TYPE, Constants.TYPE_JSON);
            try {
                HttpResponse response = httpClient.execute(httpGet);
                StatusLine statusLine = response.getStatusLine();
                //sometimes we receive HTTP 504
                if (statusLine != null && statusLine.getStatusCode() == MBGatewayTimeOutException.STATUS_CODE) {
                    throw new MBGatewayTimeOutException();
                }
                String responseString = EntityUtils.toString(response.getEntity());
                JSONObject responseJSON = new JSONObject(responseString);
                JSONArray jsonArray = responseJSON.getJSONArray(Constants.MBRAINZ.RELEASES);
                String date = getReleaseDate(release);
                List<JSONObject> candidates = new LinkedList<JSONObject>();
                for (int i = 0; i < jsonArray.length(); i++) {
                    if (jsonArray.getJSONObject(i).getString("date").equals(date)) {
                        candidates.add(jsonArray.getJSONObject(i));
                    }

                }

                ListIterator<JSONObject> listIterator = candidates.listIterator();
                boolean found = false;
                JSONObject releaseJson = null;
                String country = null;

                //USA
                while (listIterator.hasNext() && !found) {
                    releaseJson = listIterator.next();
                    country = releaseJson.getString("country");
                    if (country.equals("US")) {
                        found = true;
                        loadDetails(releaseJson, release);
                    }
                }
                //UK
                if (!found) {
                    listIterator = candidates.listIterator();
                    while (listIterator.hasNext() && !found) {
                        releaseJson = listIterator.next();
                        country = releaseJson.getString("country");
                        if (country.equals("GB")) {
                            found = true;
                            loadDetails(releaseJson, release);
                        }
                    }
                }

                //the first release
                if (!found && !candidates.isEmpty()) {
                    loadDetails(jsonArray.getJSONObject(0), release);
                }

            } catch (Exception ex) {
                //this feature is not critical
                Log.w(this.getClass().toString(), ex.getMessage());
            }
            releases.put(release.getMbid(), release);
        }
    }

    private void loadDetails(JSONObject releaseJson, Release release) throws Exception {
        release.setCountry(getCountry(releaseJson.getString("country")));
        if (release.getCountry().equals("null")) {
            release.setCountry("");
        }
        release.setMbidConcreteRelease(releaseJson.getString("id"));

        JSONArray jsonArray = releaseJson.getJSONArray("label-info");
        String label = "";
        String label2 = null;
        for (int i = 0; i < jsonArray.length(); i++) {
            label2 = jsonArray.getJSONObject(i).getJSONObject("label").getString("name");
            if (!label2.equals("null")) {
                if (!"".equals(label)) {
                    label += " & ";
                }

                label += label2;
            }
        }
        release.setLabel(label);

        JSONArray jsonArray2 = releaseJson.getJSONArray("media");

        String format = "";
        String format2 = null;
        String trackCount = "";
        String trackCount2 = null;

        for (int i = 0; i < jsonArray2.length(); i++) {
            format2 = jsonArray2.getJSONObject(i).getString("format");
            if (!format2.equals("null")) {
                if (!"".equals(format)) {
                    format += " + ";
                }
                format += format2;
            }

            trackCount2 = jsonArray2.getJSONObject(i).getString("track-count");
            if (!trackCount2.equals("null")) {
                if (!"".equals(trackCount)) {
                    trackCount += " + ";
                }
                trackCount += trackCount2;
            }

        }
        release.setFormat(format);
        release.setTrackCount(trackCount);
    }

    private String getCountry(String source) {
        String country = null;
        if (Locale.getDefault().getLanguage().equals(Constants.LOCALE_ES)) {
            country = Constants.MBRAINZ.LANG_ES.get(source);
        } else {
            country = Constants.MBRAINZ.LANG_EN.get(source);
        }
        if (country == null) {
            country = source;
        }
        return country;
    }

    private Artist populateArtist(JSONObject jsonArtist) throws JSONException {
        Artist artist = new Artist();
        artist.setMbid(jsonArtist.getString(Constants.MBRAINZ.ID));
        if (jsonArtist.has(Constants.MBRAINZ.ARTISTDIS)) {
            artist.setDisambiguation(jsonArtist.getString(Constants.MBRAINZ.ARTISTDIS));
        }
        artist.setName(jsonArtist.getString(Constants.MBRAINZ.ARTISTNAME));
        return artist;
    }

    private String getReleaseDate(Release release) {
        StringBuilder sb = new StringBuilder(release.getYear());

        if (release.getMonth() != null) {
            sb.append("-" + release.getMonth());
            if (release.getDay() != null) {
                sb.append("-" + release.getDay());
            }
        }
        return sb.toString();
    }

}