1 /* 2 * aTunes 3 * Copyright (C) Alex Aranda, Sylvain Gaudard and contributors 4 * 5 * See http://www.atunes.org/wiki/index.php?title=Contributing for information about contributors 6 * 7 * http://www.atunes.org 8 * http://sourceforge.net/projects/atunes 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 package net.sourceforge.atunes.kernel.modules.tags; 22 23 import java.util.Collection; 24 import java.util.HashMap; 25 import java.util.List; 26 import java.util.Map; 27 28 import javax.swing.ImageIcon; 29 30 import net.sourceforge.atunes.gui.views.dialogs.EditTitlesDialog; 31 import net.sourceforge.atunes.kernel.AbstractHandler; 32 import net.sourceforge.atunes.model.IAlbum; 33 import net.sourceforge.atunes.model.IAudioObject; 34 import net.sourceforge.atunes.model.IDialogFactory; 35 import net.sourceforge.atunes.model.IFileManager; 36 import net.sourceforge.atunes.model.ILocalAudioObject; 37 import net.sourceforge.atunes.model.ILocalAudioObjectReader; 38 import net.sourceforge.atunes.model.IProcessFactory; 39 import net.sourceforge.atunes.model.IStateNavigation; 40 import net.sourceforge.atunes.model.ITag; 41 import net.sourceforge.atunes.model.ITagHandler; 42 import net.sourceforge.atunes.model.ITreeObject; 43 import net.sourceforge.atunes.model.IUnknownObjectChecker; 44 import net.sourceforge.atunes.model.IWebServicesHandler; 45 import net.sourceforge.atunes.model.TextTagAttribute; 46 47 /** 48 * Responsible of change tags 49 * 50 * @author alex 51 * 52 */ 53 public class TagHandler extends AbstractHandler implements ITagHandler { 54 55 private IProcessFactory processFactory; 56 57 private IStateNavigation stateNavigation; 58 59 private IDialogFactory dialogFactory; 60 61 private Map<TextTagAttribute, ITagChecker> checkers; 62 63 private IUnknownObjectChecker unknownObjectChecker; 64 65 private IWebServicesHandler webServicesHandler; 66 67 private TagModifier tagModifier; 68 69 private IFileManager fileManager; 70 71 private TagFactory tagFactory; 72 73 private ILocalAudioObjectReader localAudioObjectReader; 74 75 /** 76 * @param localAudioObjectReader 77 */ setLocalAudioObjectReader( final ILocalAudioObjectReader localAudioObjectReader)78 public void setLocalAudioObjectReader( 79 final ILocalAudioObjectReader localAudioObjectReader) { 80 this.localAudioObjectReader = localAudioObjectReader; 81 } 82 83 /** 84 * @param tagFactory 85 */ setTagFactory(final TagFactory tagFactory)86 public void setTagFactory(final TagFactory tagFactory) { 87 this.tagFactory = tagFactory; 88 } 89 90 /** 91 * @param fileManager 92 */ setFileManager(final IFileManager fileManager)93 public void setFileManager(final IFileManager fileManager) { 94 this.fileManager = fileManager; 95 } 96 97 /** 98 * @param tagModifier 99 */ setTagModifier(final TagModifier tagModifier)100 public void setTagModifier(final TagModifier tagModifier) { 101 this.tagModifier = tagModifier; 102 } 103 104 /** 105 * @param webServicesHandler 106 */ setWebServicesHandler( final IWebServicesHandler webServicesHandler)107 public void setWebServicesHandler( 108 final IWebServicesHandler webServicesHandler) { 109 this.webServicesHandler = webServicesHandler; 110 } 111 112 /** 113 * @param unknownObjectChecker 114 */ setUnknownObjectChecker( final IUnknownObjectChecker unknownObjectChecker)115 public void setUnknownObjectChecker( 116 final IUnknownObjectChecker unknownObjectChecker) { 117 this.unknownObjectChecker = unknownObjectChecker; 118 } 119 120 /** 121 * @param dialogFactory 122 */ setDialogFactory(final IDialogFactory dialogFactory)123 public void setDialogFactory(final IDialogFactory dialogFactory) { 124 this.dialogFactory = dialogFactory; 125 } 126 127 /** 128 * @param stateNavigation 129 */ setStateNavigation(final IStateNavigation stateNavigation)130 public void setStateNavigation(final IStateNavigation stateNavigation) { 131 this.stateNavigation = stateNavigation; 132 } 133 134 /** 135 * @param processFactory 136 */ setProcessFactory(final IProcessFactory processFactory)137 public void setProcessFactory(final IProcessFactory processFactory) { 138 this.processFactory = processFactory; 139 } 140 141 /** 142 * Gets the edits the tag dialog controller. 143 * 144 * @return the edits the tag dialog controller 145 */ getEditTagDialogController()146 private EditTagDialogController getEditTagDialogController() { 147 return getBean(EditTagDialogController.class); 148 } 149 150 @Override editFiles(final List<ILocalAudioObject> list)151 public void editFiles(final List<ILocalAudioObject> list) { 152 getEditTagDialogController().editFiles(list); 153 } 154 155 @Override editFiles(final IAlbum a)156 public void editFiles(final IAlbum a) { 157 new EditTitlesDialogController( 158 this.dialogFactory.newDialog(EditTitlesDialog.class), 159 this.processFactory, this.webServicesHandler, this.fileManager) 160 .editFiles(a); 161 } 162 163 @Override setTag(final ILocalAudioObject audioObject, final ITag tag)164 public void setTag(final ILocalAudioObject audioObject, final ITag tag) { 165 this.tagModifier.setInfo(audioObject, tag); 166 } 167 168 @Override refreshAfterTagModify( final Collection<ILocalAudioObject> audioObjectsChanged)169 public void refreshAfterTagModify( 170 final Collection<ILocalAudioObject> audioObjectsChanged) { 171 this.tagModifier.refreshAfterTagModify(audioObjectsChanged); 172 } 173 174 @Override deleteTags(final ILocalAudioObject audioObject)175 public void deleteTags(final ILocalAudioObject audioObject) { 176 this.tagModifier.deleteTags(audioObject); 177 } 178 179 @Override setTag(final ILocalAudioObject audioObject, final ITag tag, final boolean editCover, final byte[] cover)180 public void setTag(final ILocalAudioObject audioObject, final ITag tag, 181 final boolean editCover, final byte[] cover) { 182 this.tagModifier.setInfo(audioObject, tag, editCover, cover); 183 } 184 185 @Override setTitle(final ILocalAudioObject audioObject, final String newTitle)186 public void setTitle(final ILocalAudioObject audioObject, 187 final String newTitle) { 188 this.tagModifier.setTitles(audioObject, newTitle); 189 } 190 191 @Override setAlbum(final ILocalAudioObject audioObject, final String albumName)192 public void setAlbum(final ILocalAudioObject audioObject, 193 final String albumName) { 194 this.tagModifier.setAlbum(audioObject, albumName); 195 } 196 197 @Override setGenre(final ILocalAudioObject audioObject, final String genre)198 public void setGenre(final ILocalAudioObject audioObject, final String genre) { 199 this.tagModifier.setGenre(audioObject, genre); 200 } 201 202 @Override setLyrics(final ILocalAudioObject audioObject, final String lyricsString)203 public void setLyrics(final ILocalAudioObject audioObject, 204 final String lyricsString) { 205 this.tagModifier.setLyrics(audioObject, lyricsString); 206 } 207 208 @Override setStars(final ILocalAudioObject audioObject, final Integer value)209 public void setStars(final ILocalAudioObject audioObject, 210 final Integer value) { 211 this.tagModifier.setStars(audioObject, value); 212 } 213 214 @Override setTrackNumber(final ILocalAudioObject audioObject, final Integer integer)215 public void setTrackNumber(final ILocalAudioObject audioObject, 216 final Integer integer) { 217 this.tagModifier.setTrackNumber(audioObject, integer); 218 } 219 220 @Override getNewTag()221 public ITag getNewTag() { 222 return this.tagFactory.getNewTag(); 223 } 224 225 @Override getNewTag(final ILocalAudioObject file, final Map<String, Object> tagInformation)226 public ITag getNewTag(final ILocalAudioObject file, 227 final Map<String, Object> tagInformation) { 228 return this.tagFactory.getNewTag(file, tagInformation); 229 } 230 231 @Override hasIncompleteTags(final IAudioObject audioObject)232 public boolean hasIncompleteTags(final IAudioObject audioObject) { 233 return hasIncompleteTags(audioObject, 234 this.stateNavigation 235 .getHighlightIncompleteTagFoldersAttributes()); 236 } 237 238 @Override hasIncompleteTags( final ITreeObject<? extends IAudioObject> treeObject)239 public boolean hasIncompleteTags( 240 final ITreeObject<? extends IAudioObject> treeObject) { 241 return hasIncompleteTags(treeObject, 242 this.stateNavigation 243 .getHighlightIncompleteTagFoldersAttributes()); 244 } 245 246 /** 247 * Returns true if audio file has filled all enabled attributes 248 * 249 * @param localAudioObject 250 * @param tagAttributesToCheck 251 * @return 252 */ hasTagAttributesFilled( final ILocalAudioObject localAudioObject, final List<TextTagAttribute> tagAttributesToCheck)253 private boolean hasTagAttributesFilled( 254 final ILocalAudioObject localAudioObject, 255 final List<TextTagAttribute> tagAttributesToCheck) { 256 if (localAudioObject.getTag() == null) { 257 return false; 258 } 259 260 for (TextTagAttribute ta : tagAttributesToCheck) { 261 if (!analyzeAttribute(localAudioObject, ta)) { 262 return false; 263 } 264 } 265 266 return true; 267 } 268 269 /** 270 * @param localAudioObject 271 * @param ta 272 * @return if attribute is filled 273 */ analyzeAttribute(final ILocalAudioObject localAudioObject, final TextTagAttribute ta)274 private boolean analyzeAttribute(final ILocalAudioObject localAudioObject, 275 final TextTagAttribute ta) { 276 return getTagCheckerForAttribute(ta) 277 .checkTagAttribute(localAudioObject); 278 } 279 280 /** 281 * Returns <code>true</code> if tree object contains audio objects with 282 * incomplete tags 283 * 284 * @param treeObject 285 * @param tagAttributes 286 * @return 287 */ hasIncompleteTags( final ITreeObject<? extends IAudioObject> treeObject, final List<TextTagAttribute> tagAttributes)288 private boolean hasIncompleteTags( 289 final ITreeObject<? extends IAudioObject> treeObject, 290 final List<TextTagAttribute> tagAttributes) { 291 for (IAudioObject f : treeObject.getAudioObjects()) { 292 if (hasIncompleteTags(f, tagAttributes)) { 293 return true; 294 } 295 } 296 return false; 297 } 298 299 /** 300 * Returns <code>true</code> if object has incomplete tag tags 301 * 302 * @param audioObject 303 * @param tagAttributes 304 * @return 305 */ hasIncompleteTags(final IAudioObject audioObject, final List<TextTagAttribute> tagAttributes)306 private boolean hasIncompleteTags(final IAudioObject audioObject, 307 final List<TextTagAttribute> tagAttributes) { 308 if (audioObject == null) { 309 throw new IllegalArgumentException("Null audioObject"); 310 } 311 if (audioObject instanceof ILocalAudioObject) { 312 return !hasTagAttributesFilled((ILocalAudioObject) audioObject, 313 tagAttributes); 314 } 315 return false; 316 } 317 318 /** 319 * @param attribute 320 * @return tag checker for given attribute 321 */ getTagCheckerForAttribute( final TextTagAttribute attribute)322 private ITagChecker getTagCheckerForAttribute( 323 final TextTagAttribute attribute) { 324 if (this.checkers == null) { 325 this.checkers = new HashMap<TextTagAttribute, ITagChecker>(); 326 this.checkers.put(TextTagAttribute.ALBUM, new AlbumTagChecker( 327 this.unknownObjectChecker)); 328 this.checkers.put(TextTagAttribute.ALBUM_ARTIST, 329 new AlbumArtistTagChecker(this.unknownObjectChecker)); 330 this.checkers.put(TextTagAttribute.ARTIST, new ArtistTagChecker( 331 this.unknownObjectChecker)); 332 this.checkers 333 .put(TextTagAttribute.COMMENT, new CommentTagChecker()); 334 this.checkers.put(TextTagAttribute.COMPOSER, 335 new ComposerTagChecker()); 336 this.checkers.put(TextTagAttribute.DISC_NUMBER, 337 new DiscNumberTagChecker()); 338 this.checkers.put(TextTagAttribute.GENRE, new GenreTagChecker( 339 this.unknownObjectChecker)); 340 this.checkers.put(TextTagAttribute.LYRICS, new LyricsTagChecker()); 341 this.checkers.put(TextTagAttribute.TITLE, new TitleTagChecker()); 342 this.checkers.put(TextTagAttribute.TRACK, new TrackTagChecker()); 343 this.checkers.put(TextTagAttribute.YEAR, new YearTagChecker( 344 this.unknownObjectChecker)); 345 } 346 return this.checkers.get(attribute); 347 } 348 349 @Override getImage(final ILocalAudioObject audioObject, final int width, final int height)350 public ImageIcon getImage(final ILocalAudioObject audioObject, 351 final int width, final int height) { 352 return this.localAudioObjectReader.getImage(audioObject, width, height); 353 } 354 } 355