Java tutorial
/* * 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(); } }