Java tutorial
/* This file is part of Madsonic. Madsonic 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, either version 3 of the License, or (at your option) any later version. Madsonic 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 along with Madsonic. If not, see <http://www.gnu.org/licenses/>. Copyright 2013 (C) Madevil */ package org.madsonic.service; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.regex.Pattern; import org.madsonic.Logger; import org.madsonic.dao.ArtistDao; import org.madsonic.dao.LastFMArtistDao; import org.madsonic.dao.LastFMArtistSimilarDao; import org.madsonic.dao.LastFMArtistTopTracksDao; import org.madsonic.dao.MediaFileDao; import org.madsonic.domain.Artist; import org.madsonic.domain.LastFMArtist; import org.madsonic.domain.LastFMArtistSimilar; import org.madsonic.domain.LastFMArtistTopTrack; import org.madsonic.domain.MediaFile; import org.madsonic.domain.MediaFileComparator; import org.madsonic.domain.MediaFileRankComparator; import org.madsonic.domain.SearchCriteria; import org.madsonic.domain.SearchResult; import org.madsonic.lastfm.Album; import org.madsonic.lastfm.Image; import org.madsonic.lastfm.ImageSize; import org.madsonic.lastfm.PaginatedResult; import org.madsonic.lastfm.Track; import org.madsonic.util.StringUtil; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.HttpConnectionParams; import org.jfree.util.Log; public class LastFMService { private static final Logger LOG = Logger.getLogger(LastFMService.class); private SecurityService securityService; private SettingsService settingsService; private MediaFileService mediaFileService; private LastFMArtistDao lastFMArtistDao; private MediaFileDao mediaFileDao; private ArtistDao artistDao; private SearchService searchService; private static LastFMArtistSimilarDao lastFMArtistSimilarDao; private static LastFMArtistTopTracksDao lastFMArtistTopTracksDao; // Use here your own Last.FM API key private static String api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; Map<String, String> storedCorrectionMap = new HashMap<String, String>(); public void setLastFMResultSize(int size) { settingsService.setLastFMResultSize(size); settingsService.save(); } public int getLastFMResultSize() { return settingsService.getLastFMResultSize(); } public String getCorrection(String ArtistName) { String stripedArtist = stripNonValidXMLCharacters(ArtistName); String RequestedArtist = null; if (stripedArtist != null && stripedArtist != "") { try { String RequestedArtistfromMap = storedCorrectionMap.get(stripedArtist); if (RequestedArtistfromMap == null) { RequestedArtist = (org.madsonic.lastfm.Artist.getCorrection(stripedArtist, api_key)).getName(); if (!stripedArtist.equalsIgnoreCase(RequestedArtist)) { storedCorrectionMap.put(stripedArtist, RequestedArtist); } } else { RequestedArtist = RequestedArtistfromMap; } } catch (NullPointerException ex) { System.out.println("## ERROR: updateTopTrackArtist - ArtistName '" + stripedArtist + "'"); } } return RequestedArtist; } public LastFMArtist getArtist(String artistname) { try { if (artistname != null || artistname.length() > 0) { String tmpArtistName = org.madsonic.lastfm.Artist.getCorrection(artistname, api_key).getName(); if (artistname != tmpArtistName) { LOG.debug("## ArtistAutoCorrect: " + artistname + " -> " + tmpArtistName); } return lastFMArtistDao.getArtist(tmpArtistName); } } catch (Exception x) { // Ignore Exception return null; } return null; } private String escape(String s) { if (s == null) { return null; } Pattern p = Pattern.compile("([-&\\|!\\(\\){}\\[\\]\\^\"\\~\\*\\?:\\\\])"); s = p.matcher(s).replaceAll("\\\\$1"); return s; } public List<MediaFile> getSearchresult(String artist, String title, int userGroupId) { StringBuilder query = new StringBuilder(); query.append("artist:" + escape(artist)).append(" AND "); query.append("title:" + escape(title)).append(" AND "); query.append("mediaType:music"); SearchCriteria criteria = new SearchCriteria(); criteria.setQuery(query.toString().trim()); criteria.setOffset(0); criteria.setCount(1); SearchResult result = searchService.search(criteria, SearchService.IndexType.SONG, userGroupId); return result.getMediaFiles(); } public List<MediaFile> getTopTrack(String artist, int limit, int userGroupId) { return null; } public void updateTopTrackStats(String artist, int toplastFMfound, int topPlayedfound) { Artist artistCandidate; String RequestedArtist = getCorrection(artist); artistCandidate = artistDao.getArtist(RequestedArtist); artistCandidate.setTopPlayFound(toplastFMfound); artistCandidate.setTopPlayCount(topPlayedfound); artistDao.createOrUpdateArtist(artistCandidate); } public List<MediaFile> updateTopTrackEntries(String artist, int limit, int userGroupId) { //TODO: check & scan with service List<MediaFile> topTrackSongs = new ArrayList<MediaFile>(); HashSet<MediaFile> hs = new HashSet<MediaFile>(); List<LastFMArtistTopTrack> topTracks = getTopTrackArtist(artist); if (topTracks.size() < 1) { updateTopTrackArtist(artist); if (topTracks.size() < 1) { } topTracks = getTopTrackArtist(artist); } for (LastFMArtistTopTrack track : topTracks) { MediaFile requested = null; List<MediaFile> searchResult = getSearchresult(track.getArtistname(), track.getSongname(), userGroupId); if (searchResult != null && searchResult.size() != 0) { requested = mediaFileService.getMediaFile(searchResult.get(0).getId(), userGroupId); } if (requested != null) { if (requested.getRank() != track.getRank()) { requested.setRank(track.getRank()); mediaFileDao.createOrUpdateMediaFile(requested); } hs.add(requested); if (hs.size() > limit) { break; } } } // Filter out duplicates topTrackSongs.clear(); topTrackSongs.addAll(hs); // Sort by Rank Comparator<MediaFile> comparator = new MediaFileRankComparator(); Set<MediaFile> set = new TreeSet<MediaFile>(comparator); set.addAll(topTrackSongs); topTrackSongs = new ArrayList<MediaFile>(set); return topTrackSongs; } public int updateTopTrackArtist(String ArtistName) { // Update TopTracks in table if (ArtistName != null && ArtistName != "") { Artist artistCandidate; String RequestedArtist = getCorrection(ArtistName); artistCandidate = artistDao.getArtist(RequestedArtist); boolean artistFound = artistCandidate == null ? false : true; int toplastFMfound = artistCandidate == null ? 0 : artistCandidate.getTopPlayCount(); LastFMArtistTopTrack topTrack = new LastFMArtistTopTrack(); Collection<Track> TopTracks = org.madsonic.lastfm.Artist.getTopTracks(RequestedArtist, api_key, getLastFMResultSize()); if (TopTracks.size() > toplastFMfound) { artistCandidate.setTopPlayCount(TopTracks.size()); artistDao.createOrUpdateArtist(artistCandidate); } int rank = 1; for (Track track : TopTracks) { topTrack.setArtistname(track.getArtist()); if (RequestedArtist != track.getArtist()) { topTrack.setAlternate(RequestedArtist); } //TODO: move to last.fm table // topTrack.setArtistmbid(track.getArtistMbid()); topTrack.setSongname(track.getName()); topTrack.setSongmbid(track.getMbid()); topTrack.setRank(rank); topTrack.setPlayCount(track.getPlaycount()); lastFMArtistTopTracksDao.createOrUpdateLastFMArtistTopTrack(topTrack); rank++; } // getTopTrack(RequestedArtist, 1, 0); LOG.debug("## TopTrack update results: " + TopTracks.size() + " -> " + RequestedArtist); return TopTracks.size(); } return 0; } public List<LastFMArtistTopTrack> getAllTopTrack(int count) { return lastFMArtistTopTracksDao.getAllTopTrack(count); } public List<LastFMArtistTopTrack> getTopTrackArtist(String ArtistName) { String alternate = null; List<LastFMArtistTopTrack> getTopTrackArtist = new ArrayList<LastFMArtistTopTrack>(); try { alternate = (org.madsonic.lastfm.Artist.getCorrection(ArtistName, api_key)).getName(); } catch (NullPointerException ex) { System.out.println("## ERROR: ArtistName '" + ArtistName + "'"); } if (alternate != null) { return lastFMArtistTopTracksDao.getTopTrack(alternate, ArtistName); } return getTopTrackArtist; } public List<String> getSimilarArtist(String ArtistName) { return lastFMArtistSimilarDao.getSimilarArtist(ArtistName); } public void CleanupArtist() { lastFMArtistDao.CleanupArtist(); } public void CleanupArtistTopTracks() { lastFMArtistTopTracksDao.CleanupArtistTopTracks(); } public void getArtistImages(List<Artist> artistList) { LOG.info("## ArtistCount: " + artistList.size()); MediaFile mediaFileArtist; for (Artist artist : artistList) { try { int id = mediaFileService.getIDfromArtistname(artist.getName()) == null ? -1 : mediaFileService.getIDfromArtistname(artist.getName()); mediaFileArtist = mediaFileService.getMediaFile(id); if (mediaFileArtist == null) { continue; } LOG.debug("## Scan for Artist: " + artist.getName()); getArtistImage(mediaFileArtist, api_key); } catch (NullPointerException ex) { System.out.println("## ERROR: " + artist.getName()); } } LOG.info("## LastFM Scan Finished"); } public void getArtistBio(List<Artist> artistList) { LOG.info("## ArtistCount: " + artistList.size()); MediaFile mediaFileArtist; //LastFMArtist for (Artist artist : artistList) { try { int id = mediaFileService.getIDfromArtistname(artist.getName()) == null ? -1 : mediaFileService.getIDfromArtistname(artist.getName()); mediaFileArtist = mediaFileService.getMediaFile(id); if (mediaFileArtist == null) { continue; } LOG.debug("## Scan for ArtistBio: " + artist.getName()); // getArtistBio(mediaFileArtist, api_key); // mediaFileService.createOrUpdateMediaFile(mediaFileArtist); } catch (NullPointerException ex) { System.out.println("## ERROR: " + artist.getName()); } } LOG.info("## LastFM Scan Finished"); } public String stripNonValidXMLCharacters(String in) { StringBuilder out = new StringBuilder(); // Used to hold the output. char current; // Used to reference the current character. if (in == null || ("".equals(in))) return ""; // vacancy test. for (int i = 0; i < in.length(); i++) { current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen. if ((current == 0x9) || (current == 0xA) || (current == 0xB) || (current == 0xD) || (current == 0x1f) || ((current >= 0x20) && (current <= 0xD7FF)) || ((current >= 0xE000) && (current <= 0xFFFD)) || ((current >= 0x10000) && (current <= 0x10FFFF))) out.append(current); } return out.toString(); } //----------------- Import ------------------ public void getArtistInfo(List<Artist> artistList) { LOG.debug("## ArtistCount: " + artistList.size()); Locale LastFMLocale = new Locale(settingsService.getLocale().toString()); LOG.debug("## LastFM Locale: " + LastFMLocale.toString()); for (Artist artist : artistList) { try { if (artist.getArtistFolder() != null) { LastFMArtist lastFMartist = new LastFMArtist(); org.madsonic.lastfm.Artist tmpArtist = null; //String escapedArtist = stripNonValidXMLCharacters(StringEscapeUtils.escapeXml(artist.getArtistFolder()) ); String stripedArtist = stripNonValidXMLCharacters(artist.getArtistFolder()); String RequestedArtist = (org.madsonic.lastfm.Artist.getCorrection(stripedArtist, api_key)) .getName(); //todo:error try { tmpArtist = org.madsonic.lastfm.Artist.getInfo(RequestedArtist, LastFMLocale, null, api_key); } catch (Exception e) { Log.error("## FATAL Error! Artist Fetch! " + tmpArtist.getName()); } lastFMartist.setArtistname(tmpArtist.getName()); lastFMartist.setMbid(tmpArtist.getMbid()); lastFMartist.setUrl(tmpArtist.getUrl()); lastFMartist.setSince(tmpArtist.getSince()); lastFMartist.setPlayCount(tmpArtist.getPlaycount()); Collection<Album> TopAlbum = org.madsonic.lastfm.Artist.getTopAlbums(RequestedArtist, api_key, 3); String CollAlbum = null; for (Album album : TopAlbum) { if (album != null) { if (CollAlbum == null) { CollAlbum = album.getName(); } else { CollAlbum = CollAlbum + "|" + album.getName(); } } } lastFMartist.setTopalbum(CollAlbum); Collection<String> GenreTags = tmpArtist.getTags(); String CollTag = null; for (String TopTag : GenreTags) { if (TopTag != null) { if (CollTag == null) { CollTag = TopTag; } else { CollTag = CollTag + "|" + TopTag; } } } lastFMartist.setToptag(CollTag); for (String TopTag : GenreTags) { if (TopTag != null) { lastFMartist.setGenre(TopTag); break; } } // String[] sep = CollTag.split("\\|"); // List list = Arrays.asList(sep); String tmpSum = tmpArtist.getWikiSummary(); tmpSum = StringUtil.removeMarkup(tmpSum); // String tmpText = tmpArtist.getWikiText(); // tmpText = StringUtil.removeMarkup(tmpText); // lastFMartist.setBio(tmpText); lastFMartist.setSummary(tmpSum); // Collection<Tag> TopTags = org.madsonic.lastfm.Artist.getTopTags(tmpArtist.getName(), api_key, 1); Collection<org.madsonic.lastfm.Artist> Similar = org.madsonic.lastfm.Artist .getSimilar(tmpArtist.getName(), 6, api_key); for (org.madsonic.lastfm.Artist x : Similar) { LastFMArtistSimilar s = new LastFMArtistSimilar(); s.setArtistName(tmpArtist.getName()); s.setArtistMbid(tmpArtist.getMbid()); s.setSimilarName(x.getName()); s.setSimilarMbid(x.getMbid()); lastFMArtistSimilarDao.createOrUpdateLastFMArtistSimilar(s); } // /** // * new Artist image importer workaround // */ // if (tmpArtist != null) { // lastFMartist.setCoverart1(tmpArtist.getImageURL(ImageSize.EXTRALARGE)); // } // deprecated // PaginatedResult <Image> artistImage = org.madsonic.lastfm.Artist.getImages(RequestedArtist, 1, 5, api_key); // Collection <Image> Imgs = artistImage.getPageResults(); // // int counter = 0; // for (Image Img : Imgs) // { switch(counter) // { case 0: lastFMartist.setCoverart1(Img.getImageURL(ImageSize.LARGESQUARE));break; // case 1: lastFMartist.setCoverart2(Img.getImageURL(ImageSize.LARGESQUARE));break; // case 2: lastFMartist.setCoverart3(Img.getImageURL(ImageSize.LARGESQUARE));break; // case 3: lastFMartist.setCoverart4(Img.getImageURL(ImageSize.LARGESQUARE));break; // case 4: lastFMartist.setCoverart5(Img.getImageURL(ImageSize.LARGESQUARE));break; // } // counter++; // } if (lastFMartist.getArtistname() != null) { LOG.info("## LastFM ArtistInfo Update: " + lastFMartist.getArtistname()); lastFMArtistDao.createOrUpdateLastFMArtist(lastFMartist); } } } catch (NullPointerException ex) { System.out.println("## ERROR: " + artist.getName()); } } LOG.info("## LastFM ArtistScan Finished"); } public void getArtistInfo(LastFMArtist lastFMartist, String api_key) { try { /// LastFM API org.madsonic.lastfm.Artist Artist = org.madsonic.lastfm.Artist .getCorrection(lastFMartist.getArtistname(), api_key); lastFMartist.setArtistname(Artist.getName()); lastFMartist.setMbid(Artist.getMbid()); } catch (Exception x) { LOG.warn("## Failed to Update ArtistCover: " + lastFMartist.getArtistname(), x); } } public void getArtistImage(MediaFile mediaFileArtist, String api_key) { if (mediaFileArtist.getCoverArtPath() == null || mediaFileArtist == null) { try { /// LastFM API String artistName = org.madsonic.lastfm.Artist.getCorrection(mediaFileArtist.getArtist(), api_key) .getName(); org.madsonic.lastfm.Artist artist = org.madsonic.lastfm.Artist.getInfo(artistName, api_key); setCoverArtImage(mediaFileArtist.getId(), artist.getImageURL(ImageSize.MEGA), true); LOG.info("## Update ArtistCover: " + mediaFileArtist.getArtist()); } catch (Exception x) { LOG.warn("## Failed to Update ArtistCover: " + mediaFileArtist.getArtist(), x); } } } public void getArtistBio(LastFMArtist lastFMartist, String api_key) { try { /// LastFM API String artist = org.madsonic.lastfm.Artist.getCorrection(lastFMartist.getArtistname(), api_key) .getName(); String summary = getSummary(artist, api_key); lastFMartist.setSummary(summary); System.out.println("summary: "); System.out.println(summary); } catch (Exception x) { LOG.warn("## Failed to Update ArtistCover: " + lastFMartist.getArtistname(), x); } } public static String getInfo(String artistName, String apiKey) { // org.madsonic.lastfm.Artist ArtistTest1 = org.madsonic.lastfm.Artist.getInfo(org.madsonic.lastfm.Artist.getCorrection("AC-DC", apiKey).getName(), apiKey); org.madsonic.lastfm.Artist temp = org.madsonic.lastfm.Artist.getInfo(artistName, apiKey); return temp.getWikiSummary(); //.getWikiSummary(); //getWikiText(); //Also .getWikiSummary(), .getWikiLastChanged(), etc... } public static String getSummary(String artistName, String apiKey) { org.madsonic.lastfm.Artist temp = org.madsonic.lastfm.Artist.getInfo(artistName, apiKey); return temp.getWikiSummary(); //.getWikiSummary(); //getWikiText(); //Also .getWikiSummary(), .getWikiLastChanged(), etc... } public String setCoverArtImage(int id, String url, boolean isArtist) { try { MediaFile mediaFile = mediaFileService.getMediaFile(id); if (mediaFile.isAlbum() || mediaFile.isAlbumSet()) { isArtist = false; } saveCoverArt(mediaFile.getPath(), url, isArtist); return null; } catch (Exception x) { LOG.warn("Failed to save cover art for media " + id, x); return x.toString(); } } private void saveCoverArt(String path, String url, boolean isArtist) throws Exception { InputStream input = null; HttpClient client = new DefaultHttpClient(); try { HttpConnectionParams.setConnectionTimeout(client.getParams(), 20 * 1000); // 20 seconds HttpConnectionParams.setSoTimeout(client.getParams(), 20 * 1000); // 20 seconds HttpGet method = new HttpGet(url); org.apache.http.HttpResponse response = client.execute(method); input = response.getEntity().getContent(); // Attempt to resolve proper suffix. String suffix = "jpg"; if (url.toLowerCase().endsWith(".gif")) { suffix = "gif"; } else if (url.toLowerCase().endsWith(".png")) { suffix = "png"; } String coverName = "cover."; if (isArtist == true) { coverName = "artist."; } // Check permissions. File newCoverFile = new File(path, coverName + suffix); if (!securityService.isWriteAllowed(newCoverFile)) { throw new Exception("Permission denied: " + StringUtil.toHtml(newCoverFile.getPath())); } // If file exists, create a backup. backup(newCoverFile, new File(path, coverName + "backup." + suffix)); // Write file. IOUtils.copy(input, new FileOutputStream(newCoverFile)); MediaFile mediaFile = mediaFileService.getMediaFile(path); // Rename existing cover file if new cover file is not the preferred. try { File coverFile = mediaFileService.getCoverArt(mediaFile); if (coverFile != null) { if (!newCoverFile.equals(coverFile)) { coverFile.renameTo(new File(coverFile.getCanonicalPath() + ".old")); LOG.info("Renamed old image file " + coverFile); } } } catch (Exception x) { LOG.warn("Failed to rename existing cover file.", x); } mediaFileService.refreshMediaFile(mediaFile); } finally { IOUtils.closeQuietly(input); client.getConnectionManager().shutdown(); } } private void backup(File newCoverFile, File backup) { if (newCoverFile.exists()) { if (backup.exists()) { backup.delete(); } if (newCoverFile.renameTo(backup)) { LOG.info("Backed up old image file to " + backup); } else { LOG.warn("Failed to create image file backup " + backup); } } } public void setMediaFileDao(MediaFileDao mediaFileDao) { this.mediaFileDao = mediaFileDao; } public void setSecurityService(SecurityService securityService) { this.securityService = securityService; } public void setSettingsService(SettingsService settingsService) { this.settingsService = settingsService; } public void setMediaFileService(MediaFileService mediaFileService) { this.mediaFileService = mediaFileService; } public void setSearchService(SearchService searchService) { this.searchService = searchService; } public void setLastFMArtistDao(LastFMArtistDao lastFMArtistDao) { this.lastFMArtistDao = lastFMArtistDao; } public void setArtistDao(ArtistDao artistDao) { this.artistDao = artistDao; } public void setLastFMArtistSimilarDao(LastFMArtistSimilarDao lastFMArtistSimilarDao) { this.lastFMArtistSimilarDao = lastFMArtistSimilarDao; } public void setLastFMArtistTopTracksDao(LastFMArtistTopTracksDao lastFMArtistTopTracksDao) { this.lastFMArtistTopTracksDao = lastFMArtistTopTracksDao; } }