package com.quiltplayer.external.covers; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.imageio.ImageIO; import org.apache.log4j.Logger; import com.quiltplayer.external.covers.comparators.ImageSizeComparator; import com.quiltplayer.external.covers.comparators.ReleaseYearComparator; import com.quiltplayer.external.covers.discogs.Album; import com.quiltplayer.external.covers.discogs.AlbumRelease; import com.quiltplayer.external.covers.discogs.ArtistRelease; import com.quiltplayer.external.covers.discogs.Format; import com.quiltplayer.external.covers.discogs.Image; import com.quiltplayer.external.covers.discogs.Resp; import com.quiltplayer.external.covers.model.ImageSizes; import com.quiltplayer.external.covers.model.LocalImage; import com.quiltplayer.external.covers.model.filesystem.LocalImageFileSystem; import com.quiltplayer.external.covers.util.ImageUtils; import com.quiltplayer.properties.Configuration; /** * Discogs web service implementation for looking up information about album. * * @author Vlado Palczynski */ public class WebServiceAlbum extends CommonWebserviceMethods { /** * Logger. */ private Logger log = Logger.getLogger(WebServiceAlbum.class); /** * @param resp * the resp to set * @param album * the album to set. */ public final Album getAlbumFromDiscogs(final Resp resp, final String albumTitle, final int songs, final File imageRepo) { XStreamXmlParser parser = new XStreamXmlParser(); try { if (resp == null) { log.debug("Resp was null"); return null; } Album album = new Album(); album.setArtist(resp.getArtist()); /* * Get all id:s matching the album name. */ List<String> albumId = getReleasesMatchingAlbum(albumTitle, resp); if (albumId.size() > 0) { /* * Get all releases from the id:s. */ List<AlbumRelease> responses = getResponsesFromAlbumIds(parser, albumId); List<AlbumRelease> nominees = getResponsesWithSameSongCount(albumTitle, responses, songs); /* * If match on the song count, choose the appropriate release in nominees. If no * match on song count, choose the first release TODO add that if no match on songs * is made that the selection should be album + cd. */ if (nominees.size() != 0) { extractImages(album, nominees, imageRepo); compareYear(album, nominees); } else { extractImages(album, responses, imageRepo); } return album; } } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } return null; } /** * As digitally remastered albums are out there this must be made, otherwise inaccurate release * years on oldies. * * @param album * @param nominees */ private void compareYear(Album album, List<AlbumRelease> nominees) { if (nominees.size() > 1) { Collections.sort(nominees, new ReleaseYearComparator()); album.setYear(nominees.get(0).getReleased()); } } /** * Extract images * * @param album * @param nominees * @throws MalformedURLException * @throws IOException */ private void extractImages(final Album album, final List<AlbumRelease> nominees, final File imageRepo) throws MalformedURLException, IOException { if (nominees.size() > 0) { AlbumRelease selectedRelease = null; /* * Pick the one with the most images, and choose CD-releases before other. */ Collections.sort(nominees, new ImageSizeComparator()); boolean b = false; for (AlbumRelease release : nominees) { // Could be 0 if (release.getImages() != null) { for (Format format : release.getFormats()) { if (format.getName().equals("CD")) { selectedRelease = release; b = true; break; } } if (b) { break; } } } if (!b) { /* * Take the one with the most pictures */ selectedRelease = nominees.get(0); } album.setImages(new ArrayList<LocalImage>()); album.setLabels(selectedRelease.getLabels()); createImages(album, selectedRelease, imageRepo); } } /** * Create images. * * @param album * @param selectedRelease * @throws MalformedURLException * @throws IOException */ private void createImages(final Album album, final AlbumRelease selectedRelease, final File imageRepo) throws MalformedURLException, IOException { if (selectedRelease != null && selectedRelease.getImages() != null && selectedRelease.getImages().size() > 0) { for (Image image : selectedRelease.getImages()) { String[] array = image.getUri().split("/"); File file = new File(imageRepo + System.getProperty("file.separator") + array[array.length - 1]); checkIfImageExists(album, file, image.getUri()); LocalImage localImage = new LocalImageFileSystem(); localImage.setHeight(image.getHeight()); localImage.setWidth(image.getWidth()); localImage.setLargeImage(file); localImage.setSmallImage(createImage(file, ImageSizes.SMALL)); localImage.setMediumImage(createImage(file, ImageSizes.MEDIUM)); localImage.setType(image.getType()); album.setYear(selectedRelease.getReleased()); album.setReleaseId(selectedRelease.getId()); album.getImages().add(localImage); } } } /** * @param file * @param image */ private void checkIfImageExists(Album album, File file, String uri) throws MalformedURLException, IOException { if (!file.exists()) { try { log.debug("Image file in album " + album + " does not exist, downloading..."); URL imageUrl = new URL(uri); BufferedImage i = ImageIO.read(imageUrl); ImageIO.write(i, "jpg", file); } catch (javax.imageio.IIOException e) { log.debug("Image file does not exist on discogs!"); return; } } else { log.debug("Image file " + file.getName() + " already exist."); } } private File createImage(File file, ImageSizes size) throws MalformedURLException, IOException { try { BufferedImage i = ImageIO.read(file); BufferedImage image = ImageUtils.scalePicture(i, size.getSize()); File newFile = new File(file.getParent(), size.name() + "-" + file.getName()); boolean b = newFile.createNewFile(); log.debug("Creating new file returned: " + b); ImageIO.write(image, "jpg", newFile); return newFile; } catch (javax.imageio.IIOException e) { log.debug("Image file does not exist on discogs!"); return null; } } /** * Get responses from Album. * * @param parser * @param albumId * @return * @throws MalformedURLException * @throws Exception * @throws IOException */ @SuppressWarnings("deprecation") private List<AlbumRelease> getResponsesFromAlbumIds(final XStreamXmlParser parser, final List<String> albumId) throws MalformedURLException, Exception, IOException { List<AlbumRelease> responses = new ArrayList<AlbumRelease>(); for (String id : albumId) { log.debug("Webservice call for release with id: " + id); URL url = new URL("http://www.discogs.com/release/" + id + "?f=xml&api_key=" + Configuration.DISCOGS_API_KEY); InputStream stream = null; try { stream = getStreamResponse(url); } catch (Exception e) { if (e.getMessage().contains("400")) { Thread.currentThread().stop(); } /* * Remove the id as this release is probably removed from Discogs... */ continue; } responses.add(parser.parseRelease(stream).getAlbumRelease()); stream.close(); } return responses; } /** * @param album * @param resp * @return */ private List<String> getReleasesMatchingAlbum(final String albumTitle, final Resp resp) { List<String> albumId = new ArrayList<String>(); for (ArtistRelease release : resp.getArtist().getReleases()) { if (release.getTitle().equalsIgnoreCase(albumTitle)) { albumId.add(release.getId()); } } return albumId; } /** * @param album * @param releases * @return */ private List<AlbumRelease> getResponsesWithSameSongCount(final String albumTitle, final List<AlbumRelease> releases, final int songs) { List<AlbumRelease> nominees = new ArrayList<AlbumRelease>(); for (AlbumRelease release : releases) { if (release.getTracklist().size() == songs) { nominees.add(release); } } return nominees; } }