View Javadoc

1   package org.musicontroller.importer;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.net.URISyntaxException;
6   import java.util.ArrayList;
7   import java.util.Date;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  import java.util.Map.Entry;
12  
13  import org.apache.log4j.Logger;
14  import org.musicontroller.core.Band;
15  import org.musicontroller.core.Playlist;
16  import org.musicontroller.core.Song;
17  import org.musicontroller.core.jobs.MetadataExtractJob;
18  import org.musicontroller.dao.Dao;
19  import org.musicontroller.service.FileUtils;
20  import org.musicontroller.service.McService;
21  import org.varienaja.util.FileOperations;
22  import org.varienaja.util.coverart.CoverArtManager;
23  import org.varienaja.util.coverart.CoverArtSearchResult;
24  
25  /**
26   * Implements Importer interface for importing music archives into the music
27   * database.
28   * 
29   * @author Hans Drexler
30   * @version $Id: ImporterImpl.java,v 1.1 2010/03/16 18:55:43 varienaja Exp $
31   */
32  public class ImporterImpl implements Importer {
33  
34  	/**
35  	 * A logger.
36  	 */
37  	private static Logger log = Logger.getLogger(ImporterImpl.class);
38  	
39  	/**
40  	 * Dao object gets imported by spring.
41  	 */
42  	private Dao _dao;
43  	
44  	/**
45  	 * The McService gets imported by spring.
46  	 */
47  	private McService _mcService;
48  	
49  	/**
50  	 * Setter for the Dao.
51  	 * @param dao The Dao.
52  	 */
53  	public void setDao(Dao dao) {
54  		_dao = dao;
55  	}
56  	
57  	/**
58  	 * Getter for the Dao.
59  	 * @return The Dao.
60  	 */
61  	public Dao getDao() {
62  		return _dao;
63  	}
64  	
65  	/**
66  	 * Getter for the McService.
67  	 * @return The McService.
68  	 */
69  	public McService getMcService() {
70  		return _mcService;
71  	}
72  	
73  	/**
74  	 * Setter for the McService.
75  	 * @param mcService
76  	 */
77  	public void setMcService(McService mcService) {
78  		_mcService = mcService;
79  	}
80  	
81  	public void importMusic(MusicArchiveBean bean) throws ImporterException {
82  		if(bean==null) {
83  			return;
84  		}
85  		if(bean.getArchiveName()==null || bean.getArchiveName().length()<1) {
86  			throw new ImporterException("Invalid archive without a name cannot be imported.");
87  		}
88  		//Use the information stored in the bean to import music into the database.
89  		log.debug("Importing music from bean: "+bean.getArchiveName());		
90  		// Build a Map of different Playlist names in the archive, and a list of entries for each name.
91  		Map<String,List<MusicArchiveEntryBean>> entryMap = new HashMap<String,List<MusicArchiveEntryBean>>();
92  		for (MusicArchiveEntryBean entry : bean.getEntrySet()) {
93  			if (entry.getInclude()) {
94  				String key = entry.getPlaylistName();
95  				if(key==null || key.length()<1) {
96  					throw new ImporterException("Invalid empty playlist name in an entry.");
97  				}
98  				if(entryMap.get(key)==null) {
99  					entryMap.put(key, new ArrayList<MusicArchiveEntryBean>());
100 				}
101 				entryMap.get(key).add(entry);
102 			}
103 		}
104 		for(Entry<String,List<MusicArchiveEntryBean>> entry: entryMap.entrySet()) {
105 			PlaylistImportProperties properties = bean.getPlaylistProperties(entry.getKey());
106 			if(properties==null) {
107 				// No properties specified, use defaults
108 				properties = new PlaylistImportProperties();
109 				properties.setAddToExistingPlaylist(false);
110 				properties.setPlaylistName(entry.getKey());
111 				properties.setCoverArt(null);
112 			}
113 			// Import all entries of this playlist name using the same settings.
114 			long playlistid = createPlaylist(properties);
115 			for(MusicArchiveEntryBean entryBean: entry.getValue()) {
116 				importIntoMusiController(bean, entryBean, playlistid);
117 			}
118 			if(!CoverArtManager.contains(playlistid, 0) && properties.getCoverArt()!=null && properties.getCoverArt().length()>7) {
119 				try {
120 					CoverArtSearchResult art = new CoverArtSearchResult(properties.getCoverArt(),64,64,64);
121 					getMcService().setPlaylistCoverArt(getDao().getPlaylistById(playlistid, null),art);
122 				} catch (IOException e) {
123 					log.error("Failed to set cover art image: "+e.getLocalizedMessage());
124 				} catch (URISyntaxException e) {
125 					log.error("Failed to set cover art image: "+e.getLocalizedMessage());
126 				}
127 			}
128 		}
129 		MetadataExtractJob.removeMusicArchiveBean(bean);
130 	}
131 	
132 	/**
133 	 * Creates an empty playlist with the given name if necessary. A new playlist is
134 	 * created if there is no playlist with the same name or if the <code>addToExistingPlaylist</code>
135 	 * is false.
136 	 * 
137 	 * @param playlistName The name of the playlist to add.
138 	 * @return The id of the persistent playlist (either created or already existing.)
139 	 * @throws ImporterException The playlist name is invalid.
140 	 */
141 	private long createPlaylist(PlaylistImportProperties properties) throws ImporterException {
142 		String playlistname = properties.getPlaylistName();
143 		if(playlistname==null||playlistname.length()<1) {
144 			throw new ImporterException("Invalid play list name (null or empty).");				
145 		}
146 		List<Playlist> playlists = getDao().searchPlaylist(playlistname);
147 		Playlist playlist = null;
148 		if(playlists.size()>0 && properties.isAddToExistingPlaylist()) {
149 			// We should use the existing playlist.
150 			return playlists.get(0).getId();
151 		}
152 		log.debug("Creating new playlist: "+properties.getPlaylistName());
153 		// Playlist does not exist => create it.
154 		playlist = new Playlist();
155 		playlist.setName(properties.getPlaylistName());
156 		playlist.setReleasedate(properties.getReleaseDate());
157 		playlist.setInserted(new Date());
158 		getDao().save(playlist);	
159 		return playlist.getId();
160 	}
161 
162 	/**
163 	 * Copy the MP3 file into the MusiController file system and data base. The MP3 file
164 	 * must be copied to its proper position in the MusiController file store and appropriate
165 	 * Song/Band/Playlist objects must be added to the MusiController database. The Importer
166 	 * does specify the final MP3 file path. We use MusiControllerTools to do the actual work.
167 	 * 
168 	 * @param archive Contains the music archive.
169 	 * @param entryToImport Contains the MP3 meta data to use.
170 	 * @param playlistid The id of a persistent playlist. The playlist must already exist.
171 	 * @throws ImporterException The band name is null or empty, the play list name is null
172 	 * 				or empty.
173 	 */
174 	private void importIntoMusiController(MusicArchiveBean archive, MusicArchiveEntryBean entryToImport, long playlistid) throws ImporterException {
175 		// First, import the band if it isn't there yet.
176 		String bandname = entryToImport.getBandName();
177 		if(bandname==null||bandname.length()<1) {
178 			throw new ImporterException("Invalid band name (null or empty) in song: "+entryToImport.getSongName()+" at index "+
179 											String.valueOf(entryToImport.getSongIndex()));
180 		}
181 		String playlistname = entryToImport.getPlaylistName();
182 		if(playlistname==null||playlistname.length()<1) {
183 			throw new ImporterException("Invalid play list name (null or empty) in song: "+entryToImport.getSongName()+" at index "+
184 					String.valueOf(entryToImport.getSongIndex()));				
185 		}
186 		String songname = entryToImport.getSongName();
187 		if(songname==null||songname.length()<1) {
188 			throw new ImporterException("Invalid song name (null or empty) in song: "+entryToImport.getSongName()+" at index "+
189 					String.valueOf(entryToImport.getSongIndex()));				
190 		}
191 		String fileName = entryToImport.getEntryName();
192 		if(fileName==null || fileName.length()<1) {
193 			throw new ImporterException("Invalid null or empty file name in song: "+entryToImport.getSongName()+" at index"+
194 					String.valueOf(entryToImport.getSongIndex()));
195 		}
196 		Band band = getMcService().addBand(bandname);
197 		// Next, create the playlist.
198 		Playlist playlist = getDao().getPlaylistById(playlistid, null);
199 		if(playlist==null) {
200 			throw new ImporterException("The playlist "+playlistname+" should already exist.");
201 		}
202 		String destination = moveMP3ToLibrary(entryToImport);
203 		
204 		try {
205 			// Add the song to the playlist
206 			Song newSong = getMcService().createSong(entryToImport.getSongName(), band, entryToImport.getSongLength(), entryToImport.getKeywords(), destination);
207 			getMcService().addSongToPlaylist(newSong, playlist, entryToImport.getSongIndex());
208 		} catch (Exception e) {
209 			log.error("Error importing beanentry. "+e);
210 			// Delete the MP3 file if an exception occured.
211 			try {
212 				FileOperations.deleteFile(destination);
213 			} catch (Exception e1) {
214 				// ignore and re-throw the first exception.
215 				throw new ImporterException(e.getLocalizedMessage());
216 			}
217 			throw new ImporterException(e.getLocalizedMessage());
218 		}
219 	}
220 
221 	/**
222 	 * Moves an entry to its final destination.
223 	 * @param entryToImport The entry to import.
224 	 * @return The relative name of the File, the entry was moved to.
225 	 * @throws ImporterException when the move failed.
226 	 */
227 	public static String moveMP3ToLibrary(MusicArchiveEntryBean entryToImport)
228 			throws ImporterException {
229 		// Move the MP3 to its final location.
230 		try {
231 			String[] location = FileUtils.getNewSongDestination(entryToImport);
232 			String dstdir = location[0] + File.separator + location[1];
233 			
234 			FileOperations.moveFile(entryToImport.getEntryName(), dstdir, location[2]);
235 			return location[1] + File.separator + location[2];
236 		} catch (Exception e) {
237 			throw new ImporterException("Failed to move the MP3 file: "+e.getLocalizedMessage());
238 		}
239 	}
240 
241 }