1 package com.melloware.jukes.gui.view.dialogs;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.Frame;
6 import java.awt.event.ActionEvent;
7 import java.io.File;
8 import java.io.IOException;
9 import java.util.Collection;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.ArrayList;
13
14 import javax.swing.AbstractAction;
15 import javax.swing.Action;
16 import javax.swing.JButton;
17 import javax.swing.JComponent;
18 import javax.swing.JFileChooser;
19 import javax.swing.JPanel;
20 import javax.swing.JPopupMenu;
21 import javax.swing.JTable;
22 import javax.swing.JProgressBar;
23 import javax.swing.ListSelectionModel;
24 import javax.swing.RowSorter;
25 import javax.swing.event.ListSelectionEvent;
26 import javax.swing.event.ListSelectionListener;
27 import javax.swing.table.TableModel;
28 import javax.swing.table.TableRowSorter;
29
30 import org.apache.commons.io.FileUtils;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import com.jgoodies.forms.builder.PanelBuilder;
36 import com.jgoodies.forms.factories.ButtonBarFactory;
37 import com.jgoodies.forms.layout.CellConstraints;
38 import com.jgoodies.forms.layout.FormLayout;
39 import com.jgoodies.uif.AbstractDialog;
40 import com.jgoodies.uif.application.Application;
41 import com.jgoodies.uif.util.Resizer;
42 import com.jgoodies.uif.util.ResourceUtils;
43 import com.jgoodies.uif.util.Worker;
44 import com.jgoodies.uifextras.panel.HeaderPanel;
45 import com.jgoodies.uifextras.util.UIFactory;
46 import com.melloware.jukes.db.HibernateDao;
47 import com.melloware.jukes.db.orm.Disc;
48 import com.melloware.jukes.exception.InfrastructureException;
49 import com.melloware.jukes.file.Disclist;
50 import com.melloware.jukes.file.filter.FilterFactory;
51 import com.melloware.jukes.file.tag.MusicTag;
52 import com.melloware.jukes.gui.tool.MainModule;
53 import com.melloware.jukes.gui.tool.Resources;
54 import com.melloware.jukes.gui.tool.Settings;
55 import com.melloware.jukes.gui.view.MainFrame;
56 import com.melloware.jukes.gui.view.MainMenuBuilder;
57 import com.melloware.jukes.gui.view.component.EnhancedTableHeader;
58 import com.melloware.jukes.gui.view.component.ExportableTable;
59 import com.melloware.jukes.util.GuiUtil;
60 import com.melloware.jukes.util.MessageUtil;
61
62
63
64
65
66
67
68
69
70 public final class GenresToolDialog
71 extends AbstractDialog {
72
73 private static final Log LOG = LogFactory.getLog(SearchDialog.class);
74 private final EnhancedTableHeader header;
75 private final ExportableTable resultsTable;
76 private JButton buttonCancel;
77 private JButton buttonSearch;
78 private JButton buttonSelect;
79 private JButton buttonStop;
80 private JButton buttonSave;
81 private JButton buttonAddToDiscList;
82 private JComponent buttonBar;
83 private JProgressBar progressBar;
84 private Object[] results;
85 private DiscTableModel tableModel;
86 private final Settings settings;
87 private RowSorter<TableModel> sorter;
88 private Disc selection;
89 private Worker worker;
90 private JPopupMenu addDiscMenu;
91
92
93
94
95
96
97 public GenresToolDialog(Frame owner, Settings settings) {
98 super(owner);
99 LOG.debug("Genre Tool Dialog created.");
100 this.settings = settings;
101 this.settings.getDatabaseLocation();
102
103 resultsTable = new ExportableTable();
104 resultsTable.setEvenColor(this.settings.getRowColorEven());
105 resultsTable.setOddColor(this.settings.getRowColorOdd());
106 header = new EnhancedTableHeader(resultsTable.getColumnModel(), resultsTable);
107 resultsTable.setTableHeader(header);
108 addDiscMenu = MainMenuBuilder.buildDiscExportableTablePopupMenu(resultsTable);
109 resultsTable.addPopupMenu(addDiscMenu);
110
111 this.setPreferredSize(new Dimension(800, 576));
112
113 }
114
115
116
117
118
119
120 public Disc getSelection() {
121 return this.selection;
122 }
123
124
125
126
127 public void doAccept() {
128 LOG.debug("Select pressed.");
129 super.doAccept();
130 final MainFrame mainFrame = (MainFrame)Application.getDefaultParentFrame();
131 String query = " and upper(disc.name) = '" + selection.getName().toUpperCase() + "'";
132 String filter = MainModule.SETTINGS.getFilter();
133
134 if (!(this.settings.isShowDefaultTree() && !StringUtils.isNotBlank(filter))) {
135 filter = query;
136 }
137 MainModule.SETTINGS.setFilter(filter);
138 mainFrame.getMainModule().refreshTree();
139 mainFrame.getMainModule().selectNodeInTree(selection);
140 }
141
142
143
144
145 public void doCancel() {
146 LOG.debug("Cancel Pressed.");
147 super.doCancel();
148 }
149
150
151
152
153
154
155 protected JComponent buildContent() {
156 JPanel content = new JPanel(new BorderLayout());
157 JButton[] buttons = new JButton[6];
158 JButton button = createAcceptButton(Resources.getString("label.Select"), false);
159 button.setEnabled(false);
160 buttonSelect = button;
161 buttonCancel = createCancelButton();
162 buttonCancel.setText(Resources.getString("label.Close"));
163
164
165 final Action export = new AbstractAction(Resources.getString("label.SaveReport"), Resources.FILE_TEXT_ICON) {
166
167 public void actionPerformed(ActionEvent evt) {
168 saveReport(evt);
169 }
170 };
171 buttonSave = new JButton(export);
172
173
174 Action search = new AbstractAction(Resources.getString("label.StartCheck"), Resources.THREAD_START_ICON) {
175 public void actionPerformed(ActionEvent evt) {
176 doSearch();
177 }
178 };
179 buttonSearch = new JButton(search);
180
181
182 Action stop = new AbstractAction(Resources.getString("label.Cancel"), Resources.THREAD_STOP_ICON) {
183 public void actionPerformed(ActionEvent evt) {
184 doStop();
185 }
186 };
187 buttonStop = new JButton(stop);
188 buttonStop.setEnabled(false);
189
190
191 Action adddisclist = new AbstractAction(Resources.getString("label.AddToDiscList"), ResourceUtils.getIcon("disc.queue.icon")) {
192 public void actionPerformed(ActionEvent evt) {
193 doAddToDiscList();
194 }
195 };
196 buttonAddToDiscList = new JButton(adddisclist);
197
198
199 buttons[0] = buttonSearch;
200 buttons[1] = buttonStop;
201 buttons[2] = buttonSelect;
202 buttons[3] = buttonSave;
203 buttons[4] = buttonAddToDiscList;
204 buttons[5] = buttonCancel;
205 buttonBar = ButtonBarFactory.buildCenteredBar(buttons);
206
207 content.add(buildMainPanel(), BorderLayout.CENTER);
208 content.add(buttonBar, BorderLayout.SOUTH);
209 return content;
210 }
211
212
213
214
215
216
217 protected JComponent buildHeader() {
218 final HeaderPanel header = new HeaderPanel(Resources.getString("label.GenresCheck"),
219 Resources.getString("label.GenresCheckText"),
220 Resources.GENRES_TOOL_ICON);
221
222 return header;
223 }
224
225
226
227
228
229
230 protected JComponent buildMainPanel() {
231 FormLayout layout = new FormLayout("fill:pref:grow", "p, 4px, p, 4px");
232 PanelBuilder builder = new PanelBuilder(layout);
233 builder.setDefaultDialogBorder();
234 CellConstraints cc = new CellConstraints();
235 builder.add(buildProgressPanel(), cc.xy(1, 1));
236 builder.add(buildResultsTablePanel(), cc.xy(1, 3));
237 return builder.getPanel();
238 }
239
240
241
242
243 protected void doSearch() {
244 LOG.debug("Searching...");
245
246 GuiUtil.setBusyCursor(this, true);
247 buttonSearch.setEnabled(false);
248 buttonCancel.setEnabled(false);
249 buttonSelect.setEnabled(false);
250 buttonSave.setEnabled(false);
251 buttonAddToDiscList.setEnabled(false);
252 buttonStop.setEnabled(true);
253
254
255
256
257
258 worker = new Worker() {
259 public Object construct() {
260 return doWork();
261 }
262
263 public void finished() {
264 threadFinished(get());
265 }
266 };
267 worker.start();
268 }
269
270
271
272
273 protected void doStop() {
274 LOG.debug("Stopping...");
275 GuiUtil.setBusyCursor(this, false);
276 worker.interrupt();
277 buttonSearch.setEnabled(true);
278 buttonCancel.setEnabled(true);
279 buttonSave.setEnabled(true);
280 buttonAddToDiscList.setEnabled(true);
281 buttonStop.setEnabled(false);
282 }
283
284
285
286
287
288
289 protected void resizeHook(JComponent component) {
290 Resizer.ONE2ONE.resizeDialogContent(component);
291 }
292
293
294
295
296
297
298 protected void threadFinished(Object result) {
299 if (LOG.isDebugEnabled()) {
300 LOG.debug("Thread Finished");
301 }
302 buttonSearch.setEnabled(true);
303 buttonCancel.setEnabled(true);
304 buttonSave.setEnabled(true);
305 buttonAddToDiscList.setEnabled(true);
306 buttonStop.setEnabled(false);
307 GuiUtil.setBusyCursor(this, false);
308
309 if (result == null) {
310 results = null;
311 tableModel = new DiscTableModel(results);
312 tableModel.setData(null);
313 tableModel.fireTableDataChanged();
314 } else {
315 final Collection items = (Collection)result;
316 results = items.toArray();
317 tableModel = new DiscTableModel(results);
318 sorter = new TableRowSorter<TableModel>(tableModel);
319 resultsTable.setModel(tableModel);
320 resultsTable.setRowSorter(sorter);
321 header.autoSizeColumns();
322 }
323
324 resultsTable.updateUI();
325
326 }
327
328
329
330
331
332
333 private JComponent buildResultsTablePanel() {
334
335
336 resultsTable.setShowGrid(false);
337 resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
338 resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
339
340 final ListSelectionModel rowSM = resultsTable.getSelectionModel();
341 rowSM.addListSelectionListener(new ListSelectionListener() {
342 public void valueChanged(ListSelectionEvent e) {
343
344 if (e.getValueIsAdjusting()) {
345 return;
346 }
347
348 final ListSelectionModel lsm = (ListSelectionModel)e.getSource();
349 if (lsm.isSelectionEmpty()) {
350 selection = null;
351 buttonSelect.setEnabled(false);
352
353 } else {
354 int selectedRow = resultsTable.getSelectedRow();
355 selectedRow = sorter.convertRowIndexToModel(selectedRow);
356 selection = (Disc)results[selectedRow];
357 buttonSelect.setEnabled(true);
358
359 }
360 }
361 });
362
363 final JComponent resultsPane = UIFactory.createTablePanel(resultsTable);
364 resultsPane.setPreferredSize(new Dimension(300, 350));
365
366
367 final FormLayout layout = new FormLayout("fill:pref:grow", "p");
368 final PanelBuilder builder = new PanelBuilder(layout);
369 final CellConstraints cc = new CellConstraints();
370 builder.add(resultsPane, cc.xy(1, 1));
371 return builder.getPanel();
372 }
373
374
375
376
377
378 private Object doWork() {
379 ArrayList<Disc> selectedDiscs = new ArrayList<Disc>();
380 boolean Stop = false;
381 try {
382
383 try {
384
385
386
387 final String hql = "select disc from Disc as disc inner join disc.artist as artist order by upper(artist.name)";
388 final Collection discs = HibernateDao.findByQuery(hql);
389 if (LOG.isDebugEnabled()) {
390 LOG.debug("Disc Count = " + discs.size());
391 }
392 int count = 0;
393
394 progressBar.setMaximum(discs.size());
395 progressBar.setValue(0);
396 progressBar.setIndeterminate(false);
397 for (final Iterator iter = discs.iterator(); ((iter.hasNext())&&(!Stop));) {
398 final Disc disc = (Disc)iter.next();
399 count++;
400 final boolean success = checkGenre(disc.getGenre());
401 progressBar.setValue(count);
402 if (!success) {
403
404 if (!(disc.getNotes()==null)) {
405
406
407 int charLength = disc.getNotes().length();
408 if (charLength > 30) {
409 charLength=30;
410 };
411
412 if (charLength > 0) {
413 String noteStr = disc.getNotes().substring(0,charLength-1);
414 String noteStrNew = "";
415 for ( int i=0; i<charLength-1; i++ ) {
416 if (((int)noteStr.charAt(i)==10)) {
417 noteStrNew= noteStrNew + " ";
418 }
419 else if (((int)noteStr.charAt(i)==13)) {
420 noteStrNew= noteStrNew + " ";
421 }
422 else {
423 noteStrNew= noteStrNew + noteStr.charAt(i);
424 }
425 }
426 disc.setNotes(noteStrNew);
427 }
428 LOG.info("Erroneous genre found: " + disc.getArtist().getName() + " - " + disc.getName() + " : " + disc.getGenre());
429 selectedDiscs.add(disc);
430 }
431 }
432 if (Thread.interrupted()) {
433 Stop = true;
434 }
435 }
436
437 } catch (RuntimeException ex) {
438
439 final String message = "Unexpected error occured performing search.";
440 LOG.debug(message, ex);
441 throw new InterruptedException(message);
442 }
443
444 if (Thread.interrupted()) {
445 LOG.debug("Thread interrupted.");
446 throw new InterruptedException();
447 }
448
449 } catch (InterruptedException e) {
450 return selectedDiscs;
451 }
452 return selectedDiscs;
453 }
454
455
456
457
458
459 private boolean checkGenre(String genre){
460 boolean isGenre = false;
461 final List GENRE_LIST = MusicTag.getGenreTypes();
462 String BasicGenre = genre;
463 String[] separatorList = {":", ";", ".", "-", ",", "/"};
464 int index = genre.length();
465 if (genre.equalsIgnoreCase("<none>")) {
466 return isGenre;
467 }
468 for(int i=0; i<separatorList.length; i++){
469 final int currentIndex = genre.indexOf(separatorList[i]);
470 if ((currentIndex > 0) & (currentIndex < index) ){
471 index = currentIndex;
472 }
473 }
474 BasicGenre = genre.substring(0, index);
475 if (containsIgnoreCase(GENRE_LIST, BasicGenre)) {
476 isGenre = true;
477 }
478 return isGenre;
479 }
480
481
482
483 public boolean containsIgnoreCase(List <String> l, String s){
484 Iterator<String> it = l.iterator();
485 while(it.hasNext()){
486 if(it.next().compareToIgnoreCase(s)==0) {
487 return true;
488 }
489 }
490 return false;
491 }
492
493
494
495
496
497 private JComponent buildProgressPanel() {
498 progressBar = new JProgressBar();
499 progressBar.setIndeterminate(false);
500 progressBar.setStringPainted(true);
501 final FormLayout layout = new FormLayout("right:max(14dlu;pref), 4dlu, p, fill:pref:grow",
502 "p, 4px, p");
503 final PanelBuilder builder = new PanelBuilder(layout);
504 final CellConstraints cc = new CellConstraints();
505
506 builder.addLabel(Resources.getString("label.Progress"), cc.xy(1, 1));
507 builder.add(progressBar, cc.xyw(3, 1, 2));
508
509 return builder.getPanel();
510 }
511
512
513
514
515
516
517 protected void saveReport(final ActionEvent aEvt) {
518 LOG.debug("Save Found Genres Errors Report pressed.");
519 final JFileChooser chooser = new JFileChooser();
520 chooser.setDialogTitle(Resources.getString("label.SaveReport"));
521 String messageString;
522
523 chooser.setFileFilter(FilterFactory.textFileFilter());
524 chooser.setMultiSelectionEnabled(false);
525 chooser.setFileHidingEnabled(true);
526 final int returnVal = chooser.showSaveDialog(this);
527 if (returnVal != JFileChooser.APPROVE_OPTION) {
528 return;
529 }
530 File file = chooser.getSelectedFile();
531 if (LOG.isDebugEnabled()) {
532 LOG.debug("Absolute: " + file.getAbsolutePath());
533 }
534
535
536 file = FilterFactory.forceTextExtension(file);
537
538 try {
539
540 final ArrayList results = new ArrayList();
541 final int col = resultsTable.getColumnCount();
542 for(int i=0; i<resultsTable.getRowCount(); i++){
543 messageString = i+Character.toString((char)9);
544 for (int ii=0; ii<col; ii++) {
545 messageString = messageString + resultsTable.getValueAt(i, ii).toString() + Character.toString((char)9);
546 }
547 results.add(messageString);
548 }
549
550 FileUtils.writeLines(file, null, results);
551
552 MessageUtil.showInformation(this, Resources.getString("label.reportsaved"));
553 } catch (IOException ex) {
554 final String errorMessage = ResourceUtils.getString("label.Errorwritingfile");
555 MessageUtil.showError(this, errorMessage);
556 LOG.error(errorMessage + "\n\n" + ex.getMessage(), ex);
557 } catch (InfrastructureException ex) {
558 final String errorMessage = ResourceUtils.getString("label.Errorwritingfile");
559 MessageUtil.showError(this, errorMessage);
560 LOG.error(errorMessage + "\n\n" + ex.getMessage(), ex);
561 } catch (Exception ex) {
562 final String errorMessage = ResourceUtils.getString("label.Errorwritingfile");
563 MessageUtil.showError(this, errorMessage);
564 LOG.error(errorMessage, ex);
565 }
566 }
567
568
569
570
571 protected void doAddToDiscList() {
572 final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
573 final Disclist disclist = mainFrame.getDisclist();
574 LOG.debug("Adding found discs to discList");
575
576 GuiUtil.setBusyCursor(this, true);
577 for (int i = 0; i < this.results.length; i++) {
578 disclist.add(tableModel.getData()[i]);
579 }
580 GuiUtil.setBusyCursor(this, false);
581 }
582
583 }